How to split Linear Layout in to two columns? - android

I have to split a Single Linear layout into a Two Columns(Like newspaper Columns).The linear layout contain text-view and image-view
I have taken the screen width and have divided it to half and made the TextView and ImageView to come in a first column , ie, A B C blocks in the picture below.. now the remaining TextView and 'ImageView has to go to next column like in D E F like that it goes on.So it would be helpful if anyone gives me any code or ideas to implement this.. I tried with GridView which is not suitable for my issue. Since the TextView and ImageView sizes are not definite.
I don't know how to split Liner layout.
I tried with calculating the rootlayout height
like this
linearLayout.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
int linsize=linearLayout.getHeight();
int relsize=root.getHeight();
int textsize=txt1.getHeight();
mainheight=relsize;
subheight=linsize;
Toast.makeText(getApplicationContext(), "Linerlayout "+linsize, Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "Relative layout"+relsize, Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "text height "+textsize, Toast.LENGTH_LONG).show();
if(mainheight==subheight)
{
Toast.makeText(getApplicationContext(), "make a new linear layout", Toast.LENGTH_LONG).show();
createsubview();
}
}
});
Screenshot

You could easily do this with nested LinearLayouts:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/item" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
<ImageView
content here/>
<TextView
content here/>
</LinearLayout>
</LinearLayout>
Then all that you need to do is put A, B and C in the first vertical layout, and D, E and F in the second.

You can't do it with GridView. You would have to create a custom view to do this.
if you know how big your grid items are, you can cut some corners. GridView is complicated mostly because it deals with items of any size and loads them dynamically. An easier way for you might be:
1.Create a HorizontalScrollView with a horizontal LinearLayout inside.
2.Determining how many rows of your item will fit on the screen. Call this rows.
3.while you still have items you need to layout:
1.Create a vertical LinearLayout, adding rows or less items to it.
2.Add your new vertical LinearLayout to the horizontal one.
There are some downsides versus what a "horizontal GridView" would get you:
1.All the views are loaded up immediately, which is bad for huge lists of items.
2.You need to know how big your items are, and they need to be the same size.
Upsides:
1.It's very easy to implement.
for more inf plz see this link
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ScrollView scrollView = new ScrollView(this);//ScrollView
LinearLayout ll = new LinearLayout(this); //root LinearLayout
ll.setOrientation(LinearLayout.HORIZONTAL);//with horizontal orientation
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT,1f);
LinearLayout l2 = new LinearLayout(this); //sub linearlayout
l2.setOrientation(LinearLayout.VERTICAL);//with vertical orientation
l2.setLayoutParams(layoutParams);
LinearLayout l3 = new LinearLayout(this); //sub linearlayout
l3.setOrientation(LinearLayout.VERTICAL);//with vertical orientation
l3.setLayoutParams(layoutParams);
int totalvalues=41; //i take count as 41
for(int i=0;i<totalvalues;i++){ // add the buttons in the layout based on condition
Button okButton=new Button(this);
okButton.setText("Button"+i);
if(i<=totalvalues/2){
l2.addView(okButton);
}
else{
l3.addView(okButton);
}
}
ll.addView(l2); //add sub linearlayout to root linearlayout
ll.addView(l3); //add sub linearlayout to root linearlayout
scrollView.addView(ll); //add the root linearlayout to scrollview
setContentView(scrollView);
}

Have you tried:
DisplayMetrics metrics = getResources().getDisplayMetrics();
float dpW = 0f;
int pixelsW = (int) (metrics.density * dpW + 0.5f);
TableLayout.LayoutParams lp = new TableLayout.LayoutParams(pixelsW, LayoutParams.WRAP_CONTENT, 1f);
TextView txt = new TextView(MainActivity.this);
ImageView img = new ImageView(MainActivity.this);
txt.setLayoutParams(lp);
img.setLayoutParams(lp);
Using TableLayout's LayoutParams, you can set the weight of the view, which, as you know, must be 1. We also use DisplayMetrics to convert a float into the "dp" format used in xml.
EDIT:
You can also set this LayoutParams to a LinearLayout.

Related

Android - Wrap buttons within view

I am trying to make buttons wrap in a LinearLayout in Android, but they are just continuing off to the right of the view (the word shown in the screenshot should be "HELLO", so I want the "O" to drop down to the next line).
I am adding the buttons programmatically, but even if I code them into the XML layout file, they still don't wrap. Here is the layout file with the LinearLayout container into which I am dynamically adding the buttons:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constrainedWidth="true"
tools:context=".LetterTileView">
<LinearLayout
android:id="#+id/TilesContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constrainedWidth="true"
android:orientation="horizontal">
</LinearLayout>
And here is the code I am using to create and add the tile buttons:
Context context = this;
LinearLayout layout = (LinearLayout) findViewById(R.id.TilesContainer);
LayoutParams params = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT );
params.setMargins(50, 50, 0, 0);
for (int i=0;i<wordLength;i++) {
Button tileButton = new Button(this);
tileButton.setLayoutParams(params);
tileButton.setText(wordStringtoLetters[i]);
tileButton.setId(i);
tileButton.setBackgroundResource(R.drawable.tile_button);
tileButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 36);
layout.addView(tileButton);
}
Any advice would be appreciated. Thanks!
I ended up using FlexboxLayout, which works great for this. Thanks to those who offered suggestions!
First of all, there is no need to use a ConstraintLayout you can use your LinearLayout as the parent layout.
Then for the purpose of displaying all buttons in one line, you have to set weight for the LinearLayout in XML and set weight for the views you add to it.
The xml file should look like:
<LinearLayout
android:id="#+id/TilesContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:weightSum="5"
app:layout_constrainedWidth="true"
android:orientation="horizontal">
</LinearLayout>
And in code you should set weight for each view you by adding ,1.0f to LayoutParam :
Context context = this;
LinearLayout layout = (LinearLayout) findViewById(R.id.TilesContainer);
LayoutParams params = new LayoutParams( LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,1.0f );
params.setMargins(50, 50, 0, 0);
for (int i=0;i<wordLength;i++) {
Button tileButton = new Button(this);
tileButton.setLayoutParams(params);
tileButton.setText(wordStringtoLetters[i]);
tileButton.setId(i);
tileButton.setBackgroundResource(R.drawable.tile_button);
tileButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 36);
layout.addView(tileButton);
}

Add multiple TextView to View dinamically

I need to add indeterminate number of textview to a view, and I would love if it can be auto adjust to the screen.
What I tried is to add horizontal LinearLayouts to a vertical parent LinearLayout, but this way I can add maybe 2 items or 3 per line but it doesn't have this unordered effect.
Is there any way to achieve this?
What i suggest is to not create dynamically a horizontal layout (if you are doing that).
instead you can create a horizontal layout resource like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="2">
<TextView
android:id="#+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_weight="1"
android:text="ONE" />
<TextView
android:id="#+id/end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:text="TWO" />
</LinearLayout>
And then in your main activity do like this:
for(i in 0..2) {
val view: View?
val inflater =
this.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
view = inflater.inflate(R.layout.horizontal, null)
val textOne = view.findViewById<TextView>(R.id.start)
textOne.text = "TEST $i"
val textTwo = view.findViewById<TextView>(R.id.start)
textTwo.text = "TEST $i"
(mainL as LinearLayout).addView(view)
}
Where mainL is main vertical layout, to which you can add padding, or you can modify your horizontal one, it depends on what you want to achive.
In this example i used a for loop just to show you that 3 lines are created, in every cicle if you have a list of text to put in you could use this syntax for loop
for ((index, value) in names.withIndex()) {
println("$index: $value")
}
reference: https://kotlinlang.org/docs/tutorials/kotlin-for-py/loops.html
For your specific case i suggest to have the main layout with padding start and end, and in horizontal layout margin top and bottom to create space between elements.
If you want to use LinearLayouts, you can go into your xml and add only a Vertical LinearLayout.
After this, you can add Horizontal LinearLayouts for your rows, to which you'll add cells, TextViews in your case.
In the "OnCreate" I'm only getting the Views and calling the methods used to add rows and cells to specified row.
public class MainActivity extends AppCompatActivity {
/**
* #verticalLayout
* Contains the rows of your String matrix
*/
LinearLayout verticalLayout;
/**
* #rowCellDivisor
* Contains the horizontal layout of each row
*/
LinkedList<LinearLayout> rows;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
verticalLayout = findViewById(R.id.verticalLayout);
addRow();
addRow();
addRow();
addRow();
addTextViewToRow(0);
addTextViewToRow(0);
addTextViewToRow(0);
addTextViewToRow(1);
addTextViewToRow(1);
addTextViewToRow(2);
addTextViewToRow(2);
addTextViewToRow(2);
addTextViewToRow(2);
addTextViewToRow(2);
}
There we create a row, which is nothing more than a LinearLayout with Horizontal orientation.
private void addRow(){
LinearLayout row
= new LinearLayout(
getApplicationContext()
);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
verticalLayout.addView(row);
}
This creates the TextView to add in the specified row.
private void addTextViewToRow(int rowAtPosition){
TextView textView = new TextView(getApplicationContext());
textView.setText("StartLongTextaaaaaaaaaaaaaaaaaaaaaaaa" +
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" +
"ccccccccccccccccccccccccccccccLongTextEnd");
/**
* Third entry for params is for weight, so that you can
* decide how much space the cell will occupy in the row
* when there will be more than one view in the same row.
*/
LinearLayout.LayoutParams layoutParams
= new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
1f
);
/**
* setMargins e.g. between cells of the row and screen
* borders
*/
layoutParams.setMargins(25, 0, 25, 25);
textView.setLayoutParams(
layoutParams
);
LinearLayout view = (LinearLayout)
verticalLayout.getChildAt(rowAtPosition);
view.addView(textView);
}
}

Programmatically create a textview with 0dp and layout weight 1

I am working on an Android project and I have an issue with the layout.
What I have is a JSONArray that I loop round inflating a new TableRow and within the loop round another array within the JSON array to populate it with fields. The fields are populated by inflating an XML file and adding this view to the table row. However, at the moment nothing shows up in the row.
Below is my TableRow XML file:
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"/>
Below is my TextView XML:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#color/black"
android:padding="5dp"/>
Below is how I am populating the TableRow and the TextView:
for (int i = 0; i < result.length(); i++) {
final TableRow tr = (TableRow) getLayoutInflater(getArguments()).inflate(R.layout.result_table_row_light_theme, resultTable, false);
if (i == 0) {
tr.setBackgroundColor(getResources().getColor(R.color.appPrimaryColour));
} else if (i % 2 == 0) {
if (settings.getInt(Defines.SharedPreferenceSettings.APPLICATION_THEME,
com.BoardiesITSolutions.Library.R.style.LibAppTheme) == com.BoardiesITSolutions.Library.R.style.LibAppTheme) {
tr.setBackgroundColor(getResources().getColor(R.color.resultRowLightThemeAlternateRow));
}
}
JSONArray array = result.getJSONArray(i);
for (int j = 0; j < array.length(); j++) {
final TextView textView;
textView = (TextView) getLayoutInflater(getArguments()).inflate(R.layout.result_textview, tr, false);
textView.setText(array.getString(j));
if (i == 0) {
textView.setTypeface(null, Typeface.BOLD);
textView.setGravity(Gravity.CENTER_HORIZONTAL);
}
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
tr.addView(textView);
}
});
}
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
resultTable.addView(tr);
}
});
}
If I change my TextView XML file so that the layout_width is wrap_parent instead of 0dp then everything is shown on the screen.
However, when the textview is 0dp and the layout_weight is 1 then nothing is displayed, however I would have expected each text view to be evenly distributed across the width of the screen to fill the space.
What I should probably mention, don't know if it makes a difference, is the TableView is within a HorizontalScrollView. The row should fit in the width of the screen, if the data is smaller than the screen, but if the row won't fit, then the view will be horizontally scrollable.
UPDATE 1
Below is the XML that hosts the TableLayout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout android:id="#+id/resultTable"
android:stretchColumns="*"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TableLayout>
</HorizontalScrollView>
</LinearLayout>
</ScrollView>
</RelativeLayout>
What I should probably mention, don't know if it makes a difference, is the TableView is within a HorizontalScrollView.
It is a logical error to tell a child view inside a scrolling container to match_parent or fill the available space in any way. A scrolling container, like ScrollView or HorizontalScrollView measures its one-and-only child view as UNSPECIFIED so that the child can grow beyond the parent bound in that one direction (and, thus, be scrollable).
The child of a scrolling container is not given what the "available space" would be for it to fill, and operations like layout weight have no effect if the parent's dimension is not well-defined.
The row should fit in the width of the screen, if the data is smaller than the screen, but if the row won't fit, then the view will be horizontally scrollable.
The functionality you are looking for is fillViewport (docs link), which tells the scrolling container to force the child to match it's size if the measured width (in the horizontal case) is less than the parent. Use this in place of applying a weight.
Try this :
public void createTextView(Context context, LinearLayout parent) {
final TextView v = new TextView(context);
parent.addView(v); // Mandatory!
v.post(new Runnable() { // In UI Thread. View Must be added to parent before getting layout params!
#Override
public void run() {
// Get params:
LinearLayout.LayoutParams lParams = (LinearLayout.LayoutParams) v.getLayoutParams();
// Set only target params:
lParams.width = 0;
lParams.weight = 1;
v.setLayoutParams(lParams);
}
});
}
Can you try to do your layout in XML (just to debug it, with dummy data)? Does it work as expected?
The docs mention that:
children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively MATCH_PARENT and WRAP_CONTENT.
Not sure if that means that it'll also mess stuff up if you try to set these values. As you've found, it's clearly not just ignoring them if they are set.
The other part says that the parent of the TableRow should be a TableLayout - is that the type of resultTable (you mentioned TableView) - otherwise it will behave as a LinearLayout with horizontal orientation.

The content of a LinearLayout isn't visible

I tried to add some GUI elements like an ImageView or a TextView to a LinearLayout programmatically. But the elements aren't displayed.
To see if a element is drawn or not, I set a different background color for each element. The result was that I can only see the background color of the LinearLayout. But why?
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context) {
super(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
setLayoutParams(params);
setBackgroundColor(Color.RED);
imageView = new ImageView(context);
params = new LinearLayout.LayoutParams(100, 100);
imageView.setLayoutParams(params);
imageView.setBackgroundColor(Color.BLUE);
addView(imageView);
}
}
The strange thing is that I can see the red background color of the LinearLayout but in the size of the ImageView. If I add some other GUI elements like a TextView, I can see how the LinearLayout grows. But I can not see the TextView.
I'm really confused, because this not the first time I do something like this. Can u tell me what I'm doing wrong?
This is a snippet of the layout.xml file:
<LinearLayout android:layout_width="match_parent"
android:layout_height="45dp"
android:id="#+id/bottom_bar"
android:layout_alignParentBottom="true"
android:gravity="bottom">
<FrameLayout android:id="#+id/block_edit_delete_layout"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:background="#drawable/block_edit_delete_selector">
<ImageView android:layout_height="match_parent"
android:layout_width="wrap_content"
android:src="#drawable/block_edit_delete"
android:scaleType="fitXY"
android:contentDescription="#string/delete"/>
</FrameLayout>
<LinearLayout
android:id="#+id/block_edit_progress"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal"/>
<FrameLayout android:id="#+id/block_edit_random_layout"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:background="#drawable/block_edit_delete_selector">
<ImageView android:layout_height="match_parent"
android:layout_width="wrap_content"
android:src="#drawable/block_edit_random"
android:scaleType="fitXY"
android:contentDescription="#string/random_numbers"/>
</FrameLayout>
</LinearLayout>
The LinearLayout with the ID block_edit_progress is the container layout of multiple instances of the class MyLinearLayout. The instances are added in the code:
for(int i = 0; i < numberOfMyLinearLayouts; i++) {
MyLinearLayout v = new MyLinearLayout(getContext());
addView(v);
}
I hope this helps.
If i convert your code to xml, it would be something like:
<LinearLayout layout_width=wrap_content, layout_height = wrap_content>
<LinearLayout id= MyLinearLayout>//just an idea, syntax may be wrong
<LinearLayout layout_width= 100, layout_width=100>
<ImageView color=BLUE>
</ImageView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Whenever you call setLayoutParams on a View, parameter params you give should be parent element.
Try something like if you want linearlayout to be the parent of your linearlayout, use MATCH_PARENT for width, height if you want your view to span the width, height of view's parent
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setLayoutParams(lp);//lp is parent view
Also try this, just in case views are getting added to right of your views, and you are not able to see them on screen
yourview.setOrientation(LinearLayout.VERTICAL);
Change the width and height of linear layout to match_parent and see how it changes. wrap_content will only show the content of the linear layout, which seems to be your problem.
I solved the problem. (Or found a workaround)
I moved the complete initialization stuff out of the constructor of the MyLinearLayout. If I then adding a View after the layout has been completely generated, everything works.
Like this:
MyLinearLayout ll = new MyLinearLayout(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(100, 100);
ll.setLayoutParams(params);
ll.setBackgroundColor(Color.RED);
ImageView v = new ImageView(getContext());
params = new LinearLayout.LayoutParams(50, 50);
v.setLayoutParams(params);
v.setBackgroundColor(Color.GREEN);
ll.addView(v);
addView(ll);
I don't know why the other way doesn't work. Thanks for the fast answers!

Add a scrollbar to a dynamic view

I have a LinearLayout and I amdynamically creating a certain number of TextViews in it.
Sometimes there are more TextViews than fit on the screen.
How do I add a scrollbar to this view, so the user can scroll up and down and see all TextViews?
Here's part of my code:
LinearLayout layout = (LinearLayout) findViewById(R.id.layout);
for (int n = 0; n < (numberOfPlayers*(numberOfPlayers-1)/2); n++) {
TextView tv = new TextView(this);
tv.setText(gamelist[n][0] + " - " + gamelist[n][1]);
layout.addView(tv);
}
Include your linearLayout in a ScrollView
<ScrollView
android:id="#+id/scroll"
android:layout_height="wrap_content"
android:layout_width="wrap_content">
<LinearLayout ... />
</ScrollView>
Note that a ScrollView can only have one view child
Wrap your LinearLayout into a ScrollView.
In this case you may consider using a ListView (tutorial here).

Categories

Resources