java - Android - View.requestLayout 在 OnLayoutChangeListener 中不起作用

标签 java android layout viewgroup

我的应用程序必须使用 GridLayoutGridLayout 的问题是权重的限制,因此我必须在运行时缩放其子项的大小。我在 OnGlobalLayoutListener 的帮助下完成了这项工作。

我的 GridLayout 的子级是两个 Button,它们具有父级的宽度和父级高度的一半。上面有一个 Button,下面有一个 Button。 如果单击上方的 Button,我想将 GridLayout 的大小切换为 500(宽度和高度)以及 700(宽度和高度)。 单击上方的 Button 后,Button 应该会正确缩放,但它们不会那样做。

public class HauptAktivitaet extends Activity implements OnLayoutChangeListener, OnClickListener{

  /** ContentView its sizes I will change on a click later */

  private GridLayout mGridLayout;

  /** LayoutParams of the above child */

  private GridLayout.LayoutParams mGridLayout_LayoutParams_Above;

  /** LayoutParams of the below child */

  private GridLayout.LayoutParams mGridLayout_LayoutParams_Below;

  /** Children of the ContentView */

  private Button mButtonAbove;
  private Button mButtonBelow;


  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    inline();

    setContentView(mGridLayout);

  }

  private void inline(){

    /* instantiation of ContentView which is named mGridLayout */

    mGridLayout = new GridLayout(this);

    /* set the count of rows and columns of ContentView */

    mGridLayout.setRowCount(2);
    mGridLayout.setColumnCount(1);

      /* set OnGlobalLayoutListener for observe a change of its layout */

    mGridLayout.addOnLayoutChangeListener(this);

    /* instantiation of the LayoutParams for the children */

    mGridLayout_LayoutParams_Above = new GridLayout.LayoutParams(GridLayout.spec(0), GridLayout.spec(0));
    mGridLayout_LayoutParams_Below = new GridLayout.LayoutParams(GridLayout.spec(1), GridLayout.spec(0));

    /* instantiation of the children and setting of their LayoutParams */

    mButtonAbove = new Button(this);
    mButtonAbove.setLayoutParams(mGridLayout_LayoutParams_Above);
    mButtonAbove.setOnClickListener(this); // A click on this Button changes the Size of its parent ViewGroup.

    /* instantiation of ContentView */

    mButtonBelow = new Button(this);
    mButtonBelow.setLayoutParams(mGridLayout_LayoutParams_Below);

    /* add children to the ContentView */

    mGridLayout.addView(mButtonAbove);
    mGridLayout.addView(mButtonBelow);

  }

  @Override
  public void onLayoutChange(View v, int left, int top, int right, int bottom,
      int oldLeft, int oldTop, int oldRight, int oldBottom) {

    /* Width and height on this time are known */

    int width = mGridLayout.getWidth();
    int height = mGridLayout.getHeight();

    /* Changes the LayoutParams of ContentViews children dynamicly*/

    mGridLayout_LayoutParams_Above.width = width;
    mGridLayout_LayoutParams_Above.height = height / 2;

    mGridLayout_LayoutParams_Below.width = width;
    mGridLayout_LayoutParams_Below.height = height / 2;

    /* ISSUE:
     * should update the rendering of the buttons but it doesn't work correctly */

    mButtonAbove.requestLayout();
    mButtonBelow.requestLayout();

    /* A little debug info for knowing of the ContentViews size */

    mButtonBelow.setText("Own Width = " + mButtonBelow.getWidth() + "\n" + 
                         "Own Height = " + mButtonBelow.getHeight() + "\n" +
                         "Perents Width = " + width + "\n" +
                         "Perents Height = " + height);


  }

  private boolean switcher = true;

  /** 
   * Works correctly
   * */

  @Override
  public void onClick(View v) {

    int width = 0;
    int height = 0;

    if(switcher){
      width = 500;
      height = 500;
      switcher = false;
    }else{
      width = 700;
      height = 700;
      switcher = true;
    }

    mGridLayout.getLayoutParams().width = width;
    mGridLayout.getLayoutParams().height = height;

    mGridLayout.requestLayout();

  }

}

谁能告诉我该怎么做?

如何让 ContentView 刷新自身及其子级?我正在寻找一个优雅的解决方案。

非常感谢您的回答!

问候! :-)

最佳答案

我遇到了同样的问题。我猜当 onLayoutChanges() 被调用时 Android 还没有完成新布局的计算,并且无法从该方法中触发重新计算。 解决方案是使用 Handler将布局更改发布到 UI 线程的末尾。

我不太确定 requestLayout(),也许用 setLayoutParams() 的另一个调用替换它。它可能具有相同的效果。

因此,在实现 Runnable 的类中实现重新布局,在 onCreate()onLayoutChanges( ) 实例化 Runnable 类并将其提交给 Handler:

public class HauptAktivitaet extends Activity implements OnLayoutChangeListener, OnClickListener{

  // this class updates the layout
  private class LayoutUpdater implements Runnable {
    private final int width;
    private final int height;

    private LayoutUpdater(int width, int height) {
      this.width = width;
      this.height = height;
    }

    public void run() {
      mGridLayout_LayoutParams_Above.width = width;
      mGridLayout_LayoutParams_Above.height = height;

      mGridLayout_LayoutParams_Below.width = width;
      mGridLayout_LayoutParams_Below.height = height;

      // might be necessary or not: set layout parameters to trigger update
      mButtonAbove.setLayoutParams(mGridLayout_LayoutParams_Above);   
      mButtonBelow.setLayoutParams(mGridLayout_LayoutParams_Below);
    }
  }

  /* snip */

  // add handler running in UI thread
  private Handler uiHandler;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // instantiate handler
    uiHandler = new Handler();

    inline();

    setContentView(mGridLayout);

  }

  /* snip */

  @Override
  public void onLayoutChange(View v, int left, int top, int right, int bottom,
      int oldLeft, int oldTop, int oldRight, int oldBottom) {

    /* Width and height on this time are known */

    int width = mGridLayout.getWidth();
    int height = mGridLayout.getHeight();

    // post layout update to the end of queue
    uiHandler.post(new LayoutUpdater(width, height / 2);
  }
}

关于java - Android - View.requestLayout 在 OnLayoutChangeListener 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25329934/

相关文章:

android - 如何让我的 Android 应用程序在触摸板上正确显示?

java - 当包含在 GridBagLayout 中时,如何使我的面板换行文本并增加高度而不是宽度?

java - 获取异常 java.util.NoSuchElementException : key not found: 'text' in spark-cassandra-connector

android - 有没有办法了解用户是否安装了 Android App Update?

java - 安卓计算器按钮不起作用

android - 带有 intentfilter 的 fragment

xaml - 有没有办法在 XAML Xamarin 中指定多个 LayoutFlags?

java - 从多个 JButtons java swing 中第一个单击的 Jbutton 返回结果

java - 如何通过Jsoup获取 "select"html元素?

java - Java 中的 Akka Cluster 使用 Java Mail API 进行 IMAP 获取