Columns not getting displayed in GridLayout in Android - android

I am trying to display a grid of buttons using gridLayout at runtime. I am trying to fit the gridLayout to fit the entire screen's width. I am able to do that for 3x3 and 5x5 button grid (using my nexus 4). But when I go for 7x7, I lose the last column of buttons i.e the last column of GridLayout. I seriously cant understand whats going wrong here.
Here's what I am doing.. I take the grid size from settings activity and this is the number of columns in GridLayout (numColumns). I use LayoutParams and get the width and height and set the buttons' width and height to (layoutWidth/numColumns) and (layoutHeight/numColumns). Please help me here guyz.. I have pasted the code below.
public class StartGameActivity extends ActionBarActivity {
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_game);
SharedPreferences sharedPref= PreferenceManager.getDefaultSharedPreferences(this);
int numColumns=Integer.parseInt(sharedPref.getString("Grid", "3").toString());
// create a RelativeLayout
RelativeLayout relativeLayout = new RelativeLayout(this);
//LinearLayout linearLayout = new LinearLayout(this);
// define the RelativeLayout layout parameters.
//LinearLayout.LayoutParams linearLayoutparams=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
DisplayMetrics metrics=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width=metrics.widthPixels;
int height=metrics.heightPixels;
RelativeLayout.LayoutParams relativeLayoutParams = new RelativeLayout.LayoutParams(width,height);
RelativeLayout.LayoutParams relativeLayoutParams1 = new RelativeLayout.LayoutParams(width,height);
GridLayout gridLayout=new GridLayout(this);
GridLayout.LayoutParams gridLayoutParams = new GridLayout.LayoutParams();
gridLayoutParams.setGravity(Gravity.FILL_HORIZONTAL);
gridLayout.setColumnCount(numColumns);
gridLayout.setRowCount(numColumns);
gridLayout.setMinimumHeight(height);
gridLayout.setMinimumWidth(width);
for(int i=0;i<numColumns*numColumns;i++)
{
Button button=new Button(this);
button.setWidth(width/numColumns);
button.setHeight(width/numColumns);
button.setMinWidth(width/numColumns);
button.setMinHeight(width/numColumns);
button.setGravity(Gravity.FILL);
//buttonForEveryRow++;
//columIndex++;
gridLayout.addView(button);
}
relativeLayout.addView(gridLayout,relativeLayoutParams1);
setContentView(relativeLayout,relativeLayoutParams);
}
}

You should set the parameters of the button only after it has been added to it's parent layout.
So inside your FOR loop, remove all the button.set.. lines and add the following lines at the end(after the gridLayout.addView line) :
ViewGroup.LayoutParams par = button.getLayoutParams();
par.width=width/numColumns;
par.height=width/numColumns;
button.setLayoutParams(par);
http://developer.android.com/reference/android/view/View.html#getLayoutParams%28%29 :
All views should have layout parameters. These supply parameters to the parent of this view specifying how it should be arranged.

Related

Adding TextViews inside horizontal LinearLayout dynamically

Click here to see the image
In the profile page of my application, I want to have an interest section as shown in the image. The user has a list of interest under his profile. I want to show his/her interests inside a horizontal LinearLayout. I have created an array of TextViews and add them dynamically inside the parent LinearLayout, but I do not want to add the TextViews when there is no more space. Instead, I want to add a TextView showing the number of remaining interests.
As shown in the picture (use the image link), the user had 24 interests, 4 of them fit horizontally on the same line and last TextView(+20) shows the number of remaining interests on the same line.
String interestList[]={"Travel","Music","Photography","Sports","Dance","Animals","SciFi Movies"};
int interestWidth =0, parentWidth=interestLinearLayout.getWidth();
for(String interest: interestList) {
TextView textView = new TextView(MainActivity.this);
textView.setBackground(getResources().getDrawable(R.drawable.interests_bg));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(2,0,10,2);
textView.setLayoutParams(params);
textView.setPadding(2, 2, 2, 2);
textView.setText(" "+interest+" ");
textView.setTextColor(getResources().getColor(R.color.white));
textView.setIncludeFontPadding(true);
interestWidth += textView.getWidth();
if(interestWidth<parentWidth) //both are 0 on first iteration of loop???
interestLinearLayout.addView(textView);
else
break;
}
You can add views dynamically but first you need a reference to the parent view to which you want to add a view.
You can do this by just using findViewById. Assuming it's a linear layout,
LinearLayout parent = findViewById(R.id.parent);
// Then create a textview
TextView textView = new TextView(this);
// Add the view to the parent
parent.addView(textView);
And that's it! To change properties about the TextView, you can use TextView getters and setters. If you want to change the margin, padding or height of width of the TextView, use LayoutParams
// Remember that I'm using LinearLayout.LayoutParams because the parent of the ttextview is a LinearLayout
LinearLayout.LayourParams params = textView.getLayoutParams();
// Remember these values are in pixels
params.height = 100;
params.width = 200;
There are tons of problems using this method, such as setting height and width in pixels instead of dps. And writing a lot of code when you could have done it in xml. You can however make this much easier by creating an xml file in your res/layout and then inflating it and finally adding it to the parent.
You can do this by -
// First get the layout inflater
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TextView textView = inflater.inflate(R.layout.myTextView, null);
linearLayout.addView(textView);
Finally addressing your problem about adding only enough views that the linearLayout doesn't go beyond the screen width.
The easiest solution is, to loop through the interest list and in every iteration of the loop, measure the combined width of the TextViews created and then checking whether it exceeds the width of the linearLayout.
It would look similar to this -
int combinedWidth = 0;
int linearLayoutWidth = linearLayout.getMeasuredWidth();
for(String interest : interests){
TextView view = inflater.inflate(R.layout.textview, null);
combinedWidth += textView.getMeasuredWidth();
view.setText(interest);
if(combinedWidth > linearLayoutWidth){
// No need to add more views
break;
}else{
linearLayout.addView(textView);
}
}
However, the above solution may or may not work depending on when it is executed. So post the activity code along with the xml file so that I can better answer your question.
The interestWidth and parentWidth are initially 0 because they have not been laid out when getWidth is called.
get width for dynamically created textViews
The above link helped me getting width of dynamically created textViews from interestList.
And by using ViewTreeObserver on interestLinearLayout I was able to get the width of LinearLayout after it was laid out.
Finally, the above code should be modified as below to add textViews from JAVA inside a LinearLayout.
final LinearLayout interestLinearLayout = findViewById(R.id.interests);
interestLinearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
interestLinearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
String interestList[]={"Travel","Music","Photography","Sports","Dance","Animals","SciFi Movies"};
int interestWidth =0;
int parentWidth = interestLinearLayout.getWidth(); // got width inside view tree observer for linearlayout
for(String interest: interestList) {
TextView textView = new TextView(MainActivity.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(2,0,10,2);
textView.setLayoutParams(params);
textView.setPadding(2, 2, 2, 2);
textView.setText(interest);
textView.setIncludeFontPadding(true);
textView.measure(0,0); //using approach mentioned in link to get width of text views
interestWidth += textView.getMeasuredWidth();
if(interestWidth<parentWidth)
interestLinearLayout.addView(textView);
else
break;
}
}
});
To create a LinearLayout,
LinearLayout layout = new LinearLayout(MainActivity.this);
To set background color of a layout,
layout.setBackgroundColor(Color.parseColor("#135517"));
To set width and height of the layout,
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(15, 5, 5, 5);
layout.setLayoutParams(params);
The orientation,
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
layout.setPadding(10, 10, 5, 5);
Then create a textview,
TextView textView = new TextView(this);
textView.setLayoutParams(params);
textView.setPadding(2, 2, 2, 2);
textView.setText(" "your" ");
textView.setTextColor(getResources().getColor(R.color.white));
textView.setIncludeFontPadding(true);
Add the view to the parent,
layout.addView(textView);

Vertical LinearLayout with WrapContent width - make children fill it up to widest child

I want to create vertical LinearLayout with couple of Button children, where each child has width of widest of them.
However depending on using MATCH_PARENT or WRAP_CONTENT for children width, I get either LinearLayout taking whole screen's width, or Buttons not filling LinearLayout. Screenshots below (fill/wrap):
Example Activity code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout mainView = new RelativeLayout(this);
mainView.setBackgroundColor(Colors.WHITE);
String[] buttonsNames = new String[] { "Short", "Looooooong", "Medium" };
View buttonsView = getButtonsView(buttonsNames);
mainView.addView(buttonsView, new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
setContentView(mainView);
}
private View getButtonsView(String[] buttonNames) {
LinearLayout buttonsView = new LinearLayout(this);
buttonsView.setOrientation(LinearLayout.VERTICAL);
buttonsView.setBackgroundColor(Colors.BLACK);
for (int i = 0; i < buttonNames.length; i++) {
Button button = new Button(this);
button.setText(buttonNames[i]);
///////////// HERE LAYS THE PROBLEM //////////
buttonsView.addView(button, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
//LinearLayout.LayoutParams.WRAP_CONTENT, // neither of them works
LinearLayout.LayoutParams.WRAP_CONTENT));
View redLineDivider = new View(this);
redLineDivider.setBackgroundColor(Colors.RED);
buttonsView.addView(redLineDivider, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 2));
}
return buttonsView;
}
As you can see on second screenshot, red lines actually take whole width without stretching LinearLayout - it is because at least one view has set width.
Potential fix I have came up with is to find widest button (with longest text) and make it use WRAP_CONTENT, while all the rest use MATCH_PARENT, which gives me expected result:
Code:
buttonsView.addView(button, new LinearLayout.LayoutParams(
isLongestText(i) ? LinearLayout.LayoutParams.WRAP_CONTENT
: LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
It doesn't feel like elegant solution though - is there any intended mechanism for situation like this, that I am missing out?
Following is the trick:
Mention the width of the LinearLayout containing the buttons (buttonsView in your code) as WRAP_CONTENT.
Mention the width of each button as MATCH_PARENT
Your program should give you the expected result if you do not include the redLineDivider View. There seems to be some issue with setting the width of redLineDivider. As an alternative you can declare it as a LinearLayout to make your code work perfectly.
// View redLineDivider = new View(this);
// Instead declare it as a LinearLayout
LinearLayout redLineDivider = new LinearLayout(this);
Hope this will be useful.

How to get RelativeLayout to change height accordingly upon adding more Layouts to it's parent?

Could some help me with Layouts? I'm having a problem getting it to display the way I'd like.
I have two relativelayouts in a linearlayout. RelativeLayout 1 is used to accomodate a fragment, RelativeLayout 2 contains the 'main' layout that should fill the screen when there is no fragment, but resize when the fragment is added.
I create the layouts dynamically like so:
LinearLayout mainLayout = new LinearLayout(this);
mainLayout.setLayoutDirection(LinearLayout.VERTICAL);
unityPlayerLayout = new RelativeLayout(this);
youtubeLayout = new RelativeLayout(this);
LinearLayout.LayoutParams mainParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
mainLayout.setLayoutParams(mainParams);
RelativeLayout.LayoutParams youtubeLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,600);
RelativeLayout.LayoutParams unityPlayerLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.MATCH_PARENT);
unityPlayerLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mainLayout.addView(youtubeLayout,0,youtubeLayoutParams);
mainLayout.addView(unityPlayerLayout);
unityPlayerLayout.addView(playerView,0,unityPlayerLayoutParams);
Upon adding the fragment, unityPlayerLayout does not resize and aligned to the bottom though. It get's pushed to the right, I can see a sliver of a couple of pixels, which is weird, since youtubeLayout and mainLayout should match the screen.
So, to summarize: Upon adding a fragment to youtubeLayout, I need unityPlayerLayout to resize it's height and drop to the bottom, but in practice unityPlayerLayout gets pushed to the right, and does not resize it's height.
Anyone any idea? Much appreciated!
You nee to set Layout orientation for the main LinearLayout, not direction
Change
mainLayout.setLayoutDirection(LinearLayout.VERTICAL);
to
mainLayout.setOrientation(LinearLayout.VERTICAL);
// try this way,hope this will help you...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout mainLayout = new LinearLayout(this);
RelativeLayout unityPlayerLayout = new RelativeLayout(this);
unityPlayerLayout.setBackgroundColor(getResources().getColor(android.R.color.holo_red_dark));
RelativeLayout youtubeLayout = new RelativeLayout(this);
youtubeLayout.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light));
mainLayout.setOrientation(LinearLayout.VERTICAL);
mainLayout.addView(youtubeLayout,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,600));
mainLayout.addView(unityPlayerLayout,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,0,1f));
setContentView(mainLayout,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
}

Programmatically add Linear layout with five buttons placed horizontally with same size in both landscape and portrait

i have programmatically creating linear layout with five buttons with fixed size, but when i change the orientation, the buttons are stretching in lanscape
here is my code:
LinearLayout button_layout = new LinearLayout(this);
button_layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 100));
button_layout.setOrientation(LinearLayout.HORIZONTAL);
button_layout.setBackgroundColor(Color.parseColor("#DCE1DC"));
FrameLayout layout = new FrameLayout(this);
layout.setLayoutParams(new LinearLayout.LayoutParams(20, 80, 1));
LayoutParams params = (LayoutParams) layout.getLayoutParams();
params.setMargins(30, 0, 30, 0);
Button A = new Button(this);
A.setLayoutParams(params);
A.setText("A");
button_layout.addView(A);
Button B = new Button(this);
B.setLayoutParams(params);
B.setText("B");
button_layout.addView(B);
Button C = new Button(this);
C.setLayoutParams(params);
C.setText("C");
button_layout.addView(C);
Button D = new Button(this);
D.setLayoutParams(params);
D.setText("D");
button_layout.addView(D);
Button E = new Button(this);
E.setLayoutParams(params);
E.setText("E");
button_layout.addView(E);
linearLayout.addView(button_layout); //added button layout.
LinearLayout bottomBarLayout = new LinearLayout(this);
bottomBarLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 50));
bottomBarLayout.setOrientation(LinearLayout.HORIZONTAL);
bottomBarLayout.setBackgroundColor(Color.parseColor("#8BC66D"));
linearLayout.addView(bottomBarLayout); //added bottomBar layout .
below is my screen shots:
I want the buttons to be square in both the orientations with equal spaces, how to achieve this?
If I understood you correctly, this is what you are trying to achieve:
Means, you want to have some space between the button and the wrapping layout such that you can set the background in it and the button itself isn't stretched. And, you need 5 buttons that have the same size in portrait and landscape view.
I took your code and made very few modifications: (I use methods here just for more clean code)
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.layout_root);
LinearLayout button_layout = new LinearLayout(this);
button_layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 100));
button_layout.setOrientation(LinearLayout.HORIZONTAL);
button_layout.setBackgroundColor(Color.parseColor("#DCE1DC"));
button_layout.addView(createButton("A"));
button_layout.addView(createButton("B"));
button_layout.addView(createButton("C"));
button_layout.addView(createButton("D"));
button_layout.addView(createButton("E"));
linearLayout.addView(button_layout);
}
/**
* Create one button view
*
* #param text
* #return
*/
private LinearLayout createButton(String text)
{
// wrapping button layout. The layout takes 20% from the parent layout
LinearLayout oneButtonLayout = new LinearLayout(this);
LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 0.2f);
oneButtonLayout.setLayoutParams(params);
params.setMargins(10, 0, 10, 0);
oneButtonLayout.setGravity(Gravity.CENTER);
// the button itself
Button button = new Button(this);
button.setLayoutParams(new LinearLayout.LayoutParams(80, 80));
button.setText(text);
oneButtonLayout.addView(button);
return oneButtonLayout;
}
The image above shows how it looks in the landscape view and this is how it looks in the portrait view:
Hope it solves your problem.
The reason the buttons get stretched is this:
button_layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 100));
You are setting the button layout width as LayoutParams.FILL_PARENT. So when you turn to horizontal orientation then this layout becomes bigger and the buttons have to adjust.
set here a fixed size and center this layout so the button appear always in the middle of the screen and you will get rid of the stretching problem.
1.Get display size as show below..
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Is deprecated, you should try this code instead:
first two line of code gives you the DisplayMetrics objecs. This objects contains the fields like heightPixels,widthPixels.
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
metrics.heightPixels;
metrics.widthPixels;
2.then set button size using those parameters
something like this
A.setWidth(width/4);
A.setheight(height/4);
so on
B.setWidth(width/4);
B.setheight(height/4);
above ratio 1/4 was just for example use how much exactly u need or fits best for ur requirement

Adding EditText to LinearLayout programmatically in Android

I can't make my EditTexts to fit in LinearLayout side by side sharing the same amout of space.
Here is the code that does it:
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textFieldsLayout = (LinearLayout) findViewById(R.id.LinearLayout2);
for(int i=1; i <= 8; i++){
final EditText ed = new EditText(this);
ed.setText("" + i);
ed.setInputType(2);
ed.setLayoutParams(lparams);
textFieldsLayout.addView(ed);
}
}
this code manages to add EditText to my layout but they appear side by side, and there is empty space at the end of LinearLayout, when I change params to WRAP_CONTENT, only first EditText added to layout fills the layout and others don't appear there, any idea what am I doing wrong here?
add layout_weight to the layout params
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1f);
To make your views stretch to fill a LinearLayout you must make sure that the widths are set to 0 and the weights are set to 1.
This will give them an even split. It's basically telling the system to defer setting the width until its parent is measured. Then come up and let children fill in whatever space they have.

Categories

Resources