Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android最牛逼的多條件篩選菜單

Android最牛逼的多條件篩選菜單

編輯:關於Android編程

說明


本來很懶,但是還是會忍不住的寫下這有用既沒有用的所謂技術博客,希望會給你帶來有所啟發,因為這樣的功能,寫的人很多,也是為了自己能夠理解的夠透徹,也是為了大家也能更好的理解吧,其實自定義控件,也就是那麼回事,沒有什麼可難的,好吧,可能是這個太簡單了。
這是58,趕集都用到的控件,這樣的控件,自定義起來其實也並不難,自己項目當中用到了這個,於是就研究了一番,可能在你的項目當中也有可能會遇到這樣的需求,正好,也可以來研究下,說真的,今天你見到的這個效果,比58,和趕集做的效果 要好多了,他們做的真的很low。


效果展示


先來看下他長什麼樣子吧

效果

對,就是這個樣子,今天我們就來看看到底是怎麼做出來的。

思路


整體的所有布局都是用代碼創建出來的,不是寫死在布局文件裡的,這樣會更靈活

創建菜單欄,就是地址呀,年齡,性別的布局,水平的LinearLayout 向菜單欄裡添加布局,就是一個簡單的TextView,和分割線,然後將該布局添加至父控件中,就是最外層布局 創建下劃線,再添加至父控件中 創建內容顯示區,注意,內容顯示區包括上圖中的顯示的內容(這裡是內容區域),還有點擊下拉菜單出來的布局,和半透明的背景,都是在內容區的,他的布局是FrameLayout,注意FrameLayout的特點,有不熟悉他的特點的可以先查一下他的特點,這樣就會更好的理解這個控件的繪制了。 內容顯示區為FrameLayout,他裡面包括3部分,最裡層是真正的的內容顯示區,就是上圖中看到的文字(這裡是內容區域),中間層是半透明區域,就是大家看到的變暗的背景,最外層是點擊下拉菜單之後彈出來的內容

代碼實現


下面將會帶你用代碼我做這個控件的思路

  public class DropDownMenu extends LinearLayout {

    //頂部菜單布局
    private LinearLayout tabMenuView;
    //底部容器,包含popupMenuViews,maskView
    private FrameLayout containerView;
    //彈出菜單父布局
    private FrameLayout popupMenuViews;
    //遮罩半透明View,點擊可關閉DropDownMenu
    private View maskView;
    //tabMenuView裡面選中的tab位置,-1表示未選中
    private int current_tab_position = -1;

    //分割線顏色
    private int dividerColor = 0xffcccccc;
    //tab選中顏色
    private int textSelectedColor = 0xff890c85;
    //tab未選中顏色
    private int textUnselectedColor = 0xff111111;
    //遮罩顏色
    private int maskColor = 0x88888888;
    //tab字體大小
    private int menuTextSize = 14;

    //tab選中圖標
    private int menuSelectedIcon;
    //tab未選中圖標
    private int menuUnselectedIcon;


    public DropDownMenu(Context context) {
        super(context, null);
    }

    public DropDownMenu(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DropDownMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        setOrientation(VERTICAL);

        //為DropDownMenu添加自定義屬性
        int menuBackgroundColor = 0xffffffff;
        int underlineColor = 0xffcccccc;

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DropDownMenu);
        underlineColor = a.getColor(R.styleable.DropDownMenu_underlineColor, underlineColor);
        dividerColor = a.getColor(R.styleable.DropDownMenu_dividerColor, dividerColor);
        textSelectedColor = a.getColor(R.styleable.DropDownMenu_textSelectedColor, textSelectedColor);
        textUnselectedColor = a.getColor(R.styleable.DropDownMenu_textUnselectedColor, textUnselectedColor);
        menuBackgroundColor = a.getColor(R.styleable.DropDownMenu_menuBackgroundColor, menuBackgroundColor);
        maskColor = a.getColor(R.styleable.DropDownMenu_maskColor, maskColor);
        menuTextSize = a.getDimensionPixelSize(R.styleable.DropDownMenu_menuTextSize, menuTextSize);
        menuSelectedIcon = a.getResourceId(R.styleable.DropDownMenu_menuSelectedIcon, menuSelectedIcon);
        menuUnselectedIcon = a.getResourceId(R.styleable.DropDownMenu_menuUnselectedIcon, menuUnselectedIcon);
        a.recycle();

        //初始化tabMenuView並添加到tabMenuView
        tabMenuView = new LinearLayout(context);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        tabMenuView.setOrientation(HORIZONTAL);
        tabMenuView.setBackgroundColor(menuBackgroundColor);
        tabMenuView.setLayoutParams(params);
        addView(tabMenuView, 0);

        //為tabMenuView添加下劃線
        View underLine = new View(getContext());
        underLine.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpTpPx(1.0f)));
        underLine.setBackgroundColor(underlineColor);
        addView(underLine, 1);

        //初始化containerView並將其添加到DropDownMenu
        containerView = new FrameLayout(context);
        containerView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        addView(containerView, 2);

    }

  }

注意下面的成員變量

private LinearLayout tabMenuView;////頂部菜單布局

private FrameLayout containerView;//底部容器,包含popupMenuViews,maskView(暗色背景)

private FrameLayout popupMenuViews;//彈出菜單父布局

private View maskView;//遮罩半透明View,點擊可關閉DropDownMenu

public class DropDownMenu extends LinearLayout {}

也就說整體的布局是繼承自LinearLayout的

setOrientation(VERTICAL);//在第三個構造方法裡指定了整體布局的方向

完成了以上步驟,其實大體上的布局差不多都搭好了,下面就是填充子布局和數據的問題了

    /**
     * 初始化DropDownMenu
     *
     * @param tabTexts
     * @param popupViews
     * @param contentView
     */
    public void setDropDownMenu(@NonNull List tabTexts, @NonNull List popupViews, @NonNull View contentView) {
        if (tabTexts.size() != popupViews.size()) {
            throw new IllegalArgumentException("params not match, tabTexts.size() should be equal popupViews.size()");
        }

        for (int i = 0; i < tabTexts.size(); i++) {
            addTab(tabTexts, i);
        }
        containerView.addView(contentView, 0);

        maskView = new View(getContext());
        maskView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        maskView.setBackgroundColor(maskColor);
        maskView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                closeMenu();
            }
        });
        containerView.addView(maskView, 1);
        maskView.setVisibility(GONE);

        popupMenuViews = new FrameLayout(getContext());
        popupMenuViews.setVisibility(GONE);
        containerView.addView(popupMenuViews, 2);

        for (int i = 0; i < popupViews.size(); i++) {
            popupViews.get(i).setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            popupMenuViews.addView(popupViews.get(i), i);
        }

    }

這一步是對外暴露的方法,專門給菜單欄,填充數據,還有為內容區填充布局的,布局可以填充任何布局,很靈活

addTab(tabTexts, i);這個方法,下面會給出代碼,用來給菜單欄添加布局和菜單欄的分割線的

containerView.addView(contentView, 0);//將傳入的內容布局添加到內容區(默認是顯示的)

containerView.addView(maskView, 1);//添加暗色背景(默認是GONG的)

containerView.addView(popupMenuViews, 2);//將點擊菜單欄後顯示的布局,注意,這個布局裡也有子布局,那就是listview,所以現在是講父布局添加到內容區的(默認是GONG的)

popupMenuViews.addView(popupViews.get(i), i);//這一步才是為點擊菜單欄後顯示的布局填充子布局的,也就是listview

  private void addTab(@NonNull List tabTexts, int i) {
        final TextView tab = new TextView(getContext());
        tab.setSingleLine();
        tab.setEllipsize(TextUtils.TruncateAt.END);
        tab.setGravity(Gravity.CENTER);
        tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, menuTextSize);
        tab.setLayoutParams(new LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
        tab.setTextColor(textUnselectedColor);
        tab.setCompoundDrawablesWithIntrinsicBounds(null, null, null, getResources().getDrawable(menuUnselectedIcon));
        tab.setText(tabTexts.get(i));
        tab.setPadding(dpTpPx(5), dpTpPx(12), dpTpPx(5), dpTpPx(12));
        //添加點擊事件
        tab.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                switchMenu(tab);
            }
        });
        tabMenuView.addView(tab);
        //添加分割線
        if (i < tabTexts.size() - 1) {
            View view = new View(getContext());
            LayoutParams layoutParams = new LayoutParams(dpTpPx(0.5f), dpTpPx(25));
            layoutParams.gravity = Gravity.CENTER_VERTICAL;
            view.setLayoutParams(layoutParams);
            view.setBackgroundColor(dividerColor);
            tabMenuView.addView(view);
        }
    }

這一步是為菜單欄添加布局,和分割線的,還有為菜單欄添加點擊事件,沒有什麼可說的

     /**
     * 切換菜單
     *
     * @param view
     */
    private void switchMenu(View view) {

        for (int i = 0; i < tabMenuView.getChildCount(); i = i + 2) {

            if (view == tabMenuView.getChildAt(i)) {
                if (current_tab_position == i) {
                    closeMenu();
                } else {
                    if (current_tab_position == -1) {
                        popupMenuViews.setVisibility(View.VISIBLE);
                        popupMenuViews.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_menu_in));
                        maskView.setVisibility(VISIBLE);
                        maskView.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_mask_in));
                        popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE);
                    } else {
                        popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE);
                    }
                    current_tab_position = i;
                    ((TextView) tabMenuView.getChildAt(i)).setTextColor(textSelectedColor);
                    ((TextView) tabMenuView.getChildAt(i)).setCompoundDrawablesWithIntrinsicBounds(null, null,
                            null, getResources().getDrawable(menuSelectedIcon));
                }
            } else {
                //設置其他未點擊tab的狀態
                ((TextView) tabMenuView.getChildAt(i)).setTextColor(textUnselectedColor);
                ((TextView) tabMenuView.getChildAt(i)).setCompoundDrawablesWithIntrinsicBounds(null, null,
                        null, getResources().getDrawable(menuUnselectedIcon));
                popupMenuViews.getChildAt(i / 2).setVisibility(View.GONE);
            }
        }
    }

這一步是切換菜單時要做的,只是改變其他狀態而已

用法


做到這,也就意味著,自定義控件寫完了,下面就是如何用他了

布局

 

將上面的布局copy到你的布局裡就ok啦

自定義的屬性

 
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

結束


ok,做到這,就大功告成了,具體的代碼還是以我的Demo為主下面是下載鏈接
DropDownMenuDemo

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved