【问题标题】:How to detect a layout resize?如何检测布局调整大小?
【发布时间】:2011-05-09 15:28:54
【问题描述】:

Dianne Hackborn 在几个线程中提到,您可以检测布局何时调整大小,例如,软键盘何时打开或关闭。这样的线程就是这个……http://groups.google.com/group/android-developers/browse_thread/thread/d318901586313204/2b2c2c7d4bb04e1b

但是,我不明白她的回答:“通过所有相应的布局遍历和回调来调整视图层次结构的大小。”

有没有人有进一步的描述或一些如何检测这个的例子?我可以链接到哪些回调来检测这一点?

谢谢

【问题讨论】:

    标签: android user-interface layout resize


    【解决方案1】:

    一种方法是查看.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

    【讨论】:

    • 应该是选择的答案
    • 这真的很有帮助!聪明漂亮:)
    • 警告。这可能会被调用太多次使用等于参数
    【解决方案2】:

    在您的View 中覆盖onSizeChanged

    【讨论】:

    • 我希望有一种不需要子类化视图的方法,但这确实可以按我的意愿工作,谢谢。为了调用视图的父活动,我在子类视图中创建了一个侦听器,该侦听器调用已调整大小的活动。再次感谢。
    • @dacwe 如何停止调整布局'
    【解决方案3】:

    我的解决方案是在布局/片段的末尾添加一个不可见的微小哑视图(或将其添加为背景),因此布局大小的任何更改都会触发该视图的布局更改事件,这可能被 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
            }
        });
    

    【讨论】:

      【解决方案4】:

      使用 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 you thing...
      }
      

      【讨论】:

        【解决方案5】:

        感谢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");
                    }
                }
            });
        

        【讨论】:

          【解决方案6】:
          View.doOnLayout(crossinline action: (view: View) -> Unit): Unit
          

          docs.

          在布局此视图时执行给定的操作。如果视图已经布局,并且没有请求布局,则立即执行该操作,否则将在视图下一次布局后执行该操作。

          该动作只会在下一个布局中被调用一次,然后被移除。

          【讨论】:

            【解决方案7】:

            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
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-04-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-08-31
              • 2016-07-17
              • 1970-01-01
              相关资源
              最近更新 更多