DropDownMenu仿美团等下拉菜单源码分析
来源:互联网 发布:lol韩服数据库 编辑:程序博客网 时间:2024/05/19 16: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.
*/
publicclass 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,
intdefStyleAttr) {
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 =
newLinearLayout(context);
LayoutParams params =
newLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
tabMenuView.setOrientation(HORIZONTAL);
tabMenuView.setBackgroundColor(menuBackgroundColor);
tabMenuView.setLayoutParams(params);
addView(tabMenuView,
0);
//为tabMenuView添加下划线
View underLine =
newView(getContext());
underLine.setLayoutParams(
newLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpTpPx(
1.0f)));
underLine.setBackgroundColor(underlineColor);
addView(underLine,
1);
//初始化containerView并将其添加到DropDownMenu
containerView =
newFrameLayout(context);
containerView.setLayoutParams(
newFrameLayout.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
(
inti =
0; i < tabTexts.size(); i++) {
addTab(tabTexts, i);
}
containerView.addView(contentView,
0);
maskView =
newView(getContext());
maskView.setLayoutParams(
newFrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
maskView.setBackgroundColor(maskColor);
maskView.setOnClickListener(
newOnClickListener() {
@Override
public
void
onClick
(View v) {
closeMenu();
}
});
containerView.addView(maskView,
1);
maskView.setVisibility(GONE);
popupMenuViews =
newFrameLayout(getContext());
popupMenuViews.setVisibility(GONE);
containerView.addView(popupMenuViews,
2);
for
(
inti =
0; i < popupViews.size(); i++) {
popupViews.get(i).setLayoutParams(
newViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
popupMenuViews.addView(popupViews.get(i), i);
}
}
private
void
addTab
(@NonNull List<String> tabTexts,
inti) {
final
TextView tab =
newTextView(getContext());
tab.setSingleLine();
tab.setEllipsize(TextUtils.TruncateAt.END);
tab.setGravity(Gravity.CENTER);
tab.setTextSize(TypedValue.COMPLEX_UNIT_PX,menuTextSize);
tab.setLayoutParams(
newLayoutParams(
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(
newOnClickListener() {
@Override
public
void
onClick
(View v) {
switchMenu(tab);
}
});
tabMenuView.addView(tab);
//添加分割线
if
(i < tabTexts.size() -
1) {
View view =
newView(getContext());
view.setLayoutParams(
newLayoutParams(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
(
booleanclickable) {
for
(
inti =
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
(
inti =
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
(
floatvalue) {
DisplayMetrics dm = getResources().getDisplayMetrics();
return
(
int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm) +
0.5);
}
}
0 0
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu仿美团等下拉菜单源码分析
- DropDownMenu下拉菜单
- 简单粗暴 下拉菜单 dropdownMenu
- 分享一个 原生javaScript - 用面向对象写的下拉菜单 - DropdownMenu
- android 史上最简单的下拉选择菜单DropDownMenu 几行代码轻松搞定!
- DropDownMenu下拉筛选排序Menu
- 仿DropDownMenu下拉筛选实现
- 下拉菜单的源码
- DropDownMenu
- 下拉列表—DropDownMenu的使用解析
- js源码--多级下拉菜单
- 下拉菜单源码30则
- css加div下拉菜单源码
- 禁用下拉菜单,android5.1源码
- Bootstrap源码解读1 下拉菜单
- android 下拉刷新源码分析
- 高通gobi系列modem
- 自己造轮子--android常用多条件筛选菜单实现思路(类似美团,爱奇艺电影票下拉菜单)
- Java、SQLServer 根据经纬度计算距离
- java如何判断char类型是否为空-CSDN论坛-CSDN.NET-中国最大的IT技术社区
- 聊聊高并发系统之HTTP缓存
- DropDownMenu仿美团等下拉菜单源码分析
- Android 登录账户密码 输入框,可清空输入信息,显隐藏密码
- 架构师于小波:魅族实时消息推送架构
- iOS应用支持IPV6,就那点事儿
- 查找练习 hash——出现过的数字
- Linux下共享内存相关函数
- 第八天:JAVA中的继承
- 一个实用的多条件筛选菜单,在很多App上都能看到这个效果,如美团,爱奇艺电影票等.
- Android状态栏微技巧,带你真正理解沉浸式模式