I have an activity in my app where I would like the user to be able to vertically scroll the content contained inside a LinearLayout which in turn is inside a ScrollView. Here is a summary of what the layout XML for this activity looks like:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="20dip"
android:orientation="vertical">
<!-- a bunch of standard widgets, omitted for brevity -->
<!-- everything renders but starting in this TextView -->
<!-- content begins to get truncated -->
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:gravity="left"
android:textSize="20dip"/>
<!-- this View, really just a trick for a horizontal row, is -->
<!-- completely cutoff -->
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="#color/green" />
</LinearLayout>
</ScrollView>
</LinearLayout>
What I am observing is that content in the inner LinearLayout is being cutoff inside the ScrollView. In the final TextView above, when it contains little text, then the View below it does render in portrait, but does not in landscape. When this TextView contains a lot of text, then it gets cutoff in portrait mode.
I tried the recommendations I found on Stack Overflow. Adding bottom padding to the ScrollView did not resolve the problem, nor did swapping the ScrollView for a NestedScrollView.
Any helpful suggestions would be welcome. This is actually turning out to be a blocker.
Change your inner LinearLayout's margin to padding. Or, if you really need it to be margin (maybe you're using a custom background), wrap your LinearLayout in a FrameLayout.
The ScrollView is taking its height (or, more accurately, it is computing its scrollable range) from the LinearLayout. This value doesn't include margins, so your ScrollView is going to be "too short" by the sum of the LinearLayout's top and bottom margins.
The margins are ignored while measuring, See this
So you can provide padding to your ScrollView and remove margins from your LinearLayout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- a bunch of standard widgets, omitted for brevity -->
<!-- everything renders but starting in this TextView -->
<!-- content begins to get truncated -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:gravity="left"
android:textSize="20dip"/>
<!-- this View, really just a trick for a horizontal row, is -->
<!-- completely cutoff -->
<View
android:layout_width="match_parent"
android:layout_height="2dip"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="#color/green" />
</LinearLayout>
</ScrollView>
Also fill_parent is deprecated and renamed match_parent in API Level 8 and higher
Related
I have an activity which should be scrollable, therefore i surrounded it with a ScrollView. I have two listViews in there, which i do not want to be as large as it would be necessary to display all items.
It would be nice if i could set a maxHeight property, so that in case there are only 2 items no empty space would be present, but if there are 50 items i would only want to see like 5 of them at a time. Unfortunately there is no such property, so i decided to just set the height to a fixed number. Any advice how to do that more properly would be much appreciated.
However the main problem is that, when i try to scroll one of the listViews the whole LinearLayout scrolls down. (I can avoid this if i use another finger to 'hold' the LinearLayout in place while scrolling the list, but that certainly not a solution.)
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_settings"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="app.ballmaschine.pages.SettingsPage">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Some other stuff here -->
<TextView
android:text="Eine Maschine"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:layout_marginTop="8dp" />
<ListView
android:layout_width="match_parent"
android:id="#+id/lvCalibsM1"
android:layout_height="200dp" />
<TextView
android:text="Zwei Maschinen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:layout_marginTop="8dp" />
<ListView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="#+id/lvCalibsM2"/>
<!-- Some more stuff here -->
</LinearLayout>
Add this to the ListView
android:scrollbars = "none"
and this in Java Code
listView.setNestedScrollingEnabled(false)
In these cases always try NestedScrollView and also add this line to it
app:layout_behavior="#string/appbar_scrolling_view_behavior"
I'm struggling on a layout management so I decided to ask here.
I would like to get 3 layouts working in a certain way.
I have 3 views vertically dispatched into a RelativeLayout (let's call them VTop, VMiddle and VBottom).
VBottom is a Button, I want him to stay aligned with the bottom of the screen and to never move or get resized (actually working).
VMiddle is a scroll view. I want this ScrollView to take all possible place between the bottom button (VBottom) and the top most layout (VTop) but never having it height inferior to an specific size.
I would like to have VTop (A linear layout containing some TextViews and other stuffs) wrapping all of its content as long as VMiddle doesn't get smaller that its minimum size.
Actually the code I have is almost working but when I Inflate too much content into VMiddle, it keeps growing towards the top of the screen and VTop completely disappear. I want VMiddle to stay at it minimum size if VTop doesn't have enough space to wrap his content.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/relativeLayout1">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/linearLayout1" <!-- VTop -->
android:layout_above="#+id/eventDetail_RateLayout"
android:layout_alignParentTop="true"
android:layout_margin="10sp"> <!-- LOT OF VIEWS, NEED TO BE WRAPPED AS MUCH AS POSSIBLE -->
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="100px"
android:id="#+id/eventDetail_RateLayout" <!-- Not visible for now, you can ignore it -->
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:minWidth="25px"
android:minHeight="25px"
android:background="#color/common_google_signin_btn_text_light_default"
android:layout_above="#+id/eventDetail_CommentScrollView"
android:visibility="gone" />
<ScrollView
android:id="#+id/eventDetail_CommentScrollView" <!-- VMiddle -->
android:background="#4D4A58"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/eventDetail_commentButton">
<LinearLayout
android:orientation="vertical"
android:minWidth="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/eventDetail_CommentLayout" />
</ScrollView>
<Button
android:text="commenter"
android:id="#+id/eventDetail_commentButton" <!-- VMiddle, this one is doing ok -->
android:background="#666"
android:textColor="#f8f8f8"
android:layout_width="match_parent"
android:layout_height="30sp"
android:layout_alignParentBottom="true" />
</RelativeLayout>
Thanks for your answers.
Try the following code for the ScrollView -
<ScrollView
android:id="#+id/eventDetail_CommentScrollView" <!-- VMiddle -->
android:background="#4D4A58"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="#id/linearLayout1"
android:layout_weight="1"
android:layout_above="#+id/eventDetail_commentButton">
...
</ScrollView>
Use this, however the kind of UI you want can be easily achieved using Linear layout and using weight and weightSum properties.. also rename ID of the layout and views accordingly
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/topLayout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentTop="true"
android:background="#70AD47"
android:orientation="vertical">
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/btnBottom"
android:layout_below="#+id/topLayout"
android:background="#ED7D31"
android:minHeight="400dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
<Button
android:id="#+id/btnBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#4472C4"
android:text="Bottom button" />
</RelativeLayout>
1. Add attribute android:layout_below="#id/linearLayout1" and android:layout_above="#id/eventDetail_commentButton" to ScrollView to keep it at middle position.
2. Use ScrollView and its child LinearLayout height android:layout_width="match_parent" although its not necessary.
No matter how big the top and bottom layout, middle scrollview will always fill the middle free spaces. It will never change the height of top and bottom layout.
Here is the working layout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/relativeLayout1">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/linearLayout1"
android:layout_alignParentTop="true"
android:layout_margin="10sp">
</LinearLayout>
<Button
android:text="commenter"
android:id="#+id/eventDetail_commentButton"
android:background="#666"
android:textColor="#f8f8f8"
android:layout_width="match_parent"
android:layout_height="30sp"
android:layout_alignParentBottom="true" />
<ScrollView
android:id="#+id/eventDetail_CommentScrollView"
android:background="#4D4A58"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/linearLayout1"
android:layout_above="#id/eventDetail_commentButton">
<LinearLayout
android:orientation="vertical"
android:minWidth="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/eventDetail_CommentLayout" />
</ScrollView>
</RelativeLayout>
Hope this will help~
Use android:layout_below="#+id/linearlayout1"
in eventDetail_RateLayout
I'm pretty sure none of the given answers achieve what you're looking for. What you wanna do is not simple because it involves a circular dependency: you basically want your vTop view to wrap and fill any space left by your vMiddle view (android:layout_above="#id/vMiddle") and at the same time you want your vMiddle view to wrap and fill any space left by your vTop view (android:layout_below="#id/vTop").
The only solution I can imagine would be to check and set the view sizes programmatically, I don't think this is doable only by rearranging your layout.
I finally achieved to get something close to what I wanted. I combined layout_above and below and fixed the size of VTop by making the Huge TextView scrollable. I have now VTop and VBottom at a fixed size and VMiddle taking the rest of the place at the center.
Thanks for your fast answers :)
I have the following:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/layout_question_types"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="18sp"
android:layout_marginTop="18sp"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- some content -->
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="18sp"
android:gravity="right"
android:orientation="vertical" >
<!-- some more content -->
</RelativeLayout>
</LinearLayout>
</ScrollView>
However, when I turn the phone horizontal to force the scrollbar, the scrollbar appears but the content at the bottom of the screen gets hidden.
Any ideas? There are similar questions on SO but they don't seem to fix the problem. Thanks.
Reason of this are margins and ScrollView parent FrameLayout which has some margin problems. Margins are ignored in measuring and scroll view measure its size without these margins and that is why the bottom part of inner views in ScrollView is not visible.
You can solve it simple wrapping child LinearLayout with another LinearLayout without margins.
I'm trying to optimize the layouts in an Android app by flattening view hierarchies. Here's a particularly difficult one!
This layout has a main LinearLayout to hold the top and bottom rows (which are horizontal sub-LinearLayouts themselves). Each of the four items in the middle is a vertical RelativeLayout (to accommodate the ImageView and textView) spread out using layout_weights. Each row containing two items is ALSO a horizontal LinearLayout.
Needless to say, this layout is atrociously inefficient, leading to a lot of "Choreographer has skipped frames" messages when it is being drawn. I'd like to eliminate these nested Layouts, but AFAIK RelativeLayout is not helpful in equally spacing out the items in a row horizontally, and the two rows in the centre vertically. Also, I considered replacing the ImageView and TextView with a compound drawable, but I don't know how I can control the drawable's size.
Any help is appreciated!
Edit:
Here's a rough description of the Layout.
<!-- The top bar -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="80dip"
android:background="#drawable/some_image">
...
</LinearLayout>
<!-- Central Layout -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="2"
android:orientation="vertical">
<!-- First Row -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:baselineAligned="false"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:weightSum="2">
<!-- Item 1 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
<!-- Item 2 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
</LinearLayout>
<!-- End of first row layout -->
<!-- Second Row -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:baselineAligned="false"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:weightSum="2">
<!-- Item 3 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
<!-- Item 4 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
</LinearLayout>
<!-- End of second row layout -->
</LinearLayout>
<!-- End of central layout -->
<!-- Bottom bar -->
<LinearLayout...>
....
</LinearLayout>
Your example looks a lot like the one shown in demo given by the Android team here:
http://developer.android.com/reference/android/widget/GridLayout.html
I am by no means super savvy with GridLayout (lots of trial and error before I get it working) but looking at what you have it should do the trick (esp if you would move all the buttons at the bottom to the top, and had them as an ActionBar).
Getting rid of the layout_weights will improve everything lots as every time those are used they are measure again and again.
The most optimum way of doing this would be to write your own custom ViewGroup. It's quite straightforward if you understand how android does its laying out.
See these slides by Romain Guy:
https://docs.google.com/leaf?id=0B_VKZCqEnHblNDdiY2UxODgtYWNhNS00MmU4LWE4NDMtZjQ1OWI5MDMxZTVh&sort=name&layout=list&num=50.
I am trying to keep the ScrollView from taking too much space at the bottom of the screen as it keeps my two buttons from showing. I also don't want to manually set a height for the ScrollView.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
...
android:orientation="horizontal">
<Button .../>
<TextView .../>
<Button .../>
</LinearLayout>
<ScrollView
android:layout_width="math_parent"
android:layout_height="wrap_content">
<ImageView .../>
<ImageView .../>
<ImageView .../>
</ScrollView>
<LinearLayout
...
android:orientation="horizontal">
<Button .../>
<Button .../>
</LinearLayout>
</LinearLayout>
This is a generalized version of my layout. What is happening is that the ScrollView extends all the way to the bottom of the screen no matter how many items are in it. This causes the two buttons at the bottom of the screen to not be visible.
How can I stop this from happening without manually setting a height for the ScrollView?
I've used android:layout_height="wrap_content" for all my views.
Isn't this supposed to automatically distribute the height of the views to fit the screen's height?
(Wanted to include images, but my rep isn't high enough yet (-_-))
The way I would resolve this today is by using RelativeLayout as a base. Anchor the two LinearLayout's to the top and bottom of the RelLayout respectively. Then I would insert the ScrollView but I would make sure to set it's layout properties as follows:
android:layout_below="topLinearLayout"
android:layout_above="bottomLinearLayout"
Have you tried using layout_weight for the ScrollView. IIRC, if a non-zero weight is set for ONE element (and the corresponding dimension set to 0dp) then it'll fill up the remaining space in that dimension, after setting out the measurements for sibling views (in this case, the LinearLayout on top and bottom of the ScrollView.
Apologies, not got an Android environment to check and it's been a while.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout>
...
Something at the top
...
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
**android:layout_height="0dp"
android:layout_weight="1"**>
<ImageView .../>
<ImageView .../>
<ImageView .../>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
...
buttons
...
</LinearLayout>
</LinearLayout>
Here's an answer with more information about the layout_weight attribute.