Dynamically adding views to RelativeLayout inside ScrollView - android

I am trying to add dynamically created several RelativeLayouts into a LinearLayout which is inside a RelativeLayout, which is inside a ScrollView. When the total height of the all views exceed the size of the phone screen, all views are displayed correctly. But when the total size of dynamically added views is not enough for filling the screen, only the first RelativeLayout element is shown and the others are not displayed in the screen. I am really hopeless and do not understand why.
Here is the code to dynamically populate views inside linear layout:
LinearLayout commentsLayout = (LinearLayout) findViewById(R.id.comments_layout);
LayoutInflater inflater = (LayoutInflater)
this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for(Comment c: commentsList) {
RelativeLayout layoutItem = (RelativeLayout) inflater.inflate(
R.layout.list_item_comment, null, false);
TextView tv = (TextView) layoutItem.findViewById(R.id.textView);
ImageView iv = (ImageView) layoutItem.findViewById(R.id.imageView);
// set tv's text
// set iv's image and onclicklistener, nothing fancy here, everything goes well
commentsLayout.addView(layoutItem);
}
Here is list_item_comment.xml:
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/white"
>
<ImageView
android:id="#+id/imageView"
android:layout_width="50dip"
android:layout_height="50dip"
android:layout_alignParentLeft="true"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
/>
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="10dp"
android:textSize="16sp"
android:layout_toRightOf="#id/imageView"
/>
</RelativeLayout>
And here is the xml file for this activity:
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/main_layout"
>
...
<ScrollView
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:id="#+id/scrollView"
>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/relativeContainer"
>
...
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/comments_layout"
/>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
And the screenshots:
Without sufficient layouts: (INCORRECT, needs to show 3 comments)
With enough layouts: (CORRECT ONE, screen is filled)
I just need to show all three comments in the first case :/ Thanks in advance.

instead of fill_parent, try changing the layout_height of the <RelativeLayout> of your list_item_comment.xml to wrap_content.
Also, why do you need another <RelativeLayout> inside your <ScrollView> of the xml of your activity. The LinearLayout is sufficient to do what you want your activity to look like. Maybe you can just remove it.

Related

How can i create multiple RelativeLayouts(with existing xml layout) in an LinearLayout programmatically?

I want to put multiple RelativeLayouts in one LinearLayout programmatically. Instead of using a ListView. My layout XML looks like following:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background_select_app" >
<ScrollView
android:id="#+id/scroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#80000000" >
<LinearLayout
android:id="#+id/parent_linear_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#FFFFFF" >
</LinearLayout>
</ScrollView>
</RelativeLayout>
and following is the RelativeLayout which I want to add as child in LinearLayout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="280dp"
android:layout_height="40dp"
android:background="#drawable/row"
android:gravity="center" >
<TextView
android:id="#+id/name_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#333333" />
</RelativeLayout>
Can i do it programmatically? Thanks in advance.
try like this:
public void testgenerate() {
LinearLayout rootLaout=findViewById(R.id.idofliner);
LayoutInflater layoutInflater = getLayoutInflater();
for(int i=0;i<10;i++){
RelativeLayout inflate = (RelativeLayout) layoutInflater.inflate(R.layout.relativelayutid, null);
rootLaout.addView(inflate);
}
}
Usually there is no need to nest a RelativeLayout in your LinearLayout, you can achieve the same as Linearlayout with just a single RelativeLayout (so your view hierarchy has one Layout less to traverse --> improves performance ) or if you simply want to align your elements verticaly / horizontally than use only one LinearLayout instead of an extra RelativeLayout
Im not sure what you want to do, but to me it sounds like that RecyclerView or ListView is what you are looking for?

Linearlayout inside scrollview with even distriburtion

I have a data entry type activity and im using a linear layout to space out evenly the sets of textviews and edittexts. Then I have a scroll view that is supposed to make it so the user can scroll while the softkeyboard is up.
If I use android:fillViewport the linearlayout works properly and fills the screen and spreads each item out evenly but then when the keyboard comes up and stops each item being spread out evenly. If i use android:windowSoftInputMode="stateVisible|adjustPan" then the linearlayout remains spread out but the scroll view doesn't work anymore (from all the unsolved posts on this i don't think you can have a working scroll view with adjustPan)
is there any way to have a linearlayout inside a scrollview, with items spread out evenly and still work while the softkeyboard is up with out changing the linearlayout?
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport
>
<LinearLayout
android:gravity="left"
android:orientation="vertical"
android:id="#id/tab2"
android:paddingLeft="40.0dip"
android:paddingTop="0.0dip"
android:paddingRight="40.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0">
<TextView
android:id="#id/textViewBrand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/brand" />
<AutoCompleteTextView
android:id="#id/editTextBrand"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</AutoCompleteTextView>
</LinearLayout>
...more linearlayouts with textview and edittext to be spaced out evenly
set the property android:fillViewport="true" in your scrollview it will work
Maybe the ScrollView isn't working because your
android:layout_height attribute
is defined to match_parent. You have to put
wrap_content
Follow This Code, I hope it resolves your Problem
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
//Your Main Layout
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="100">
// First Sub Layout Under Main Layout
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:layout_weight="10"
android:weightSum="100" >
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="TextView"
android:layout_weight="70" />
<EditText
android:id="#+id/editText1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="30" />
</LinearLayout>// Finishing First Sub layout
// Second Sub Layout Under Main Layout
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:layout_weight="10"
android:weightSum="100" >
<TextView
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="TextView"
android:layout_weight="70" />
<EditText
android:id="#+id/editText2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="30" />
</LinearLayout>// Finishing Second Sub layout
similarly for 3rd,4rth,5th sub layouts and so on........
</LinearLayout> // Finishing Main Layout
</ScrollView> // Finishing ScrollView
you can go over the child views of the LinearLayout and set their size to a fixed size yourself in code using a ViewTreeObserver.OnGlobalLayoutListener.
the following code sets the sizes to not change, so you can use the android:fillViewport option with weights, and then essentially remove the weights, but keep the calculated sizes.
I used this code with some modifications to also make sure child views are distributed evenly in a LinearLayout that is inside a ScrollView, where the LinearLayout is too big for the android:fillViewport option to get the weights to actually work. this was done by doing 2 iterations over the children. first getting the max view's height, and then setting all child views to that max height.
private void distributeViewsEvenlyInLinearLayout() {
ViewTreeObserver observer = linearParentView.getViewTreeObserver();
final ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
linearParentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
linearParentView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
for (int i = 0; i < linearParentView.getChildCount(); i++) {
View child = linearParentView.getChildAt(i);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, child.getHeight());
child.setLayoutParams(layoutParams);
}
}
};
observer.addOnGlobalLayoutListener(globalLayoutListener);
}

add listView and imageView at its end

I want to create the layout to be like what in the diagram
how can I make the listView Scroll independently and make the textView and ImageView stead?
just replace your xml layout like below 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:background="#android:color/white"
android:padding="5dp"
android:weightSum="2"
android:orientation="vertical" >
<LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Small Text"
android:layout_gravity="right"
android:textColor="#android:color/black"
android:textAppearance="?android:attr/textAppearanceSmall" />
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
<ImageView
android:id="#+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:src="#drawable/yourimg" />
</LinearLayout>
above xml given output below screenshot:
For the Lower Steady Image View you can use : Create a footer view
layout consisting of text that you want to set as footer and then try
View footerView = ((LayoutInflater) ActivityContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
ListView.addFooterView(footerView);
For Header: The solution that works for me is to create a TableLayout
that has a row with the heading and a row with the list like this:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include layout="#layout/header" />
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</TableLayout>
Please make sure that the ListView has #android:id/list as the ID.
OR
Rather google adding header and footer to listview in android that
will help u much better
Sorry for the pseudo code, I can try a better attempt later on, but you need:
RelativeLayout
TextView - align top
ImageView - align bottom
ScrollView - align above ImageView, align below TextView
Create a linear layout with orientation as vertical. Add textview listview and imageview with the weight as you want. Remember to give layout_height as 0dp for all the three components.
Add Header And Footer To the Listview,Like
ListView mList=getListView();
mList.addHeaderView(View v);//Your textView
and
mList.addFooterView(v);//your imageview

Why doesn't this nested TextView work while others do in the same code?

Considering this LinearLayout containing..
One nested Linear Layout with two child views
one imageView
one Textview
One textView
One Button
Why can I successfully show text content on the outer TextView using findViewById and setText while the inner Textview (inside nested linear view) shows blank?
Here is the code for onCreate:
LayoutInflater inflater = LayoutInflater.from(Item.this);
LinearLayout itemLayout = (LinearLayout)inflater.inflate(R.layout.activity_item, null);
Button proformaButton = (Button)itemLayout.getChildAt(2);
roformaButton.setOnClickListener(this);
setContentView(itemLayout);
TextView titleTitla = (TextView)findViewById(R.id.item_title);
TextView itemBody = (TextView)findViewById(R.id.item_body);
titleTitla.setText("Tomatoes");
itemBody.setText("Potatoes");
While debugging I can see that the view is found by Id and I can also see that setText does it work (mText field of TextView), but the activity does not show anything for item_title.
I am asking how to fix this but if it's not a trivial thing a hint of explanation would be very appreciated.
If it helps, here's the xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:orientation="horizontal"
android:layout_weight="1">
<ImageView
android:id="#+id/item_picture"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:contentDescription="#string/image_item">
</ImageView>
<TextView
android:id="#+id/item_title"
android:layout_width="0dip"
android:layout_height="fill_parent">
</TextView>
</LinearLayout>
<TextView
android:id="#+id/item_body"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="2">
</TextView>
<Button
android:id="#+id/btnOrderItem"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/order_button"
/>
</LinearLayout>
<TextView
android:id="#+id/item_body"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="2">
</TextView>
It's the layout_height="0dp". The reason it works on the other LinearLayout is because you have a weight attribute. Change the 0dp to wrap_content.

LinearLayout with weight-attributes on children inside a ScrollView

The usual question regarding ScrollViews seems to be how to use fillViewport to let the ScrollView stretch to the whole screen. My problem is similar, but going the other way :)
I got a LinearLayout that contains multiple elements. All except one element have a fixed height, the special one is an ImageView that should stretch to fill the remaining space. This works fine :)
Now I want to put the LinearLayout into a ScrollView, as some of my elements should expand at runtime (e.g. click on "more"-icon that expands a TextView). In the unexpanded version I would like to have all elements fit on the screen, as if the ScrollView wouldn't exist.
Unfortunately, when wrapping the ScrollView around the LinearLayout, the ImageView is scaled to maxSize und the screen does not fit the screen. Do you have any ideas how to achieve my goal?
I reproduced the problem in an example app to share it with you:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="#ffff0000"
android:scaleType="fitCenter"
android:src="#drawable/background" />
<TextView
android:layout_width="fill_parent"
android:layout_height="80dp"
android:background="#ff00ff00"
android:text="element 2"
tools:context=".MainActivity" />
<TextView
android:layout_width="fill_parent"
android:layout_height="80dp"
android:background="#ff00ff00"
android:text="element 1"
tools:context=".MainActivity" />
</LinearLayout>
</ScrollView>
Here are the screenshots from the two versions:
The one above is the Layout with ScrollView (notice the scrollbar and cropping on element 1), the one below without.
Update: The original height of the image in the image-view is bigger than the screen. So it should be downscaled (that's why it has weight 1 and scaleType set).
Solution: The following code solved the problem for me (based on Luksprog answer)
Main Activity (excerpt, change of layout is induced by click on ImageView):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = (ScrollView) findViewById(R.id.scroller);
frame = (FrameLayout) findViewById(R.id.frame);
layout = (LinearLayout) findViewById(R.id.layout);
final ImageView image = (ImageView) findViewById(R.id.image);
image.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ImageView image = (ImageView) findViewById(R.id.image);
frame.removeView(layout);
scrollView.addView(layout);
image.getLayoutParams().height = image.getHeight();
}
});
}
Layout XML file
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ScrollView
android:id="#+id/scroller"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:fillViewport="true"
>
</ScrollView>
<LinearLayout
android:id="#+id/layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="#ffff0000"
android:scaleType="fitCenter"
android:src="#drawable/background" />
<TextView
android:id="#+id/text1"
android:layout_width="fill_parent"
android:layout_height="80dp"
android:background="#ff00ff00"
android:text="element 2"
tools:context=".MainActivity" />
<TextView
android:layout_width="fill_parent"
android:layout_height="80dp"
android:background="#ff00ff00"
android:text="element 1"
tools:context=".MainActivity" />
<TextView
android:layout_width="fill_parent"
android:layout_weight="0.1"
android:layout_height="0px"
android:background="#ff00ff00"
android:text="element 3"
tools:context=".MainActivity" />
</LinearLayout>
</FrameLayout>
As I said in my comments, I don't know if what you're trying to do is possible at the xml level. One option would be to modify your current layout and add a root FrameLayout to which you'll, initially, add the ScrollView and above it, the LinearLayout. In this position the ImageView will behave as you want as the user didn't modify the layout. When you need to show more in your layout you'll detach the LinearLayout from the view hierarchy(with removeView) and attach it to the ScrollView(with addView). You'll reverse this when the user goes back to the initial layout.
This will make the ImageView to have different heights when making the views switch so you'd want to get the height of the ImageView and re set it when doing the switch. To get the height, you could do it in a listener or using the post method in onCreate(as the views haven't been laid out yet at that moment). Also, remember that the user could turn the phone, I don't know if this will affect your layout, but take it consideration.
Firstly i tried running your code and it didn't cause any issue for me. The scrollView did not show up although the image was scaled to a ScreenHeight-160dp height which i expected because you have used weight 1 for this imageview.
I would suggest that you remove the weight and give height as wrapcontent. In that case the Imageview will just enclose the Image. When it becomes bigger in size, automatically scrollview come into use if the total heights of all screen contents is more than the screenheight.

Categories

Resources