您的位置:首页 > 移动开发 > Android开发

Android笔记——ExpandableListV的使用和三级list的实现

2016-11-02 15:03 232 查看
写这篇的原因说起来很惭愧,面试的时候被问怎么实现二级list,我没接触过expandablelistview支支吾吾的回答用listview扩展getcount(),面试官说expandablelistview很基础的东西你都没用过,接着便是一些我也回答不上了的问题。。。

回归正题,ExpandableListView是用于实现二级listview的控件,其用法几乎和listview一样,在xml中添加,代码中获取id,实现适配器,设置适配器。不同的是,使用自定义ExpandableListView时所需设置的适配器的一些方法需要重写。这里以实现3级list作为一个例子。

首先是数据的准备,这里简单准备一下数据

<pre style="background-color:#1e1e1a;color:#a9b7c6;font-family:'Consolas';font-size:9.0pt;"><span style="color:#fd9720;">private </span><span style="color:#f63ce6;">Map</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#ea882f;">, </span><span style="color:#f63ce6;">Map</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#ea882f;">, </span><span style="color:#f63ce6;">List</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#fd9720;">>>> </span><span style="color:#58c5e7;">dataMap </span><span style="color:#fd9720;">= new </span><span style="color:#b4dc27;">HashMap</span><span style="color:#fd9720;"><></span><span style="color:#efefe8;">()</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f4005d;">String</span><span style="color:#efefe8;">[] </span><span style="color:#58c5e7;">str1 </span><span style="color:#fd9720;">= </span><span style="color:#f6f6ef;">{</span><span style="color:#e0d067;">"first"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"second"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"third"</span><span style="color:#f6f6ef;">}</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f4005d;">String</span><span style="color:#efefe8;">[] </span><span style="color:#58c5e7;">str2 </span><span style="color:#fd9720;">= </span><span style="color:#f6f6ef;">{</span><span style="color:#e0d067;">"1"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"2"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"3"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"4"</span><span style="color:#f6f6ef;">}</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f63ce6;">Map</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#ea882f;">, </span><span style="color:#f63ce6;">List</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#fd9720;">>> </span><span style="color:#58c5e7;">childMap </span><span style="color:#fd9720;">= new </span><span style="color:#b4dc27;">HashMap</span><span style="color:#fd9720;"><></span><span style="color:#efefe8;">()</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f63ce6;">List</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#fd9720;">> </span><span style="color:#58c5e7;">childList </span><span style="color:#fd9720;">= new </span><span style="color:#b4dc27;">ArrayList</span><span style="color:#fd9720;"><></span><span style="color:#efefe8;">()</span><span style="color:#fd9720;">;</span>Map嵌套,简单的放一下数据,然后是初始化数据
private void initData(){
childList.add("f1");
childList.add("f2");
childList.add("f3");
childMap.put(str2[0], childList);
childMap.put(str2[1], childList);
childMap.put(str2[2], childList);
childMap.put(str2[3], childList);
dataMap.put(str1[0], childMap);
dataMap.put(str1[1], childMap);
dataMap.put(str1[2], childMap);
}


最重要的来了,我们需要为自己的ExpandableListView写适配器,继承自BaseExpandableListAdapter
private class GroupExpandableListViewAdapter extends BaseExpandableListAdapter{

@Override
public Object getGroup(int parentPos){
return dataMap.get(str1[parentPos]);
}
@Override
public Object getChild(int parentPos, int childPos){
return dataMap.get(str1[parentPos]).get(childPos);
}

@Override
public int getGroupCount(){
return dataMap.size();
}

@Override
public int getChildrenCount(int parentPos){
return 1;
}

@Override
public long getGroupId(int parentPos){
return parentPos;
}

@Override
public long getChildId(int parentPos, int childPos){
return  childPos;
}

@Override
public boolean hasStableIds(){
return false;
}

@Override
public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){
if(view == null){
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.group_item, null);
}
view.setTag(R.layout.group_item, parentPos);
view.setTag(R.layout.child_item, -1);
TextView groupText = (TextView) view.findViewById(R.id.group_item);
groupText.setText(str1[parentPos]);
return view;

}

@Override
public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){
if(view == null){
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.child_listview, null);
}
view.setTag(R.layout.group_item, parentPos);
view.setTag(R.layout.child_item, childPos);

ChildExpandableListView childExpandableListView = (ChildExpandableListView) view.findViewById(R.id.child_listview);
ChildExpandableListViewAdapter childExpandableLVAdapter = new ChildExpandableListViewAdapter();
childExpandableListView.setAdapter(childExpandableLVAdapter);
return view;
}

@Override
public boolean isChildSelectable(int i, int i1){
return true;
}

}

这里解释一下,最重要的两个:getGroupView是获取list中父级内容的,第一层的父级很简单,只有一个TextView;

getChildView是获取list中子项内容的。想一下,由于要实现3级的list,第一季的list子项自然也是ExpandableListView,而且每一个父项里只有一个ExpandableListView。

在getChildView中获取到第二级的ExpandableListView,并且实现它的适配器(注意第一级和第二级的适配器类型是不一样的),并设置好适配器

需要注意的是,第一级中isChildSelectable的返回值一定要设为true,该方法是用于判断子项能否被点击的,我们实现3级菜单,所以必然要设为true。

所以这里getChildCount返回的子项个数是1,我们只需要一个ExpandableListView来表示子项内容,子项里具体的东西再交给下一级的getGroupView来实现。

这里我用了自定义的ChildExpandableListView,之所以自定义是因为,双层的ExpandableListView嵌套会使第一层子项的内容显示不全,百度后得知需要重绘他的高度,这里是ChildExpandableListView的代码:
public class ChildExpandableListView extends ExpandableListView {

public ChildExpandableListView(Context context) {
super(context);
}

public ChildExpandableListView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public ChildExpandableListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}


最后是第二级ExpandableListView,很简单,是普通的ExpandableListView的用法,父项只有一个TExtView,子项也只有一个TextView。
private class ChildExpandableListViewAdapter extends BaseExpandableListAdapter{

@Override
public Object getGroup(int parentPos){
return childMap.get(str2[parentPos]);
}
@Override
public Object getChild(int parentPos, int childPos){
return childMap.get(str2[parentPos]).get(childPos);
}

@Override
public int getGroupCount(){
return childMap.size();
}

@Override
public int getChildrenCount(int parentPos){
return childMap.get(str2[parentPos]).size();
}

@Override
public long getGroupId(int parentPos){
return parentPos;
}

@Override
public long getChildId(int parentPos, int childPos){
return  childPos;
}

@Override
public boolean hasStableIds(){
return false;
}

@Override
public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){
if(view == null){
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.child_item, null);
}
view.setTag(R.layout.group_item, parentPos);
view.setTag(R.layout.child_item, -1);
TextView childText = (TextView) view.findViewById(R.id.child_item);
childText.setText(str2[parentPos]);
return view;

}

@Override
public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){
if(view == null){
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.child_child_item, null);
}
view.setTag(R.layout.group_item, parentPos);
view.setTag(R.layout.child_item, childPos);

TextView child_child_text = (TextView) view.findViewById(R.id.child_child_item);
child_child_text.setText(childMap.get(str2[parentPos]).get(childPos));
return view;
}

@Override
public boolean isChildSelectable(int i, int i1){
return true;
}

}

第二级中只需要加载父项和子项的内容即可。

最后实现效果:

以下是全部代码:
package com.example.yxc.expandlistviewtest;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

private ExpandableListView expandableListView;
private Map<String, Map<String, List<String>>> dataMap = new HashMap<>();
private String[] str1 = {"first", "second", "third"};
private String[] str2 = {"1", "2", "3", "4"};
private Map<String, List<String>> childMap = new HashMap<>();
private List<String> childList = new ArrayList<>();
private GroupExpandableListViewAdapter mExpandableListAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initData();

expandableListView = (ExpandableListView) findViewById(R.id.listview);
mExpandableListAdapter = new GroupExpandableListViewAdapter();
expandableListView.setAdapter(mExpandableListAdapter);

expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView expandableListView, View view, int parentPos, int childPos, long l) {
Toast.makeText(MainActivity.this,
"you press the childitem " + childMap.get(str2[parentPos]).get(childPos),
Toast.LENGTH_SHORT).show();
return false;
}
});
}

private void initData(){ childList.add("f1"); childList.add("f2"); childList.add("f3"); childMap.put(str2[0], childList); childMap.put(str2[1], childList); childMap.put(str2[2], childList); childMap.put(str2[3], childList); dataMap.put(str1[0], childMap); dataMap.put(str1[1], childMap); dataMap.put(str1[2], childMap); }

private class GroupExpandableListViewAdapter extends BaseExpandableListAdapter{ @Override public Object getGroup(int parentPos){ return dataMap.get(str1[parentPos]); } @Override public Object getChild(int parentPos, int childPos){ return dataMap.get(str1[parentPos]).get(childPos); } @Override public int getGroupCount(){ return dataMap.size(); } @Override public int getChildrenCount(int parentPos){ return 1; } @Override public long getGroupId(int parentPos){ return parentPos; } @Override public long getChildId(int parentPos, int childPos){ return childPos; } @Override public boolean hasStableIds(){ return false; } @Override public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){ if(view == null){ LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.group_item, null); } view.setTag(R.layout.group_item, parentPos); view.setTag(R.layout.child_item, -1); TextView groupText = (TextView) view.findViewById(R.id.group_item); groupText.setText(str1[parentPos]); return view; } @Override public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){ if(view == null){ LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.child_listview, null); } view.setTag(R.layout.group_item, parentPos); view.setTag(R.layout.child_item, childPos); ChildExpandableListView childExpandableListView = (ChildExpandableListView) view.findViewById(R.id.child_listview); ChildExpandableListViewAdapter childExpandableLVAdapter = new ChildExpandableListViewAdapter(); childExpandableListView.setAdapter(childExpandableLVAdapter); return view; } @Override public boolean isChildSelectable(int i, int i1){ return true; } }

private class ChildExpandableListViewAdapter extends BaseExpandableListAdapter{ @Override public Object getGroup(int parentPos){ return childMap.get(str2[parentPos]); } @Override public Object getChild(int parentPos, int childPos){ return childMap.get(str2[parentPos]).get(childPos); } @Override public int getGroupCount(){ return childMap.size(); } @Override public int getChildrenCount(int parentPos){ return childMap.get(str2[parentPos]).size(); } @Override public long getGroupId(int parentPos){ return parentPos; } @Override public long getChildId(int parentPos, int childPos){ return childPos; } @Override public boolean hasStableIds(){ return false; } @Override public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){ if(view == null){ LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.child_item, null); } view.setTag(R.layout.group_item, parentPos); view.setTag(R.layout.child_item, -1); TextView childText = (TextView) view.findViewById(R.id.child_item); childText.setText(str2[parentPos]); return view; } @Override public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){ if(view == null){ LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.child_child_item, null); } view.setTag(R.layout.group_item, parentPos); view.setTag(R.layout.child_item, childPos); TextView child_child_text = (TextView) view.findViewById(R.id.child_child_item); child_child_text.setText(childMap.get(str2[parentPos]).get(childPos)); return view; } @Override public boolean isChildSelectable(int i, int i1){ return true; } }

}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android