The set of alternative TextViews and ExpandableListView inside the RelativeLayout do not scroll when they take up extra screen space
I have three sets of TextView as title and ExpandableListView as content inside RelativeLayout, i.e. I have 3 TextViews and 3 ExpandableListViews alternating with each other. Now, on devices with smaller screen sizes, my layouts go out of sight below the screen. So logically the user will try to scroll down. But its not scrolling like it should be
As shown in the picture above, men, women and children are TextViews, and each has its own ExpandableListViews. I also have a list view above for home and settings. As you can see in the picture, most of the Kids content is below the screen. But when I try to loop through it without having it.
Here is my layout file
<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="#cccc">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#cccc"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Men"
android:textSize="30dp"
android:textAllCaps="true"
android:textAlignment="center"
android:layout_below="@id/listView"
android:id="@+id/menTextView"/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/menExpandableListView"
android:layout_below="@id/menTextView" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="women"
android:textSize="30dp"
android:textAllCaps="true"
android:textAlignment="center"
android:layout_below="@id/menExpandableListView"
android:id="@+id/womenTextView"/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/womenExpandableListView"
android:layout_below="@id/womenTextView" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="kids"
android:textSize="30dp"
android:textAllCaps="true"
android:textAlignment="center"
android:layout_below="@id/womenExpandableListView"
android:id="@+id/kidsTextView"/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/kidsExpandableListView"
android:layout_below="@id/kidsTextView" />
</RelativeLayout>
This is how I solved it, I just had one Expandable List view and the other text items are group headers inside an expanded list view without any children.
As suggested by one of the answers, I had a property that says if my group is a header, so isHeader () gives if my group is a header or not.
Here is my layout file
<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:orientation="vertical"
android:weightSum="15"
android:background="#cccc">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#cccc"
android:fadeScrollbars="false"
/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/expandableListView"
android:fadeScrollbars="false"
android:layout_below="@id/listView"
/>
</RelativeLayout>
And my updated getGroupView in adapter for expandableListView which extends BaseExpandableListAdapter
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
ProductHeadGroup headGroup = getGroup(groupPosition);
String header = headGroup.getGroupName();
if (headGroup.isHeader()) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.expandable_list_main_header, null);
TextView headerTextView = (TextView) convertView.findViewById(R.id.idExpandableHeaderItem);
headerTextView.setText(header);
} else {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.expandable_list_header, null);
ImageView imageView = (ImageView) convertView.findViewById(R.id.expandableHeaderIcon);
if (isExpanded){
imageView.setImageResource(R.drawable.ic_action_collapse_dark);
} else {
imageView.setImageResource(R.drawable.ic_action_expand_dark);
}
TextView headerTextView = (TextView) convertView.findViewById(R.id.idExpandableHeaderItem);
headerTextView.setText(header);
}
return convertView;
}
As shown above, I have implemented my custom extend / anti-aliasing indicators having their own ImageView in the GroupLayout. and disabled it in my work with
expandableListView.setGroupIndicator(null)
source to share
The whole problem is in your design. First of all, the RelativeLayout takes up the entire screen (or the free space left over) so the last ExpandableListView becomes very small and practically non-fetching.
To do this on the right , you must:
- Make a separate ExpandableListView
- Headers act like empty groups
- Custom type
-
getGroupTypeCount
return 2 (title and non-title) -
getGroupType
returns 1 if heading, else returns 0
-
- Custom layout
- Determine the type of band in
getGroupView
and inflate accordingly - No indicators
- Determine the type of band in
- Custom type
- Custom group indicators
- Disable indicators by default (
expListView.setIndicator(null);
) - Make them part of your regular group layout (like ImageView).
- Install (expanded / minimized) image in
getGroupView
andelv.setOnGroupItemClick()
- Default drawables (action bar icons -> ic_action_expand.png and ic_action_collapse.png)
- Disable indicators by default (
It looks like a lot of work, but in the end it will be worth it.
Result: a dynamic ExpandableListview that scrolls correctly no matter how many headers, groups and children you have.
Side note. I would recommend using CursorTreeAdapter to use CursorLoader to retrieve and SQLite to store data.
source to share
RelativeLayout
does not scroll, so there can be no more physical display.
The first solution that comes to mind is placement RelativeLayout
in ScrollView
. There are several problems with this:
- You need to set
RelativeLayout
height towrap_content
if it is insideScrollView
. If the height isExpandableListView
set aswrap_content
, then the parent's height cannot bewrap_content
. From the docs :
Note. You cannot use the wrap_content value for android: layout_height of the ExpandableListView attribute in XML unless the parent's size is also strictly defined (for example, if the parent was a ScrollView, you could not specify wrap_content, as it can also be of any length. However, you can use wrap_content if the ExpandableListView's Parent is of a specific size, such as 100px.
-
ListView
should never be placed underScrollView
. From the docs :
You should never use a ScrollView with a ListView because the ListView takes care of its own vertical scrolling. Most importantly, doing this hits all the important optimizations in the ListView for working with large lists, since it effectively forces the ListView to display its entire list of items to fill the infinite container supplied by the ScrollView.
In this particular case, since the view hierarchy is flat (only one level), you should use LinearLayout
instead RelativeLayout
. RelativeLayout
usually makes a 2 gauge pass.
Decision:
Use LinearLayout
instead RelativeLayout
and set layout_weight
for all list views, including the expanded list view, so that the remaining space is equally divided across all list views.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cccc"
android:orientation="vertical"
android:weightSum="4">
<ListView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/listView"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#cccc"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Men"
android:textSize="30dp"
android:textAllCaps="true"
android:textAlignment="center"
android:id="@+id/menTextView" />
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/menExpandableListView"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="women"
android:textSize="30dp"
android:textAllCaps="true"
android:textAlignment="center"
android:id="@+id/womenTextView"/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/womenExpandableListView"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="kids"
android:textSize="30dp"
android:textAllCaps="true"
android:textAlignment="center"
android:id="@+id/kidsTextView"/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/kidsExpandableListView"/>
</LinearLayout>
source to share