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! :-)
@user3492470
Thank you so much for your answer. I thought nobody has an idea.
Your “solution” is interesting but unfortunately a little bit wrong. Optically it works great but in the background you have got an endless loop …
You will see it if you set a counter at the text of one of the Button
s. The counter increases endlessly.
The setting of Button
s' new layout size in the Handler
is followed by a new call of the OnLayoutChangeListener
and this Listener
starts the Handler
again and so on …
You will get the same problem if you are using the OnGlobalLayoutListener
instead of the OnLayoutChangeListener
with a Handler
.
The reason is the following. The view.requestLayout()
or view.setLayoutParams(…)
does not work in the onLayoutChange
method, but it works in the onGlobalLayout
method or in a Handler
which creates a new thread.
Now the part I really don't understand:
A successful call on the child.requestLayout()
makes a new call on the parent's onLayoutChange
method. This is peculiar because the parent's layout should not change again.
However that be, a little if/else logic solves the endless calls.
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++);
}
In this case I use the OnGlobalLayoutListener
instead of the OnLayoutChangeListener
/uiHandler
Combination. ;-) The if/else logic is the same.
My original question, why requestLayout
does not work in onLayoutChange
, is still open but a satisfying solution was presented here so I am happy.
Thank you again for your concern!