DropDownMenu仿美团等下拉菜单源码分析
来源:互联网 发布:linux mv 目录非空 编辑:程序博客网 时间:2024/05/12 06:51
前言
最近项目中用到了,多条件可选搜索,因此用到了下拉菜单,效果如下图:
这是一个第三方的控件,在此向作者致敬。项目地址:
https://github.com/dongjunkun/DropDownMenu
作者关于项目的介绍:自己造轮子–android常用多条件筛选菜单实现思路(类似美团,爱奇艺电影票下拉菜单)
之所以将这个自定义控件贴出来,是感觉作者分析问题的能力很强,解决问题的方法也比较巧妙。
源码分析
先分析一下这个视图层级:
这个自定义控件难度不大,但是却很巧妙。弄懂了视图的层级也就搞懂了这个控件的原理。
顶层的菜单布局比较简单,就是一个线性水平布局。
通过对顶层的菜单布局的tab设置点击事件,来决定下方containerView这个FrameLayout布局的显示。
上源码
package com.yyydjk.library;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.TextView;import java.util.List;/** * Created by dongjunkun on 2015/6/17. */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_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); 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); } /** * 初始化DropDownMenu * * @param tabTexts * @param popupViews * @param contentView */ public void setDropDownMenu(@NonNull List<String> tabTexts, @NonNull List<View> 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); } } private void addTab(@NonNull List<String> 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, getResources().getDrawable(menuUnselectedIcon), null); 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()); 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) tabMenuView.getChildAt(current_tab_position)).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) tabMenuView.getChildAt(current_tab_position)).setTextColor(textUnselectedColor); ((TextView) tabMenuView.getChildAt(current_tab_position)).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) { if (target == 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, getResources().getDrawable(menuSelectedIcon), null); } } else { ((TextView) tabMenuView.getChildAt(i)).setTextColor(textUnselectedColor); ((TextView) tabMenuView.getChildAt(i)).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); }}
1 0
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu下拉菜单
- 简单粗暴 下拉菜单 dropdownMenu
- 分享一个 原生javaScript - 用面向对象写的下拉菜单 - DropdownMenu
- android 史上最简单的下拉选择菜单DropDownMenu 几行代码轻松搞定!
- DropDownMenu下拉筛选排序Menu
- 仿DropDownMenu下拉筛选实现
- 下拉菜单的源码
- DropDownMenu
- 下拉列表—DropDownMenu的使用解析
- js源码--多级下拉菜单
- 下拉菜单源码30则
- css加div下拉菜单源码
- 禁用下拉菜单,android5.1源码
- Bootstrap源码解读1 下拉菜单
- android 下拉刷新源码分析
- Thread和Service的区别以及适用场景
- Virtualization Support for RHEL High Availability and Resilient Storage Clusters
- 安装weblogic一直不成功
- Mysql中的date与datetime,以及如何向Mysql中插入“日期+时间”数据
- 建造者模式
- DropDownMenu仿美团等下拉菜单源码分析
- Android studio去掉actionbar
- TabPageIndicator 分割线
- glBlendFunc();--混合
- 通话录音和CoreTelephony框架的简单使用
- Linux - 命令大全
- java给图片添加水印文字
- A Painless Q-learning Tutorial (一个 Q-learning 算法的简明教程)
- [Android] Activity ConfigChanges属性