Reputation: 41
I want to use ExpandableListView inside ScrollView with other views but i faced the problem of self scroller in ExpandableListView l tried to disable it but the problem is with the height of the ExpandableListView and the layout it's inside. So i want to
I googled a solution and i found one for that works for ListView only
I want to make the same workout but with ExpandableListView (with custom Adapter).
Here is My Code: MainActivity.java
package fablabegypt.android.expandablelistview2;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends ActionBarActivity {
mListAdapter listAdapter;
ExpandableListView expListView;
LinearLayout linearLayout;
List<String> listDataHeader;
HashMap<String, List<String>> listDataChild;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
linearLayout = (LinearLayout) findViewById(R.id.linear_holder);
prepareListData();
expListView = (ExpandableListView) findViewById(R.id.expand_list);
//expListView.setScrollContainer(false);
expListView.setHorizontalScrollBarEnabled(false);
expListView.setVerticalScrollBarEnabled(false);
expListView.setFastScrollEnabled(false);
expListView.setSmoothScrollbarEnabled(false);
//expListView.setOverscrollHeader(null);
expListView.setFooterDividersEnabled(false);
//expListView.setOverscrollFooter(null);
//expListView.setVerticalFadingEdgeEnabled(false);
//expListView.setHorizontalFadingEdgeEnabled(false);
expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
return true;
}
});
expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if (parent.isGroupExpanded(groupPosition)) {
parent.collapseGroup(groupPosition);
} else {
parent.expandGroup(groupPosition);
}
//telling the listView we have handled the group click, and don't want the default actions.
return true;
}
});
expListView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
return false;
}else {
}
return true;
}
});
listAdapter = new mListAdapter(this, listDataHeader,listDataChild);
expListView.setAdapter(listAdapter);
}
private void prepareListData() {
listDataHeader = new ArrayList<String>();
listDataChild = new HashMap<String, List<String>>();
// Adding child data
listDataHeader.add("Top 250");
listDataHeader.add("Now Showing");
listDataHeader.add("Coming Soon..");
// Adding child data
List<String> top250 = new ArrayList<String>();
top250.add("The Shawshank Redemption");
top250.add("The Godfather");
top250.add("The Godfather: Part II");
top250.add("Pulp Fiction");
top250.add("The Good, the Bad and the Ugly");
top250.add("The Dark Knight");
top250.add("12 Angry Men");
List<String> nowShowing = new ArrayList<String>();
nowShowing.add("The Conjuring");
nowShowing.add("Despicable Me 2");
nowShowing.add("Turbo");
nowShowing.add("Grown Ups 2");
nowShowing.add("Red 2");
nowShowing.add("The Wolverine");
List<String> comingSoon = new ArrayList<String>();
comingSoon.add("2 Guns");
comingSoon.add("The Smurfs 2");
comingSoon.add("The Spectacular Now");
comingSoon.add("The Canyons");
comingSoon.add("Europa Report");
listDataChild.put(listDataHeader.get(0), top250); // Header, Child data
listDataChild.put(listDataHeader.get(1), nowShowing);
listDataChild.put(listDataHeader.get(2), comingSoon);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
mListAdapter.java
package fablabegypt.android.expandablelistview2;
import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.TextView;
import java.util.HashMap;
import java.util.List;
/**
* Created by Mouso on 4/27/2015.
*/
public class mListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> header_list;
private HashMap<String, List<String>> children_data_list;
public mListAdapter(Context context,List<String> header_list,HashMap<String,List<String>> children_data_list){
this.context = context;
this.header_list = header_list;
this.children_data_list = children_data_list;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
@Override
public int getGroupCount() {
return this.children_data_list.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return this.children_data_list.get(this.header_list.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPosition) {
return this.header_list.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.children_data_list.get(this.header_list.get(groupPosition)).get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
final String headerText = (String) getGroup(groupPosition);
if (convertView == null){
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_group,null);
}
TextView headerTxt = (TextView) convertView.findViewById(R.id.list_group_txt);
headerTxt.setTextSize(20);
headerTxt.setText(headerText);
//Log.d("Mouso",headerText);
return convertView;
}
@Override
public View getChildView(int groupPosition, 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_item,null);
}
TextView childTxt = (TextView) convertView.findViewById(R.id.list_child_txt);
childTxt.setText(childText);
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
@Override
public boolean areAllItemsEnabled() {
return true;
}
@Override
public boolean isEmpty() {
if (header_list.size() > 0)
return true;
return false;
}
@Override
public void onGroupExpanded(int groupPosition) {
}
@Override
public void onGroupCollapsed(int groupPosition) {
}
@Override
public long getCombinedChildId(long groupId, long childId) {
return (groupId*100)+childId;
}
@Override
public long getCombinedGroupId(long groupId) {
return groupId;
}
}
activity_main.xml
<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<ScrollView
android:layout_width="wrap_content"
android:layout_height="500px"
android:fillViewport="true">
<LinearLayout
android:id="@+id/linear_holder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="we 7yat 3neak we fadaha 3neya \n\n\n dana ba7ebak ad 3naya"/>
<ExpandableListView
android:id="@+id/expand_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:isScrollContainer="false">
</ExpandableListView>
</LinearLayout>
</ScrollView>
</RelativeLayout>
list_group.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/list_group_txt"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/list_child_txt"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
My Try for implmenting the workout
Helper.java
package fablabegypt.android.expandablelistview2;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ListAdapter;
import android.widget.ListView;
/**
* Created by Mouso on 4/29/2015.
*/
public class ListViewHelper {
public static void getListViewSize(ExpandableListView myListView) {
ListAdapter myListAdapter = myListView.getAdapter();
if (myListAdapter == null) {
//do nothing return null
return;
}
//set listAdapter in loop for getting final size
int totalHeight = 0;
for (int groupSize = 0; groupSize < myListAdapter.getGroupCount(); groupSize++) {
View listItem = myListAdapter.getGroupView(groupSize, false, null, myListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
for (int size = 0; size < myListAdapter.getChildrenCount(groupSize); size++) {
if (size == myListAdapter.getChildrenCount(groupSize)-1)
listItem = myListAdapter.getChildView(groupSize, size, true, null, myListView);
listItem = myListAdapter.getChildView(groupSize, size, false, null, myListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
}
//setting listview item in adapter
ViewGroup.LayoutParams params = myListView.getLayoutParams();
params.height = totalHeight + (myListView.getDividerHeight() * (myListAdapter.getGroupCount() - 1));
myListView.setLayoutParams(params);
// print height of adapter on log
Log.d("mouso", "height of listItem:"+String.valueOf(totalHeight));
}
//Read more: http://www.androidhub4you.com/2012/12/listview-into-scrollview-in-android.html#ixzz3Yh4m4MPG
}
Upvotes: 3
Views: 7754
Reputation: 963
I have same problemm
I solve this problem adding header and footer in ExpandableListView
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ExpandableListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ExpandableListView>
</LinearLayout>
</ScrollView>
/// add header
ExpandableListView listview
ViewGroup headerView = (ViewGroup) getLayoutInflater().inflate(R.layout.item_header, listview, false);
listview.addHeaderView(headerView_right);
*/// add footer*
ViewGroup footerview= (ViewGroup) getLayoutInflater().inflate(R.layout.item_footer, listview, false);
listview.addFooterView(headerView_right);
Upvotes: 3
Reputation: 1126
Extend the ExpandableListView class and set expand to false
public class CustomExpandableListView extends ExpandableListView {
boolean expanded = false;
public CustomExpandableListView (Context context) {
super(context);
}
public CustomExpandableListView (Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomExpandableListView (Context context, AttributeSet attrs,int defStyle) {
super(context, attrs, defStyle);
}
public boolean isExpanded() {
return expanded;
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isExpanded()) {
int expandSpec = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
}
In your activity class
CustomExpandableListView customExpandableListView = (CustomExpandableListView ) findViewById(R.id.expandable_list);
customExpandableListView .setExpanded(true);
Layout file
<com.xxx.xxx.util.ExpandableHeightListView
android:id="@+id/expandable_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Now It will work within a scroll view
Upvotes: 3
Reputation: 791
As I can see in your "activity_main.layout" I think you want to put the ExpandableListView to make the textview scroll always with the List, isn't it?
You have two solutions.
-The prettiest and easiest solution is to put the textview as a header of the ExpandableListView using
list.addHeaderView(listHeader,null,false);
important: Using "false" as the third the header can't be clicked as a row.
-The other solution is to call "getListViewSize()" every time you call "parent.collapseGroup(groupPosition)" or "parent.expandGroup(groupPosition);" I know using a listview inside a scrollview is not recommended but sometimes is useful. Unfortunately this isn't that case, I recommend to use the first solution.
I hope I could help you.
Upvotes: 1
Reputation: 657
It is ALWAYS a very bad idea to put a view that has it's own scrolling functionality inside another view with scrolling functionality. This can lead to touch actions being intercepted by the wrong view, poor performance, etc. Also, from your main layout, you don't seem to be using the ScrollView for anything other than making the TextView scroll with the list view. Why not add it as a header view? expListView.setHeaderView(View)
and inflate the textview into it.
Upvotes: 2