• Android BadgeView 工具包


      前言:消息未读,显示红点或者红色数字,其实就是一个TextView,有推送一般就有badgeView。

      Step 1

      因为在github上看到了一些类似的第三方库,嫌麻烦,不如直接封装一个类,直接使用。当然这也是在网上找的。代码如下:

    public class BadgeView extends AppCompatTextView {
    
        public static final int POSITION_TOP_LEFT = 1;
        public static final int POSITION_TOP_RIGHT = 2;
        public static final int POSITION_BOTTOM_LEFT = 3;
        public static final int POSITION_BOTTOM_RIGHT = 4;
        public static final int POSITION_CENTER = 5;
    
        private static final int DEFAULT_MARGIN_DIP = 5;
        private static final int DEFAULT_LR_PADDING_DIP = 5;
        private static final int DEFAULT_CORNER_RADIUS_DIP = 8;
        private static final int DEFAULT_POSITION = POSITION_TOP_RIGHT;
        private static final int DEFAULT_BADGE_COLOR = Color.parseColor("#CCFF0000"); //Color.RED;
        private static final int DEFAULT_TEXT_COLOR = Color.WHITE;
    
        private static Animation fadeIn;
        private static Animation fadeOut;
    
        private Context context;
        private View target;
    
        private int badgePosition;
        private int badgeMarginH;
        private int badgeMarginV;
        private int badgeColor;
    
        private boolean isShown;
    
        private ShapeDrawable badgeBg;
    
        private int targetTabIndex;
    
        public BadgeView(Context context) {
            this(context, (AttributeSet) null, android.R.attr.textViewStyle);
        }
    
        public BadgeView(Context context, AttributeSet attrs) {
            this(context, attrs, android.R.attr.textViewStyle);
        }
    
        /**
         * Constructor -
         *
         * create a new BadgeView instance attached to a target {@link View}.
         *
         * @param context context for this view.
         * @param target the View to attach the badge to.
         */
        public BadgeView(Context context, View target) {
            this(context, null, android.R.attr.textViewStyle, target, 0);
        }
    
        /**
         * Constructor -
         *
         * create a new BadgeView instance attached to a target {@link TabWidget}
         * tab at a given index.
         *
         * @param context context for this view.
         * @param target the TabWidget to attach the badge to.
         * @param index the position of the tab within the target.
         */
        public BadgeView(Context context, TabWidget target, int index) {
            this(context, null, android.R.attr.textViewStyle, target, index);
        }
    
        public BadgeView(Context context, AttributeSet attrs, int defStyle) {
            this(context, attrs, defStyle, null, 0);
        }
    
        public BadgeView(Context context, AttributeSet attrs, int defStyle, View target, int tabIndex) {
            super(context, attrs, defStyle);
            init(context, target, tabIndex);
        }
    
        private void init(Context context, View target, int tabIndex) {
    
            this.context = context;
            this.target = target;
            this.targetTabIndex = tabIndex;
    
            // apply defaults
            badgePosition = DEFAULT_POSITION;
            badgeMarginH = dipToPixels(DEFAULT_MARGIN_DIP);
            badgeMarginV = badgeMarginH;
            badgeColor = DEFAULT_BADGE_COLOR;
    
            setTypeface(Typeface.DEFAULT_BOLD);
            int paddingPixels = dipToPixels(DEFAULT_LR_PADDING_DIP);
            setPadding(paddingPixels, 0, paddingPixels, 0);
            setTextColor(DEFAULT_TEXT_COLOR);
    
            fadeIn = new AlphaAnimation(0, 1);
            fadeIn.setInterpolator(new DecelerateInterpolator());
            fadeIn.setDuration(200);
    
            fadeOut = new AlphaAnimation(1, 0);
            fadeOut.setInterpolator(new AccelerateInterpolator());
            fadeOut.setDuration(200);
    
            isShown = false;
    
            if (this.target != null) {
                applyTo(this.target);
            } else {
                show();
            }
    
        }
    
        private void applyTo(View target) {
    
            ViewGroup.LayoutParams lp = target.getLayoutParams();
            ViewParent parent = target.getParent();
            FrameLayout container = new FrameLayout(context);
    
            if (target instanceof TabWidget) {
    
                // set target to the relevant tab child container
                target = ((TabWidget) target).getChildTabViewAt(targetTabIndex);
                this.target = target;
    
                ((ViewGroup) target).addView(container,
                        new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    
                this.setVisibility(View.GONE);
                container.addView(this);
    
            } else {
    
                // TODO verify that parent is indeed a ViewGroup
                ViewGroup group = (ViewGroup) parent;
                int index = group.indexOfChild(target);
    
                group.removeView(target);
                group.addView(container, index, lp);
    
                container.addView(target);
    
                this.setVisibility(View.GONE);
                container.addView(this);
    
                group.invalidate();
    
            }
    
        }
    
        /**
         * Make the badge visible in the UI.
         *
         */
        public void show() {
            show(false, null);
        }
    
        /**
         * Make the badge visible in the UI.
         *
         * @param animate flag to apply the default fade-in animation.
         */
        public void show(boolean animate) {
            show(animate, fadeIn);
        }
    
        /**
         * Make the badge visible in the UI.
         *
         * @param anim Animation to apply to the view when made visible.
         */
        public void show(Animation anim) {
            show(true, anim);
        }
    
        /**
         * Make the badge non-visible in the UI.
         *
         */
        public void hide() {
            hide(false, null);
        }
    
        /**
         * Make the badge non-visible in the UI.
         *
         * @param animate flag to apply the default fade-out animation.
         */
        public void hide(boolean animate) {
            hide(animate, fadeOut);
        }
    
        /**
         * Make the badge non-visible in the UI.
         *
         * @param anim Animation to apply to the view when made non-visible.
         */
        public void hide(Animation anim) {
            hide(true, anim);
        }
    
        /**
         * Toggle the badge visibility in the UI.
         *
         */
        public void toggle() {
            toggle(false, null, null);
        }
    
        /**
         * Toggle the badge visibility in the UI.
         *
         * @param animate flag to apply the default fade-in/out animation.
         */
        public void toggle(boolean animate) {
            toggle(animate, fadeIn, fadeOut);
        }
    
        /**
         * Toggle the badge visibility in the UI.
         *
         * @param animIn Animation to apply to the view when made visible.
         * @param animOut Animation to apply to the view when made non-visible.
         */
        public void toggle(Animation animIn, Animation animOut) {
            toggle(true, animIn, animOut);
        }
    
        private void show(boolean animate, Animation anim) {
            if (getBackground() == null) {
                if (badgeBg == null) {
                    badgeBg = getDefaultBackground();
                }
                setBackgroundDrawable(badgeBg);
            }
            applyLayoutParams();
    
            if (animate) {
                this.startAnimation(anim);
            }
            this.setVisibility(View.VISIBLE);
            isShown = true;
        }
    
        private void hide(boolean animate, Animation anim) {
            this.setVisibility(View.GONE);
            if (animate) {
                this.startAnimation(anim);
            }
            isShown = false;
        }
    
        private void toggle(boolean animate, Animation animIn, Animation animOut) {
            if (isShown) {
                hide(animate && (animOut != null), animOut);
            } else {
                show(animate && (animIn != null), animIn);
            }
        }
    
        /**
         * Increment the numeric badge label. If the current badge label cannot be converted to
         * an integer value, its label will be set to "0".
         *
         * @param offset the increment offset.
         */
        public int increment(int offset) {
            CharSequence txt = getText();
            int i;
            if (txt != null) {
                try {
                    i = Integer.parseInt(txt.toString());
                } catch (NumberFormatException e) {
                    i = 0;
                }
            } else {
                i = 0;
            }
            i = i + offset;
            setText(String.valueOf(i));
            return i;
        }
    
        /**
         * Decrement the numeric badge label. If the current badge label cannot be converted to
         * an integer value, its label will be set to "0".
         *
         * @param offset the decrement offset.
         */
        public int decrement(int offset) {
            return increment(-offset);
        }
    
        private ShapeDrawable getDefaultBackground() {
    
            int r = dipToPixels(DEFAULT_CORNER_RADIUS_DIP);
            float[] outerR = new float[] {r, r, r, r, r, r, r, r};
    
            RoundRectShape rr = new RoundRectShape(outerR, null, null);
            ShapeDrawable drawable = new ShapeDrawable(rr);
            drawable.getPaint().setColor(badgeColor);
    
            return drawable;
    
        }
    
        private void applyLayoutParams() {
    
            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    
            switch (badgePosition) {
                case POSITION_TOP_LEFT:
                    lp.gravity = Gravity.LEFT | Gravity.TOP;
                    lp.setMargins(badgeMarginH, badgeMarginV, 0, 0);
                    break;
                case POSITION_TOP_RIGHT:
                    lp.gravity = Gravity.RIGHT | Gravity.TOP;
                    lp.setMargins(0, badgeMarginV, badgeMarginH, 0);
                    break;
                case POSITION_BOTTOM_LEFT:
                    lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
                    lp.setMargins(badgeMarginH, 0, 0, badgeMarginV);
                    break;
                case POSITION_BOTTOM_RIGHT:
                    lp.gravity = Gravity.RIGHT | Gravity.BOTTOM;
                    lp.setMargins(0, 0, badgeMarginH, badgeMarginV);
                    break;
                case POSITION_CENTER:
                    lp.gravity = Gravity.CENTER;
                    lp.setMargins(0, 0, 0, 0);
                    break;
                default:
                    break;
            }
    
            setLayoutParams(lp);
    
        }
    
        /**
         * Returns the target View this badge has been attached to.
         *
         */
        public View getTarget() {
            return target;
        }
    
        /**
         * Is this badge currently visible in the UI?
         *
         */
        @Override
        public boolean isShown() {
            return isShown;
        }
    
        /**
         * Returns the positioning of this badge.
         *
         * one of POSITION_TOP_LEFT, POSITION_TOP_RIGHT, POSITION_BOTTOM_LEFT, POSITION_BOTTOM_RIGHT, POSTION_CENTER.
         *
         */
        public int getBadgePosition() {
            return badgePosition;
        }
    
        /**
         * Set the positioning of this badge.
         *
         * @param layoutPosition one of POSITION_TOP_LEFT, POSITION_TOP_RIGHT, POSITION_BOTTOM_LEFT, POSITION_BOTTOM_RIGHT, POSTION_CENTER.
         *
         */
        public void setBadgePosition(int layoutPosition) {
            this.badgePosition = layoutPosition;
        }
    
        /**
         * Returns the horizontal margin from the target View that is applied to this badge.
         *
         */
        public int getHorizontalBadgeMargin() {
            return badgeMarginH;
        }
    
        /**
         * Returns the vertical margin from the target View that is applied to this badge.
         *
         */
        public int getVerticalBadgeMargin() {
            return badgeMarginV;
        }
    
        /**
         * Set the horizontal/vertical margin from the target View that is applied to this badge.
         *
         * @param badgeMargin the margin in pixels.
         */
        public void setBadgeMargin(int badgeMargin) {
            this.badgeMarginH = badgeMargin;
            this.badgeMarginV = badgeMargin;
        }
    
        /**
         * Set the horizontal/vertical margin from the target View that is applied to this badge.
         *
         * @param horizontal margin in pixels.
         * @param vertical margin in pixels.
         */
        public void setBadgeMargin(int horizontal, int vertical) {
            this.badgeMarginH = horizontal;
            this.badgeMarginV = vertical;
        }
    
        /**
         * Returns the color value of the badge background.
         *
         */
        public int getBadgeBackgroundColor() {
            return badgeColor;
        }
    
        /**
         * Set the color value of the badge background.
         *
         * @param badgeColor the badge background color.
         */
        public void setBadgeBackgroundColor(int badgeColor) {
            this.badgeColor = badgeColor;
            badgeBg = getDefaultBackground();
        }
    
        private int dipToPixels(int dip) {
            Resources r = getResources();
            float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, r.getDisplayMetrics());
            return (int) px;
        }
    
    }
    View Code

       Step 2

      然后就是怎么用了。

        有一个Button名字暂且叫做bt

      BadgeView badge=BadgeView(context,bt)

      badge.setBadgePosition=BadgeView.POSITION_TOP_RIGHT

         badge.setText="99+"   //这里自己设置显示未读消息的条数

       badge.setTextSize=10.0f    //这里设置显示数字的大小

       badge.setTextColor(Color.WHITE)   //这里设置显示的颜色

       badge.setVisiblility=View.VISIBLE   //这是设置显示或隐藏,默认是显示的

       badge.show()    //这里就真的show出来了,没有这句话,都是纸上谈兵

      Warning

      1.需求:如果你想要覆盖之前的消息,就是说你要更新显示的数字,比如原来有99条未读的消息,然后读了一条,需要更新未读数目。

      解决方案:如果用多次BadgeView(context,bt)是没有效果的。这里坑了我很久。

              你需要判断badge是否为null,如果为null就用BadgeView(context,bt)

            如果badge不为null,也就是要更新数字了,直接badge.setText="你要更新的数字即可"

       

      2.需求:如果没有未读的消息了,要去掉badge,怎么办?

      解决方案:因为BadgeView就是类似TextView的,所以当没有未读消息,直接隐藏就行了。

           badge.setVisibility=View.GONE

     

    既然选择了,便不顾风雨兼程。Just follow yourself.
  • 相关阅读:
    idea打开service窗口
    windows使用命令行终止端口的进程
    struts2
    struts_spring_hibernate
    struts
    pycharm自动提示documentation (auto Ctrl+Q)
    C语言结构体初始化的几种方法
    github sshkey生成踩坑
    修复Windows11搜索框卡死问题/关闭Windows 11网络搜索
    fastjson的字段
  • 原文地址:https://www.cnblogs.com/Jason-Jan/p/7590609.html
Copyright © 2020-2023  润新知