ButtonNavigationView+Badage+反射,聊一下思路构想。

参考资料:
ButtonNavigationViewEx
https://blog.csdn.net/qq_35064774/article/details/54177702

反射机制
https://blog.csdn.net/ju_362204801/article/details/90578678
1.
最近学习了ButtonNavigationView,发现用起来很方便但是有一定的局限性,然后去网络查资料看人家是怎么修改的。利用反射官方存在的View去构造自己自定义个的"View",这样子就可以突破这个限制性。所以用博客记录一下。

ButtonNavigationView

问题1:ButtonNavigationView是什么?
回答1:ButtonNavigationView是Android谷歌官方中的底部导航栏的组件,也比较容易实现自己的功能,但是存在一定的局限性,只能使用其内部的方法和定义。若想改变样式/文字大小,如果没有方法放出则无法修改。

Badge

问题2:Badge是啥?
问题2:Badge就是角标,Android的View如何添加角标去告诉用户这有变化之类的操作。比如APP有的更新了,那就给这个View添加一个角标。

反射

问题3:反射是什么?
回答3:反射就是把Java类中的各个部分,映射成一个个的Java对象,拿到这些对象后可以做一些事情。简单点说:反射就是能把类中的属性,方法,字段映射成一个对象。

好了,了解了三个基本概念之后,WTF?这这这这,之间有什么联系吗?
在这里插入图片描述

当然有联系了,来,我们来利用第三方库去给你的ButtonNavigationView中的底部栏某个 mune来个角标。
~~

  • 这里留个疑问,那我自建一个BadgeView如何弄,讲道理,个人认为和自定义View应该是一个尿性。有空可以去人家的项目里面去解析。

~~
Badge库:
https://github.com/qstumn/BadgeView
发现方法:
new QBadgeView(context).bindTarget(textview).
这不是很简单吗?
只要bindTarget内知道相应的View就可以了!
那我这样写:

//这是错误的写法!!!!!!!!!!!!!
BottomNavigationView mbnView; 
new QBadgeView(context).bindTarget(mbnView).

这就是你的下场
如果比较熟悉的人,应该一眼就看出来问题了。要的在ButtonNavigationView下的mune出现角标,而不是整个ButtonNavigationView出现角标。
在这里插入图片描述
那我赶紧到ButtonNavigationView类中找公开的方法,可以获取到其中的mune项,但是最后发现只有setOnNavigationItemSelectedListener,只用来设定点击监听器的。 好了~需求解决不了,我放弃了GG.
在这里插入图片描述
作为积极向上的社会主义接班人,怎么能埋没了胸前那如此靓丽的红领巾呢,不行,我要解决这个问题!!!不就是找到ButtonNavigationView里面的View嘛,打开源码,我取出来不就完了。打开一看,里面有个属性BottomNavigationMenuView,这不就是我想要的嘛?但是转眼一看,不好意思,全是private,谷歌并不想让你修改。虽然上帝把你门关上了,但是窗户还是不会忘记焊上的。
在这里插入图片描述
在这里插入图片描述
(那简单啊,那我复制一份,当做我的自定义控件,再把我需要的View全部改为public不就完了。—作者没试过,不过想想好像是可以的吧。
不过大佬说的好,缺点不少:需要把整个控件的代码都复制一份,每次官方对控制做出修改后,无法享受新特性。每次更新,你都要修改代码,迭代累死你啊!)

那这时候,反射的用处就出来了,还记得吗?
反射就是把Java类中的各个部分,映射成一个个的Java对象,拿到这些对象后可以做一些事情。 拥有反射的我,可以为所欲为,管你是不是private,老子是开发者,我是上帝!(至于原理啥的,去参考资料去看。这里不解释了。)
在这里插入图片描述
这时候思路就清楚多了吧,先分析ButtonNavigationView的源码,发现里面又特定的方法和子View,但是全都是private.那我又要修改,那怎么办呢,那当然是通过反射就可以获取这个类,从而去构造出我们自己的View。

最后,我们看看大佬是怎么实现的,只做分析和想法,个人作为初学者还没那么强大的实力,只能讲一下想法和思路仅供参考。

第一步:

//反正根据这个getBottomNavigationItemView方法获得mute子项
        return new QBadgeView(this)
                .setBadgeNumber(number)
          	  .bindTarget(bind.bnve.getBottomNavigationItemView(position))

第二步:(大佬有一个接口类作为防代码冗余,这就不贴出来了)

public BottomNavigationItemView getBottomNavigationItemView(int position) {
        return getBottomNavigationItemViews()[position];
    }
    //再跟踪进入getBottomNavigationItemViews()
        public BottomNavigationItemView[] getBottomNavigationItemViews() {
     if (null != mButtons)
            return mButtons;
        BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
        mButtons = getField(mMenuView.getClass(), mMenuView, "buttons");
        return mButtons;//private BottomNavigationItemView[] mButtons
       }

第三步: 可以看到,getBottomNavigationMenuView 和getField两个方法则返回了原本private的BottomNavigationItemView.
这才是我们想要的,而为什么要得到这个,是根据源码分析出来的,然后再看这个字段是在藏哪里的。
BottomNavigationView–>BottomNavigationMenuView–>BottomNavigationItemView
而得到这个字段的手段就是反射,getBottomNavigationMenuView实质上也是使用方法getField.代码如下:

 private <T> T getField(Class targetClass, Object instance, String fieldName) {
        try {
            Field field = targetClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            return (T) field.get(instance);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

我给出的资料,用的是Class.ForName.而这里用的是getDeclaredField.为什么是这个方法,可以去官方文档去查看。这样子,通过反射得到了我们想要的View.
这样我们就可以解决我们的问题了。

思路总结:
一些官方控件,如果满足不了你的需求,就改造它!获取不到的资源就改造它!反正差不多就是自定义View.通过反射可以使用它的内部方法。
好嘞,学习总结结束!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值