BadgeView源码分析
来源:互联网 发布:java web项目打war包 编辑:程序博客网 时间:2024/06/06 02:02
最近做项目时用到了BadgeView,当时没有看源码,现在闲下来了,就分析一下。
public class BadgeView extends TextView可以看到,BadgeView是通过继承了TextView来实现的。接下来,不要看源码,先从它的用法入手,分析哪个函数真正实现了它。它的用法很简单,如下面demo所示
public class MainActivity extends ActionBarActivity { public final String tag = this.getClass().getName(); private BadgeView bv1; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); bv1 = new BadgeView(this); bv1.setBadgeCount(1); bv1.setTargetView(tv); }我们看到只要三条语句就可以使用BadgeView,现在再让我们返回源码去看看这三个函数。首先是它的构造函数。
public BadgeView(Context context) {this(context, null);}public BadgeView(Context context, AttributeSet attrs) {this(context, attrs, android.R.attr.textViewStyle);}public BadgeView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}里面只有一个init函数,那让我们看看它。
private void init() {if (!(getLayoutParams() instanceof LayoutParams)) {LayoutParams layoutParams = new LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT,android.view.ViewGroup.LayoutParams.WRAP_CONTENT,Gravity.RIGHT | Gravity.TOP);setLayoutParams(layoutParams);}// set default fontsetTextColor(Color.WHITE);setTypeface(Typeface.DEFAULT_BOLD);setTextSize(TypedValue.COMPLEX_UNIT_SP, 11);setPadding(dip2Px(5), dip2Px(1), dip2Px(5), dip2Px(1));// set default backgroundsetBackground(9, Color.parseColor("#d3321b"));setGravity(Gravity.CENTER);// default valuessetHideOnNull(true);setBadgeCount(0);}看完之后,发现这个函数大多数是一些样式的设定语句,先给BadgeView设定layout_width,layout_height和布局中的位置,接下来就是其他的样式,就不一一说了。函数的末尾我们又看到了setBadgeCount函数,虽然从名字看就知道这只是用来设置显示的数字的,但我们还是去看看源码。
public void setBadgeCount(int count) {setText(String.valueOf(count));}发现调用了setText方法
/* * (non-Javadoc) * * @see android.widget.TextView#setText(java.lang.CharSequence, * android.widget.TextView.BufferType) */@Overridepublic void setText(CharSequence text, BufferType type) {if (isHideOnNull()&& (text == null || text.toString().equalsIgnoreCase("0"))) {setVisibility(View.GONE);} else {setVisibility(View.VISIBLE);}super.setText(text, type);}我们看到,这个重载方法加上了条件判断来决定是否显示内容,setHideOnNull方法只是单纯用来设定是否显示BadgeView而已。那么最后就看看setTargetView函数。
/* * Attach the BadgeView to the target view * * @param target the view to attach the BadgeView */public void setTargetView(View target) {if (getParent() != null) {((ViewGroup) getParent()).removeView(this);}if (target == null) {return;}if (target.getParent() instanceof FrameLayout) {((FrameLayout) target.getParent()).addView(this);} else if (target.getParent() instanceof ViewGroup) {// use a new Framelayout container for adding badgeViewGroup parentContainer = (ViewGroup) target.getParent();int groupIndex = parentContainer.indexOfChild(target);parentContainer.removeView(target);FrameLayout badgeContainer = new FrameLayout(getContext());ViewGroup.LayoutParams parentLayoutParams = target.getLayoutParams();badgeContainer.setLayoutParams(parentLayoutParams);target.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));parentContainer.addView(badgeContainer, groupIndex,parentLayoutParams);badgeContainer.addView(target);badgeContainer.addView(this);} else if (target.getParent() == null) {Log.e(getClass().getSimpleName(), "ParentView is needed");}}看完这个函数,相信大家都明白BadgeView的实现原理了。BadgeView先是将target(demo中是TextView)从原来的布局中移除,再动态创建了一个FrameLayout,并将LayoutParams设置为target原来布局的LayoutParams,然后就将创建的FrameLayout添加到target的原有布局中,最后将target和BadgeView添加到FrameLayout中。总体看来,源码不算复杂,但是从中我们可以学习到源码作者解决问题的思路,隔空膜拜一下大神。
最后让我们来找找碴。
1、为什么先添加target再添加BadgeView
ViewGroup源码中,addView是这样子的
public void addView(View child) { addView(child, -1); }-1的位置下标表示将View添加的ViewGroup的最后一个位置,所以如果没有先添加target再添加BadgeView,由于这是个FrameLayout,BadgeView会被遮盖,怎么都看不到。
2、为什么要先添加badgeContainer布局再添加View
实测先添加View到badgeContainer布局,最后再添加badgeContainer布局也没影响……
3、为什么BadgeView是圆形的
@SuppressWarnings("deprecation") public void setBackground(int dipRadius, int badgeColor) { int radius = dip2Px(dipRadius); float[] radiusArray = new float[] { radius, radius, radius, radius, radius, radius, radius, radius }; //set the shape,you can change it to create other new shape RoundRectShape roundRect = new RoundRectShape(radiusArray, null, null); ShapeDrawable bgDrawable = new ShapeDrawable(roundRect); bgDrawable.getPaint().setColor(badgeColor); setBackgroundDrawable(bgDrawable); }看到了吧,你完全可以改为其他形状,尽管其他形状很丑~
0 0
- BadgeView源码分析
- BadgeView源码分析
- BadgeView实现源码分析
- oschina-app源码分析-提醒标签BadgeView使用方法
- oschina-app源码分析-提醒标签BadgeView使用逻辑流程
- oschina-app源码分析-提醒标签BadgeView使用逻辑流程
- Badgeview
- BadgeView
- BadgeView
- [安卓自定义控件]BadgeView源码解析
- android BadgeView
- BadgeView 实现
- android badgeview
- github badgeView
- BadgeView使用
- BadgeView+weixinUi
- 源码分析
- 源码分析
- SQL数据库的表table操作方法:查询+插入+删除+增加+修改+替换+排序+运算
- 真正统治世界的十大算法
- 循环结构中break、continue、return和exit的区别
- HDOJ 1865 1sting(大数斐波那契数列)
- python socket 入门
- BadgeView源码分析
- 预留应用发布地址
- Android之Http通信——3.Android HTTP请求方式:HttpURLConnection
- Vertica节点宕机处理一例
- win7解决远程桌面凭据无法使用(密码正确)
- 第一天 linux源码下载编译
- c++primer第一章
- android开源项目和框架
- Eclipse里面使用Maven搭建Web工程