I have to use the GridLayout
for my application. The problem of GridLayout
is the limitation of weight so I must scale its children size at runtime. I do this by the help of an OnGlobalLayoutListener
.
The children of my GridLayout
are two Button
s which have got the width of the parent and the half of parents height. One Button
above and one Button
below.
If the upper Button
is clicked I want to switch the size of the GridLayout
to 500 in width and height and 700 in width and height.
After the click at the upper Button
the Button
s should scale correctly but they don't do that.
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();
}
}
Can anybody tell me what to do?
How can I tell the ContentView
to refresh itself and its children? I am searching for an elegant solution.
Thank you very much for answers!
Regards! :-)
I ran into the same problem. I guess Android has not finished calculating the new layout when onLayoutChanges()
is called, and a recalculation cannot be triggered from within the method.
The solution is to use a Handler to post layout changes to the end of the UI thread.
I am not really sure about requestLayout()
, maybe replace it with another call of setLayoutParams()
. It probably has the same effect.
So implement your re-layout in a class implementing Runnable
, instantiate a Handler
in onCreate()
and in onLayoutChanges()
instantiate the Runnable class and post it to the 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);
}
}