So I'm trying to create a GridView style layout in Android without actually using a custom Gridview adapter, since I don't want it to scroll. I've tried just turning scrolling off, but it ruins my layout since I'm adding other elements around it in a vertical LinearLayout.
My next experiment was to use a TableLayout and then just add inflated layouts as table cells, but I'm also having an issue with this. Here is a test that I am running for a brief proof of concept:
TableRow trackingActivityRow = new TableRow(getActivity());
for(int j = 0; j < trackingActivities.size(); j ++) {
TrackingActivity trackingActivity = trackingActivities.get(j);
View trackingActivityCell = getActivity().getLayoutInflater()
.inflate(R.layout.table_cell_tracking_activity, trackingActivityRow, true);
TextView txtDescription = (TextView)trackingActivityCell.findViewById(R.id.txtDescription);
txtDescription.setText(trackingActivity.getDescription());
}
tableLayout.addView(trackingActivityRow);
It seems to create the number of cells correctly, but it doesn't want to set the text like it should be. Furthermore, I'm having an issue of logic when it comes to creating a new row for every 4 TrackingActivities.
If anyone has any input it would be appreciated.
/Update/
Here is a graphic of the issue. The cell with "Walk" in it is displaying correctly, but the other cells only display the placeholder text inside the textview which should have been replaced.
I created a customized GridView based on a tablelayout with a listadapter.
Simplified version of the setAdapterMethod in the extended TableLayout:
int itemPos = -1;
int numRows = (int) Math.ceil((double) adapter.getCount() / (double) mNumColumns);
for (int yPos = 0; yPos < numRows; yPos++) {
//Create new row
TableRow tableRow = new TableRow(this.getContext());
for (int xPos = 0; xPos < mNumColumns; xPos++) {
itemPos++;
View itemView = adapter.getView(itemPos, null, tableRow);
tableRow.addView(itemView);
}
this.addView(tableRow, new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT));
}
Related
I have a requirement to display a question along with a list of options that i am getting from server. Each option has a title and an image and these options should be clickable. So I am creating a class ImageButton extending to RelativeLayout and each option is an ImageButton. I am also creating a class ImageButtonGroup extending to GridLayout and dynamimcally adding all the ImageButtons to this ImageButtonGroup.
It works fine except for the alignment of the ImageButtons. The ImageButton's size depends on the length of the title text (the image is of same size for all options) and I am having hard time in distributing equal cell space to each ImageButton in the grid layout. See below my code where I am adding ImageButtons to ImageButtonGroup:
ImageButtonGroup imageButtonGroup =
(ImageButtonGroup)
mInflater.inflate(
R.layout.button_image_response_layout, holder.richTextContainer, false);
int total = item.getMessage().getResponseOptions().size();
int col = 3;
int row = total / col;
imageButtonGroup.setColumnCount(col);
imageButtonGroup.setRowCount(row + 1);
for (int i = 0; i < total; i++) {
ResponseOption responseOption = item.getMessage().getResponseOptions().get(i);
ImageButtonView imageButtonView =
(ImageButtonView)
mInflater.inflate(
R.layout.image_button_layout, holder.richTextContainer, false);
imageButtonView.setData(
responseOption.getImage(), responseOption.getViewText(), responseOption.getValue());
GridLayout.LayoutParams gridParam = new GridLayout.LayoutParams();
gridParam.setGravity(Gravity.CENTER);
gridParam.topMargin = 10;
gridParam.bottomMargin = 10;
gridParam.width = GridLayout.LayoutParams.WRAP_CONTENT;
gridParam.height = GridLayout.LayoutParams.WRAP_CONTENT;
imageButtonGroup.addView(imageButtonView, gridParam);
This gets me the following view:(The text isn't always Happy as shown below)
How to dynamically allocate fixed sized cell to these buttons inside a grid layout?
You can to specify row and column while creating the GridLayoutParams so that it will handle itself the matching of the size dependending on the total space:
GridLayout.LayoutParams first = new GridLayout.LayoutParams(row, col);
GridLayout.LayoutParams(GridLayout.Spec rowSpec, GridLayout.Spec
columnSpec)
Constructs a new LayoutParams instance for this rowSpec and
columnSpec.
In your specific case it will be something like :
for (int i = 0; i < total; i++) {
ResponseOption responseOption = item.getMessage().getResponseOptions().get(i);
ImageButtonView imageButtonView =
(ImageButtonView)
mInflater.inflate(
R.layout.image_button_layout, holder.richTextContainer, false);
imageButtonView.setData(
responseOption.getImage(), responseOption.getViewText(), responseOption.getValue());
Spec row = GridLayout.spec(Math.round(i / 3);
Spec col = GridLayout.spec(i % 3);
GridLayout.LayoutParams gridParam = new GridLayout.LayoutParams(row, col);
gridParam.setGravity(Gravity.CENTER);
gridParam.topMargin = 10;
gridParam.bottomMargin = 10;
gridParam.width = GridLayout.LayoutParams.WRAP_CONTENT;
gridParam.height = GridLayout.LayoutParams.WRAP_CONTENT;
imageButtonGroup.addView(imageButtonView, gridParam);
I was able to achieve this taking a hint from here
I got the screen width, calculated my layout size in terms of %age point (came out to be 70% of the total width) and divided it by 3 (the number of column). So basically what i did is:
int dWidth = (int)(presenter.getView().getScreenWidth() * .70) / 3;
gridParam.width = dWidth;
the actual wondering is the following : I have a full-screen GridLayout which has half of it visible. To see the second part we have to scroll.
I tried some ways and looked around for answers but none of whichs I found gave me what I need. In my grid there are square cells and each one contains a view, and I need to get the x and the y of these views.
Problem is that I could get the coordinates of the views that were put into the visible cells, the views that are not displayed have a x and a y set to 0... Whereas they were drawn..
Here it is, hope some of you guys could help! :)
private void createGrid(){
//I call the function several times
int gridsLength = 19*48*grids;
for(int i = 0; i < 19; i++) {
for (int j = 0; j < 48; j++) {
GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
layoutParams.width = 40;
layoutParams.height = 40;
View view = new View(this);
view.setLayoutParams(layoutParams);
Util.setDrawableBackground(view, R.drawable.border_black, this);
view.setOnTouchListener(newViewListener());
gridViews.add(view);
//glMain is my gridLayout that i put into global variable
glMain.addView(view, i + j + gridsLength);
}
}
grids++;
}
EDIT : I finally found out that I was not always accessing the views AFTER the grid were drawn so I changed that and it's working... Figured out that I was just a fool ^^
I'm trying to create a TableLayout programmatically, in order to make a grid-like layout with a configurable row and column count. This would likely be trivial to do in a layout file, but because each child element will be nearly identical and I want the row and column count to be configurable, I would like to do it programmatically if possible.
So far this is what I have.
MainActivity.java
private void displayBoard() {
TableLayout l = (TableLayout) findViewById(R.id.GameGrid);
l.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
for (int y = 0; y < b.height(); y++) {
TableRow r = new TableRow(this);
r.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, 15));
for (int x = 0; x < b.width(); x++) {
r.addView(b.getSpaceAt(x, y));
}
l.addView(r);
}
}
Board.java
for (int y = 0; y < spaces.length; y++) {
for (int x = 0; x < spaces[0].length; x++) {
spaces[y][x] = new BoardSpace(context, x, y);
}
}
BoardSpace.java
public class BoardSpace extends Button {
private ReversiPiece piece;
protected int x, y;
private BoardSpace(Context c) {
super(c);
}
public BoardSpace(Context c, int x, int y) {
super(c);
// this.setWidth(25); // Doesn't make a difference, either
// this.setHeight(15); // Doesn't make a difference, either
piece = null;
this.x = x;
this.y = y;
}
public ReversiPiece piece() {
return piece;
}
public void setPiece(ReversiPiece p) {
piece = p;
}
}
I'm basically trying to create a grid of buttons, but so far I cannot get the size of the buttons to change so I can make sure they all fit on the screen. At the moment they appear at a standard size, and any changes I make to the LayoutParams definitions do not make a difference.
I suspect this issue has to do with my usage of LayoutParams. There are a lot of LayoutParams classes associated with each View type, so perhaps I'm not using the right one? Any help would be appreciated.
EDIT: Now creating a new TableLayout.LayoutParams object for each TableRow based on cyanide's recommendation, but the buttons are still displaying at default size.
You are right, that's about LayoutParams, which must not be shared between views: each view should have its own copy of LayoutParams.
In other words, this is what you need:
r.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 15));
About getSpaceAt (there is not code for it). Does it create a view programmatically? Remember to set LayoutParams and again it should be separate for each view.
Hopefully it will help.
Got it! I was trying to manipulate the LayoutParams of my TableLayout and TableRows when in reality I needed to set TableRow.LayoutParams on the buttons themselves, when I add them to TableRow. This involves specifying the weight of each child element (Button) as well.
private void displayBoard() {
TableLayout l = (TableLayout) findViewById(R.id.GameGrid);
l.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
for (int y = 0; y < b.height(); y++) {
TableRow r = new TableRow(this);
r.setWeightSum(b.width());
for (int x = 0; x < b.width(); x++) {
BoardSpace s = b.getSpaceAt(x, y);
s.setLayoutParams(new TableRow.LayoutParams(
TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT, 1.0f));
r.addView(s);
}
l.addView(r);
}
}
TableRow.setWeightSum() is used to set the weight sum of the row to the number of elements in the row, then passing a weight of 1 to the LayoutParams for the button causes the buttons to adjust in size to fit on the screen, as intended.
Surprisingly this answer was for a more generic question but this is what led me to the solution:
How to set layout_weight attribute dynamically from code?
I have created a TableLayout and then I created TableRow dynamically in my java code, and added some buttons in the form of an 8x8 grid. But I want to reduce the space between the buttons. I tried setting LayoutParam for the TableRow , but when I do this , the output shows just a blank screen. Here's my code:
LayoutParams param= new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
field=new Button[8][8];
tb=new TableLayout(this);
param.setMargins(10, 2, 10, 2);
for (int i = 0; i < field.length; i++) {
TableRow current=new TableRow(this);
for (int j = 0; j < field[i].length; j++) {
Button button=new Button(this);
field[i][j]=button;
button.setWidth(40);
button.setHeight(40);
button.setLayoutParams(param);
current.addView(button);
}
tb.addView(current);
}
t.addView(tb);
But when I don't write button.setLayoutParams(param)
I get an output like this:
which is the normal output except that I want the space between the buttons reduced.
The spacing you're seeing is padding built into the standard Android button background asset. You can see that your layout is correct by turning on "Show Layout Bounds" in Settings > Developer Options. You just need to make your own button asset, or if a simple color is all that is needed, then just set the button background to be a color.
In the param.setMargins() call, use negative values as necessary to get past what seems to be some natural spacing. You will also want to give the same layout margins to the table layout, and use WRAP_CONTENT for both the width and height. I am not sure if variable "t" is needed as I created the buttons without it using a TableLayout in an XML file. (I also did a 5x5 grid to fit onto my screen.)
LayoutParams param= new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
field=new Button[5][5];
tb=new TableLayout(this);
// these are the two important changes
param.setMargins(-5, -5, -5, -5);
tb.setLayoutParams(param);
for (int i = 0; i < field.length; i++) {
TableRow current=new TableRow(this);
for (int j = 0; j < field[i].length; j++) {
Button button=new Button(this);
field[i][j]=button;
button.setWidth(40);
button.setHeight(40);
button.setLayoutParams(param);
current.addView(button);
}
tb.addView(current);
}
t.addView(tb);
I'm trying to learn how to write Android programs, and I'm having trouble figuring out how padding works, in particular in a FrameLayout within a TableLayout.
private void fillTable(int nrows, int ncols) {
final int CENTER = 0x11; // used for "gravity" parameters
TableLayout table = (TableLayout) this.findViewById(R.id.tablelayout);
int counter = 1;
TextView text;
for (int i = 0; i < nrows; i++) {
TableRow row = new TableRow(this);
table.addView(row);
for (int j = 0; j < ncols; j++) {
View cell;
text = new TextView(this);
text.setTextColor(Color.BLUE);
text.setText(Integer.toString(counter++));
text.setGravity(CENTER);
if (i == 2 && j == 2) {
FrameLayout frame = new FrameLayout(this);
text.setLayoutParams(new FrameLayout.LayoutParams(90, 45, CENTER));
frame.setPadding(0, 0, 0, 0);
frame.addView(text);
cell = frame;
} else {
cell = text;
}
cell.setBackgroundColor((i + j) % 2 == 0 ? Color.YELLOW : Color.WHITE);
row.addView(cell);
cell.setLayoutParams(new TableRow.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1F/ncols));
}
row.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1F/nrows));
}
}
tablelayout just looks like this:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tablelayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</TableLayout>
I'm calling this with nrows=12 and ncols=5. I'm running on an emulator whose width is 720 pixels. If I change if (i==2&&j==2) to if (false), so that only an array of TextView is displayed, the columns are even, as I expect. However, with the code as written, the middle column is wider than the others.
I've also tried this adding android:stretchColumns="*" to the tablelayout definition and removing the weight parameter from cell.setLayoutParams, and the results are the same.
Assuming I have a reason to want to specify pixels for text.setLayoutParams (because of what I plan to do later), how would I get the column widths to be the same? Since 90*5 is well under 720, I don't understand why, or where, the extra width is being added.
Whenever you are dealing with weights, you must let the option take care of the remaining space. In this case width. Just set the width of each element to 0:
cell.setLayoutParams(new TableRow.LayoutParams(0, LayoutParams.MATCH_PARENT, 1F/ncols));