BadgeView源码分析

1 简介

BadgeView继承自TextView,可用于消息提醒,如微信的消息提醒数目的显示。
源码 https://github.com/stefanjauker/BadgeView

2 源码

1 知识点

1 继承textview时构造函数的attrs属性

 public BadgeView(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

2 初始化

private void init() {
        // 用代码new时,getLayoutParams()为null,因此要设置其位置。或者类型不匹配也要设置
        if (!(getLayoutParams() instanceof LayoutParams)) {
        // 类型 android.widget.FrameLayout.LayoutParams,因为badgeview父就是FrameLayout
            LayoutParams layoutParams =
                    new LayoutParams(
                            android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                            android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                            Gravity.RIGHT | Gravity.TOP);
            setLayoutParams(layoutParams);
        }
        // set default font
        setTextColor(Color.WHITE);
        setTypeface(Typeface.DEFAULT_BOLD);
        setTextSize(TypedValue.COMPLEX_UNIT_SP, 11);
        setPadding(dip2Px(5), dip2Px(1), dip2Px(5), dip2Px(1));
        // set default background --- down
        setBackground(9, Color.parseColor("#d3321b"));        

        // default values --- down
        setHideOnNull(true);
        //  --- down
        setBadgeCount(0);
    }

setBackground函数

    public void setBackground(int dipRadius, int badgeColor) {
        int radius = dip2Px(dipRadius);
        float[] radiusArray = new float[] { radius, radius, radius, radius, radius, radius, radius, radius };
        /**  RoundRectShape constructor. Specifies an outer (round)rect and an optional inner (round)rect.
    outerRadii: An array of 8 radius values, for the outer roundrect. The first two floats are for the top-left corner (remaining pairs correspond clockwise). For no rounded corners on the outer rectangle, pass null.
    inset: A RectF that specifies the distance from the inner rect to each side of the outer rect. For no inner, pass null.
    innerRadii: An array of 8 radius values, for the inner roundrect. The first two floats are for the top-left corner (remaining pairs correspond clockwise). For no rounded corners on the inner rectangle, pass null. If inset parameter is null, this parameter is ignored. 
        */
        // 创建一个圆角矩形的形状,dipRadius如果够大了就会近圆的形状了
        RoundRectShape roundRect = new RoundRectShape(radiusArray, null, null);
        // 创建ShapeDrawable,利用的是上面创建的shape
        ShapeDrawable bgDrawable = new ShapeDrawable(roundRect);
        // 设置画笔颜色
        bgDrawable.getPaint().setColor(badgeColor);
        // 设置背景为ShapeDrawable
        setBackgroundDrawable(bgDrawable);
    }

位置的设置

    public void setBadgeGravity(int gravity) {
        FrameLayout.LayoutParams params = (LayoutParams) getLayoutParams();
        params.gravity = gravity;
        setLayoutParams(params);
    }

text数字的递变

   public void incrementBadgeCount(int increment) {
        Integer count = getBadgeCount();
        if (count == null) {
            setBadgeCount(increment);
        } else {
            setBadgeCount(increment + count);
        }
    }

public void setBadgeMargin方法等等边距

3 设置所指示的目标view

    /*
     * Attach the BadgeView to the target view
     * 
     * @param target the view to attach the BadgeView
     */
    public void setTargetView(View target) {
        if (getParent() != null) { // 确保只有一个目标view
            ((ViewGroup) getParent()).removeView(this);
        }

        if (target == null) {
            return;
        }

        if (target.getParent() instanceof FrameLayout) {
            // 因为对于FrameLayout,layoutParams在初始化的时候已经设置好了
            ((FrameLayout) target.getParent()).addView(this);

        } else if (target.getParent() instanceof ViewGroup) {
            // 添加一个FrameLayout去将目标view和badgeview封装起来
            // use a new Framelayout container for adding badge
            ViewGroup parentContainer = (ViewGroup) target.getParent();
            int groupIndex = parentContainer.indexOfChild(target);
            parentContainer.removeView(target); // 移除目标view

            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));
            // 将新创建的FrameLayout添加到刚刚删除了的目标view的位置
            parentContainer.addView(badgeContainer, groupIndex, parentLayoutParams);
            badgeContainer.addView(target); // 目标view新位置

            badgeContainer.addView(this);
        } else if (target.getParent() == null) {
            Log.e(getClass().getSimpleName(), "ParentView is needed");
        }

    }

2 源码例子

1 主Activity

        // Set up the action bar. 利用actionbar的导航功能
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) { // 设置actionbar的当前tab
                actionBar.setSelectedNavigationItem(position);
            }
        });

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            Tab tab = actionBar.newTab()
                    .setText(mSectionsPagerAdapter.getPageTitle(i))
                    .setTabListener(this);
            actionBar.addTab(tab);
        }
            @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
        // When the given tab is selected, switch to the corresponding page in
        // the ViewPager. 点击tab时的监听回调
        mViewPager.setCurrentItem(tab.getPosition());
    }

2 ListFragment extends android.support.v4.app.ListFragment
继承ListFragment后,只需要下面代码即可

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(new ListAdapter(getActivity()));
    }

TextView的几个系统属性设置
android:id=”@android:id/text1”
android:minHeight=”?android:attr/listPreferredItemHeight”
android:textAppearance=”?android:attr/textAppearanceLarge”

3
设置背景为图片资源而不是默认的圆角矩形
backgroundDrawableBadge.setBackgroundResource(R.drawable.badge_blue);
设置圆角的大小和颜色backgroundShapeBadge.setBackground(12, Color.parseColor(“#9b2eef”));
风格样式textStyleBadge.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.ITALIC));
Sets the typeface and style in which the text should be displayed

阴影吧textStyleBadge.setShadowLayer(2, -1, -1, Color.GREEN);
解释:Gives the text a shadow of the specified radius and color, the specified distance from its normal position。
setShadowLayer(float radius, float dx, float dy, int color)

最后, 源码点击下载!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值