android中用ExpandableListView实现三级扩展列表(附源码)
2016-11-27 01:51
555 查看
工作中遇到一个选择车型的问题,需要在扩展列表中选择车辆品牌->车型->年款,所以必须得使用三级的扩展列表来实现,而且第三级还得使用GridView来展示。下面就一步步来吧。
1.定义需要使用的车型类,每个车辆品牌下面包含n个车型,每个车型下面包含n个年款
点击(此处)折叠或打开
/**
* 汽车的品牌类
*
* @author liyanshun 2014-2-21
*/
public
class CarBrand {
/**
* 汽车的品牌名字
*/
public
String mBrandName;
public
String mSortLetters;
/** 该品牌下包含的汽车类型 */
public
ArrayList<CarStyle> mCarStyleList;
}
/**
* 汽车车类型
*
* @author liyanshun 2014-2-26
*/
public
class CarStyle {
/** 汽车的类型名 */
public
String mStyleName;
/** 该类型下包含的年款 */
public
ArrayList<String> mModelList;
}
2.列表要可以按照首字母快速定位,这个功能参考了别人的实现,详情见这篇博客:http://blog.csdn.net/xiaanming/article/details/12684155
3.实现第一级扩展列表。第一级比较好实现,只用使用一个ExpandableListView,并定义Adapter就可以了。需要注意的是每个品牌下面的子View个数即为其包含的车型个数,而每个车型都是一个新 的ExpandableListView。当然也可以使用一个ExpandableListView来展示所有的车型,但是那样的话会导致点击靠下的车型时,其后面的车型可能会被后一项的品牌给覆盖掉。所以在这里使用多了多
个ExpandableListView。Adapter的实现如下:
点击(此处)折叠或打开
/**
* 用来选择车辆品牌并且带字母排序的adapter
*
* @author liyanshun 2014-2-21
*/
public
class CarBrandAdapter extends BaseExpandableListAdapter
implements
SectionIndexer {
private
List<CarBrand> mBrandList
=
null;
private
Context mContext;
public CarBrandAdapter(Context
mContext,
List<CarBrand>
list)
{
this.mContext
= mContext;
this.mBrandList
=
list;
}
/**
* 当ListView数据发生变化时,调用此方法来更新ListView
*
* @param mBrandList
*/
public
void updateListView(List<CarBrand>
list)
{
this.mBrandList
=
list;
notifyDataSetChanged();
}
public
int
getCount()
{
return
this.mBrandList.size();
}
public
Object
getItem(int
position)
{
return mBrandList.get(position);
}
public
long getItemId(int
position)
{
return
position;
}
final
static
class ViewHolder {
TextView tvLetter;
TextView tvTitle;
ImageView carBrand;
ImageView
close;
View body;
View titleBar;
}
final
static
class CarStyleViewHolder {
ExpandableListView styleList;
}
/**
* 根据ListView的当前位置获取分类的首字母的Char ascii值
*/
public
int getSectionForPosition(int
position)
{
return mBrandList.get(position).mSortLetters.charAt(0);
}
/**
* 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置
*/
public
int getPositionForSection(int section)
{
for
(int i
= 0; i
<
getCount(); i++)
{
String sortStr
= mBrandList.get(i).mSortLetters;
char firstChar
= sortStr.toUpperCase().charAt(0);
if
(firstChar
== section)
{
return i;
}
}
return
-1;
}
/**
* 提取英文的首字母,非英文字母用#代替。
*
* @param str
* @return
*/
private
String
getAlpha(String str)
{
String sortStr
= str.trim().substring(0,
1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if
(sortStr.matches("[A-Z]"))
{
return sortStr;
}
else
{
return
"#";
}
}
@Override
public
Object[] getSections()
{
return
null;
}
@Override
public
int getGroupCount()
{
return mBrandList
==
null
? 0 : mBrandList.size();
}
@Override
public
int getChildrenCount(int groupPosition)
{
return mBrandList
==
null
? 0
:
(mBrandList.get(groupPosition)
==
null
? 0 :
(mBrandList
.get(groupPosition).mCarStyleList
==
null
? 0
: mBrandList.get(groupPosition).mCarStyleList.size()));
}
@Override
public
Object
getGroup(int groupPosition)
{
return mBrandList.get(groupPosition);
}
@Override
public
Object
getChild(int groupPosition,
int childPosition)
{
return mBrandList.get(groupPosition).mCarStyleList.get(childPosition);
}
@Override
public
long
getGroupId(int groupPosition)
{
return groupPosition;
}
@Override
public
long getChildId(int groupPosition,
int childPosition)
{
return groupPosition;
}
@Override
public
boolean hasStableIds()
{
return false;
}
@Override
public
View getGroupView(int groupPosition,
boolean
isExpanded,
View convertView, ViewGroup
parent)
{
ViewHolder viewHolder =
null;
final CarBrand mContent
= mBrandList.get(groupPosition);
if
(convertView
==
null)
{
viewHolder =
new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.car_brand_item,
null);
viewHolder.tvTitle
=
(TextView) convertView
.findViewById(R.id.title);
viewHolder.tvLetter
=
(TextView) convertView
.findViewById(R.id.catalog);
viewHolder.carBrand
=
(ImageView) convertView
.findViewById(R.id.item_img);
viewHolder.close
=
(ImageView) convertView
.findViewById(R.id.close_img);
viewHolder.body
= convertView.findViewById(R.id.item_body);
viewHolder.titleBar
= convertView.findViewById(R.id.title_bar);
convertView.setTag(viewHolder);
}
else
{
viewHolder =
(ViewHolder) convertView.getTag();
}
// 根据position获取分类的首字母的Char ascii值
int section
= getSectionForPosition(groupPosition);
// 如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
if
(groupPosition
== getPositionForSection(section))
{
viewHolder.titleBar.setVisibility(View.VISIBLE);
viewHolder.tvLetter.setText(mContent.mSortLetters);
}
else
{
viewHolder.titleBar.setVisibility(View.GONE);
}
viewHolder.tvTitle
.setText(this.mBrandList.get(groupPosition).mBrandName);
if
(isExpanded)
{
viewHolder.close.setVisibility(View.VISIBLE);
}
else
{
viewHolder.close.setVisibility(View.GONE);
}
return convertView;
}
@Override
public
View getChildView(int groupPosition,
int childPosition,
boolean isLastChild,
View convertView, ViewGroup
parent)
{
CarStyleAdapter carStyleAdapter =
new CarStyleAdapter(mContext,
mBrandList.get(groupPosition).mCarStyleList.get(childPosition));
CustExpListview SecondLevelexplv
=
new CustExpListview(mContext);
SecondLevelexplv.setAdapter(carStyleAdapter);
SecondLevelexplv.setGroupIndicator(null);
return SecondLevelexplv;
}
@Override
public
boolean isChildSelectable(int groupPosition,
int childPosition)
{
return true;
}
public
class CustExpListview
extends ExpandableListView
{
public CustExpListview(Context
context)
{
super(context);
}
protected
void onMeasure(int widthMeasureSpec,
int heightMeasureSpec)
{
widthMeasureSpec = MeasureSpec.makeMeasureSpec(960,
MeasureSpec.AT_MOST);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(600,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
}
}
}
4 .将这个Adapter加到ExpandableListView中就可以实现二级的扩展菜单了,下面来实现带GridView的三级扩展菜单。与二级的不同,三级的GridView必须使用一个来实现,也就是说
每个车型下面的n个年款使用一个GridView来展示。所以需要注意的就是返回ChildCount的时候只能返回1。这个Adapter的实现如下:
点击(此处)折叠或打开
/**
* 显示车型和年款的adapter
*
* @author liyanshun 2014-2-27
*/
public
class CarStyleAdapter extends BaseExpandableListAdapter
implements
OnItemClickListener {
private
static
final String TAG
=
"CarStyleAdapter";
private CarStyle mCarStyle
=
null;
private
Context mContext;
public CarStyleAdapter(Context
mContext, CarStyle carStyle)
{
this.mContext
= mContext;
this.mCarStyle
= carStyle;
}
@Override
public
int getGroupCount()
{
return mCarStyle
==
null
? 0 : 1;
}
@Override
public
int getChildrenCount(int groupPosition)
{
//只显示一个Child,否则会造成GridView的重复显示
return mCarStyle
==
null
? 0 :
(mCarStyle.mModelList
==
null
? 0 : 1);
}
@Override
public
Object
getGroup(int groupPosition)
{
return mCarStyle;
}
@Override
public
Object
getChild(int groupPosition,
int childPosition)
{
return mCarStyle.mModelList.get(childPosition);
}
@Override
public
long
getGroupId(int groupPosition)
{
return groupPosition;
}
@Override
public
long getChildId(int groupPosition,
int childPosition)
{
return groupPosition;
}
@Override
public
boolean hasStableIds()
{
return false;
}
@Override
public
View getGroupView(int groupPosition,
boolean
isExpanded,
View convertView, ViewGroup
parent)
{
Logger.d(TAG,
"groupPosition:"
+ groupPosition);
ViewHolder viewHolder =
null;
if
(convertView
==
null)
{
viewHolder =
new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.car_style_item,
null);
viewHolder.tvTitle
=
(TextView) convertView
.findViewById(R.id.style_name);
viewHolder.bottmLine
=
(View) convertView
.findViewById(R.id.style_bottom_line);
viewHolder.styleArrow
=
(ImageView) convertView
.findViewById(R.id.style_arrow);
viewHolder.closeView
=
(ImageView) convertView
.findViewById(R.id.style_close_img);
convertView.setTag(viewHolder);
}
else
{
viewHolder =
(ViewHolder) convertView.getTag();
}
viewHolder.tvTitle.setText(mCarStyle.mStyleName);
if
(isExpanded)
{
viewHolder.styleArrow.setVisibility(View.VISIBLE);
viewHolder.closeView.setVisibility(View.VISIBLE);
}
else
{
viewHolder.styleArrow.setVisibility(View.GONE);
viewHolder.closeView.setVisibility(View.GONE);
}
return convertView;
}
@Override
public
View getChildView(int groupPosition,
int childPosition,
boolean isLastChild,
View convertView, ViewGroup
parent)
{
GridView gridView =
null;
if
(convertView
==
null)
{
LayoutInflater layoutInflater
=
(LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.car_model_grid,
null);
gridView =
(GridView) convertView.findViewById(R.id.gridview);
gridView.setNumColumns(2);//
设置每行列数
gridView.setGravity(Gravity.CENTER);//
位置居中
gridView.setHorizontalSpacing(10);//
水平间隔
gridView.setAdapter(new
GridAdapter());
//计算并设置gridView的高度
final
int rowHeightDp
= 40;
final
float ROW_HEIGHT
= mContext.getResources()
.getDisplayMetrics().density
* rowHeightDp;
double
size
= mCarStyle.mModelList.size();
int rowCount
=
(int)
Math.ceil(size/2);
final
int GRID_HEIGHT
=
(int)
(ROW_HEIGHT
* rowCount);
gridView.getLayoutParams().height
= GRID_HEIGHT;
gridView.setOnItemClickListener(this);
}
return convertView;
}
@Override
public
boolean isChildSelectable(int groupPosition,
int childPosition)
{
return true;
}
final
static
class ViewHolder {
TextView tvTitle;
View bottmLine;
ImageView styleArrow;
ImageView closeView;
}
private
class GridAdapter
extends BaseAdapter
{
@Override
public
int
getCount()
{
return mCarStyle.mModelList.size();
}
@Override
public
Object
getItem(int
position)
{
return mCarStyle.mModelList.get(position);
}
@Override
public
long getItemId(int
position)
{
return 0;
}
@Override
public
View
getView(int
position,
View convertView, ViewGroup
parent)
{
ViewHolder viewHolder =
null;
if
(convertView
==
null)
{
viewHolder =
new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.car_model_item,
null);
viewHolder.tvTitle
=
(TextView) convertView
.findViewById(R.id.name);
convertView.setTag(viewHolder);
}
else
{
viewHolder =
(ViewHolder) convertView.getTag();
}
viewHolder.tvTitle.setText((mCarStyle.mModelList.get(position)));
return convertView;
}
}
@Override
public
void onItemClick(AdapterView<?>
parent,
View
view,
int position,
long
id)
{
Toast.makeText(mContext,
""
+ position, Toast.LENGTH_SHORT).show();
}
}
5.好了,最重要的两个Adapter已经实现了,只需要将其加入了界面中就可以了。在这里我使用了一个fragment来进行展示:
点击(此处)折叠或打开
/**
* 选择汽车品牌
*
* @author liyanshun 2014-2-21
*/
public class SelectBrandFragment extends FatherFragment implements
OnClickListener, OnItemClickListener {
private static final String TAG =
"SelectBrandFragment";
private ExpandableListView mSortListView;
private SideBar mSideBar;
private TextView mDialog;
private CarBrandAdapter mAdapter;
/**
* 汉字转换成拼音的类
*/
private CharacterParser characterParser;
private List<CarBrand> SourceDateList;
/**
* 根据拼音来排列ListView里面的数据类
*/
private PinyinComparator pinyinComparator;
String[] data={"奥迪","宝马","奔驰","雪铁龙","大众","牧马人"};
@Override
public void onStart()
{
super.onStart();
Logger.d(TAG,"onStart");
//已经设置过layout了,无需再次设定
if(mLayoutAdded){
return;
}
super.setLayout(R.layout.select_brand);
mSortListView =
(ExpandableListView) mBodyView.findViewById(R.id.lv);
mSideBar =
(SideBar) mBodyView.findViewById(R.id.sidrbar);
mDialog =
(TextView) mBodyView.findViewById(R.id.dialog);
mSideBar.setTextView(mDialog);
mTitle.setText(R.string.select_brand);
mRightTitle.setText(R.string.jump);
mRightTitle.setOnClickListener(this);
// 实例化汉字转拼音类
characterParser = CharacterParser.getInstance();
pinyinComparator = new PinyinComparator();
mSortListView.setOnItemClickListener(this);
// 设置右侧触摸监听
mSideBar.setOnTouchingLetterChangedListener(new
OnTouchingLetterChangedListener() {
@Override
public void onTouchingLetterChanged(String
s) {
// 该字母首次出现的位置
int position
= mAdapter.getPositionForSection(s.charAt(0));
if
(position
!=
-1) {
mSortListView.setSelection(position);
}
}
});
SourceDateList = filledData(data);
//
// // 根据a-z进行排序源数据
Collections.sort(SourceDateList,
pinyinComparator);
mAdapter = new CarBrandAdapter(mContext,
SourceDateList);
// CarStyleAdapter carStyleAdapter=new CarStyleAdapter(mContext,SourceDateList.get(2).mCarStyleList);
mSortListView.setAdapter(mAdapter);
}
@Override
public void onClick(View v)
{
int id
= v.getId();
switch (id) {
case R.id.right_button:
Logger.d(TAG,"rightbutton");
break;
}
}
@Override
public void onItemClick(AdapterView<?>
parent, View view,
int position,
long id) {
Logger.d(TAG,"onItemClick:"+position);
}
/**
* 为ListView填充数据
* @param date
* @return
*/
private List<CarBrand> filledData(String
[] date){
List<CarBrand> mBrandList
= new ArrayList<CarBrand>();
for(int i=0;
i<date.length;
i++){
CarBrand carBrand = new CarBrand();
carBrand.mBrandName=date[i];
//汉字转换成拼音
String pinyin = characterParser.getSelling(date[i]);
String sortString = pinyin.substring(0,
1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if(sortString.matches("[A-Z]")){
carBrand.mSortLetters=sortString.toUpperCase();
}else{
carBrand.mSortLetters="#";
}
ArrayList<CarStyle> mStyleList
= new ArrayList<CarStyle>();
for(int j=0;j<=i;j++){
CarStyle carStyle=new CarStyle();
carStyle.mStyleName=date[i]+"201"+j;
ArrayList<String> mModelList
= new ArrayList<String>();
for(int k=0;k<=j;k++){
mModelList.add(carStyle.mStyleName+":"+"手动款");
}
carStyle.mModelList=mModelList;
mStyleList.add(carStyle);
}
carBrand.mCarStyleList=mStyleList;
mBrandList.add(carBrand);
}
return mBrandList;
}
}
6.大功告成了,来看一下显示的效果吧。
源码又重新整理一下放在github上。https://github.com/Chaoba/android-ThreeLevelExpandableListView
1.定义需要使用的车型类,每个车辆品牌下面包含n个车型,每个车型下面包含n个年款
点击(此处)折叠或打开
/**
* 汽车的品牌类
*
* @author liyanshun 2014-2-21
*/
public
class CarBrand {
/**
* 汽车的品牌名字
*/
public
String mBrandName;
public
String mSortLetters;
/** 该品牌下包含的汽车类型 */
public
ArrayList<CarStyle> mCarStyleList;
}
/**
* 汽车车类型
*
* @author liyanshun 2014-2-26
*/
public
class CarStyle {
/** 汽车的类型名 */
public
String mStyleName;
/** 该类型下包含的年款 */
public
ArrayList<String> mModelList;
}
2.列表要可以按照首字母快速定位,这个功能参考了别人的实现,详情见这篇博客:http://blog.csdn.net/xiaanming/article/details/12684155
3.实现第一级扩展列表。第一级比较好实现,只用使用一个ExpandableListView,并定义Adapter就可以了。需要注意的是每个品牌下面的子View个数即为其包含的车型个数,而每个车型都是一个新 的ExpandableListView。当然也可以使用一个ExpandableListView来展示所有的车型,但是那样的话会导致点击靠下的车型时,其后面的车型可能会被后一项的品牌给覆盖掉。所以在这里使用多了多
个ExpandableListView。Adapter的实现如下:
点击(此处)折叠或打开
/**
* 用来选择车辆品牌并且带字母排序的adapter
*
* @author liyanshun 2014-2-21
*/
public
class CarBrandAdapter extends BaseExpandableListAdapter
implements
SectionIndexer {
private
List<CarBrand> mBrandList
=
null;
private
Context mContext;
public CarBrandAdapter(Context
mContext,
List<CarBrand>
list)
{
this.mContext
= mContext;
this.mBrandList
=
list;
}
/**
* 当ListView数据发生变化时,调用此方法来更新ListView
*
* @param mBrandList
*/
public
void updateListView(List<CarBrand>
list)
{
this.mBrandList
=
list;
notifyDataSetChanged();
}
public
int
getCount()
{
return
this.mBrandList.size();
}
public
Object
getItem(int
position)
{
return mBrandList.get(position);
}
public
long getItemId(int
position)
{
return
position;
}
final
static
class ViewHolder {
TextView tvLetter;
TextView tvTitle;
ImageView carBrand;
ImageView
close;
View body;
View titleBar;
}
final
static
class CarStyleViewHolder {
ExpandableListView styleList;
}
/**
* 根据ListView的当前位置获取分类的首字母的Char ascii值
*/
public
int getSectionForPosition(int
position)
{
return mBrandList.get(position).mSortLetters.charAt(0);
}
/**
* 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置
*/
public
int getPositionForSection(int section)
{
for
(int i
= 0; i
<
getCount(); i++)
{
String sortStr
= mBrandList.get(i).mSortLetters;
char firstChar
= sortStr.toUpperCase().charAt(0);
if
(firstChar
== section)
{
return i;
}
}
return
-1;
}
/**
* 提取英文的首字母,非英文字母用#代替。
*
* @param str
* @return
*/
private
String
getAlpha(String str)
{
String sortStr
= str.trim().substring(0,
1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if
(sortStr.matches("[A-Z]"))
{
return sortStr;
}
else
{
return
"#";
}
}
@Override
public
Object[] getSections()
{
return
null;
}
@Override
public
int getGroupCount()
{
return mBrandList
==
null
? 0 : mBrandList.size();
}
@Override
public
int getChildrenCount(int groupPosition)
{
return mBrandList
==
null
? 0
:
(mBrandList.get(groupPosition)
==
null
? 0 :
(mBrandList
.get(groupPosition).mCarStyleList
==
null
? 0
: mBrandList.get(groupPosition).mCarStyleList.size()));
}
@Override
public
Object
getGroup(int groupPosition)
{
return mBrandList.get(groupPosition);
}
@Override
public
Object
getChild(int groupPosition,
int childPosition)
{
return mBrandList.get(groupPosition).mCarStyleList.get(childPosition);
}
@Override
public
long
getGroupId(int groupPosition)
{
return groupPosition;
}
@Override
public
long getChildId(int groupPosition,
int childPosition)
{
return groupPosition;
}
@Override
public
boolean hasStableIds()
{
return false;
}
@Override
public
View getGroupView(int groupPosition,
boolean
isExpanded,
View convertView, ViewGroup
parent)
{
ViewHolder viewHolder =
null;
final CarBrand mContent
= mBrandList.get(groupPosition);
if
(convertView
==
null)
{
viewHolder =
new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.car_brand_item,
null);
viewHolder.tvTitle
=
(TextView) convertView
.findViewById(R.id.title);
viewHolder.tvLetter
=
(TextView) convertView
.findViewById(R.id.catalog);
viewHolder.carBrand
=
(ImageView) convertView
.findViewById(R.id.item_img);
viewHolder.close
=
(ImageView) convertView
.findViewById(R.id.close_img);
viewHolder.body
= convertView.findViewById(R.id.item_body);
viewHolder.titleBar
= convertView.findViewById(R.id.title_bar);
convertView.setTag(viewHolder);
}
else
{
viewHolder =
(ViewHolder) convertView.getTag();
}
// 根据position获取分类的首字母的Char ascii值
int section
= getSectionForPosition(groupPosition);
// 如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
if
(groupPosition
== getPositionForSection(section))
{
viewHolder.titleBar.setVisibility(View.VISIBLE);
viewHolder.tvLetter.setText(mContent.mSortLetters);
}
else
{
viewHolder.titleBar.setVisibility(View.GONE);
}
viewHolder.tvTitle
.setText(this.mBrandList.get(groupPosition).mBrandName);
if
(isExpanded)
{
viewHolder.close.setVisibility(View.VISIBLE);
}
else
{
viewHolder.close.setVisibility(View.GONE);
}
return convertView;
}
@Override
public
View getChildView(int groupPosition,
int childPosition,
boolean isLastChild,
View convertView, ViewGroup
parent)
{
CarStyleAdapter carStyleAdapter =
new CarStyleAdapter(mContext,
mBrandList.get(groupPosition).mCarStyleList.get(childPosition));
CustExpListview SecondLevelexplv
=
new CustExpListview(mContext);
SecondLevelexplv.setAdapter(carStyleAdapter);
SecondLevelexplv.setGroupIndicator(null);
return SecondLevelexplv;
}
@Override
public
boolean isChildSelectable(int groupPosition,
int childPosition)
{
return true;
}
public
class CustExpListview
extends ExpandableListView
{
public CustExpListview(Context
context)
{
super(context);
}
protected
void onMeasure(int widthMeasureSpec,
int heightMeasureSpec)
{
widthMeasureSpec = MeasureSpec.makeMeasureSpec(960,
MeasureSpec.AT_MOST);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(600,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
}
}
}
4 .将这个Adapter加到ExpandableListView中就可以实现二级的扩展菜单了,下面来实现带GridView的三级扩展菜单。与二级的不同,三级的GridView必须使用一个来实现,也就是说
每个车型下面的n个年款使用一个GridView来展示。所以需要注意的就是返回ChildCount的时候只能返回1。这个Adapter的实现如下:
点击(此处)折叠或打开
/**
* 显示车型和年款的adapter
*
* @author liyanshun 2014-2-27
*/
public
class CarStyleAdapter extends BaseExpandableListAdapter
implements
OnItemClickListener {
private
static
final String TAG
=
"CarStyleAdapter";
private CarStyle mCarStyle
=
null;
private
Context mContext;
public CarStyleAdapter(Context
mContext, CarStyle carStyle)
{
this.mContext
= mContext;
this.mCarStyle
= carStyle;
}
@Override
public
int getGroupCount()
{
return mCarStyle
==
null
? 0 : 1;
}
@Override
public
int getChildrenCount(int groupPosition)
{
//只显示一个Child,否则会造成GridView的重复显示
return mCarStyle
==
null
? 0 :
(mCarStyle.mModelList
==
null
? 0 : 1);
}
@Override
public
Object
getGroup(int groupPosition)
{
return mCarStyle;
}
@Override
public
Object
getChild(int groupPosition,
int childPosition)
{
return mCarStyle.mModelList.get(childPosition);
}
@Override
public
long
getGroupId(int groupPosition)
{
return groupPosition;
}
@Override
public
long getChildId(int groupPosition,
int childPosition)
{
return groupPosition;
}
@Override
public
boolean hasStableIds()
{
return false;
}
@Override
public
View getGroupView(int groupPosition,
boolean
isExpanded,
View convertView, ViewGroup
parent)
{
Logger.d(TAG,
"groupPosition:"
+ groupPosition);
ViewHolder viewHolder =
null;
if
(convertView
==
null)
{
viewHolder =
new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.car_style_item,
null);
viewHolder.tvTitle
=
(TextView) convertView
.findViewById(R.id.style_name);
viewHolder.bottmLine
=
(View) convertView
.findViewById(R.id.style_bottom_line);
viewHolder.styleArrow
=
(ImageView) convertView
.findViewById(R.id.style_arrow);
viewHolder.closeView
=
(ImageView) convertView
.findViewById(R.id.style_close_img);
convertView.setTag(viewHolder);
}
else
{
viewHolder =
(ViewHolder) convertView.getTag();
}
viewHolder.tvTitle.setText(mCarStyle.mStyleName);
if
(isExpanded)
{
viewHolder.styleArrow.setVisibility(View.VISIBLE);
viewHolder.closeView.setVisibility(View.VISIBLE);
}
else
{
viewHolder.styleArrow.setVisibility(View.GONE);
viewHolder.closeView.setVisibility(View.GONE);
}
return convertView;
}
@Override
public
View getChildView(int groupPosition,
int childPosition,
boolean isLastChild,
View convertView, ViewGroup
parent)
{
GridView gridView =
null;
if
(convertView
==
null)
{
LayoutInflater layoutInflater
=
(LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.car_model_grid,
null);
gridView =
(GridView) convertView.findViewById(R.id.gridview);
gridView.setNumColumns(2);//
设置每行列数
gridView.setGravity(Gravity.CENTER);//
位置居中
gridView.setHorizontalSpacing(10);//
水平间隔
gridView.setAdapter(new
GridAdapter());
//计算并设置gridView的高度
final
int rowHeightDp
= 40;
final
float ROW_HEIGHT
= mContext.getResources()
.getDisplayMetrics().density
* rowHeightDp;
double
size
= mCarStyle.mModelList.size();
int rowCount
=
(int)
Math.ceil(size/2);
final
int GRID_HEIGHT
=
(int)
(ROW_HEIGHT
* rowCount);
gridView.getLayoutParams().height
= GRID_HEIGHT;
gridView.setOnItemClickListener(this);
}
return convertView;
}
@Override
public
boolean isChildSelectable(int groupPosition,
int childPosition)
{
return true;
}
final
static
class ViewHolder {
TextView tvTitle;
View bottmLine;
ImageView styleArrow;
ImageView closeView;
}
private
class GridAdapter
extends BaseAdapter
{
@Override
public
int
getCount()
{
return mCarStyle.mModelList.size();
}
@Override
public
Object
getItem(int
position)
{
return mCarStyle.mModelList.get(position);
}
@Override
public
long getItemId(int
position)
{
return 0;
}
@Override
public
View
getView(int
position,
View convertView, ViewGroup
parent)
{
ViewHolder viewHolder =
null;
if
(convertView
==
null)
{
viewHolder =
new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.car_model_item,
null);
viewHolder.tvTitle
=
(TextView) convertView
.findViewById(R.id.name);
convertView.setTag(viewHolder);
}
else
{
viewHolder =
(ViewHolder) convertView.getTag();
}
viewHolder.tvTitle.setText((mCarStyle.mModelList.get(position)));
return convertView;
}
}
@Override
public
void onItemClick(AdapterView<?>
parent,
View
view,
int position,
long
id)
{
Toast.makeText(mContext,
""
+ position, Toast.LENGTH_SHORT).show();
}
}
5.好了,最重要的两个Adapter已经实现了,只需要将其加入了界面中就可以了。在这里我使用了一个fragment来进行展示:
点击(此处)折叠或打开
/**
* 选择汽车品牌
*
* @author liyanshun 2014-2-21
*/
public class SelectBrandFragment extends FatherFragment implements
OnClickListener, OnItemClickListener {
private static final String TAG =
"SelectBrandFragment";
private ExpandableListView mSortListView;
private SideBar mSideBar;
private TextView mDialog;
private CarBrandAdapter mAdapter;
/**
* 汉字转换成拼音的类
*/
private CharacterParser characterParser;
private List<CarBrand> SourceDateList;
/**
* 根据拼音来排列ListView里面的数据类
*/
private PinyinComparator pinyinComparator;
String[] data={"奥迪","宝马","奔驰","雪铁龙","大众","牧马人"};
@Override
public void onStart()
{
super.onStart();
Logger.d(TAG,"onStart");
//已经设置过layout了,无需再次设定
if(mLayoutAdded){
return;
}
super.setLayout(R.layout.select_brand);
mSortListView =
(ExpandableListView) mBodyView.findViewById(R.id.lv);
mSideBar =
(SideBar) mBodyView.findViewById(R.id.sidrbar);
mDialog =
(TextView) mBodyView.findViewById(R.id.dialog);
mSideBar.setTextView(mDialog);
mTitle.setText(R.string.select_brand);
mRightTitle.setText(R.string.jump);
mRightTitle.setOnClickListener(this);
// 实例化汉字转拼音类
characterParser = CharacterParser.getInstance();
pinyinComparator = new PinyinComparator();
mSortListView.setOnItemClickListener(this);
// 设置右侧触摸监听
mSideBar.setOnTouchingLetterChangedListener(new
OnTouchingLetterChangedListener() {
@Override
public void onTouchingLetterChanged(String
s) {
// 该字母首次出现的位置
int position
= mAdapter.getPositionForSection(s.charAt(0));
if
(position
!=
-1) {
mSortListView.setSelection(position);
}
}
});
SourceDateList = filledData(data);
//
// // 根据a-z进行排序源数据
Collections.sort(SourceDateList,
pinyinComparator);
mAdapter = new CarBrandAdapter(mContext,
SourceDateList);
// CarStyleAdapter carStyleAdapter=new CarStyleAdapter(mContext,SourceDateList.get(2).mCarStyleList);
mSortListView.setAdapter(mAdapter);
}
@Override
public void onClick(View v)
{
int id
= v.getId();
switch (id) {
case R.id.right_button:
Logger.d(TAG,"rightbutton");
break;
}
}
@Override
public void onItemClick(AdapterView<?>
parent, View view,
int position,
long id) {
Logger.d(TAG,"onItemClick:"+position);
}
/**
* 为ListView填充数据
* @param date
* @return
*/
private List<CarBrand> filledData(String
[] date){
List<CarBrand> mBrandList
= new ArrayList<CarBrand>();
for(int i=0;
i<date.length;
i++){
CarBrand carBrand = new CarBrand();
carBrand.mBrandName=date[i];
//汉字转换成拼音
String pinyin = characterParser.getSelling(date[i]);
String sortString = pinyin.substring(0,
1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if(sortString.matches("[A-Z]")){
carBrand.mSortLetters=sortString.toUpperCase();
}else{
carBrand.mSortLetters="#";
}
ArrayList<CarStyle> mStyleList
= new ArrayList<CarStyle>();
for(int j=0;j<=i;j++){
CarStyle carStyle=new CarStyle();
carStyle.mStyleName=date[i]+"201"+j;
ArrayList<String> mModelList
= new ArrayList<String>();
for(int k=0;k<=j;k++){
mModelList.add(carStyle.mStyleName+":"+"手动款");
}
carStyle.mModelList=mModelList;
mStyleList.add(carStyle);
}
carBrand.mCarStyleList=mStyleList;
mBrandList.add(carBrand);
}
return mBrandList;
}
}
6.大功告成了,来看一下显示的效果吧。
源码又重新整理一下放在github上。https://github.com/Chaoba/android-ThreeLevelExpandableListView
相关文章推荐
- android中用ExpandableListView实现三级扩展列表(附源码)
- android中用ExpandableListView实现三级扩展列表
- android 实现QQ好友列表(扩展listview:ExpandableListView)
- 站在巨人的肩膀上---重新自定义 android- ExpandableListView 收缩类,实现列表的可收缩扩展
- Android ExpandableListView使用(3): ExpandableListView实现三级列表
- android 实现QQ好友列表(扩展listview:ExpandableListView)
- android 列表ListView和可扩展列表ExpandableListView的实现
- android 实现QQ好友列表(扩展listview:ExpandableListView)
- 在android里用ExpandableListView实现二层和三层列表源码
- 在android里用ExpandableListView实现二层和三层列表源码
- 在android里用ExpandableListView实现二层和三层列表源码
- android 实现QQ好友列表(扩展listview:ExpandableListView)
- Android之用 ExpandableListView使用解析(三级列表的实现)
- Android UI ExpandableListView实现扩展列表
- android中使用BaseAdapter的实现灵活扩展的ListView列表
- Android_ExpandableListView_一个ListView实现二级列表
- android开发之ExpandableListView的使用,实现类似QQ好友列表
- android开发之ExpandableListView的使用,实现类似QQ好友列表
- ExpandableListView使用解析(三级列表的实现)
- Android_QQ好友列表实现---ExpandableListView可展开列表视图