DropDownMenu下拉菜单

Posted hygok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DropDownMenu下拉菜单相关的知识,希望对你有一定的参考价值。

最近项目要用到一个下拉菜单的功能,网上找了个例子http://www.jcodecraeer.com/a/opensource/2016/0110/3855.html,发现用起来不太方便,这个例子的内容区是外部addview进去的,不好控制实时刷新页面的情况,对控件操作也比较麻烦。然后自己就把别人的例子拿过来修改了一下,就可以在xml里面直接编写UI使用了,使用起来就方便了很多。

 

1,使用预览

<pre name="code" class="html"><com.hyg.dropdownmenu.DropDownMenu
    android:id="@+id/dropDownMenu"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:dddividerColor="@color/gray"
    app:ddmaskColor="@color/mask_color"
    app:ddmenuBackgroundColor="@color/white"
    app:ddmenuSelectedIcon="@mipmap/drop_down_selected_icon"
    app:ddmenuIconToRight="true"
    app:ddmenuTextSize="13sp"
    app:ddmenuUnselectedIcon="@mipmap/drop_down_unselected_icon"
    app:ddtextSelectedColor="@color/drop_down_selected"
    app:ddtextUnselectedColor="@color/drop_down_unselected"
    app:ddunderlineColor="@color/gray"
    >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/dropDownMenu_underLine"
        android:clickable="true"
        android:gravity="center"
        android:text="demo"
        android:textSize="40sp"/>
</com.hyg.dropdownmenu.DropDownMenu>
 
 
只需xml只需简单添加如上代码,必须在
com.hyg.dropdownmenu.DropDownMenu的最外层添加android:layout_below="@id/dropDownMenu_underLine"添加这一行代码,否则内容区会有一部分被顶部菜单覆盖了,这个id名字是在ids里面写死的。 
效果如下图,图片也是从那个例子拿过来的,感谢原作者dongjunkun。  

2,代码分析

能在xml里面添加内容的主要原因是id必须预先写好,使在布局时在xml里面能调用java代码编写的控件,因此在资源文件夹新建一个ids的文件夹写死几个id名字。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="dropDownMenu_tabMenuView" type="id"></item>
    <item name="dropDownMenu_underLine" type="id"></item>
</resources>
菜单列表是从上往下弹出来的,为了能显示从菜单底部弹出列表,菜单就必须在顶层,这里说的菜单是上面图片最上一行的菜单,采用removeView和addView的方法使菜单置于顶层会有些问题,因为remove后,前面与其为参照物的控件的位置就失效了,所以我在底部放置一个view,只要view的高度和菜单栏的高度一样就行了。如果是在dropdownmenu的java文件里面对xml的控件的位置采用 addRule重新设置的,不能显示实时更新,必须要调用 requestLayout方法才可以。
//初始化tabMenuView并添加到tabMenuView的参照物
tabMenuViewButtom = new LinearLayout(context);
tabMenuViewButtom.setId(R.id.dropDownMenu_tabMenuView);
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
addView(tabMenuViewButtom,0);
这写代码就是那个底部的view。,

3,直接上最关键的代码。

package com.hyg.dropdownmenu;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.List;

/**
 * 使用时,在这个布局最外层的view添加android:layout_below="@id/dropDownMenu_underLine"这一行代码。
 * Created by HuangYuGuang on 2016/4/14.
 */
public class DropDownMenu extends RelativeLayout 

    //底层参照物控件,作为其他控件布局时候的相对参照
    private LinearLayout tabMenuViewButtom;
    //顶部菜单布局
    private LinearLayout tabMenuView;
    //底部容器,包含popupMenuViews,maskView
    private View 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;
    //菜单背景色
    private int menuBackgroundColor = 0xffffffff;
    //菜单下面的分割线颜色
    private int underlineColor = 0xffcccccc;
    //菜单的箭头是否靠右边
    private boolean menuIconToRight = false;


    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);

        //为DropDownMenu添加自定义属性
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DropDownMenu);
        underlineColor = a.getColor(R.styleable.DropDownMenu_ddunderlineColor, underlineColor);
        dividerColor = a.getColor(R.styleable.DropDownMenu_dddividerColor, dividerColor);
        textSelectedColor = a.getColor(R.styleable.DropDownMenu_ddtextSelectedColor, textSelectedColor);
        textUnselectedColor = a.getColor(R.styleable.DropDownMenu_ddtextUnselectedColor, textUnselectedColor);
        menuBackgroundColor = a.getColor(R.styleable.DropDownMenu_ddmenuBackgroundColor, menuBackgroundColor);
        maskColor = a.getColor(R.styleable.DropDownMenu_ddmaskColor, maskColor);
        menuTextSize = a.getDimensionPixelSize(R.styleable.DropDownMenu_ddmenuTextSize, menuTextSize);
        menuSelectedIcon = a.getResourceId(R.styleable.DropDownMenu_ddmenuSelectedIcon, menuSelectedIcon);
        menuUnselectedIcon = a.getResourceId(R.styleable.DropDownMenu_ddmenuUnselectedIcon, menuUnselectedIcon);
        menuIconToRight = a.getBoolean(R.styleable.DropDownMenu_ddmenuIconToRight, menuIconToRight);
        a.recycle();

        //初始化tabMenuView并添加到tabMenuView的参照物
        tabMenuViewButtom = new LinearLayout(context);
        tabMenuViewButtom.setId(R.id.dropDownMenu_tabMenuView);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        addView(tabMenuViewButtom,0);

        //为tabMenuView添加下划线
        View underLine = new View(getContext());
        underLine.setId(R.id.dropDownMenu_underLine);
        LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
        lp.addRule(RelativeLayout.BELOW, R.id.dropDownMenu_tabMenuView);
        underLine.setLayoutParams(lp);
        underLine.setBackgroundColor(underlineColor);
        addView(underLine, 1);
    

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

        LayoutParams plp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        plp.addRule(RelativeLayout.BELOW, R.id.dropDownMenu_underLine);

        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();
            
        );
        maskView.setVisibility(GONE);
        maskView.setLayoutParams(plp);
        addView(maskView);

        popupMenuViews = new FrameLayout(getContext());
        popupMenuViews.setVisibility(GONE);
        popupMenuViews.setLayoutParams(plp);
        addView(popupMenuViews);

        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);
        

        //初始化tabMenuView并添加到tabMenuView,为了能tabMenuView使位于顶层,所以最后添加tabMenuView
        tabMenuView = new LinearLayout(getContext());
        tabMenuView.setId(R.id.dropDownMenu_tabMenuView);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        tabMenuView.setOrientation(LinearLayout.HORIZONTAL);
        tabMenuView.setBackgroundColor(menuBackgroundColor);
        tabMenuView.setLayoutParams(params);
        addView(tabMenuView);

        for (int i = 0; i < tabTexts.size(); i++) 
            addTab(tabTexts, i);
        

        //为了使tabMenuViewButtom和tabMenuView的高度一样
        LayoutParams tparams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,tabMenuView.getHeight());
        tabMenuViewButtom.setLayoutParams(tparams);
    

    private void addTab(@NonNull List<String> tabTexts, int i) 
        final TextView tab = new TextView(getContext());
        LinearLayout menuItenmView = new LinearLayout(getContext());
        menuItenmView.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
        menuItenmView.setGravity(Gravity.CENTER);
        menuItenmView.setOrientation(LinearLayout.HORIZONTAL);
        tab.setSingleLine();
        tab.setEllipsize(TextUtils.TruncateAt.END);
        tab.setGravity(Gravity.CENTER);
        tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, menuTextSize);
        if(menuIconToRight)
            tab.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        else
            tab.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        tab.setTextColor(textUnselectedColor);
        tab.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(menuUnselectedIcon), null);
        tab.setText(tabTexts.get(i) + "  ");
        tab.setPadding(dpTpPx(5), dpTpPx(8), dpTpPx(5), dpTpPx(8));
        menuItenmView.addView(tab, 0);
        //添加点击事件
        menuItenmView.setOnClickListener(new OnClickListener() 
            @Override
            public void onClick(View v) 
                switchMenu(tab);
            
        );
        tabMenuView.addView(menuItenmView);
        //添加分割线
        if (i < tabTexts.size() - 1) 
            View view = new View(getContext());
            view.setLayoutParams(new LayoutParams(dpTpPx(0.5f), ViewGroup.LayoutParams.MATCH_PARENT));
            view.setBackgroundColor(dividerColor);
            tabMenuView.addView(view);
        
    

    /**
     * 改变tab文字
     *
     * @param text
     */
    public void setTabText(String text) 
        if (current_tab_position != -1) 
            ((TextView) ((ViewGroup)tabMenuView.getChildAt(current_tab_position)).getChildAt(0)).setText(text+"  ");
        
    

    public void setTabClickable(boolean clickable) 
        for (int i = 0; i < tabMenuView.getChildCount(); i = i + 2) 
            tabMenuView.getChildAt(i).setClickable(clickable);
        
    

    /**
     * 关闭菜单
     */
    public void closeMenu() 
        if (current_tab_position != -1) 
            TextView tab = (TextView) ((ViewGroup)tabMenuView.getChildAt(current_tab_position)).getChildAt(0);
            tab.setTextColor(textUnselectedColor);
            tab.setCompoundDrawablesWithIntrinsicBounds(null, null,
                    getResources().getDrawable(menuUnselectedIcon), null);
            popupMenuViews.setVisibility(View.GONE);
            popupMenuViews.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_menu_out));
            maskView.setVisibility(GONE);
            maskView.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_mask_out));
            current_tab_position = -1;
        

    

    /**
     * DropDownMenu是否处于可见状态
     *
     * @return
     */
    public boolean isShowing() 
        return current_tab_position != -1;
    

    /**
     * 切换菜单
     *
     * @param target
     */
    private void switchMenu(View target) 
        System.out.println(current_tab_position);
        for (int i = 0; i < tabMenuView.getChildCount(); i = i + 2) 
            TextView tab = (TextView) ((ViewGroup)tabMenuView.getChildAt(i)).getChildAt(0);
            if (target == tab) 
                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));
                        View view = popupMenuViews.getChildAt(i / 2);
                        popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE);
                     else 
                        popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE);
                    
                    current_tab_position = i;
                    tab.setTextColor(textSelectedColor);
                    tab.setCompoundDrawablesWithIntrinsicBounds(null, null,
                            getResources().getDrawable(menuSelectedIcon), null);
                
             else 
                tab.setTextColor(textUnselectedColor);
                tab.setCompoundDrawablesWithIntrinsicBounds(null, null,
                        getResources().getDrawable(menuUnselectedIcon), null);
                popupMenuViews.getChildAt(i / 2).setVisibility(View.GONE);
            
        
    

    public int dpTpPx(float value) 
        DisplayMetrics dm = getResources().getDisplayMetrics();
        return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm) + 0.5);
    

 

4,改进

模块经过项目的反复使用过程,又改进了一些,时使用起来更方便快捷了。XML里不用变,java文件了只需添加下面这段代码即可完成菜单的添加。
<pre name="code" class="java">mDropDownMenu1 = (DropDownMenu) findViewById(R.id.dropDownMenu1);
DropDownMenuUtils.addTextList(this, mDropDownMenu1, new DropDownMenuUtils.OnMenuClickListener() 
            @Override
            public void onMenuClick(int viewPosition, int itemPosition) 
                textView.setText(viewPosition+"---"+itemPosition);
            
        , Arrays.asList("全部", "衣服","鞋子"),Arrays.asList("默认排序","升序","降序"),Arrays.asList("好评","差评"));
 
 
  如有还能改进的请大神在评论里面说一下。                 点击下载源码           改进版源码

以上是关于DropDownMenu下拉菜单的主要内容,如果未能解决你的问题,请参考以下文章

下拉菜单

Bootstrap如何让下拉菜单dropdown-menu整体DOM向右对齐

下拉菜单

bootstarap下拉菜单

Bootstrap 关于下拉菜单的使用

使用 ReactJS / Reactstrap 的 DropdownMenu 和 DropdownItem onClick