scrollable linearlayout with weights bigger than screen in android - android

I am trying to create a vertical linearlayout with weights that has a size bigger than the screen. Let's say 2x the size of the screen. In order for this to work I would obviously need to be able to scroll through it. Unfortunately I can't figure out a way to do this. I tried using the layout weights, and setting the weight sum as half of the actual sum of the weights of all components (so if all components weights sum is 20 I set the weight sum as 10) and managed to make it work but unfortunately the scrolling is not working anymore for some reason.
Is there anything that I am missing?
this is the code that makes the linearlayout twice as big as the screen but the scroll is not working:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:fillViewport="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2">
<EditText android:id="#+id/id1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:textSize="25dp"
android:gravity="center"
android:layout_weight="2"/>
<EditText android:id="#+id/id2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:textSize="25dp"
android:gravity="center"
android:layout_weight="2"/>
</LinearLayout>
</ScrollView>

Based on your comment, here is a programmatic way of achieving what you're looking for. I do not believe there is a way to accomplish this in pure layout XML.
Layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="#000000"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:orientation="vertical" >
<EditText
android:id="#+id/id1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#DCDCDC"
android:gravity="center"
android:text="ONE ONE ONE"
android:textIsSelectable="false"
android:textSize="45sp" />
<EditText
android:id="#+id/id2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AAAAAA"
android:gravity="center"
android:text="TWO TWO TWO"
android:textIsSelectable="false"
android:textSize="45sp" />
<EditText
android:id="#+id/id3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#777777"
android:gravity="center"
android:text="THREE THREE THREE"
android:textIsSelectable="false"
android:textSize="45sp" />
</LinearLayout>
</ScrollView>
Activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get display size -- API L13 and up. Otherwise use getResources().getDisplayMetrics();
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// You want size to be 50% per EditText, so divide available height by 2.
// Note: this is absolute height, does not take into consideration window decoration!
int editTextHeight = size.y / 2;
// Get a handle to your EditTexts
EditText t1 = (EditText) findViewById(R.id.id1);
EditText t2 = (EditText) findViewById(R.id.id2);
EditText t3 = (EditText) findViewById(R.id.id3);
// Set height to 50% of screen size each
t1.setHeight(editTextHeight);
t2.setHeight(editTextHeight);
t3.setHeight(editTextHeight);
}
That'll do it. End result:

You declared height of your LinearLayout "match_parent" that is equal to its parents height. It will never scroll as long as the content is bigger then ScrollView. First of all you have to give a fixed height like (50dp) or wrap_content or you have to set Its height programmatically(like 2x screen height as you mention).
weightSum and weight will always force your items to fit in your LinearLayouts current size so try not to use it.
I hope this helps.

The problem here is your use of layout_weight and weightSum is invalid. It's important to remember that android:layout_weight can only use the remaining space available in the view; anything exceeding that boundary is automatically cropped.
Therefore, in your example, your first EditText is taking up the entirety of the screen, and your second one is entirely excluded from the view. Because the second EditText is cropped, the LinearLayout has taken the entire screen and there's nothing for the ScrollView to do.
I'm not entirely sure what your end goal is; are you trying to have text inputs that grow with user entry, and the ScrollView handles the overflow?
If so, this will work:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="#000000"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:orientation="vertical" >
<EditText
android:id="#+id/id1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#DCDCDC"
android:gravity="center"
android:text="ONE ONE ONE"
android:textIsSelectable="false"
android:textSize="45sp" />
<EditText
android:id="#+id/id2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AAAAAA"
android:gravity="center"
android:text="TWO TWO TWO"
android:textIsSelectable="false"
android:textSize="45sp" />
</LinearLayout>
</ScrollView>
I've included some basic background colors so that you can see where each item begins & ends in layout preview. Typing in the first EditText will correctly push the second one down, producing a scroll bar.
Also note that you should use sp instead of dp for textSize values.
Edit: I should also note, for clarification, that weightSum will also take away space when necessary. To test this, set the weightSum of your LinearLayout to 2, and then add android:layout_weight="1" to each of the EditText controls. The end result will be a 50/50 split when the view loads, and then as you start typing in the first control, the 2nd space will shrink accordingly. Adding text to the second control will result in a scrollbar appearing.

Related

Android: ImageView next to TextView not showing

I have a TextView and ImageView in a ListView row, positioned next to each other. However, the ImageView doesn't show up at all, and doesn't register clicks either. This is the XML code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:text="text"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_centerVertical="true"
android:padding="10dp" />
<ImageView
android:id="#+id/imageView"
android:clickable="true"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/textView"
android:src="#drawable/ic_action"/>
</RelativeLayout>
The problem seems to lie in the layout_toRightOf line, if I remove it, the ImageView is shown, but in the wrong place. But I don't understand why it's causing a problem. What am I missing?
The issue is that the TextView is pushing the ImageView off the screen.
You can fix this using a LinearLayout and android:layout_weight
eg:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:text="text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="10dp"
android:layout_centerVertical="true"
android:padding="10dp" />
<ImageView
android:id="#+id/imageView"
android:clickable="true"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/textView"
android:src="#drawable/ic_action"/>
</LinearLayout>
More info on the layout_weight attribute:
This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero.
For example, if there are three text fields and two of them declare a weight of 1, while the other is given no weight, the third text field without weight will not grow and will only occupy the area required by its content. The other two will expand equally to fill the space remaining after all three fields are measured. If the third field is then given a weight of 2 (instead of 0), then it is now declared more important than both the others, so it gets half the total remaining space, while the first two share the rest equally.
You need to use LinearLayout with weight.. if you set fixed width and the size of the phone is small, it will either stretch out of the screen.
//do linearlayout with orientation horizontal
<LinearLayout
...
orientation = "horizontal"
...
>
<TextView
....
android:layout_width="0dp"
android:layout_weight="1"
...
/>
<Button
....
android:layout_width="wrap_content"
...
/>
</LinearLayout>
Play with android:layout_weight, you will understand

Relativelayout position view between two views

so I'm currently working on an app on Android, and I got stuck on a specific problem regarding the RelativeLayout, which I can't find a way to solve.
I have in the layout three views as follows: TextView, Textview and ImageView (laid horizontally), here is a screenshot of the ios counterpart:
the Textview at the middle should stick to the first one, until he gets to the Imageview, when he does, he keeps his minimum size (wrap content), while the first Textview truncate.
On IOS I setted priorities to the constraint to accomplish this, but I can't figure out how to solve this on Android.
Here what I tried:
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#drawable/daily_movie_title_box">
<TextView
android:id="#+id/daily_header_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
android:text="New Text aawi oa ioawfwi"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#color/white"
android:lines="1"
android:singleLine="true"
android:layout_alignParentStart="true"
/>
<TextView
android:id="#+id/duration_text"
android:text="138 mins"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:textSize="13sp"
android:textColor="#color/white"
android:lines="1"
android:layout_alignBaseline="#id/daily_header_textview"
android:layout_toStartOf="#+id/certification_icon"
android:layout_toEndOf="#id/daily_header_textview"
/>
<ImageView
android:id="#id/certification_icon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:src="#drawable/uk12a"
android:layout_alignBottom="#id/daily_header_textview"
app:layout_aspectRatio="100%"/>
</android.support.percent.PercentRelativeLayout>
Which resulted in this (which is what I want):
But when I increase the first Textview text it's not behaving as I desire...
Is it possible to achieve the behaviour I want in Android (keep the middle Textview wrap content, and truncate the first one if needed)?
I will post an update if I find a solution eventually, just wanted to see if anyone can find an easy way to achieve this behaviour, as I suspect there is.
Thanks.
From my understanding, you want the first TextView to be as large as possible, without adding space after the text if the text is too small. The second TextView should only wrap_content, but it should fill the rest of the parent layout when the row doesn't. The ImageView is set to wrap_content.
I tested it with this layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="0"
android:stretchColumns="1">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="Shrinking text dddddddddddddddddddddd"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Midle column"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/ic_launcher"/>
</TableRow>
</TableLayout>
</LinearLayout>
The only problem is that if the second column has a incredibly large text, it will push the other views out of the parent. But in your case, I don't think that will be a problem. Otherwise, I think it does the job.
These are some suggested solutions:
You can use LinearLayout with horizontal orientation and weight for each component (TextViews and ImageView).
You can set the minimum and maximum text length for the second TextView.
But i prefer to apply the first solution. You can assign a weight for each component ( amount of space on the screen ) using:
android:layout_height

Android RecyclerView messing up layout_weight

I have a pretty simple RecyclerView within a DialogFragment
A single-line item is supposed to show an image, first and last name and some numbers. They are laid out with the help of layout_weight to equally share the available space.
For some reason, some of the items randomly seem to calculate the layout_weight wrong.
Note that in the editor preview, and after scrolling the problematic item out of view, the problem is fixed and the layout returns to normal.
As you can see in the image, in the first item (it's not always (just) the first) the image gets way too much space.
My layout is as follows;
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/dodger_blue"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="#+id/iv_face"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="vertical">
<TextView
android:id="#+id/et_first_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLargeInverse"
android:textStyle="bold"/>
<TextView
android:id="#+id/et_surname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMediumInverse"/>
</LinearLayout>
<TextView
android:id="#+id/et_id"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMediumInverse"/>
<TextView
android:id="#+id/et_place"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:gravity="center|end"
android:textAppearance="?android:attr/textAppearanceLargeInverse"/>
</LinearLayout>
And my adapter;
https://gist.github.com/StefanDeBruijn/f032eac6619ac1b8420e352b883ea4dd
I suspect this is happening because of the large image being set in the image view. As you have set the height of the image as match_parent. To maintain the aspect ratio it is also expanding across the width.
Probably you should try adding this property to the in your xml file and fixing the height of the image.
android:scaleType="fitXY"
android:layout_height=100dp
Let me know if this fixes your issue.

Text being truncated in TextView with width set to wrap_content

I'm trying to create a simple component in my layout, where there are two TextViews horizontally next to each other. The one on the right should start where the one on the left finishes. My code for this is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#android:color/white"
android:textIsSelectable="false"
android:textSize="25sp" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:textColor="#android:color/white"
android:textSize="20sp" />
</LinearLayout>
I programmatically set the text on each TextView after the view has rendered. However, sometimes the text does not display correctly in the first TextView- I can see that the width has been set correctly, as the second TextView is not next to it, but the text is truncated rather than using the space. If I lock/unlock the device to refresh the screen then the text displays correctly (without the widths of the TextViews changing).
I've tried changing this to use a RelativeLayout, but I see the same issue.
Any ideas?
Although i dont understant what exactly you mean, would suggest you to use weightSum property in the parent view and android:layout_weight in child views. The same allows to put many child views inside a parent view with respect to ratio (like navigation tabs).
for eg :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1" >
<TextView
android:id="#+id/text1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#android:color/white"
android:textIsSelectable="false"
android:textSize="25sp"
android:layout_weight="0.4" /> //60% width
<TextView
android:id="#+id/text2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:textColor="#android:color/white"
android:textSize="20sp"
android:layout_weight="0.6" /> //40% width
</LinearLayout>
also, dont forget to put the width if child views as 0dp. as that will result in ignoring the calculations regarding the width of view. or you can set the width of child view as "match_parent" as well. any other property to width will not work. (and if you want half matchparent for both child views set layout_width to 0.5 both views.. ithink thats obvious to note)
Hopw it helps.

Android how do I set a percentage padding/margin so EditText has 10% margin on either side?

Does android support % or is there a way to approximate. I have two very different screen sizes and I but percentage-wise I want the EditBox in the activity to have same margin for both screen size as a proportion of screen size. How can this be done.
It doesn't really support setting values by percent(except for some of the xml Animation files seem to) If you are dead set on using a percentage the best way I can think of is from java call getWidth and getHeight then multiply those by your decimal and set the result with setMargin(), or setPadding().
This is possible in XML by wrapping your EditText inside of a LinearLayout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="10"
android:gravity="center"
>
<EditText
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="8"
/>
</LinearLayout>
Edit: The Layouts from this answer are now deprecated. Use the solution that Eugene Brusov proposed. Also, thank you chancyWu for the comment.
There is now a better way that came out with support library version 23.0.0 (about time, right?). You can now use PercentFrameLayout or PercentRelativeLayout.
If you wanted the EditText to be 80% of the screen's width with a 10% margin on either side, the code would look like this:
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_height="wrap_content"
app:layout_widthPercent="80%"
app:layout_marginStartPercent="10%"
app:layout_marginEndPercent="10%"/>
</android.support.percent.PercentRelativeLayout>
You can also take a look at PercentLayoutHelper.PercentLayoutParams
It's possible with Guideline introduced in ConstraintLayout.
For example you can place your EditText top at 25% of screen height and left and right at 20% of screen width:
Here's the layout source:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintLeft_toLeftOf="#+id/left_guideline"
app:layout_constraintRight_toLeftOf="#+id/right_guideline"
app:layout_constraintTop_toTopOf="#+id/top_guideline" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/top_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.25" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/left_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.2" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/right_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8" />
</androidx.constraintlayout.widget.ConstraintLayout>
What I did in this situation was put the view inside a horizontal LinearLayout, add an empty view (before or after your main view or layout depending on whether you want the margin to be on the left or on the right) turn both views' width to 0dp and then give the empty view a value of "1" in weight while I gave the View/Layout that needed margin a value of "4" in weight.
This resulted in a 1/5 (20%) left margin.
You can apply this to Top and Bottom margin/padding as well.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="4"
>
<!--Your content goes here -->
</LinearLayout>
</LinearLayout>

Categories

Resources