Android 自定义分层级筛选控件
今天下午写了一个分层级筛选控件,效果如下
该控件由两部分组成:
1.上面一排的筛选标题按钮(就是四个toggleButton,根据筛选项的数量动态追加)
2.点击筛选按钮弹出来的筛选内容(一个Popupwindow,它包含一个Gridview和一个Button)
需求开发点:
1.单个筛选项内容视图的生成,也就是那个Popupwindow的内容的生成
2.主控件的实现,根据筛选项的数量动添加上面一排内容(这里是四个筛选项),并且关联好每一个筛选项。
1.单个弹出内容视图的生成
我说的单个视图指的是下面红框框部分
首先分析,单个视图包含什么?
1)一个Gridview
2)一个底部Button
3)可筛选的数据List<\string>指的是A学校、B学校这些
4)其实上面的标题(大学、院系等)也归结为单个弹出视图的一部分,所以也得有一个变量叫title
总结: 所以单个视图的生成至少有以上四个成员变量,所以我们的单个视图实现如下:
package com.example.expandableview;
import java.util.ArrayList;
import java.util.List;
import com.example.expandableview.adapter.MyBaseAdapter;
import com.example.expandableview.adapter.ViewHolder;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.GridView;
import android.widget.LinearLayout;
public class ExpandleItemView extends LinearLayout {
/**显示在toggleButton的标题文字*/
public String mTitle;
/** 底部按钮 */
private Button mBottomBtn;
/** 展示要筛选的数据*/
private GridView mGridView;
/** 筛选的数据内容*/
private List mGridviewDatas;
public ExpandleItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ExpandleItemView(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public ExpandleItemView(Context context) {
this(context, null);
}
public ExpandleItemView(String title, Context context,List datas) {
this(context);
setTitle(title);
mGridviewDatas = datas;
init();
}
private void init() {
setBackgroundColor(getResources().getColor(android.R.color.white));
/**将布局inflate到此视图中*/
LayoutInflater.from(getContext()).inflate(R.layout.expand_item_layout, this, true);
setOrientation(LinearLayout.VERTICAL);
mGridView = (GridView) findViewById(R.id.gridview);
mBottomBtn = (Button) findViewById(R.id.btn_all);
/**自己写的通用适配器,传入数据项和layoutid,一句话就使用了*/
mGridView.setAdapter(new MyBaseAdapter(mGridviewDatas, R.layout.gridview_item, getContext()) {
@Override
protected void convert(ViewHolder viewHolder, String t) {
viewHolder.setBtnText(R.id.item_text, t);
}
});
/**每一个子项回调给监听者*/
mGridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
if(mOnExpandItemClick != null)
{
mOnExpandItemClick.onItemClick(position);
}
}
});
/**底部按钮的点击事件回调给监听者*/
mBottomBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(mOnExpandItemClick != null)
{
mOnExpandItemClick.onBottomClick();
}
}
});
}
public String getTitle() {
return mTitle == null ? new String() : mTitle;
}
public void setTitle(String mTitle) {
this.mTitle = mTitle;
}
public List getmGridviewDatas() {
return mGridviewDatas == null ? new ArrayList() : mGridviewDatas;
}
public void setmGridviewDatas(List mGridviewDatas) {
this.mGridviewDatas = mGridviewDatas;
}
/**
* 累加子类的高度作为自身的高度
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int cCount = getChildCount();
int desireWidth = MeasureSpec.getSize(widthMeasureSpec);
int desireHeight = 0;
for (int i = 0; i < cCount; i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
desireHeight += child.getMeasuredHeight();
}
setMeasuredDimension(desireWidth, desireHeight);
}
/**
* 点击item事件回调给监听者
* @author rander
*/
public interface OnExpandItemClick
{
void onItemClick(int position);
void onBottomClick();
}
private OnExpandItemClick mOnExpandItemClick;
public void setOnExpandItemClick(OnExpandItemClick onExpandItemClick) {
this.mOnExpandItemClick = onExpandItemClick;
}
}
该视图的布局R.layout.expand_item_layout如下:
Gridview的Item布局R.layout.gridview_item,就是一个Button
分析好了,写起代码来还是爽歪歪吧。
2.主体控件的实现
我说的主体控件就是这个控件的功能的实现了。
首先:分析主控件包含什么
1)有多少个筛选项List<\View>,这个View就是我们上面定义的ExpandleItemView,针对父类编程,兼容性好。也有人说所有的筛选项复用一个View就行了,是可以,但是没有必要给自己找麻烦。
2)上面有一排按钮,所以需要List<\View>来保存,我这里使用的是ToggleButton,针对父类编程,用View。
3)我们点击的时候总要记住当前筛选的是哪一项,所以我定义了一个ToggleButton记录当前的筛选项mSelectToggleBtn
4)内容的弹出使用PopupWindow,当然需要一个变量
5)还有两个变量,有没有发现选中和不选中的标题颜色是不一样的,所以定义两个变量记录选中的标题颜色和不选中的标题颜色。
总结:其实主控件有这也属性就行啦,当然这里我还定义了两个变量记录了PopupWindow的宽高属性,必要性不是很大。
OK,实现代码如下:
package com.example.expandableview;
import java.util.ArrayList;
import java.util.List;
import com.example.expandableview.ExpandleItemView.OnExpandItemClick;
import android.content.Co