android 如何检测布局调整?

x6yk4ghg  于 2023-01-07  发布在  Android
关注(0)|答案(7)|浏览(174)

Dianne Hackborn在几个线程中提到,你可以检测布局何时被调整大小,例如,软键盘何时打开或关闭。
然而,我没听懂她的回答:“通过使用所有相应的布局遍历和回调调整视图层次结构的大小.”
有没有人有进一步的描述或者一些例子来说明如何检测这个问题?我可以链接到哪些回调函数来检测这个问题?
谢啦,谢啦

o8x7eapl

o8x7eapl1#

一种方法是View.addOnLayoutChangeListener。在这种情况下,不需要子类化视图。但是您需要API级别11。并且根据边界(API中没有说明)正确计算大小有时可能是一个陷阱。下面是一个正确的示例:

view.addOnLayoutChangeListener( new View.OnLayoutChangeListener()
{
    public void onLayoutChange( View v,
      int left,    int top,    int right,    int bottom,
      int leftWas, int topWas, int rightWas, int bottomWas )
    {
        int widthWas = rightWas - leftWas; // Right exclusive, left inclusive
        if( v.getWidth() != widthWas )
        {
            // Width has changed
        }
        int heightWas = bottomWas - topWas; // Bottom exclusive, top inclusive
        if( v.getHeight() != heightWas )
        {
            // Height has changed
        }
    }
});

另一种方法(正如dacwe所回答的)是将视图子类化并覆盖onSizeChanged。

6kkfgxo0

6kkfgxo02#

覆盖View中的大小更改!

cl25kdpy

cl25kdpy3#

使用Kotlin分机:

inline fun View?.onSizeChange(crossinline runnable: () -> Unit) = this?.apply {
    addOnLayoutChangeListener { _, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
        val rect = Rect(left, top, right, bottom)
        val oldRect = Rect(oldLeft, oldTop, oldRight, oldBottom)
        if (rect.width() != oldRect.width() || rect.height() != oldRect.height()) {
            runnable();
        }
    }
}

这样使用:

myView.onSizeChange { 
     // Do your thing...
}
qeeaahzv

qeeaahzv4#

我的解决方案是在布局/片段的末尾添加一个不可见的小哑视图(或者将其添加为背景),因此布局大小的任何更改都将触发该视图的布局更改事件,OnLayoutChangeListener可以捕捉到该事件:
将哑视图添加到布局末尾的示例:

<View 
    android:id="@+id/theDumbViewId"
    android:layout_width="1dp"
    android:layout_height="1dp"
     />

侦听事件:

View dumbView = mainView.findViewById(R.id.theDumbViewId);
    dumbView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
            // Your code about size changed
        }
    });
hjqgdpho

hjqgdpho5#

多亏了https://stackoverflow.com/users/2402790/michael-allan,如果你不想覆盖所有的视图,这是一个很好很简单的方法。随着API的发展,我建议用复制粘贴代替:

String TAG="toto";
    ///and last listen for size changed
    YourView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v,
                                   int left, int top, int right, int bottom,
                                   int oldLeft, int oldTop, int oldRight, int oldBottom) {

           boolean widthChanged = (right-left) != (oldRight-oldLeft);
            if( widthChanged )
            {
                // width has changed
                Log.e(TAG,"Width has changed new width is "+(right-left)+"px");
            }
            boolean heightChanged = (bottom-top) != (oldBottom-oldTop);
            if( heightChanged)
            {
                // height has changed
                Log.e(TAG,"height has changed new height is "+(bottom-top)+"px");
            }
        }
    });
jk9hmnmh

jk9hmnmh6#

View.doOnLayout(crossinline action: (view: View) -> Unit): Unit

参见文档。
在布局此视图时执行给定的操作。如果视图已布局且未请求布局,则将立即执行该操作,否则将在下一次布局视图后执行该操作。
该操作将仅在下一个布局上调用一次,然后删除。

l7mqbcuq

l7mqbcuq7#

Kotlin版本基于@Michael Allan答案检测布局大小变化

binding.root.addOnLayoutChangeListener { view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
    if(view.height != oldBottom - oldTop) {
        // height changed
    }
    if(view.width != oldRight - oldLeft) {
        // width changed
    }
}

相关问题