I have a ScrollView which contains a lot of items. On the bottom of it I add a set of items from another Activity. I check the input ArrayList from another Activity and should to add proper count of checkbox to my Activity with ScrollView. I add items with the help of LinearLayout like that:
public void addFiles()
{
adapter = new ArrayAdapter<File>(this,
R.layout.new_order, R.id.fileCheck,
FileManagerActivity.finalAttachFiles)
{
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// creates view
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.file, null);
view.setFocusable(false);
CheckBox textView = (CheckBox) view
.findViewById(R.id.fileCheck);
textView.setClickable(true);
textView.setText(FileManagerActivity.finalAttachFiles.get(position).getName().toString());
textView.setTextColor(Color.BLACK);
textView.setPadding(55, 0, 0, 0);
textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.file_icon, 0, 0, 0);
textView.setTextSize(16);
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
int dp5 = (int) (5 * getResources().getDisplayMetrics().density + 0.5f);
textView.setCompoundDrawablePadding(dp5);
textView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(((CheckBox)v).isChecked()){
checks.set(position, 1);
}
else{
checks.set(position, 0);
}
}
});
return view;
}
};
}
I know that using ListView inside a ScrollView is not recomended but I tried to use LinearLayout for my aim, but it worked bad - it couldn't updated properly. To display ListView in proper way I use such a class:
public class UtilityListView {
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
Log.i("ListAdapter count",Integer.toString(listAdapter.getCount()));
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
}
And use it after every data changing like that:
fileList = (ListView) findViewById(R.id.fileListView);
fileList.setAdapter(adapter);
UtilityListView.setListViewHeightBasedOnChildren(fileList);
But the height of the ListView is much bigger than quantity of items of the list...How can I fix it?
I solved the problem using the ListView with footers and headers. All the attempts to use ListView inside the ScrollView were unworkable or unefficient. I did it like this:
View header = getLayoutInflater().inflate(R.layout.header_listview, null);
View footer = getLayoutInflater().inflate(R.layout.footer_listview, null);
fileList.addHeaderView(header);
fileList.addFooterView(footer);
fileList.setCacheColorHint(Color.WHITE);
fileList.setAdapter(adapter);
All my items shows properly and I can get functionality, what I wanted.
Related
I put the listView in a popupWindow, when it has many items, the popupWindow exceed the screen size, so I want to limit the max height(or max item, show scroll bar if exceed) of the listView, thanks all
Try this it may be help to you
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
for (int i = 0; i < 5; i++) //here you can set 5 row at a time if row excceded the scroll automatically available
{
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
and you can use like this
YourAdapter mYoursAdapter = new YourAdapter();
mListview.setAdapter(mYoursAdapter);
setListViewHeightBasedOnChildren(mListview);
Create a class AppUtil in your project.Try like this:
public class AppUtil{
public static void setListViewHeightBasedOnChildren(ListView listView) {
if (listView == null) {
return;
}
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
}
To call the above method in your activity or fragment you can proceed like this:
public class MedicalReportsFragment extends Fragment {
#Bind(R.id.lv_investigative_report)
ListView investigativeReportLV;
private MedicalReportsAdapter mMedicalReportsAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mMedicalReportsAdapter = new MedicalReportsAdapter(getActivity(), mMedicalReportOverviews,true);
investigativeReportLV.setAdapter(mMedicalReportsAdapter);
AppUtil.setListViewHeightBasedOnChildren(investigativeReportLV);
}
}
I think you can try this trick in your layout.xml:
<ListView
android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp" />
<LinearLayout
android:id="#+id/layout_bottom_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="-40dp" />
In fact the marginBottom will reserve 40dp for the layouts below ListView, so your ListView would not cover the whole screen like before.
I had a problem that stems from the fact that Android has certain difficulty with nested scrolling elements.
I have a ScrollView that hosts a horizontal RecyclerView and an ExpandableListView just beneath it.
The issue I encountered was that the ScrollView didn't scroll.
I fixed it by :
1. setting fixed height to the RecyclerView.
2. calculating the ExpandableListView height with each group item click.
Like this:
expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
setListViewHeight(parent, groupPosition);
return false;
}
});
private void setListViewHeight(ExpandableListView listView, int group) {
ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),View.MeasureSpec.EXACTLY);
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View groupItem = 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 (int j = 0; j < listAdapter.getChildrenCount(i); j++)
{
View listItem = listAdapter.getChildView(i, j, false, null,listView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
}
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight + (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1));
if (height < 10)
height = 200;
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
}
Problem :
since I calculate the listview height only on group item click, when I just open the fragment and up until I click on a group item, the ScrollView doesn't work.
I have found that calculating the height of the ExpandableListView adapter in onCreateView is problematic since it is still empty at that point.
Any ideas would be much apreciated.
If you need to wait until the view has been laid out, you can use
a ViewTreeObserver. For example :
protected void onCreate(Bundle savedInstanceState) {
...
final View someView = findViewById(R.id.some_id);
someView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
// the values are now available
int mesuredHeight = someView.getMeasuredHeight();
int height = someView.getHeight();
// done, remove the observer
someView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
...
}
I have 3 components in my layout ListView, EditText, Button.
When the user enters text in the edittext and hits the Button, the app makes an Api call, my just added text is added to an existing list,and fetches the list of items. Now, my issue is that that the api call is successful and I get the list with my new item properly. But when I show it in the listview, the first item in the ListView is never visible. The text I add after the first text are visible properly, even if I have a list of 10 or more items, the first item never shows. Also, Iam showing the listview and other components inside a scrollview to take full length.
Here is my code:-
public class ItemListAdapter : BaseAdapter
{
public ItemListAdapter(Activities.Detail detail, List<Models.ListOfItems> itemList)
{
// TODO: Complete member initialization
this.detail = detail;
this.itemList = itemList;
inflater = detail.LayoutInflater;
}
public override int Count
{
get { return itemList.Count; }
}
public override Java.Lang.Object GetItem(int position)
{
return position;
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = inflater.Inflate(Resource.Layout.item_row_layout, null);
}
txtAuthorName = convertView.FindViewById<TextView>(Resource.Id.txtCommentAuthor);
txtItemName = convertView.FindViewById<TextView>(Resource.Id.txtTime);
txtItemDate = convertView.FindViewById<TextView>(Resource.Id.txtItemDate);
var mData = itemList.ElementAt(position);
txtAuthorName.Text = mData.AuthorDisplayName;
txtItemName.Text = DateTime.Parse(mData.DateUpdated).ToString("dd MMMM yyyy", CultureInfo.InvariantCulture);
txtItemDate.Text = mData.Text;
return convertView;
}
}
Code for listview to take full height :-
public static void SetListViewHeightBasedOnChildren(ListView listView)
{
IListAdapter listAdapter = listView.Adapter;
if (listAdapter == null)
return;
int desiredWidth = Android.Views.View.MeasureSpec.MakeMeasureSpec(listView.Width, MeasureSpecMode.Unspecified);
int totalHeight = 0;
View view = null;
for (int i = 0; i < listAdapter.Count; i++)
{
view = listAdapter.GetView(i, view, listView);
if (i == 0)
view.LayoutParameters = new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WrapContent);
totalHeight += view.MeasuredHeight;
view.Measure(desiredWidth, totalHeight);
}
ViewGroup.LayoutParams param = listView.LayoutParameters;
param.Height = totalHeight + (listView.DividerHeight * (listAdapter.Count - 1));
listView.LayoutParameters = param;
listView.RequestLayout();
}
Try the below code may be its because of divider height. Have you defined custom height for divider in your listview?.
/**
* Sets ListView height dynamically based on the height of the items.
*
* #param listView to be resized
*
*/
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
float singleViewHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
singleViewHeight = listItem.getMeasuredHeight();
}
// Get total height of all item dividers.
int totalDividersHeight = listView.getDividerHeight() *
(listAdapter.getCount() - 1);
// Set list height
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + totalDividersHeight + (Math.round(singleViewHeight / 2));
listView.setLayoutParams(params);
listView.requestLayout();
}
I have few contents follwed by Expandable listview.I am not able to scroll the entire layout.
I have been searching for appropriate answer more than a week..Suggest some answers.
This solution worked for me, when i used custom layout inside navigation view having scroll view with LinearLayout which has Expandable listview.
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header">
<ScrollView
android:fillViewport="true"
android:layout_marginTop="130dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="#+id/homeLayout"
android:clickable="true"
android:gravity="center_vertical"
android:background="#drawable/layout_click_effect"
android:layout_width="match_parent"
android:layout_height="45dp">
<ImageView
android:id="#+id/homeIv"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:src="#mipmap/ic_home_black_24dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Home" />
</LinearLayout>
<View
android:background="#android:color/darker_gray"
android:layout_width="match_parent"
android:layout_height="1dp"/>
<ExpandableListView
android:id="#+id/topCatgExpLv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:groupIndicator="#null"
android:dividerHeight="1dp" />
</ScrollView>
</android.support.design.widget.NavigationView>
In your onCreate
mListView = (ExpandableListView) findViewById(R.id.activity_expandable_list_view);
MyExpandableListAdapter adapter = new MyExpandableListAdapter(this,
mGroups);
mListView.setAdapter(adapter);
mListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
setListViewHeight(parent, groupPosition);
return false;
}
});
private void setListViewHeight(ExpandableListView listView, int group) {
ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.EXACTLY);
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View groupItem = 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 (int j = 0; j < listAdapter.getChildrenCount(i); j++) {
View listItem = listAdapter.getChildView(i, j, false, null,
listView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
//Add Divider Height
totalHeight += listView.getDividerHeight() * (listAdapter.getChildrenCount(i) - 1);
}
}
//Add Divider Height
totalHeight += listView.getDividerHeight() * (listAdapter.getGroupCount() - 1);
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1));
if (height < 10)
height = 200;
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
}
you can do this very simple . set your height of scroll view to wrap_content. set your height of root view inside scroll view as wrap_content (such as linear layout) and set your expandable list view to wrap_content. after that set OnGroupExpandListener and OnGroupCollapseListener for your expandable list view and set height for that as long as child of expandable list view. like this code :
your layout :
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollViewDrawer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#color/mainGray"
>
<ExpandableListView
android:id="#+id/expandableListCategory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
</ScrollView>
and this is your fragment: (or in your activity)
public class DrawerFragment extends Fragment implements, OnGroupExpandListener, OnGroupCollapseListener{
ScrollView scrollView;
ExpandableListView expListView;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view rootView = inflater.inflate(R.layout.fragment_layout, container, false);
scrollView = (ScrollView) rootView.findViewById(R.id.scrollViewDrawer);
expListView = (ExpandableListView) rootView.findViewById(R.id.expandableListCategory);
....
}
#Override
public void onGroupExpand(int groupPosition) {
LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) expListView.getLayoutParams();
param.height = (childCount * expListView.getHeight());
expListView.setLayoutParams(param);
expListView.refreshDrawableState();
scrollView.refreshDrawableState();
}
#Override
public void onGroupCollapse(int groupPosition) {
LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) expListView.getLayoutParams();
param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
expListView.setLayoutParams(param);
expListView.refreshDrawableState();
scrollView.refreshDrawableState();
}
I know the question is pretty old, but may be it will be helpful for someone. Basically my answer is some what a combination of the answers of Amit Tumkur and user2141833. After a lot of trial and error, the following code is working for me:
First calculating the initial height of the Expandable list view i.e. when the whole thing is collapsed
for (Integer i = 0; i < mAdapter.getGroupCount(); i++) {
View groupItem = mAdapter.getGroupView(i, false, null, mExpandableListView);
groupItem.measure(mExpandableListView.getWidth(), View.MeasureSpec.UNSPECIFIED);
mInitialHeight += groupItem.getMeasuredHeight();
}
Then when the group is clicked set the height of the Expandable List view to Wrap Content
mExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
//Other Expansion/Collapsing Logic
setListHeightToWrap();
return true;
}
});
setListHeightToWrap is a different method:
private void setListHeightToWrap() {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mExpandableListView.getLayoutParams();
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
mExpandableListView.setLayoutParams(params);
mExpandableListView.refreshDrawableState();
mScrollView.refreshDrawableState();
}
Then in OnGroupExpandListener set the height of the Expandable List View as:
mExpandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mStitchingWorksListView.getLayoutParams();
//The Logic here will change as per your requirements and the height of each of the children in the group
if (mAdapter.getRealChildrenCount(groupPosition) > 6) {
params.height = 9 * mInitialHeight;
} else {
params.height = 6 * mInitialHeight;
}
//For Last Group in the list and the number of children were less as compared to other groups
if (groupPosition == mAdapter.getGroupCount() - 1) {
params.height = 3 * mInitialHeight;
}
mExpandableListView.setLayoutParams(params);
mExpandableListView.refreshDrawableState();
}
});
Also the layout was ExpandableListView inside LinearLayout inside ScrollView.
Hope this helps someone. :)
Firstly I suppose you are not using more than one child layout inside a scroll view, as a scroll view can have only one direct child.
Secondly you should not use any scrolling component like expandable list, inside a scroll view
here's why ListView inside ScrollView is not scrolling on Android.
For users who are looking for expandable listview into scrollview, use views instead of expandable list follow the below link & code-
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/linear_listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
And In Java Class some thing like this-
for (int i = 0; i < pProductArrayList.size(); i++) {
LayoutInflater inflater = null;
inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View mLinearView = inflater.inflate(R.layout.row_first, null);
final TextView mProductName = (TextView) mLinearView.findViewById(R.id.textViewName);
final RelativeLayout mLinearFirstArrow=(RelativeLayout)mLinearView.findViewById(R.id.linearFirst);
final ImageView mImageArrowFirst=(ImageView)mLinearView.findViewById(R.id.imageFirstArrow);
final LinearLayout mLinearScrollSecond=(LinearLayout)mLinearView.findViewById(R.id.linear_scroll);
if(isFirstViewClick==false){
mLinearScrollSecond.setVisibility(View.GONE);
mImageArrowFirst.setBackgroundResource(R.drawable.arw_lt);
}
else{
mLinearScrollSecond.setVisibility(View.VISIBLE);
mImageArrowFirst.setBackgroundResource(R.drawable.arw_down);
}
mLinearFirstArrow.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(isFirstViewClick==false){
isFirstViewClick=true;
mImageArrowFirst.setBackgroundResource(R.drawable.arw_down);
mLinearScrollSecond.setVisibility(View.VISIBLE);
}else{
isFirstViewClick=false;
mImageArrowFirst.setBackgroundResource(R.drawable.arw_lt);
mLinearScrollSecond.setVisibility(View.GONE);
}
return false;
}
});
Enter the code below adapteSet
enter code hereListAdapter listAdapter = listView.getAdapter();
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
Plese, try this once.
1) Add this line setExpandableListViewHeight(expandableListViewCategories) right after setting your adapter.
expandableListCategoriesAdapter = new ExpandableListCategoriesAdapter(getActivity(), listDataHeader, listDataChild);
expandableListViewCategories.setAdapter(expandableListCategoriesAdapter);
expandableListCategoriesAdapter.notifyDataSetChanged();
setExpandableListViewHeight(expandableListView);
2) Coppy the bellow content and past it in to setExpandableListViewHeight() method.
private void setExpandableListViewHeight(ExpandableListView listView) {
try {
ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
int totalHeight = 0;
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View listItem = listAdapter.getGroupView(i, false, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight + (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1));
if (height < 10) height = 200;
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
scrollBody.post(new Runnable() {
public void run() {
scrollBody.fullScroll(ScrollView.FOCUS_UP);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
Note: This will automatically bring down your ExpandableListView and you can scroll with full view.
After trying too many solutions,i had combined two solutions any it's work properly menuHeight is important.
expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
LinearLayout.LayoutParams param = (LinearLayout.LayoutParams)
expandableListView.getLayoutParams();
param.height = (2 * menuHeight); //adjust 2 according to you
expandableListView.setLayoutParams(param);
expandableListView.refreshDrawableState();
findViewById(R.id.sv_menu).refreshDrawableState();
}
});
static int menuHeight =0; // declare globally
public static void setListViewHeightBasedOnChildren(ExpandableListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) return;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.UNSPECIFIED);
int totalHeight = 0;
View view = null;
for (int i = 0; i < listAdapter.getCount(); i++) {
view = listAdapter.getView(i, view, listView);
if (i == 0) view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += view.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
menuHeight = totalHeight;}
Starting from API Level 21 (Lollipop) nested scroll containers are officially supported by Android SDK. There're a bunch of methods in View and ViewGroup classes which provide this functionality. To make nested scrolling work on the Lollipop you have to enable it for a child scroll view by adding android:nestedScrollingEnabled="true" to its XML declaration or by explicitly calling setNestedScrollingEnabled(true).
i have ExpandableListview inside ScrollView and i know that's not good but i had too, the only solution to show the whole list is by set its height by code using layoutParams
RelativeLayout.LayoutParams params = new
RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT,
ListViewData.length());
this solution is good but i can't figure the right height that i should give in the Params, SO is there a way to know the actual size from the size of the array
Edit:
i came up with a solution that everytime i expand a group of the list am gonna change the height to fit with new geight
try this, Use Child based on listview. setListViewHeightBasedOnChildren() this will set your listview child based height
public class Utils {
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
}
Your ListView is effectively unneeded in this case. You can as well loop over your adapter's items and just add them to a vertical LinearLayout inside your ScrollView.
In case you do not want to change a lot of code:
Replace ListView.setAdapter with
LinearLayout ll; //this should be the vertical LinearLayout that you substituted the listview with
for(int i=0;i<adapter.getCount();i++) {
View v = adapter.getView(position, null, null);
ll.addView(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
}
If you already use an OnItemClickListener add after View v = adapter.getView(position, null, null); the following
final int position = i;
v.setOnClickListener(new OnClickListener() {
public onClick(View v) {
yourOnItemClickListener.onItemClick(null, v, position, 0);
}
});
In this case you do not have to worry about any miscalculation in the height.
Try this, it works for my same problem
public static boolean setListViewHeightBasedOnItems(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter != null) {
int numberOfItems = listAdapter.getCount();
// Get total height of all items.
int totalItemsHeight = 0;
for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
View item = listAdapter.getView(itemPos, null, listView);
item.measure(0, 0);
totalItemsHeight += item.getMeasuredHeight();
}
// Get total height of all item dividers.
int totalDividersHeight = listView.getDividerHeight() *
(numberOfItems - 1);
// Set list height.
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalItemsHeight + totalDividersHeight;
listView.setLayoutParams(params);
listView.requestLayout();
return true;
} else {
return false;
}}
requestLayout() method is called on the view because something has changed that invalidated its layout - forces redrawing.
you can set a variable in dimensions file for different screen sizes and then multiply it by the number of items of list you want to display.