android自定义选年控件,Android 自定义分层级罗选控件

今天下午写了一个分层级筛选控件,效果如下

1343301101.gif

该控件由两部分组成:

1.上面一排的筛选标题按钮(就是四个toggleButton,根据筛选项的数量动态追加)

2.点击筛选按钮弹出来的筛选内容(一个Popupwindow,它包含一个Gridview和一个Button)

需求开发点:

1.单个筛选项内容视图的生成,也就是那个Popupwindow的内容的生成

2.主控件的实现,根据筛选项的数量动添加上面一排内容(这里是四个筛选项),并且关联好每一个筛选项。

1.单个弹出内容视图的生成

我说的单个视图指的是下面红框框部分

1343301102.png

首先分析,单个视图包含什么?

1)一个Gridview

2)一个底部Button

3)可筛选的数据List指的是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如下:

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:columnWidth="90dp"

android:gravity="center"

android:horizontalSpacing="10dp"

android:numColumns="auto_fit"

android:stretchMode="columnWidth"

android:descendantFocusability="blocksDescendants"

android:verticalSpacing="10dp" />

layout="@layout/line" />

android:layout_width="match_parent"

android:layout_height="50dp"

android:background="@drawable/bottom_selector"

android:text="全部"

android:textColor="@color/grey"

android:textSize="18dp" />

Gridview的Item布局R.layout.gridview_item,就是一个Button

android:id="@+id/item_text"

android:layout_width="wrap_content"

android:layout_height="40dp"

android:paddingLeft="20dp"

android:paddingRight="20dp"

android:gravity="center"

android:focusable="false"

android:clickable="false"

android:background="@drawable/btn_selctor"

>

分析好了,写起代码来还是爽歪歪吧。

2.主体控件的实现

我说的主体控件就是这个控件的功能的实现了。

首先:分析主控件包含什么

1)有多少个筛选项List,这个View就是我们上面定义的ExpandleItemView,针对父类编程,兼容性好。也有人说所有的筛选项复用一个View就行了,是可以,但是没有必要给自己找麻烦。

2)上面有一排按钮,所以需要List来保存,我这里使用的是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.Context;

import android.graphics.Color;

import android.graphics.drawable.BitmapDrawable;

import android.util.AttributeSet;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.LinearLayout;

import android.widget.PopupWindow;

import android.widget.PopupWindow.OnDismissListener;

import android.widget.RelativeLayout;

import android.widget.ToggleButton;

public class ExpandableView extends LinearLayout implements OnExpandItemClick {

/** 记录选中的ToggleButton */

private ToggleButton mSelectToggleBtn;

/** 筛选 */

private List mToggleButtons = new ArrayList<>();

/** 筛选项集合 */

private List mPopupviews;

/** popupwindow展示的宽 */

private int mDisplayWidth;

/** popupwindow展示的高 */

private int mDisplayHeight;

/** 筛选内容用PopupWindow弹出来 */

private PopupWindow mPopupWindow;

private Context mContext;

/** toggleButton正常的字体颜色 */

int mNormalTextColor = getResources().getColor(R.color.grey);

/** toggleButton被选中的类型字体颜色 */

int mSelectTextColor = Color.RED;

public ExpandableView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

public ExpandableView(Context context, AttributeSet attrs) {

this(context, attrs, -1);

}

public ExpandableView(Context context) {

this(context, null);

}

private void init() {

setOrientation(LinearLayout.HORIZONTAL);

mDisplayWidth = getResources().getDisplayMetrics().widthPixels;

mDisplayHeight = getResources().getDisplayMetrics().heightPixels;

mContext = getContext();

setBackgroundResource(R.drawable.choosearea_bg_right);

}

/**

* 初始化数据和布局,做的工作如下: 1.根据筛选项的数量,动态增加上面一排ToggleButton 2.设置每一个ToggleButton的监听事件

* 3.toggleButton.setTag(i)这一句非常重要,我们取View数据都是根据这个tag取的 4.

*

*@param views

*/

public void initViews(List views) {

mPopupviews = new ArrayList<>();

LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

for (int i = 0; i < views.size(); i++) {

ExpandleItemView view = views.get(i);

view.setOnExpandItemClick(this);

final RelativeLayout r = new RelativeLayout(mContext);

RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,

RelativeLayout.LayoutParams.WRAP_CONTENT);

r.addView(view, rl);

mPopupviews.add(r);

final ToggleButton toggleButton = (ToggleButton) inflater.inflate(R.layout.toggle_button, this, false);

toggleButton.setText(view.getTitle());

mToggleButtons.add(toggleButton);

addView(toggleButton);

toggleButton.setTag(i);

toggleButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

/** 记录选中的ToggleButton,有了这个什么都好办 */

mSelectToggleBtn = toggleButton;

showPopWindow();

}

});

/**

* 点击popupwindow外部,就隐藏popupwindow,这个r是点击事件包裹了一个ExpandleItemView

* 如果用户所点之处为ExpandleItemView所在范围,点击事件由ExpandleItemView,如果点到

* ExpandleItemView外面,则有r处理,处理方式就是收缩

*/

r.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

onPressBack();

}

private void onPressBack() {

hidePopWindow();

}

});

}

}

/**

* 隐藏popupWindow,并且重置ToggleButton字体颜色

*/

private void hidePopWindow() {

if (mPopupWindow != null) {

mPopupWindow.dismiss();

}

if (mSelectToggleBtn != null) {

mSelectToggleBtn.setTextColor(mNormalTextColor);

mSelectToggleBtn.setChecked(false);

}

}

/**

* 显示popupWindow

*/

private void showPopWindow() {

if (null == mPopupWindow) {

mPopupWindow = new PopupWindow(mPopupviews.get((int) mSelectToggleBtn.getTag()), mDisplayWidth,

mDisplayHeight);

/** 监听popupWindow的收缩,并重置字体颜色 */

mPopupWindow.setOnDismissListener(new OnDismissListener() {

@Override

public void onDismiss() {

if (mSelectToggleBtn != null) {

mSelectToggleBtn.setTextColor(mNormalTextColor);

mSelectToggleBtn.setChecked(false);

}

}

});

mPopupWindow.setAnimationStyle(R.style.PopupWindowAnimation);

mPopupWindow.setFocusable(true);

mPopupWindow.setOutsideTouchable(true);

mPopupWindow.setBackgroundDrawable(new BitmapDrawable());

} else {

mPopupWindow.setContentView(mPopupviews.get((int) mSelectToggleBtn.getTag()));

}

if (mPopupWindow.isShowing()) {

hidePopWindow();

} else {

/** 显示的时候,设为选中颜色 */

mSelectToggleBtn.setTextColor(mSelectTextColor);

mPopupWindow.showAsDropDown(mToggleButtons.get(0), 0, 0);

}

}

/**

* Item项选中的回调 注意Tag的使用 筛选项视图是根据tag拿的,因为mSelectToggleBtn的tag就是视图的索引

* mSelectToggleBtn显示筛选的内容

*/

@Override

public void onItemClick(int position) {

hidePopWindow();

if (null != mSelectToggleBtn) {

int selectBtnIndex = (int) mSelectToggleBtn.getTag();

mSelectToggleBtn

.setText(((ExpandleItemView) (((RelativeLayout) mPopupviews.get(selectBtnIndex)).getChildAt(0)))

.getmGridviewDatas().get(position));

}

}

/**

* 底部按钮点击的回调 mSelectToggleBtn显示筛选的内容

*/

@Override

public void onBottomClick() {

hidePopWindow();

if (null != mSelectToggleBtn) {

int selectBtnIndex = (int) mSelectToggleBtn.getTag();

mSelectToggleBtn

.setText((((ExpandleItemView) (((RelativeLayout) mPopupviews.get(selectBtnIndex)).getChildAt(0)))

.getTitle()));

}

}

}

上面使用的单个ToggleButton的视图R.layout.toggle_button如下:

android:layout_width="match_parent"

android:layout_height="40dp"

android:layout_weight="1"

android:background="@null"

android:drawablePadding="-10dp"

android:drawableRight="@drawable/index_icon_targetdown_grey"

android:gravity="center"

android:paddingRight="20dp"

android:singleLine="true"

android:textColor="@color/grey"

android:textOff="@null"

android:textOn="@null"

android:textSize="16sp"

android:textStyle="bold" >

接下来就是使用了,使用的布局如下:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/expandview"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal" >

Activity代码如下:

package com.example.expandableview;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.LinkedHashMap;

import java.util.Map;

import android.app.Activity;

import android.os.Bundle;

public class MainActivity extends Activity {

private ExpandableView mExpandableView;

private Map mExpandleItemViews;

private String[] mColleages = { "A学校", "B学校", "C学校", "D学校", "E学校", "F学校", "G学校", "H学校", "I学校", "J学校" };

private String[] mDepartments = { "A系", "B系", "C系", "D系", "E系", "F系", "G系", "H系" , "I系" };

private String[] mProfessions = { "A专业", "B专业", "C专业" , "D专业" , "E专业" , "F专业" };

private String[] mClasses = { "A班", "B班", "C班", "D班" , "E班" };

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mExpandableView = (ExpandableView) findViewById(R.id.expandview);

mExpandleItemViews = new LinkedHashMap<>();

//不要问我为什么这么用,因为我想用LinkedHashMap

mExpandleItemViews.put("大学", new ExpandleItemView("大学", this, Arrays.asList(mColleages)));

mExpandleItemViews.put("院系", new ExpandleItemView("院系", this, Arrays.asList(mDepartments)));

mExpandleItemViews.put("专业", new ExpandleItemView("专业", this, Arrays.asList(mProfessions)));

mExpandleItemViews.put("班级", new ExpandleItemView("班级", this, Arrays.asList(mClasses)));

mExpandableView.initViews(new ArrayList<>(mExpandleItemViews.values()));

}

}

使用起来如此easy,效果就是上面看到的效果了

源码下载地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值