手把手教您撸一个底部中心凸起的可以添加通知条数的底栏(安卓APP底栏点击第一次选中当前Fragment第二次点击更新当前页面(实现))
2017-09-26 13:09
856 查看
首先我们来看下实现之后的效果动图:
效果还可以吧?哈哈!
下面我们就来一步步做这个效果,这里面的坑还是比较多的,可能文章中大家体验不到,但是在做的时候确实会有很多问题,我这里会在文章中给大家写出来的!
首先,我们来写布局文件,有同学可能会问了,这个功能页面不是可以用RadioButton+RadioGroup的形式做出来吗,那是之前一贯的做法,这种做法确实行之有效,它的最大优势在于屏蔽了大家在底栏单选时候的逻辑,直接设置RadioButton的id相同就能实现单选效果(看不懂这段话的同学们面壁思过去!),我们这里的思路是,将困难分解,并且逐个击破,底下的每个item都是一个小的布局:
学习平台这里,咱们作为例子,布局如下:
其他四个模块大家请自行脑补一下!除了id和selector不同,其他都是保持一致的!
咱们继续,我们这里把高度写死
大家不要吐槽为啥会写死了,因为基本上都是写死的,这种布局始终会在当前页面的最下面,图片和文字大小也一般会固定,所以常规来说都是这样。
下面本文第一个重点来了,中间这种突出的底栏怎么做?
其实大家觉得难正常,因为没有找到思路呗,其实只需要在当前底栏布局设置一个参数即可:
下面贴出来视频选项的完整代码:
接下来贴出来完整的布局代码:
就这样基本的就能跑起来了。
这里的布局有个坑啊,就是当前页面如果用相对布局,把底栏放在最下面,然后上面的布局(一般是Fragment)切换,直接写成above会形成一个覆盖,底栏中间的视频模块会被覆盖,这里因为底栏写死了高度,我就直接marginBottom了,很好的解决了这个问题!
但是大家会发现这样做的话是没有点击逻辑的,是的,因为我们这边是使用普通布局来做的,这样有个好处就是灵活性比较强,但是有个缺点就是需要去自己处理点击的逻辑。
下面来说说解决思路:
每次点击我们都可以得到相应的事件,如果单个控件去添加监听,非常的麻烦,我们这里通过一个巧妙的办法来注册监听事件:
我们通过获取底部的最外层布局,然后遍历到每个子布局,接着添加点击事件就可以了:
然后呢?我们来处理下底栏选中和为被选中的逻辑:
我们是通过设置Enable以及Disable来设置额,非常方便。
好的,基本上主要的代码逻辑已经说完,下面我们来聊一聊底栏上的数字红点。
其实,我第一次碰到这个红点的时候也是没啥思路,但时候来发现TextView可以设置背景色,后来突发奇想,能不能设置红色圆形的shape,然后直接设置图片上的数字就可以实现这种效果?事实证明这种想法是可行的,而且非常容易实现。
首先看下布局:
关于这里的消息更新,我提一句,直接用EventBus即可,在主页面BaseActivity注册,然后Subscribe一下,相应一下之后更新数字就行!
代码是最好的老师,下面放出代码:
MyBottomListShowTest,点击打开链接
加油!
永远不是别人说你什么样,你就是什么样,而是你想成为什么样,才会成为什么样!
效果还可以吧?哈哈!
下面我们就来一步步做这个效果,这里面的坑还是比较多的,可能文章中大家体验不到,但是在做的时候确实会有很多问题,我这里会在文章中给大家写出来的!
首先,我们来写布局文件,有同学可能会问了,这个功能页面不是可以用RadioButton+RadioGroup的形式做出来吗,那是之前一贯的做法,这种做法确实行之有效,它的最大优势在于屏蔽了大家在底栏单选时候的逻辑,直接设置RadioButton的id相同就能实现单选效果(看不懂这段话的同学们面壁思过去!),我们这里的思路是,将困难分解,并且逐个击破,底下的每个item都是一个小的布局:
学习平台这里,咱们作为例子,布局如下:
<FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@color/colorTitleBlack"> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="学习平台" android:textColor="@color/main_bottom_tv_color"/> <ImageView android:id="@+id/imageView" android:layout_width="35dp" android:layout_height="35dp" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" android:background="@android:color/transparent" android:src="@drawable/study_selector"/> </FrameLayout>看不懂的同学自己打自己一下!嗯!
其他四个模块大家请自行脑补一下!除了id和selector不同,其他都是保持一致的!
咱们继续,我们这里把高度写死
android:layout_height="65dp"
大家不要吐槽为啥会写死了,因为基本上都是写死的,这种布局始终会在当前页面的最下面,图片和文字大小也一般会固定,所以常规来说都是这样。
下面本文第一个重点来了,中间这种突出的底栏怎么做?
其实大家觉得难正常,因为没有找到思路呗,其实只需要在当前底栏布局设置一个参数即可:
android:clipChildren="false"
下面贴出来视频选项的完整代码:
<FrameLayout android:id="@+id/ll_first" android:layout_width="0dp" android:layout_height="90dp" android:layout_weight="1" android:background="@android:color/transparent" android:clipChildren="false"> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="视频" android:textColor="@color/main_bottom_tv_color"/> <ImageView android:id="@+id/iv_circle_video" android:layout_width="match_parent" android:layout_height="70dp" android:background="@android:color/transparent" android:src="@drawable/video_selector"/> </FrameLayout>
接下来贴出来完整的布局代码:
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" > <data></data> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:orientation="vertical"> <FrameLayout android:id="@+id/main_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="65dp"/> <LinearLayout android:id="@+id/main_bottome_switcher_container" android:layout_width="match_parent" android:layout_height="65dp" android:layout_alignParentBottom="true" android:background="@color/colorTitleBlack" android:clipChildren="false" android:gravity="bottom" android:orientation="horizontal"> <FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@color/colorTitleBlack"> <TextView android:layout_width="20dp" android:layout_height="20dp" android:layout_gravity="right" android:background="@drawable/bg_red_point_style" android:gravity="center" android:text="99+" android:textColor="@color/colorTitleWhite" android:textSize="10sp" android:visibility="gone"/> <ImageView android:layout_width="35dp" android:layout_height="35dp" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" android:background="@android:color/transparent" android:src="@drawable/store_selector"/> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="商城" android:textColor="@color/main_bottom_tv_color"/> </FrameLayout> <FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@color/colorTitleBlack"> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="学习平台" android:textColor="@color/main_bottom_tv_color"/> <ImageView android:id="@+id/imageView" android:layout_width="35dp" android:layout_height="35dp" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" android:background="@android:color/transparent" android:src="@drawable/study_selector"/> </FrameLayout> <FrameLayout android:id="@+id/ll_first" android:layout_width="0dp" android:layout_height="90dp" android:layout_weight="1" android:background="@android:color/transparent" android:clipChildren="false"> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="视频" android:textColor="@color/main_bottom_tv_color"/> <ImageView android:id="@+id/iv_circle_video" android:layout_width="match_parent" android:layout_height="70dp" android:background="@android:color/transparent" android:src="@drawable/video_selector"/> </FrameLayout> <FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@color/colorTitleBlack" android:visibility="gone"> <ImageView android:layout_width="match_parent" android:layout_height="50dp" android:background="@android:color/transparent" android:src="@drawable/live_selector"/> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="直播" android:textColor="@color/main_bottom_tv_color"/> </FrameLayout> <FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@color/colorTitleBlack"> <ImageView android:layout_width="35dp" android:layout_height="35dp" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" android:background="@android:color/transparent" android:src="@drawable/robot_selector"/> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="语音" android:textColor="@color/main_bottom_tv_color"/> </FrameLayout> <FrameLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@color/colorTitleBlack"> <ImageView android:layout_width="match_parent" android:layout_height="32dp" android:layout_marginTop="5dp" android:background="@android:color/transparent" android:src="@drawable/person_selector"/> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="bottom" android:gravity="center" android:text="个人中心" android:textColor="@color/main_bottom_tv_color"/> </FrameLayout> </LinearLayout> </RelativeLayout> </layout>
就这样基本的就能跑起来了。
这里的布局有个坑啊,就是当前页面如果用相对布局,把底栏放在最下面,然后上面的布局(一般是Fragment)切换,直接写成above会形成一个覆盖,底栏中间的视频模块会被覆盖,这里因为底栏写死了高度,我就直接marginBottom了,很好的解决了这个问题!
但是大家会发现这样做的话是没有点击逻辑的,是的,因为我们这边是使用普通布局来做的,这样有个好处就是灵活性比较强,但是有个缺点就是需要去自己处理点击的逻辑。
下面来说说解决思路:
每次点击我们都可以得到相应的事件,如果单个控件去添加监听,非常的麻烦,我们这里通过一个巧妙的办法来注册监听事件:
我们通过获取底部的最外层布局,然后遍历到每个子布局,接着添加点击事件就可以了:
//初始化布局 private void initViews() { int count = binding.mainBottomeSwitcherContainer.getChildCount(); for (int i = 0; i < count; i++) { FrameLayout childAt = (FrameLayout) binding.mainBottomeSwitcherContainer.getChildAt(i); childAt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int index = binding.mainBottomeSwitcherContainer.indexOfChild(view); } }); } // binding.civVideo.setOnClickListener(new View.OnClickListener() { // @Override // public void onClick(View view) { // startFragmentAdd(2); // changeUI(2); // } // }); }
然后呢?我们来处理下底栏选中和为被选中的逻辑:
//通过点击的时候来改变底部导航栏的UI private void changeUI(int index) { // ToastUtil.showText(MainActivity.this, index + ""); // if (index == 2) { // binding.civVideo.setImageResource(R.mipmap.video_on); // } else { // binding.civVideo.setImageResource(R.mipmap.video_off); // } if (beforePosition != -1) { if (beforePosition == index) { //这里大家可以加上底栏二次点击你想要实现相应的操作 } } int childCount = binding.mainBottomeSwitcherContainer.getChildCount(); for (int i = 0; i < childCount; i++) { if (i == index) { setEnable(binding.mainBottomeSwitcherContainer.getChildAt(i), false); } else { setEnable(binding.mainBottomeSwitcherContainer.getChildAt(i), true); } } beforePosition = index; } /** * 将每个Item中的所用控件状态一同改变 * 由于我们处理一个通用的代码,那么Item可能会有很多层,所以我们需要使用递归 * * @param item * @param b */ private void setEnable(View item, boolean b) { if (!(item instanceof FrameLayout)) { item.setEnabled(b); } else { item.setEnabled(true); } if (item instanceof ViewGroup) { int childCount = ((ViewGroup) item).getChildCount(); for (int i = 0; i < childCount; i++) { setEnable(((ViewGroup) item).getChildAt(i), b); } } }
我们是通过设置Enable以及Disable来设置额,非常方便。
if (!(item instanceof FrameLayout)) { item.setEnabled(b); } else { item.setEnabled(true); }setEnable方法里面的这句代码看似简单,实则暗藏玄机,我们这样做的目的是不让底栏的单个布局事件被设置成Disable,防止不能响应第二次点击的事件。这样做的好处就是在未来我们看可以利用这个来实现类似于京东点击当前页面的底栏,更新当前页面的效果。
好的,基本上主要的代码逻辑已经说完,下面我们来聊一聊底栏上的数字红点。
其实,我第一次碰到这个红点的时候也是没啥思路,但时候来发现TextView可以设置背景色,后来突发奇想,能不能设置红色圆形的shape,然后直接设置图片上的数字就可以实现这种效果?事实证明这种想法是可行的,而且非常容易实现。
首先看下布局:
<TextView style="@style/myRedPointTextStyle" android:text="99+" android:visibility="visible"/>抽取了Style,方便统一管理:
<style name="myRedPointTextStyle"> <item name="android:layout_width">20dp</item> <item name="android:layout_height">20dp</item> <item name="android:layout_gravity">right</item> <item name="android:background">@drawable/bg_red_point_style</item> <item name="android:gravity">center</item> <item name="android:textColor">@color/colorTitleWhite</item> <item name="android:textSize">10sp</item> </style>这样就实现啦,哈哈,是不是非常简单呢?
关于这里的消息更新,我提一句,直接用EventBus即可,在主页面BaseActivity注册,然后Subscribe一下,相应一下之后更新数字就行!
代码是最好的老师,下面放出代码:
MyBottomListShowTest,点击打开链接
加油!
永远不是别人说你什么样,你就是什么样,而是你想成为什么样,才会成为什么样!
相关文章推荐
- 关于安卓APP底栏点击第一次选中当前Fragment第二次点击更新当前页面的问题(思路)
- 安卓HTML中打开一个连接!点击跳转了,可以实现返回上一级的HTML的页面!
- 【安卓】安卓App开发思路 一步一个脚印(二)FragmentTabHost实现底部的菜单
- 在页面中,我们经常看到,一个button按钮,如果属标点击,就会触发一个窗口的显示,如果二次点击并可以隐藏,那么如何通过JAVA配合html来实现这一功能呢?
- objective-c开发iosapp如何实现一个页面通知另一个页面调用某函数?
- FragmentTabHost、Fragment实现底部点击切换Tab页面
- 在Fragment中点击按钮关闭当前的Fragment返回上一个Fragment该如何实现
- 一个实现了APP内部集中式通知中心,简化通知管理,简化代码逻辑和debug
- app进入后台之后接收到通知,点进去进入新的页面,再次进入后台,再点击通知进入页面(,两次通过通知进入的页面,创建了两次,会多一个页面,)解决办法监听
- Android 一个Activity 里面放置多个 Fragment 实现点击切换的Tab 页面效果
- 安卓APP底部导航栏(有消息圆点指示器),实现fragment切换(eclipse)
- radio 实现点击两次 第一次点击选中第二次点击取消
- radio实现第一次点击选中第二次点击取消
- 安卓开发,点击通知栏进入指定页面及判断App是否启动
- objective-c开发iosapp如何实现一个页面通知另一个页面调用某函数?
- android安卓 Fragment实现页面标题左右同步切换以及点击标题切换页面
- 有一个table表格,选中某一行后,点击“查看(button)”按钮可以实现对该行内容的显示
- Fragment中实现自动定位当前城市,点击刷新按钮更新天气信息
- CocosCreator中。取消当前选中的状态并给第二次点击的物品添加选中状态的代码(自定义事件版)
- 火焰灯menu修改之后,可以实现数遍点击小方块停留在当前页面