Center elements of HorizontalScrollView when not enough to make it scroll - android

I have a Layout with a HorizontalScrollView containing a LinearLayout for a Menu where the contents are inflated with the contents of the DB. This works fine however when there are not enough elements to make the HSV scroll this does not fill the width of the screen which ideally should be centered. i.e.
Currently:
| Element 1 Element 2 | <- edge of screen
Instead of:
| Element 1 Element 2 | <- edge of screen
whilst still being able to:
| Element 1 Element 2 Element 3 Element 4 Elem| <- edge of screen now scrolling
The layout XML is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLinearLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_height="25dp" >
</TextView>
<ScrollView
android:id="#+id/scroll1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<LinearLayout
android:id="#+id/contentLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="fill_parent"
android:layout_height="30dp">
<LinearLayout
android:id="#+id/footerLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
With the following XML being inflated inside footerLayout:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/footer_content"
android:textSize="18sp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="FOOTER"
android:singleLine="true" />

I just solved this issue. I ran into it a few hours ago. You need to center the HorizontalScrollView in its parent and set its width/height to wrap_content. The layout you put in the the HSV must have its width/height set to wrap content as well. The important part here is to not set any gravity/layout_gravity on this layout or you may experience (very annoying) clipping issues after inflating your views. Example below is contained in a RelativeLayout.
<HorizontalScrollView android:id="#+id/svExample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/rlExample">
<LinearLayout
android:id="#+id/llExample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView >

I had the same problem and finally got it to work. Here is a minimal example:
The main activity layout with the HorizontalScrollView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true" >
<LinearLayout
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
The layout of the elements that will be inflated and put inside the scroll view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="your text" />
</LinearLayout>
And this is an example of the code to inflate and add the elements:
LinearLayout container = (LinearLayout) findViewById(R.id.container);
LayoutParams elementLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
int elementCount = 3; // ...or however many you like
for (int i = 0; i < elementCount; i++) {
LinearLayout element = (LinearLayout) getLayoutInflater().inflate(R.layout.element, null);
container.addView(element, elementLayoutParams);
}
It's mainly based on a technique for stretching the content of ScrollViews explained in this article by Romain Guy.
However in this case where you are adding contents dynamically, another key point is setting the positive value for the weight (1f in this example) using LayoutParams when adding the elements to the container. If you have a static set of elements that you can include directly in the container and don't need to inflate you can specify the weight of the elements' outer LinearLayout in the XML layout like so:
android:layout_weight="1"
But if you do it dynamically that won't work because the weight will reset to 0 and the elements collapse. Hence you need to set it via the LayoutParams.

Below is the simplest way worked for me.
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<LinearLayout
android:id="#+id/layout_others"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</HorizontalScrollView>

managed to get round center-horizontal clipping the left side:
HorizontalScrollView part of layout has been changed to:
<LinearLayout
android:id="#+id/footerWrapperLayoutToGetAroundCenteringIssue"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:gravity="center_horizontal">
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_height="fill_parent"
android:layout_width="wrap_content">
<LinearLayout
android:id="#+id/footerLayout"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
Its just a pity when it centers them they are not evenly distributed.
If anyone has any ideas please let me know.

assign wieght 1 to the textview in inflated view and make width wrapcontent

If the parent layout is a constraint layout:
<HorizontalScrollView
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="wrap_content"
android:layout_height="0dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
.
.
</LinearLayout>
</HorizontalScrollView>

Related

Align objects into middle of layout

I am dealing with ADK and I have a problem. I use LinearLayout, and I want to put my objects into middle and center of layout.
Here is my code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal|center_vertical"
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal|center_vertical"
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal|center_vertical"
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal|center_vertical"
</LinearLayout>
Still it goes to the TOP CENTER or to left. Should I use something else instead of LinearLayout? Or is there special code for centering and middling?
Thank you for helping!
Note: Unnecessary parts are removed.
You can use RelativeLayout with nested LinearLayout. Put all your view into LinearLayout without applying centering and set centerInParent="true".
But in your case just remove layout_gravity attribute from your views and add gravity="center" to the root view.
And also you forget to close your view's tags;)
So the final layout will be something like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
You should consider these things
Because LinearLayout just adds views one by one, your LinearLayout android:layout_width and android:layout_height should be "fill_parent" to show your views correctly
android:layout_gravity should be "center_horizontal|center_vertical"
Try adding android:layout_weight for your objects

Nested Layouts inside Linear Layout (vertical) - Ensuring the last nested layout displays its contents

I have a linear-layout (vertically-oriented) that contains two nested linear layouts inside of it.
The first linear-layout has a background image that is applied dynamically based on the context o the particular activity. The image pretty much takes up the whole size of the screen
The second linear-layout contains two checkboxes (horizontally-oriented) that should be displayed at the bottom of the activity.
My question is, how can I ensure that the second linear-layout displays at the bottom of the screen and just shows the minimal amount it needs to, allowing the first linear-layout to display as much as its background image as possible? Currently it's being pushed off the screen by the first LL's bg image.
Thank you.
Using Weight you can do what you want:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FF0000"
android:layout_weight="1"
>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#00FF00"
android:layout_weight="1"
>
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox" />
<CheckBox
android:id="#+id/checkBox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox" />
</LinearLayout>
</LinearLayout>
You can use RelativeLayout as the outer layout instead of LinearLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/bottomLayout"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
...
</LinearLayout>
<LinearLayout
android:id="#+id/topLayout"
android:layout_above="#id/bottomLayout"
android:layout_centerHorizontal="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
...
</LinearLayout>
</RelativeLayout>
<LinearLayout
... >
<LinearLayout
...
android:layout_height="0dp"
android:layout_weight="1"
>
...
</LinearLayout>
<LinearLayout
...
android:layout_height="wrap_content"
>
...
</LinearLayout>
</LinearLayout>
Notice on the weighted layout, the height is set to "0dp". With only one weighted, the weighted one will stretch to fit the rest of the available area.

How can I place new items under scrollview

I have a vertical scrollable layout with lots of items, working fine.
I am trying to place a new linearlayout to the bottom of the screen that would NOT be part of the scrollable layout.
That is, it would sit on the buttom (like an adview) independent of the scrollable part.
I was only able to place it inside the scrollView. How can I place it below, so it would always visible ?
Use a RelativeLayout, and organize it like this:
<?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="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:layout_above="#+id/linearLayoutThatDoesNotScroll" >
<LinearLayout
android:id="#+id/linearLayoutWithLotofContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="#+id/linearLayoutThatDoesNotScroll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" >
</LinearLayout>
</RelativeLayout>
The trick is in the ScrollView placement, at the same time it is aligned with the top of the screen AND above the lower, fixed, LinearLayout. It just works.
something like this :)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ScrollView android:id="#+id/scroll_view"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<LinearLayout android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</ScrollView>
<LinearLayout android:id="#+id/bottom"
android:layout_width="fill_parent"
android:layout_height="10dip" />
</LinearLayout>
You will add your bottom content to the bottom linearLayout with the android:id=bottom :)
If you used a vertical LinearLayout to hold the scrollable layout, then you could add the adview to the LinearLayout below the scrollable layout and it would appear at the bottom of the screen. (assuming your weights are set correctly,and the scroll layout is set to WRAP_CONTENT)
A RelativeLayout would allow you to set the adview to align itself with the bottom of the scrollable layout as well, but you would still need to make sure the scrollable layout was set to WRAP_CONTENT so it didn't automatically take up the entire screen.
<?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" >
<Button
android:id="#+id/dialogButtonOK"
android:layout_width="100px"
android:layout_height="wrap_content"
android:text=" Ok "
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:background="#drawable/button_style"
/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:id="#+id/scrView"
android:layout_above="#id/dialogButtonOK"
android:layout_alignParentTop="true"
>
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TableLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="*"
android:id="#+id/main_table" >
</TableLayout>
</HorizontalScrollView>
</ScrollView>
</RelativeLayout>
This is worked for me

LinearLayout problem

I am facing problem to customize Linear Layout. My xml is as follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
>
<LinearLayout android:id="#+id/LinearLayout_LeftPanel"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="#0000ff"
>
<TextView android:id="#+id/LeftPanel_Title"
android:text="Frequently asked questions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
/>
</LinearLayout>
<LinearLayout android:id="#+id/LinearLayout_MainContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_toRightOf="#+id/LinearLayout_LeftPanel"
>
<TextView android:id="#+id/MainContent_Title"
android:text="Alabama Rules of Civil Procedure"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff0000"
android:textSize="19px"
android:textStyle="bold"
/>
</LinearLayout>
</RelativeLayout>
I want to set the width of #+id/LinearLayout_LeftPanel layout one third of the screen width pro-grammatically on the onCreate().
so how can do this ?
The answer from Mina Samy is almost correct, but you're using a RelativeLayout as your topmost container. The android:layout_weight attribute only works when the surrounding container is a LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:id="#+id/LeftPanel"
android:layout_weight="1">
...
</LinearLayout>
<LinearLayout android:id="#+id/MainContent"
android:layout_weight="3">
...
</LinearLayout>
</LinearLayout>
EDIT:
I just saw that you said you wanted to set it "programmatically in the onCreate method". If you really want to do this instead of setting it in the XML like I wrote above, you have to do do something like this:
protected void onCreate(Bundle b) {
LinearLayout leftPanel = (LinearLayout)findViewById(R.id.LeftPanel);
LinearLayout.LayoutParams leftPanelParams = (LinearLayout.LayoutParams)leftPanel.getLayoutParams();
leftPanelParams.weight = 1;
// do the same thing for MainContent but set the Weight to 3;
}
you can use set the weight property of both Linearlayouts
set the first android:layout_weight="1"
and the left panel android:layout_weight="3"
thanks

TextView inside LinearLayout stretches the LinearLayout and fill_parent fix causes weight flip

If I have 2 LinearLayouts split %50/%50 everything is fine. Weights are 1 and 1. As soon as I add a TextView inside the top LinearLayout, it stretches that layout. I use wrap_content as the documentation says I should when it comes to weights.
As you can see the red and green should be split evenly and text on grey background should be inside red box. Here is the code:
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ff0000"
>
<TextView
android:text="#string/hello"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#cccccc"
android:textColor="#000000"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#00ff00"
>
</LinearLayout>
Now if I switch to "fill parent" as follows it actually works but it creates another problem. Here is the code (so far so good):
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ff0000"
>
<TextView
android:text="#string/hello"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#cccccc"
android:textColor="#000000"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#00ff00"
>
</LinearLayout>
So looking at above we were forced to use fill_parent and we would think like we fixed the problem but here is the problem if we are using fill_parent (I took out the TextView just to show the problem, TextView doesn't make the problem go away anyways):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="3"
android:background="#ff0000"
>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="2"
android:background="#00ff00"
>
</LinearLayout>
</LinearLayout>
As you can see I assign the weights 3 (top red) and 2 (bottom green) but what actually happens is they get flipped: The red becomes 2 and bottom becomes 3. Just measure the pixels too see.
Here are the results of the 3 codes:
Just to be clear, every single time the layout was wrapped inside this (the top layout):
android:layout_width="fill_parent"
android:layout_height="fill_parent"
With XML version="1.0" encoding="utf-8" and proper namespace.
Combined child view weights should add up to 1..... Eg. .3, .3, .4 = 1, or 100%
Try adding a child view to the bottom layout.

Categories

Resources