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向右对齐
使用 ReactJS / Reactstrap 的 DropdownMenu 和 DropdownItem onClick