I have a xml view that contains a ScrollView(with a child LinearLayout).
...
<ScrollView
android:id="#+id/scrollView_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_marginTop="33dp" >
<LinearLayout
android:id="#+id/image_holder"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</LinearLayout>
</ScrollView>
...
I am trying to dynamically add some images, I want 3 per row.
private void createDice(LinearLayout ll, Integer required) {
ArrayList<Integer> images = new ArrayList<Integer>();
images.add(R.drawable.one);
images.add(R.drawable.two);
images.add(R.drawable.three);
images.add(R.drawable.four);
images.add(R.drawable.five);
images.add(R.drawable.six);
ScreenHelper screen = new ScreenHelper(MainActivity.this);
Map<String, Float> s = screen.getScreenSize();
Integer maxPerRow = (int) (s.get("width") / 90); // images are 89px wide
Log.d(TAG, "max across::"+maxPerRow);
Integer rows = (required / maxPerRow);
Log.d(TAG, "rows::"+rows);
for (int i=0; i < rows; i++) {
Log.d(TAG, "i::"+i);
// create linear layout for row
LinearLayout llAlso = new LinearLayout(this);
llAlso.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
//llAlso.setOrientation(LinearLayout.HORIZONTAL);
for (int j=0; j < 3; j++) {
Log.d(TAG, "j::"+j);
// create/add image for the row
ImageView iv = new ImageView(this);
iv.setImageResource(images.get(i));
llAlso.addView(iv);
}
// add to main layout
ll.addView(llAlso, i);
Log.d(TAG, "adding to main view");
}
}
I am testing with the required parameter value of 6.
The problem is that the first row of images gets added, but either the second isn't because it is getting added adjacent to the first row (and therefore off the screen) and not under it.
How to achieve my desired output?
Set the orientation in your image_holder layout to vertical. By default, the orientation of a LinearLayout is horizontal. That means that all child views will be added in a horizontal row. Since your child layouts use fill_parent for their width, only one child can fit in the row. By switching it to vertical, your layouts are added in a vertical column instead of in a row. That allows more layouts to be visible.
Also you should consider to use a GridLayout instead. That is made for exactly this case.
Related
I am trying to add many button into Relativelayout or Linearlayout,
Layout
<Relativelayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
>
</Relativelayout>
then in the class
_ll_layout = (RelativeLayout) findViewById(R.id.container);
I only know how add the button dynamically with code.
JSONArray jsonArray = new JSONArray(tmp.getString("productos"));
Button bt[] = new Button[jsonArray.length()]; // size of product
for (int i = 0; i < jsonArray.length(); i ++){
int padding_40dp = (int) (40 * scale + 0.5f);
int margin_10dp = (int) (10 * scale + 0.5f);
int padding_90dp = (int) (90 * scale + 0.5f);
LinearLayout.LayoutParams params = new Relativelayout.LayoutParams(padding_90dp, padding_40dp);
params.setMargins(margin_10dp, 0 , 0, 0);
bt[i] = new Button(DetalleServicioActivity.this);
bt[i].setText(jsonArray.getJSONObject(i).getString("nombre"));
bt[i].setTag(new TagInfo(jsonArray.getJSONObject(i).getString("id_producto")));
bt[i].setTextColor(Color.parseColor("#FFFFFF"));
bt[i].setBackgroundColor(Color.parseColor("#D8D8D8"));
bt[i].setEnabled(false);
bt[i].setId(Integer.parseInt(jsonArray.getJSONObject(i).getString("id_producto")));
bt[i].setLayoutParams(params);
_ll_layout.addView(bt[i]);
}
but the result is
One on another one, but I need something like this:
Edit
If I use LinearLayout with orientation horizontal and gravity center, this happend
Instead of using Relative Layout or Linear Layout I would rather suggest you to create custom flow layout.Custom flow layout will adjust child views accordingly in rows, and will jump the button in new row according to screen width.
Please have a look here : Flow layout example
Happy Coding :)
Instead of RelativeLayout, make use of LinearLayout with orientation as horizontal and add the button in them at run time
As per your design requirement, make sure you have two linear layouts here.
you can use griedlayout for solved your problem
I need to create buttons dynamically to a linear layout. The width of each button will be wrap_content. Once the whole row is full, the button should be created in the next row.
I have seen other answers in stackOverflow where this is done, but in those cases the no of buttons in a row is constant. In my case it is dynamic, because the width of each button is dynamic based on text width.
It is similar to how tags are added to a question in this site.
e.g. the answers in one of questions was:
LinearLayout layout = (LinearLayout) findViewById(R.id.linear_layout_tags);
layout.setOrientation(LinearLayout.VERTICAL); //Can also be done in xml by android:orientation="vertical"
for (int i = 0; i < 3; i++) {
LinearLayout row = new LinearLayout(this);
row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
for (int j = 0; j < 4; j++) {
Button btnTag = new Button(this);
btnTag.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
btnTag.setText("Button " + (j + 1 + (i * 4));
btnTag.setId(j + 1 + (i * 4));
row.addView(btnTag);
}
layout.addView(row);
}
But here the no of buttons in a row is constant. In my case , this will be different because the width of each button is different.
You need a FlowLayout, which is an Extended linear layout that wrap its content when there is no place in the current line.
Check this out: https://github.com/ApmeM/android-flowlayout
Have you tried using GridLayout ?
linearLayoutParent = findViewById(R.id.ll_buttons_parent); // container layout or parent layout - orientation vertical
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.button_horizontal_layout, linearLayoutParent, false);
LinearLayout linearLayoutButton = view.findViewById(R.id.ll_button_horizontal);
int rows = 3;
for (int r = 0; r < rows; r++) {
GridLayout gridLayout = new GridLayout(this);
gridLayout.setColumnCount(2);
for (int i = 0; i < 4; i++) {
Button optionButton = new Button(this);
optionButton.setGravity(Gravity.CENTER);
optionButton.setText(String.valueOf(i + 1));
gridLayout.addView(optionButton); // adding buttons to grid layout
}
linearLayoutButton.addView(gridLayout); // adding grid layout to vertical linear layout row by row
}
linearLayoutParent.addView(linearLayoutButton); //adding linear layouts to container layout
Container : ll_buttons_parent
<LinearLayout
android:id="#+id/ll_buttons_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"/>
button_horizontal_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/ll_button_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#F8CCCC"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
app:layout_constraintTop_toTopOf="parent" />
I have XML:
<RelativeLayout
android:id="#+id/IcdSearchMainPanel"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="UselessParent" >
<own_components.SearchOutput
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:orientation="vertical" >
<!-- HERE ARE ADDED ROWS WITH RESULTS IN JAVA CODE (look into SearchOutput.java) -->
</own_components.SearchOutput>
</ScrollView>
</RelativeLayout>
I have class SearchOutput.java (which extends LinearLayout) with such a method (generally it adds some graphical components to row and then this row to a ScrollView):
public void setResultOutput(ResultContainer result)
{
for (int i = 0; i < result.size(); i++)
{
LinearLayout resultRow = new LinearLayout(getContext());
resultRow.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
resultRow.setOrientation(LinearLayout.HORIZONTAL);
resultRow.setGravity(Gravity.CENTER_VERTICAL);
if (i % result.getIterationStep() == 0)
{
resultRow.setPadding(0, 0, 0, 10);
}
addView(resultRow);
ImageView langFlag = new ImageView(resultRow.getContext());
langFlag.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
try
{
Bitmap bitmap = BitmapFactory.decodeStream(MainClass.getAssetManager().open(Pathes.FLAGS_DIR + result.get(i)[0] + ".gif"));
langFlag.setImageBitmap(bitmap);
langFlag.setPadding(10, 0, 0, 0);
}
catch (IOException e)
{
Log.e("IMAGE_OPEN_EXC", e.toString());
}
resultRow.addView(langFlag);
TextView number = new TextView(resultRow.getContext());
number.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
number.setPadding(10, 0, 0, 0);
number.setText(result.get(i)[1]);
resultRow.addView(number);
TextView text = new TextView(resultRow.getContext());
text.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
text.setPadding(20, 0, 0, 0);
text.setText(result.get(i)[2]);
resultRow.addView(text);
}
}
PROBLEM:
No matter how many elements are in result variable there is always one row showned:
QUESTION:
What i do wrong? In my opinion logically everything is all right.
Another question: is this way efficient? Maybe i should add results in different way? I ask because there can be plenty of them.
A ScrollView can have only one child, so wrap your layouts in another big layout which you add to your ScrollView.
But as suggested in the comments, use a ListView!!! That's what it's for...especially when you have many rows to display. ListView will recycle unused views and definitely yield a better performance than your approach.
Scroll view is a container that make its own child scrollable, so, you will have to add a child to the scrollview, later add the items to that child.
No master what is the child, it can be list view, can be linear layout, etc.
I'm using a TableLayout to create a square gameboard in Android. I want to set the dp of the table's width and height, and have its contents automatically expand and contract to fit the table.
I got this working with the entries in the tableRows as LinearLayouts with a single ImageView inside, but I need to change what images are displayed with click actions, so I thought I would use a ViewFlipper.
Now that I'm using the ViewFlipper, though, my image sizes have gone all wonky. Does anyone know if there's a setting I can set on ViewFlipper to get the images to auto adjust their size in a table?
Here's my xml:
<TableLayout
android:id="#+id/gameBoard"
android:layout_width="#dimen/boardWidth"
android:layout_height="#dimen/boardWidth"
android:layout_margin="0dp"
android:padding="0dp"
android:shrinkColumns="*"
android:stretchColumns="*" >
</TableLayout>
And here's the code I'm programmatically creating the table with:
TableLayout gameBoard = (TableLayout) findViewById(R.id.gameBoard);
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT);
rowParams.setMargins(0, 0, 0, 0);
for (int y = settings.getBoardSide() - 1; y > -1; y--) {
TableRow row = new TableRow(this);
row.setPadding(0, 0, 0, 0);
for (int x = 0; x < settings.getBoardSide(); x++) {
ViewFlipper flipper = new ViewFlipper(this);
flipper.setOnClickListener(new TileClick());
//default image
ImageView cloud = new ImageView(this);
cloud.setImageResource(R.drawable.transparent_cloud);
cloud.setAdjustViewBounds(true);
flipper.addView(cloud, 0);
//second image
ImageView landscape = new ImageView(this);
landscape.setImageResource(R.drawable.land_scape);
landscape.setAdjustViewBounds(true);
flipper.addView(landscape, 1);
row.addView(flipper);
}
gameBoard.addView(row, rowParams);
}
It turned out that for my purpose a FrameLayout with its width and height set to a specific dp was best. That way I can control the view and ensure it has the right height and width. With the FrameLayout I can add and remove views at will, and layer different views on top of each other as well.
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));