I need an ExpandableList in my Android app. By extending ExpandableListActivity whose content view is as the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ExpandableListView
android:id="#id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<TextView
android:id="#+id/tv_add"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/txt_add" />
</LinearLayout>
and extending BaseExpandableListAdapter I am now able to display data of groups and children in a TextView.
However, I want to customize the view of children. How may I be able to do so through another xml file?
EDIT:
Here's my row.xml for the view of children:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/title"
android:textSize="16sp"
android:textStyle="bold"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
/>
<TextView
android:id="#+id/description"
android:textSize="10sp"
android:textStyle="normal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
/>
</LinearLayout>
Create two layout xml files for Group and Child views respectively -
For example, *group_layout.xml* and *child_layout.xml*
These layouts are inflated and used in the custom ExpandableListAdapter as shown below.
You can customize the Adapter class and set that adapter to the ExpandableListView.
public class SampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
ExpandableListView listView = (ExpandableListView) findViewById(R.id.listView);
ExpandableListAdapter adapter = new ExpandableListAdapter(this, new ArrayList<String>(), new ArrayList<ArrayList<Vehicle>>());
// Set this adapter to the list view
listView.setAdapter(adapter);
}
}
Custom Adapter class can be created as shown below:
class ExpandableListAdapter extends BaseExpandableListAdapter {
public ExpandableListAdapter(Context context, ArrayList<String> groups,
ArrayList<ArrayList<Vehicle>> children) {
this.context = context;
this.groups = groups;
this.children = children;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return children.get(groupPosition).get(childPosition);
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
// Return a child view. You can load your custom layout here.
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
Vehicle vehicle = (Vehicle) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.child_layout, null);
}
TextView tv = (TextView) convertView.findViewById(R.id.tvChild);
tv.setText(" " + vehicle.getName());
return convertView;
}
#Override
public int getChildrenCount(int groupPosition) {
return children.get(groupPosition).size();
}
#Override
public Object getGroup(int groupPosition) {
return groups.get(groupPosition);
}
#Override
public int getGroupCount() {
return groups.size();
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
// Return a group view. You can load your custom layout here.
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
String group = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.group_layout, null);
}
TextView tv = (TextView) convertView.findViewById(R.id.tvGroup);
tv.setText(group);
return convertView;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public boolean isChildSelectable(int arg0, int arg1) {
return true;
}
}
Hope this helps you.
Thx to PRC, but according to my row.xml, the correct version of getChildView would be
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
LinearLayout layout;
Vehicle vehicle = (Vehicle) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (LinearLayout) infalInflater.inflate(R.layout.child_layout, null);
}
TextView tv = (TextView) convertView.findViewById(R.id.tvChild);
tv.setText(" " + vehicle.getName());
return layout;
}
Related
I implement an ExpandableList in my app.
when i finish it work totally wrong.
List have only one row and in it display child data in row title view,
Here is my code :
My list adpater :
public class JoinUsAdapter extends BaseExpandableListAdapter {
public static final String DESCRIPTION_TG = "description";
public static final String TITLE_TG = "title";
private Context mContext;
private List<Map<String, String>> mData;
private LayoutInflater inflater;
private ViewHolder vholder;
public JoinUsAdapter(Context context, List<Map<String, String>> data) {
this.mContext = context;
this.mData = data;
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getGroupCount() {
return mData.size();
}
#Override
public int getChildrenCount(int groupPosition) {
return 1;
}
#Override
public Map<String , String> getGroup(int groupPosition) {
return mData.get(groupPosition);
}
#Override
public String getChild(int groupPosition, int childPosition) {
return mData.get(groupPosition).get(DESCRIPTION_TG);
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return 1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_title_join_us, null);
vholder = new ViewHolder();
vholder.txtTitle = (TextView) convertView.findViewById(R.id.txtNewsTitle);
vholder.txtShortDesc = (TextView) convertView.findViewById(R.id.txtNewsShortDesc);
convertView.setTag(vholder);
}
else {
vholder = (ViewHolder) convertView.getTag();
}
Map item = getGroup(groupPosition);
vholder.txtTitle.setText(item.get(TITLE_TG).toString());
vholder.txtTitle.setText(truncate(item.get(DESCRIPTION_TG).toString(),35)+" ...");
return convertView;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_detail_join_us, null);
}
TextView txtLongDesc =(TextView) convertView.findViewById(R.id.txtLongDescription);
txtLongDesc.setText(getChild(groupPosition,childPosition));
return convertView;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
And here is my Layouts :
title(as list row view) :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/txtNewsTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TITLE"
android:textStyle="bold"
android:textColor="#color/white"/>
<TextView
android:id="#+id/txtNewsShortDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="news description news description news description news description"
android:textStyle="bold"
android:textColor="#color/white"/>
</LinearLayout>
Detail: (as child of rows)
<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/txtLongDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#color/white"
android:text="long description long description long description long description long description long description "/>
</LinearLayout>
I cant find where is my mistake :/
Update:
My method for create fake data :
public void getData() {
dataList = new ArrayList<Map<String, String>>();
Map<String, String> item = new HashMap<String, String>();
String fake = "We asked respondents how satisfied they are with their current job or jobs. 76% of developers report being at least satisfied with their job, and 36% love their job. Developers are generally more fulfilled by work than most employees.\n" +
"\n" +
"And developers in Iran are more satisfied with their jobs than developers anywhere else. Stack Overflow Careers may not have any jobs available in Iran, but you can still move there and apply for one of our many available remote jobs.";
for(int i=0; i<10; i++) {
item.put(JoinUsAdapter.TITLE_TG,"Title "+i);
item.put(JoinUsAdapter.DESCRIPTION_TG,fake);
dataList.add(item);
}
So, I created a custom ExpandableListAdapter because I wanted an expandable list capable of having multiple children, essentially a two-tiered list. It's been working perfectly fine, as long as it was the first and only View in the Activity. However, I recently added some other Views (a set of TextViews) to the LinearLayout it's in, and all of a sudden it's stopped displaying at all, without giving any errors.
First, I'm wondering if it is, for some reason, required to be the first/only view in the Activity, and if so, if there's any way of getting around that. Code is below.
expListView = (ExpandableListView) this.findViewById(R.id.finalcalculation_list_view);
final ExpandableListAdapter expListAdapter = new ExpandableListAdapter(
this, groupList, totalCollection);
expListView.setAdapter(expListAdapter);
<?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:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<!-- Here are some TextViews -->
</LinearLayout>
<ScrollView android:id="#+id/finalcalculation_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ExpandableListView
android:id="#+id/finalcalculation_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ExpandableListView>
</ScrollView>
</LinearLayout>
Here is how it was originally, when it was last working:
<?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:orientation="vertical" >
<ExpandableListView
android:id="#+id/finalcalculation_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ExpandableListView>
</LinearLayout>
And here is the unfortunately large code-dump of my ExpandableListAdapter.
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Activity context;
private Map<String, List<String>> collections;
private List<String> groups;
public ExpandableListAdapter(Activity context, List<String> groups,
Map<String, List<String>> collections) {
this.context = context;
this.collections = collections;
this.groups = groups;
}
public Object getChild(int groupPosition, int childPosition) {
return collections.get(groups.get(groupPosition)).get(childPosition);
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String laptop = (String) getChild(groupPosition, childPosition);
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.finalcalculation_child_item, null);
}
TextView item = (TextView) convertView.findViewById(R.id.finalcalculation_child_item_textview);
item.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Do you want to remove?");
builder.setCancelable(false);
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
List<String> child =
collections.get(groups.get(groupPosition));
child.remove(childPosition);
notifyDataSetChanged();
}
});
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
});
item.setText(laptop);
return convertView;
}
public int getChildrenCount(int groupPosition) {
return collections.get(groups.get(groupPosition)).size();
}
public Object getGroup(int groupPosition) {
return groups.get(groupPosition);
}
public int getGroupCount() {
return groups.size();
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String itemName = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater groupInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = groupInflater.inflate(R.layout.finalcalculation_group_item, null);
}
TextView item = (TextView) convertView.findViewById(R.id.finalcalculation_group_item_textview);
item.setTypeface(null, Typeface.BOLD);
item.setText(itemName);
return convertView;
}
public boolean hasStableIds() {
return true;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
I've tried changing the Inflators for both getChildView and getGroupView from
convertView = inflater.inflate(R.layout.finalcalculation_child_item, null);
to both
convertView = inflater.inflate(R.layout.finalcalculation_child_item, parent, false); //AND
convertView = inflater.inflate(R.layout.finalcalculation_child_item, parent, true); //AND
But it either doesn't work, or throws an error.
All help and input greatly appreciated.
The layout_height of the nested LinearLayout is set to match_parent, which causes the nested LinearLayout to be the same height of the parent LinearLayout and hides the ScrollView. It should be something like wrap_content or a fixed size. Also, you don't need a ScrollView.
Try something like this:
<?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:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<!-- Here are some TextViews -->
</LinearLayout>
<ExpandableListView
android:id="#+id/finalcalculation_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ExpandableListView>
</LinearLayout>
I need to use Android ExpandableListView with custom layout for each group(groups have one child). To accomplish this, I've created a class which extends BaseExpandableListAdapter. On the getChildView method, I've created the view of each child. It works. When I click a group, its child comes with true layout. However, during the debuging, I see that it triggers getchildview method many times, so it is too slow to display child. Because there are a lot of operations on each child (db operations, dynamic sub layouts...).
There are a small project, which similar to my project(Logic and code structure are same, only layout code and code of creating each child view are different).
public class MainActivity extends Activity {
private ArrayList<String> groups;
private ArrayList<ArrayList<ArrayList<String>>> childs;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExpandableListView l = (ExpandableListView)findViewById(R.id.expandableListView1);
loadData();
final myExpandableAdapter adapter = new myExpandableAdapter(this, groups, childs);
l.setAdapter(adapter);
}
public class myExpandableAdapter extends BaseExpandableListAdapter {
private ArrayList<String> groups;
private ArrayList<ArrayList<ArrayList<String>>> children;
private Context context;
public myExpandableAdapter(Context context, ArrayList<String> groups, ArrayList<ArrayList<ArrayList<String>>> children) {
this.context = context;
this.groups = groups;
this.children = childs;
}
#Override
public boolean areAllItemsEnabled()
{
return true;
}
public ArrayList<String> getChild(int groupPosition, int childPosition) {
return children.get(groupPosition).get(childPosition);
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,View convertView, ViewGroup parent) {
String child=(String)getChild(groupPosition, childPosition).get(0);
switch (groupPosition){
case 0:
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_row, null);
TextView tvPlayerName = (TextView) convertView.findViewById(R.id.tvPlayerName);
tvPlayerName.setText(child);
break;
case 1:
LayoutInflater inflater1 = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater1.inflate(R.layout.child_row1, null);
TextView tvPlayerName1 = (TextView) convertView.findViewById(R.id.tvPlayerName);
tvPlayerName1.setText(child);
Button btn=(Button)convertView.findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
TextView tv=(TextView)findViewById(R.id.tv);
tv.setText("Clicked");
}
});
break;
case 2:
LayoutInflater inflater2 = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater2.inflate(R.layout.child_row1, null);
TextView tvPlayerName12 = (TextView) convertView.findViewById(R.id.tvPlayerName);
tvPlayerName12.setText(child);
Button btn2=(Button)convertView.findViewById(R.id.button1);
btn2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
TextView tv=(TextView)findViewById(R.id.tv);
tv.setText("Clicked");
}
});
break;
}
return convertView;
}
public int getChildrenCount(int groupPosition) {
return children.get(groupPosition).size();
}
public String getGroup(int groupPosition) {
return groups.get(groupPosition);
}
public int getGroupCount() {
return groups.size();
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String group = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.expandablelistview_group, null);
}
TextView grouptxt = (TextView) convertView.findViewById(R.id.TextViewGroup);
grouptxt.setText(group);
return convertView;
}
public boolean hasStableIds() {
return true;
}
public boolean isChildSelectable(int arg0, int arg1) {
return true;
}
}
private void loadData(){
groups= new ArrayList<String>();
childs= new ArrayList<ArrayList<ArrayList<String>>>();
groups.add("Group 1");
groups.add("Group 2");
groups.add("Group 3");
childs.add(new ArrayList<ArrayList<String>>());
childs.get(0).add(new ArrayList<String>());
childs.get(0).get(0).add("Child 1 group 1");
childs.add(new ArrayList<ArrayList<String>>());
childs.get(1).add(new ArrayList<String>());
childs.get(1).get(0).add("Child 1 group 2");
childs.add(new ArrayList<ArrayList<String>>());
childs.get(2).add(new ArrayList<String>());
childs.get(2).get(0).add("Child 1 group 3");
}}
During debugging, If I click any group, it comes to String child=(String)getChild(groupPosition, childPosition).get(0); line. After break; }return convertView;, it comes to there again and again, and then it displays layout.
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" >
<ExpandableListView
android:id="#+id/expandableListView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="34dp" >
</ExpandableListView>
expandablelistview_group.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/TextViewGroup"
android:layout_width="wrap_content"
android:layout_height="50px"
android:layout_marginLeft="50px"
android:gravity="center_vertical"
>
</TextView>
child_row.xml
<?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:orientation="vertical" >
<TextView
android:id="#+id/tvPlayerName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox" />
childrow1.xml
<?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:orientation="horizontal" >
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Row1" />
<TextView
android:id="#+id/tvPlayerName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
Is there any suggestion to solve this.
Thanks
instead of inflating the view from getChildView use Holder read here
Try changing your ExpandableListView xml and instead of android:layout_height="wrap_content", put android:layout_height="fill_parent"
I am using Expandable ListView example found on net
Activity:
public class ExpandableListViewActivity extends ExpandableListActivity {
/**
* strings for group elements
*/
static final String arrGroupelements[] = { "India", "Australia", "England",
"South Africa" };
/**
* strings for child elements
*/
static final String arrChildelements[][] = {
{ "Sachin Tendulkar", "Raina", "Dhoni", "Yuvi" },
{ "Ponting", "Adam Gilchrist", "Michael Clarke" },
{ "Andrew Strauss", "kevin Peterson", "Nasser Hussain" },
{ "Graeme Smith", "AB de villiers", "Jacques Kallis" } };
DisplayMetrics metrics;
int width;
ExpandableListView expList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
expList = getExpandableListView();
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
width = metrics.widthPixels;
// this code for adjusting the group indicator into right side of the
// view
expList.setIndicatorBounds(width - GetDipsFromPixel(50), width
- GetDipsFromPixel(10));
expList.setAdapter(new ExpAdapter(this));
expList.setOnGroupExpandListener(new OnGroupExpandListener() {
public void onGroupExpand(int groupPosition) {
Log.e("onGroupExpand", "OK");
}
});
expList.setOnGroupCollapseListener(new OnGroupCollapseListener() {
public void onGroupCollapse(int groupPosition) {
Log.e("onGroupCollapse", "OK");
}
});
expList.setOnChildClickListener(new OnChildClickListener() {
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
Log.e("OnChildClickListener", "OK");
return false;
}
});
}
public int GetDipsFromPixel(float pixels) {
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
return (int) (pixels * scale + 0.5f);
}
}
Adapter:
public class ExpAdapter extends BaseExpandableListAdapter {
private Context myContext;
public ExpAdapter(Context context) {
myContext = context;
}
public Object getChild(int groupPosition, int childPosition) {
return null;
}
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) myContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_row, null);
}
TextView tvPlayerName = (TextView) convertView
.findViewById(R.id.tvPlayerName);
tvPlayerName
.setText(ExpandableListViewActivity.arrChildelements[groupPosition][childPosition]);
return convertView;
}
public int getChildrenCount(int groupPosition) {
return ExpandableListViewActivity.arrChildelements[groupPosition].length;
}
public Object getGroup(int groupPosition) {
return null;
}
public int getGroupCount() {
return ExpandableListViewActivity.arrGroupelements.length;
}
public long getGroupId(int groupPosition) {
return 0;
}
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) myContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.group_row, null);
}
TextView tvGroupName = (TextView) convertView
.findViewById(R.id.tvGroupName);
tvGroupName
.setText(ExpandableListViewActivity.arrGroupelements[groupPosition]);
return convertView;
}
public boolean hasStableIds() {
return false;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
main.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ExpandableListView
android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:groupIndicator="#drawable/group_indicator" >
<TextView
android:id="#+id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="No Items" >
</TextView>
</ExpandableListView>
</LinearLayout>
I tried this solution, but didn't work :(
Android: Custom ListAdapter extending BaseAdapter crashes on application launch
there its told to add a third parameter "false", to the inflater.inflate(R.layout.group_row, null, false);
Move the TextView outside the ExpandableListView element:
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ExpandableListView
android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:groupIndicator="#drawable/group_indicator" >
</ExpandableListView>
<TextView
android:id="#+id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="No Items" >
</TextView>
</LinearLayout>
Subclasses of AdapterView(like ExpandableListView) can't have children in a xml layout(like you did in your layout).
If you're like me and found this question without using ExpandableListView, try using adding the third parameter to the inflate method, as #Luksprog mentions, also mentioned here:
inflater.inflate(R.layout.group_row, parent, false);
Don't use true instead of false or you will get the same error that brought you here, because it's trying to attach/add it to the parent, hence the addView is not supported in AdapterView error.
I'm trying to write a simple example which pulls external data over the network and populates an ExpandableListView via a ExpandableListAdapter. I've tried a couple examples and am pretty much lost. I'm familiar with working with the ArrayAdapter class, but it seems that ExpandableListAdapter is WAY different. Here is my current application code that is displaying nothing:
MyExpandableListAdapter:
public class MyExpandableListAdapter extends BaseExpandableListAdapter {
public static class GroupHolder {
TextView title;
}
public static class ChildHolder {
TextView title;
ImageView icon;
}
// groups.getChildren() returns the children
private List<Group> groups;
private Context context;
private LayoutInflater inflater;
public MyExpandableListAdapter(Context context, List<Group> groups) {
this.context = context;
this.groups = groups;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public boolean hasStableIds() {
return true;
}
public Object getGroup(int groupPosition) {
return groups.get(groupPosition);
}
public int getGroupCount() {
return groups.size();
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
GroupHolder holder;
if (convertView != null) {
holder = (GroupHolder)convertView.getTag();
} else {
convertView = inflater.inflate(R.layout.group_item, parent, false);
holder = new GroupHolder();
holder.title = (TextView) convertView.findViewById(R.id.group_item_title);
convertView.setTag(holder);
}
holder.title.setText(this.groups.get(groupPosition).getName());
return convertView;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public Object getChild(int groupPosition, int childPosition) {
return groups.get(groupPosition).getChildren().get(childPosition);
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public int getChildrenCount(int groupPosition) {
return groups.get(groupPosition).getChildren().size();
}
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
ChildHolder holder;
if (convertView != null) {
holder = (ChildHolder) convertView.getTag();
} else {
convertView = inflater.inflate(R.layout.child_item, parent, false);
holder = new ChildHolder();
holder.title = (TextView) convertView.findViewById(R.id.child_item_title);
holder.icon = (ImageView) convertView.findViewById(R.id.child_item_icon);
convertView.setTag(holder);
}
holder.title.setText(groups.get(groupPosition).getChildren().get(childPosition).getName());
// TODO add in image loading.
return convertView;
}
}
MyExpandableListActivity:
public class MyExpandableListActivity extends ExpandableListActivity {
private List<Group> groups;
private ExpandableListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.group_list);
this.groups = new ArrayList<Group>();
Group group = new Group("$1", "Colors");
Child child = new Child("$2", "Red");
groups.getChildren().add(child);
this.adapter = new MyExpandableListAdapter(this, groups);
setListAdapter(this.adapter);
}
}
R.layout.group_list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ExpandableListView android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<TextView android:id="#+id/android:empty"
android:text="EMPTY! DOOM!"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
R.layout.group_item:
<?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">
<TextView android:id="#+id/group_item_title"/>
</LinearLayout>
R.layout.child_item:
<?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:orientation="horizontal">
<ImageView android:id="#+id/child_item_icon"
android:layout_width="48px" android:layout_height="48px"/>
<TextView android:id="#+id/child_item_title"/>
</LinearLayout>
I, of course, am seeing "EMPTY! DOOM!" rather than the list item I added in my activity. What am I doing wrong?
Also, it seems that the SimpleExpandableListAdapter is supposed to make things easy, but I totally can't figure out how it works or how to use it. Can anyone help me figure this out?
I got bit this week with two items trying to use "fill_parent" at the same time and in the same space. It's possible your list is being shoved to the back or off screen. I see you have a simlar setup in your group_list layout. Hope that helps with the invisible list piece.
What about changing the LinearLayout to have a vertical orientation in your group_list.xml?
It doesn't quite match the layout given in the ExpandableListActivity docs.
You can also set breakpoints in places like your getView() method and see if it's being called at all.