ListView in ScrollView android
In Android application, if you want to show items in a list with expandable feature. The ExpandableListView is a option that show items in a vertically scrolling two level list. It is different from the listview by allowing two level groups which can individually be expanded to show its children. In this post, we going to share a simple solution to increase and decrease height of ExpandableListView at run time when ExpandableListView expand or collapse. Sometime, it's required to increase height of ExpandableListView because you cannot use the wrap_content value for the height attribute of a ExpandableListView in XML if the parents size is not strictly specified. In other words, if the parent is the ScrollView then you could not specify wrap_content since it can be of any length. Let's try to understand the problem. As you can see above, all three bottom button(Save As, Save in Progress, Exit) not visible when we expend all group of ExpandableListView. Even we put all views inside of scroll view. Here, we have resolved output:
val listAdapter = listView.expandableListAdapter as ExpandableListAdapter var totalHeight = 0 val desiredWidth: Int = View.MeasureSpec.makeMeasureSpec( listView.width, View.MeasureSpec.EXACTLY ) for (i in 0 until listAdapter.groupCount) { val groupItem: View = listAdapter.getGroupView(i, false, null, listView) groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED) totalHeight += groupItem.getMeasuredHeight() if (listView.isGroupExpanded(i) && i != group || !listView.isGroupExpanded(i) && i == group ) { for (j in 0 until listAdapter.getChildrenCount(i)) { val listItem: View = listAdapter.getChildView( i, j, false, null, listView ) listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED) totalHeight += listItem.getMeasuredHeight() } } } val params = listView.layoutParams var height = (totalHeight + listView.dividerHeight * (listAdapter.groupCount - 1)) if (height < 10) height = 200 params.height = height listView.layoutParams = params listView.requestLayout() } Now we going to screen a small Android application to understand it with a example. Creating a new project1. Create an Android Application and name it ExpandableListView. We using following array list that declared in the string file of the project. 2. After that, update activity_main.xml file and add ExpandableListView as we have designed. android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> android:layout_width="match_parent" android:layout_height="wrap_content" />
android:layout_height="wrap_content" android:orientation="vertical" android:background="@android:color/white" android:padding="16dp"> android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@android:color/black" android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft" android:textSize="17dp" /> layout for group: android:layout_height="wrap_content" android:background="#778899" android:padding="8dp"> android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="8dp" android:paddingBottom="8dp" android:textColor="#FFFFFF" /> 4. Here, we have adapter of ExpandableListView that display child and header of list. import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.TextView; import java.util.HashMap; import java.util.List; public class ExpandableListViewAdapter extends BaseExpandableListAdapter { private Context context; // group titles private List // child data private HashMap public ExpandableListViewAdapter(Context context, List HashMap this.context = context; this.listDataGroup = listDataGroup; this.listDataChild = listChildData; } @Override public Object getChild(int groupPosition, int childPosititon) { return this.listDataChild.get(this.listDataGroup.get(groupPosition)) .get(childPosititon); } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { final String childText = (String) getChild(groupPosition, childPosition); if (convertView == null) { LayoutInflater layoutInflater = (LayoutInflater) this.context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(R.layout.list_row_child, null); } TextView textViewChild = convertView .findViewById(R.id.textViewChild); textViewChild.setText(childText); return convertView; } @Override public int getChildrenCount(int groupPosition) { return this.listDataChild.get(this.listDataGroup.get(groupPosition)) .size(); } @Override public Object getGroup(int groupPosition) { return this.listDataGroup.get(groupPosition); } @Override public int getGroupCount() { return this.listDataGroup.size(); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { String headerTitle = (String) getGroup(groupPosition); if (convertView == null) { LayoutInflater layoutInflater = (LayoutInflater) this.context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(R.layout.list_row_group, null); } TextView textViewGroup = convertView .findViewById(R.id.textViewGroup); textViewGroup.setTypeface(null, Typeface.BOLD); textViewGroup.setText(headerTitle); return convertView; } @Override public boolean hasStableIds() { return false; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } }
import android.os.Bundle import android.view.View import android.widget.ExpandableListAdapter import android.widget.ExpandableListView import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private var expandableListView: ExpandableListView? = null private var expandableListViewAdapter: ExpandableListViewAdapter? = null private lateinit var listDataGroup: ArrayList private lateinit var listDataChild: HashMap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) expandableListView = activity_expandable_list_view // initializing the listeners expandableListView!!.setOnGroupClickListener { parent, v, groupPosition, id -> setListViewHeight(parent, groupPosition) false } // initializing the objects initObjects() // preparing list data initListData() } /** * method to initialize the objects */ private fun initObjects() { // initializing the list of groups listDataGroup = ArrayList() // initializing the list of child listDataChild = HashMap() // initializing the adapter object expandableListViewAdapter = ExpandableListViewAdapter(this, listDataGroup, listDataChild) // setting list adapter expandableListView!!.setAdapter(expandableListViewAdapter) } /* * Preparing the list data * * Dummy Items */ private fun initListData() { // Adding group data listDataGroup.add(getString(R.string.text_alcohol)) listDataGroup.add(getString(R.string.text_coffee)) // array of strings // list of alcohol val alcoholList: MutableList var array: Array for (item in array) { alcoholList.add(item) } // list of coffee val coffeeList: MutableList array = resources.getStringArray(R.array.string_array_coffee) for (item in array) { coffeeList.add(item) } // Adding child data listDataChild[listDataGroup[0]] = alcoholList listDataChild[listDataGroup[1]] = coffeeList // notify the adapter expandableListViewAdapter!!.notifyDataSetChanged() } private fun setListViewHeight( listView: ExpandableListView, group: Int ) { val listAdapter = listView.expandableListAdapter as ExpandableListAdapter var totalHeight = 0 val desiredWidth: Int = View.MeasureSpec.makeMeasureSpec( listView.width, View.MeasureSpec.EXACTLY ) for (i in 0 until listAdapter.groupCount) { val groupItem: View = listAdapter.getGroupView(i, false, null, listView) groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED) totalHeight += groupItem.measuredHeight if (listView.isGroupExpanded(i) && i != group || !listView.isGroupExpanded(i) && i == group ) { for (j in 0 until listAdapter.getChildrenCount(i)) { val listItem: View = listAdapter.getChildView( i, j, false, null, listView ) listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED) totalHeight += listItem.measuredHeight } } } val params = listView.layoutParams var height = (totalHeight + listView.dividerHeight * (listAdapter.groupCount - 1)) if (height < 10) height = 200 params.height = height listView.layoutParams = params listView.requestLayout() } } If you have followed the above post carefully. You can see all bottom buttons visible when you scolling from bottomm to up even you have expend all group of ExpandableListView. But if you are facing any problem to build or run it and you have any quires, feel free to ask it from comment section below. Share:
|