我必须使用GridLayout
作为我的应用程序。 GridLayout
的问题是权重的限制因此我必须在运行时缩放其子项大小。我是在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
刷新自己及其子女?我正在寻找一个优雅的解决方案。
非常感谢您的回答!
问候! : - )
答案 0 :(得分:6)
我遇到了同样的问题。我猜Android在调用onLayoutChanges()
时还没有完成计算新布局,并且无法从方法中触发重新计算。
解决方案是使用Handler将布局更改发布到UI线程的末尾。
我对requestLayout()
并不十分确定,可能会将其替换为setLayoutParams()
。它可能具有相同的效果。
因此,在实现Runnable
的类中实现重新布局,在Handler
中实例化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);
}
}
答案 1 :(得分:6)
@ user3492470
非常感谢你的回答。我以为没人知道。
你的“解决方案”很有意思,但遗憾的是有点不对劲。光学上它很有效,但在后台你有一个无限循环...
如果您在其中一个Button
的文本处设置计数器,您将看到它。柜台无休止地增加
在Button
中设置Handler
s'新布局尺寸之后是OnLayoutChangeListener
的新调用,此Listener
再次启动Handler
,因此在...上
如果您使用OnGlobalLayoutListener
而不是OnLayoutChangeListener
并使用Handler
,则会遇到同样的问题。
原因如下。 view.requestLayout()
或view.setLayoutParams(…)
在onLayoutChange
方法中不起作用,但它适用于onGlobalLayout
方法或创建新主题的Handler
。<登记/>
现在这部分我真的不明白:
child.requestLayout()
上的成功通话会对父母的onLayoutChange
方法进行新的调用。这很奇怪,因为父母的布局不应该再改变
然而,有一点if / else逻辑解决了无休止的调用。
private int counter = 0;
@Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
/* Width and height on this time are known */
int width = mGridLayout.getWidth();
int height = mGridLayout.getHeight();
/* Buttons width and height are supposed to be */
int mButtons_width = width;
int mButtons_height = height / 2;
if(!(mButtonAbove.getWidth() == mButtons_width &&
mButtonAbove.getHeight() == mButtons_height &&
mButtonBelow.getWidth() == mButtons_width &&
mButtonBelow.getHeight() == mButtons_height)
){
/* Changes the LayoutParams of ContentViews children dynamicly */
mGridLayout_LayoutParams_Above.width = mButtons_width;
mGridLayout_LayoutParams_Above.height = mButtons_height;
mGridLayout_LayoutParams_Below.width = mButtons_width;
mGridLayout_LayoutParams_Below.height = mButtons_height;
/* NO ISSUE ANYMORE:
* updates the rendering of the buttons */
mButtonAbove.requestLayout();
mButtonBelow.requestLayout();
}
/* A little debug info for knowing the ContentView's and Children's size */
mButtonBelow.setText("Own Width = " + mButtonBelow.getWidth() + "\n" +
"Own Height = " + mButtonBelow.getHeight() + "\n" +
"Perents Width = " + width + "\n" +
"Perents Height = " + height + "\n" +
"Calls = " + counter++);
}
在这种情况下,我使用OnGlobalLayoutListener
代替OnLayoutChangeListener
/ uiHandler
组合。 ;-) if / else逻辑是相同的。
我原来的问题,为什么requestLayout
在onLayoutChange
中不起作用,仍然是开放的,但这里提出了一个令人满意的解决方案,所以我很高兴。
再次感谢您的关注!
答案 2 :(得分:0)
处理程序很危险。建议使用
view.getViewTreeObserver().addOnPreDrawListener();
这不是冲突;