扩展第三方DropDownMenu v1.5

修改效果

dropdown_demo.gif

解析结构

  • 导读
    想要扩展首先我需要执行下面几个步骤

1.fork DropDownMenu到自己的github账号
2.使用 as 的 vcs checkout 出来
3.提交到github
4.发起 pull request

  • 源码实现原理
    作者对该控件的分析 导读
DropDwonMenu 的结构.png

这是我对该 DropDownMenu 的组成结构进行的图解

DropDownMenu :下拉菜单控件 继承自 LinearLayout
tabMenuView :顶部菜单布局 继承自 LinearLayout
containerView :底部容器,包含 popupMenuViews , maskView 继承自 FrameLayout
popupMenuViews :弹出菜单父布局 继承自 FrameLayout
maskView: 遮罩半透明 View ,点击可关闭 DropDownMenu 继承自 View
contentView :一个页面除了顶部菜单栏以外的所有内容
tabView : ListView → 1 : 1

调用方法基本解析

DropDownMenu :对 tabMenuView 、 containerView 进行初始化
setDropDownMenu :传参为 tabTexts (字符串数组), popupViews ( ListView 数组), contentView (内容 View )。调用 addtab 方法向 tabMenuView 添加 tabView 并设置对应 tabView 点击切换显示 ListView
addTab :循环 tabTexts 文本, TextView 赋值添加到 tabMenuView
switchMenu :切换 tab 调用对应的 popupMenuViews 里面的 ListView 显示,其他的 ListView 隐藏

一般情况下在我们的 UI 图不是对 tab 特别要求的话,那么这种已经符合要求了。但是奈不住它就是不长这样啊。

  • tabView 样式扩展
    有时候 UI 图就是这么可恶,^这个箭头不是靠右,空的那么开。当然我这里只是举一个例子。
箭头居中而不是居最右
  • tabView 功能扩展
    这个需求更加丧心病狂了, tab 不都是下拉框。实现扩展之后可以在 tabMenu 中任意顺序插入自定义的 tabView ,且不影响下拉功能。
可以在 tab 位置中插入自己需要的 tabView

代码实现细则

tabView 样式扩展源码实现

这里我们说这个 dropDownMenu 的 tab 为 TextView 肯定无法达到我们想要的效果了。
那么最差将 tab 换成 LinearLayout ,那么自定义效果就随你自己了。但是我们就这样实现的话肯定性能跟原来有些差距。那么这个库 tab 都默认是 viewGroup 多渲染了一层,我们能不能在用的时候,自己定义的 tab_item.xml。 xml 中我们想要 viewGroup 就写 ViewGroup 包裹,想只要 TextView 就只有 TextView 。
其实我们只需要定义 id 约束, xml 中 TextView 必须指定为(例如)R.id.tv_tab。 DropDownMenu 底层在设置 tab 的内容的时候多一步操作,加载指定的 tab_laytou.xml,然后如果是 ViewGroup 就 findViewById 找到 TextView ,否则就直接转成 TextView 。

1.addTab()方法从代码中直接 new TextView 改成从 layout 中加载
2.将原来 tabView ( textView )相关的设置代码全部先用获取 textView 的过滤方法筛选一下 textView

这里只截取关键代码
原 addTab()

    private void addTab(@NonNull List<String> tabTexts, int i) {
        final TextView tab = new TextView(getContext());
        ...//tab的样式设置
        tab.setText(tabTexts.get(i));
        tab.setPadding(dpTpPx(5), dpTpPx(12), dpTpPx(5), dpTpPx(12));
        //添加点击事件
        ...
        tabMenuView.addView(tab);
        //添加分割线
        ...
    }

改 addTab()

    private void addTab(@NonNull List<String> tabTexts, int i) {
        View tab = inflate(getContext(), R.layout.tab_item, null);
        tab.setLayoutParams(new LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
        ...//样式设置
        tabMenuView.addView(tab);
        //添加分割线
        ...
    }

增加 tab_item.xml( viewGroup 包含 textView / 只是 textView ) ,样式的可扩展性大大增强

<!-----------ViewGroup------------------>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:gravity="center">

    <TextView
        android:id="@+id/tv_tab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawablePadding="7dp"
        android:gravity="center"
        android:paddingBottom="12dp"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:paddingTop="12dp"
        android:text="adfad"
        android:textColor="#26a8e0" />
</LinearLayout>
<!-------或者只有TextView,也没有问题---------------------->
<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/tv_tab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawablePadding="7dp"
    android:gravity="center"
    android:paddingBottom="12dp"
    android:paddingLeft="5dp"
    android:paddingRight="5dp"
    android:paddingTop="12dp"
    android:textColor="#26a8e0"
    xmlns:android="http://schemas.android.com/apk/res/android" />

过滤获取 TextView 方法

    /**
     * 获取tabView中id为tv_tab的textView
     *
     * @param tabView
     * @return
     */
    private TextView getTabTextView(View tabView) {
        TextView tabtext = (TextView) tabView.findViewById(R.id.tv_tab);
        return tabtext;
    }

hint: 然后代码中凡是涉及到设置 tab textView 相关设置的地方都需要先用我这个方法过滤,替换一下。主要有这么几个地方,初始化设置 tab ,选中 List 单项确定设置 tab ,打开和关闭菜单对 tab 的文本颜色的设置。
效果:就是最上面扩展的效果图
插曲:
赵萝贝要求加了箭头在文本的方向属性

icon方向属性

效果图

jeff_sun要求添加了可以控制分隔线的高度的属性

分隔线高度属性

效果图

还是这位 jeff_sun (ps: 你们公司 UI 要求真特殊),应他的要求为 popupWindows 集合的 view 增加了对 LayoutParams 的支持。
代码图

效果图

tabView 功能扩展源码实现

从上面可以知道,现在 tabMenuView 的 tab 和 popupMenuViews 的 ListView 的数量是相同的。而现在我们要实现的是 tabMenuView 中 tab 的数量> popupMenuViews 的 ListView 的数量。多的那部分 tabView 就只是展示的功能,不会触发点击下拉展示。
  另外因为 tabtexts 文本是作为数组顺序添加的。所以我们需要用 dropTabViews 类记录 tabtexts 添加的顺序。当点击了一个 tabView 看是否存在于 dropTabViews 数组中,不存在就不处理,存在就 indexOf 获取当前 tabView 在 dropTabViews 中的顺序然后去对应找 ListView 。这样处理之后, tabMenuView 设置 tabtexts 之后就可以随便在哪个位置上插入需要的 tabView 样式了,且不影响功能。

1. 创建记录 tabtexts 顺序的而创建的 tabView 数组
2. 在 switchMenu 切换 popupMenuViews 的 ListView 的获取方式要过滤一下

旧 switchMenu 方法

   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)) {//找到点击到的tabView
                if (current_tab_position == i) {//点击的view是原来显示的tabView则关闭菜单
                    closeMenu();
                } else {//不是,就显示菜单
                    if (current_tab_position == -1) {
                        ...
                        popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE);
                    } else {
                        popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE);
                    }
                    ...
                }
            } else {//没找到就颜色等属性设置成普通
                TextView textView = getTabTextView(tabMenuView.getChildAt(i));
                textView.setTextColor(textUnselectedColor);
                textView.setCompoundDrawablesWithIntrinsicBounds(null, null,
                        getResources().getDrawable(menuUnselectedIcon), null);
                popupMenuViews.getChildAt(i / 2).setVisibility(View.GONE);
            }
        }
    }

修改的 switchMenu 方法

 private void switchMenu(View target) {
        for (int i = 0; i < tabMenuView.getChildCount(); i = i + 2) {
            if (target == tabMenuView.getChildAt(i)) {//找到点击到的tabView
                if (current_tab_position == i) {//点击的view是原来显示的tabView则关闭菜单
                    closeMenu();
                } else {//不是,就显示菜单
                    ...
                    View listView = getListView(tabMenuView.getChildAt(i));
                    if (listView != null) {
                        listView.setVisibility(View.VISIBLE);
                    }
                    ...
                }
            } else {//没找到就颜色等属性设置成普通
                TextView textView = getTabTextView(tabMenuView.getChildAt(i));
                View listView = getListView(tabMenuView.getChildAt(i));
                if (listView != null) {
                    if(textView!=null){
                        textView.setCompoundDrawablesWithIntrinsicBounds(null, null,
                                getResources().getDrawable(menuUnselectedIcon), null);
                    }
                    listView.setVisibility(View.GONE);
                }
            }
        }
    }

addTab 进一步修改

    private void addTab(@NonNull List<String> tabTexts, int i) {
       ...
        dropTabViews.add(tab);//记录创建的添加顺序
    }

新增 getListView 方法

    /**
     * 获取dropTabViews中对应popupMenuViews数组中的ListView
     *
     * @param view
     * @return
     */
    private View getListView(View view) {
        if (dropTabViews.contains(view)) {
            int index = dropTabViews.indexOf(view);
            return popupMenuViews.getChildAt(index);
        } else {
            return null;
        }
    }

调用演示 MainActivity.java

      mDropDownMenu.setDropDownMenu(Arrays.asList(headers), popupViews, contentView);
        //测试tabView扩展功能
        TextView textView= (TextView) getLayoutInflater().inflate(R.layout.tab_text,null);
        textView.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
        textView.setText("2位置");
        mDropDownMenu.addTab(textView,2);
使用方式

Paste_Image.png

新增tabMenu点击回调接口

ItemMenu.png

总结

样式性扩展:我们尽量从 xml 中加载 view ,根据指定 id 获取控件,到达最大程度的样式解耦
功能性扩展:将 tabViews 数组顺序的位置不依赖于父 View 的 child ,而是依赖于一个动态的数组。我们对父 View 的 child 的添加并不会影响到原来的功能。这样可以做到 tabView 的功能性扩展

该篇文章代码在 Github上

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,612评论 4 59
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一种新的协议。它实...
    香橙柚子阅读 22,956评论 8 183
  • 我叫肖丝丝。 25岁的年纪里, 遇见一个叫何小锦的男人, 还小我两岁。 我从未试过姐弟恋, 我甚至并不能照顾好自己...
    肖丝丝阅读 244评论 0 0
  • 01 有趣的灵魂万里挑一 今天听老师讲写作课,主题是我特别感兴趣的“如何写出一篇具有吸引力的文章?”说心里话,也许...
    富兰克刘阅读 905评论 18 25
  • 大雨 积成了水洼 深一脚 浅一脚 摇摇晃晃向前走着 雨水泼在伞上 散开 慌乱往下爬 有几滴来不及跑开 从中间掉了下...
    水色森森阅读 245评论 1 0