Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 自定義分層級篩選控件

Android 自定義分層級篩選控件

編輯:關於Android編程

今天下午寫了一個分層級篩選控件,效果如下
這裡寫圖片描述
該控件由兩部分組成:
1.上面一排的篩選標題按鈕(就是四個toggleButton,根據篩選項的數量動態追加)
2.點擊篩選按鈕彈出來的篩選內容(一個Popupwindow,它包含一個Gridview和一個Button)

需求開發點:
1.單個篩選項內容視圖的生成,也就是那個PZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcHVwd2luZG93tcTE2sjdtcTJ+rPJPGJyIC8+DQoyLtb3v9i8/rXEyrXP1qOsuPm+3cm40aHP7rXEyv3Bv7avzO2808nPw+bSu8XFxNrI3aOo1eLA78rHy8S49sm40aHP7qOpo6yyosfSudjBqrrDw7/Su7j2ybjRoc/uoaM8L3A+DQo8cD4xLrWluPa1r7P2xNrI3crTzby1xMn6s8k8YnIgLz4NCs7Sy7W1xLWluPbK08281ri1xMrHz8LD5rrsv/K/8rK/t9Y8YnIgLz4NCjxpbWcgYWx0PQ=="這裡寫圖片描述" src="/uploadfile/Collfiles/20160328/20160328090803154.png" title="\" />
首先分析,單個視圖包含什麼?
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.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如下:




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



    
    

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()));
    }
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved