扩展第三方DropDownMenu
找工作之际,静下心总结工作中的想法。
我的简书
原来的效果

#解析结构
导读
想要扩展首先我需要执行下面几个步骤
1.fork DropDownMenu到自己的github账号
2.使用as的vcs checkout出来
3.提交到github
4.发起pull request(还没发)
源码实现原理
作者对该控件的分析 导读
这是我对该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,且不影响下拉功能。
#代码实现细则
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的文本颜色的设置。
效果:就是最上面扩展的效果图
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);
总结
样式性扩展:我们尽量从xml中加载view,根据指定id获取控件,到达最大程度的样式解耦
功能性扩展:将tabViews数组顺序的位置不依赖于父View的child,而是依赖于一个动态的数组。我们对父View的child的添加并不会影响到原来的功能。这样可以做到tabView的功能性扩展
该篇文章代码在 Github上
扩展第三方DropDownMenu的更多相关文章
- Yii 1.1.17 四、属性标签、AR类增删改查、使用上传类与扩展第三方类库
一.属性标签与规则设置 当进入网站页面,将会读数据库返回信息到视图上.那么,现在定义模型中的属性在视图标签上的显示, 也就是模型属性到前台标签的映射 // 定义模型属性到前台标签的映射 public ...
- Java项目中如何扩展第三方jar包中的类?
有些时候你对第三方得到jar包中的类并不是很满意,想根据实际情况做一些扩展.如果说第三方的jar包已经提供了一些可扩展的类,比如提供了Interceptor,Filter或者其他的类,那么使用原生的比 ...
- chrome扩展第三方浏览器下载安装
1.使用其他浏览器打开谷歌应用市场,复制扩展详情地址url 2. 粘贴到:http://chrome-extension-downloader.com/中进行扩展的下载. 3. 拖拽到chrome e ...
- YII 1.0 扩展第三方类
扩展缩略图类在blog\protected\extensions 中建立 Image/CThumb.php 1. 自己瞎弄的,一点都不优雅 include_once Yii::app()->Ba ...
- [ffmpeg 扩展第三方库编译系列] 关于libopenjpeg mingw32编译问题
在mingw32如果想编译libopenjpeg 会比较麻烦 会出现undefined reference to `_imp__opj_destroy_cstr_info@4' 等错误 因此编译时候需 ...
- [ffmpeg 扩展第三方库编译系列] 关于需要用到cmake 创建 mingw32编译环境问题
我在这里给出我编译的例子 cmake -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=& ...
- [ffmpeg 扩展第三方库编译系列] 关于libvpx mingw32编译问题
在编译libvpx的时候遇到挺多的问题, 1.[STRIP] libvpx.a < libvpx_g.a strip: Bad file number 这个错误也是比较难搞的,一开始以为只是 ...
- [ffmpeg 扩展第三方库编译系列] frei0r mingw32 下编译问题
在编译安装frei0r的时候遇到两个错误地方, 两个都是在install的时候. 一开始编译都很顺利,输入了 make install之后就走开了,回来一看,报错误. 提示mkdir -p //usr ...
- [ffmpeg 扩展第三方库编译系列] 关于 mingw32 下编译libcaca
在编译前最好先看一下帮助 ./configure --help 开始编译 ./configure --disable-shared --disable-cxx \ --disable-csharp ...
随机推荐
- 超越css读书笔记
一.运用所有有效的css选择符 1.属性选择符(基于一个元素是否有属性名称,例如href,或者属性值) 例如:img[alt]{border:1px;} 所有包含alt属性的图像都将会有一个灰色的边框 ...
- checkbook全选/反选/全不选
<!doctype html><html lang="en"><head> <meta charset="UTF-8" ...
- STM32F407VG (三)ADC
12位ADC是一种逐次逼近型模拟数字转换器. 它有多达19个通道,可測量16个外部和2个内部信号源和VBAT通道.各通道的A/D转换能够单次.连续.扫描或间断模式运行. ADC的结果能够左对齐或右对齐 ...
- 分享一个用安卓手机就能引导pc安装linux系统办法
1.首先安卓手机下载软件DriveDroid.apk http://pan.baidu.com/s/1qW4pbT6 2.下载linux镜像文件放手机存储卡存储,放到Download/images/以 ...
- node.js url模块
URL url.parse(urlStr[, parseQueryString][, slashesDenoteHost]) url.format(urlObj) url.resolve(from, ...
- for练习--凑法
static void Main14购物卡(string[] args) { //小明单位发了50元的购物卡,他到超市买洗化用品,一是牙刷(5元),二是香皂(2元),三是牙膏(10元)怎么可以正好把五 ...
- python基础之语句结束
1 2 3 4 5 if a : if b: # 这里是if b的作用区间 #这里是if a的作用区间 #这里不在if 区间 python 是按缩进来识别代码块的.
- 安装MYSQL出现的问题
安装MYSQL接近三天了还是没有安装好,原因1:我觉得错误日志产生的原因是因为 计算机的名称是中文名 :小石头 瓦卡卡,果然是这个原因,折腾了三四天,最后换了系统!!!!把计算机名命名成了英文,果然一 ...
- 利用js闭包获取索引号
以tab选项卡效果为例: 网页中的选项卡效果
- 容易上手-类似ERP系统 简单特效
今天大概简单写一个效果, 这个效果 很容易 上手的: html: <style type="text/css">.menu_list ul{display:none;} ...