expandable.....View
http://www.bubuko.com/infodetail-770461.html
官方没有ExpandableGridView
那么怎么样用ExpandableListView来实现一个ExpandableGridView呢
大概的原理是:在每个ExpandableListView 中显示一行,用这行来加载一个GridView
1.加载一个ExpandableListView
private SimpleDataAdapter simpleDataAdapter;
private ExpandableListView mexpandableListview;
mexpandableListview = (ExpandableListView) findViewById(R.id.expandablelist);
mSuperAdapter = new SuperveseDataExpandableAdapter(this,mSuperveseData);
mexpandableListview.setAdapter(mSuperAdapter);
mexpandableListview.expandGroup(0);
2.重写BaseExpandableListAdapter
重写BaseExpandableListAdapter,主要是重写getChildView方法 加载一个GridView 动态的计算GridView 高度
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.view, null);
}
CustomGridView gridView = (CustomGridView) convertView .findViewById(R.id.GridView_toolbar);
gridView.setNumColumns(2);
gridView.setHorizontalSpacing(10);
gridView.setGravity(Gravity.CENTER);
GridAdapter adapter = new GridAdapter(context, superveseDatas.get(groupPosition).controlDatas);
gridView.setAdapter(adapter);// Adapter
int totalHeight = 0;
for (int size = 0; size < adapter.getCount(); size++) {
RelativeLayout relativeLayout = (RelativeLayout) adapter.getView(size, null, gridView);
TextView textView = (TextView) relativeLayout.getChildAt(0);
textView.measure(0, 0);
totalHeight += textView.getMeasuredHeight()*2;
if(size == adapter.getCount() -1){
if (size%2 == 0 ){
totalHeight += textView.getMeasuredHeight()*2;
}
}
}
gridView.SetHeight(totalHeight);
return convertView;
}
另外一个地方也需要注意下:
getChildrenCount返回1 因为用一个Item 来加载GridView
@Override
public int getChildrenCount(int groupPosition) {
return 1;
}
http://blog.chinaunix.net/uid-20771867-id-4125554.html
工作中遇到一个选择车型的问题,需要在扩展列表中选择车辆品牌->车型->年款,所以必须得使用三级的扩展列表来实现,而且第三级还得使用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;
-
-
}
- }
浙公网安备 33010602011771号