美文网首页android
Android自定义未读消息提示View

Android自定义未读消息提示View

作者: Anieal | 来源:发表于2017-08-23 08:10 被阅读768次

    先上图

    未读消息View

    介绍

    1.可根据文本长度动态改变view的宽度,数字10以下的显示为圆形,10以上的显示为上述效果
    2.使用方便,引用到xml中后,直接显示高度即可,即可根据高度自动生成最佳显示效果
    3.直接在代码中调用setText()即可

    分析

    其实完成这样的效果还是很简单的,主要我是通过画一个圆角矩形来实现这样的效果,圆角矩形很轻松就能实现这两种效果的切换,至于怎样子写,之后会有介绍。
    关于自适应宽度的实现,我只要是通过重写onMeasure方法,对其进行拦截。

    开始实现

    实现步骤其实很简单,因为功能上不是很多,对于我现在的需求,只要能显示未读数量并做好适配就好了。所以只要写好onMeasure和onDraw就好了,方法很简单。因为本人实力有限,实现起来肯定还是使用很简单的方法的。

    现在我们先看onMeasure,这里主要是是为了做好实现自适应宽度
     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //获取控件高度
            height = MeasureSpec.getSize(heightMeasureSpec);
            //定义字体大小,自测了一下,与高度相差6dp的字体大小看着还是挺舒服的
            textSize = height - getResources().getDimensionPixelSize(R.dimen.dp6);
            textPaint.setTextSize(textSize);
            //获取文本宽度
            int textWidth = (int) textPaint.measureText(text);
            //区分画圆的是圆形还是圆角矩形
            if (text.length() > 1) {
                roundWidth = textWidth + height - textWidth / text.length();
            } else {
                roundWidth = height;
            }
            //重新测量控件
            setMeasuredDimension(roundWidth, height);
        }
    

    上述方法还是很简单的也标号注释了,不用一句句来讲了。
    roundWidth = textWidth + height - textWidth / text.length();实现上述效果的核心就是这段代码,我想应该看得懂的。逻辑不是很强。

    现在我们再看onDraw,也是最后一步画矩形与画字
    @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //画矩形
            canvas.setDrawFilter(paintFlagsDrawFilter);
            roundRectF.set(0, 0, roundWidth, height);
            canvas.drawRoundRect(roundRectF, height / 2, height / 2, roundRectPaint);
    
            //画字
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            float top = fontMetrics.top;
            float bottom = fontMetrics.bottom;
            int baseLintY = (int) (roundRectF.centerY() - top / 2 - bottom / 2);
            canvas.drawText(text, roundRectF.centerX(), baseLintY, textPaint);
        }
    

    对于画矩形和画字不是这篇的重点,不懂的可以自己百度一下,我也是百度慢慢学起来的。主要是画字需要居中,关键在于int baseLintY = (int) (roundRectF.centerY() - top / 2 - bottom / 2);这边代码,获取字体的基线,来实现居中效果。

    最后上所有代码,不是很难,代码量也不多,很容易懂

    package com.demo.view;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PaintFlagsDrawFilter;
    import android.graphics.RectF;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.view.View;
    
    import com.demo.R;
    
    public class MyTextView extends View {
    
        private Paint roundRectPaint;
        private RectF roundRectF;
        private int height;
        private int roundWidth;
    
        private Paint textPaint;
        private float textSize;
        private String text;
        private PaintFlagsDrawFilter paintFlagsDrawFilter;
    
        public MyTextView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView();
        }
    
    
        private void initView() {
            text = "2";
            roundRectPaint = new Paint();
            roundRectPaint.setStyle(Paint.Style.FILL);
            roundRectPaint.setAntiAlias(true);
            roundRectPaint.setColor(Color.RED);
            roundRectF = new RectF();
    
            //设置字体为粗体
            textPaint = new Paint(Paint.LINEAR_TEXT_FLAG);
            textPaint.setColor(Color.WHITE);
            textPaint.setAntiAlias(true);
            textPaint.setTextAlign(Paint.Align.CENTER);
            //实现抗锯齿
            paintFlagsDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //获取控件高度
            height = MeasureSpec.getSize(heightMeasureSpec);
            //定义字体大小,自测了一下,与高度相差6dp的字体大小看着还是挺舒服的
            textSize = height - getResources().getDimensionPixelSize(R.dimen.dp6);
            textPaint.setTextSize(textSize);
            //获取文本宽度
            int textWidth = (int) textPaint.measureText(text);
            //区分画圆的是圆形还是圆角矩形
            if (text.length() > 1) {
                roundWidth = textWidth + height - textWidth / text.length();
            } else {
                roundWidth = height;
            }
            //重新测量控件
            setMeasuredDimension(roundWidth, height);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //画矩形
            canvas.setDrawFilter(paintFlagsDrawFilter);
            roundRectF.set(0, 0, roundWidth, height);
            canvas.drawRoundRect(roundRectF, height / 2, height / 2, roundRectPaint);
    
            //画字
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            float top = fontMetrics.top;
            float bottom = fontMetrics.bottom;
            int baseLintY = (int) (roundRectF.centerY() - top / 2 - bottom / 2);
            canvas.drawText(text, roundRectF.centerX(), baseLintY, textPaint);
        }
    
        public void setText(String text) {
            this.text = text;
            //重走onMeasure
            requestLayout();
        }
    }
    
    

    代码真的很少,看不懂的查一下也很快能看懂的。
    最后在xml中

    <com.demo.view.MyTextView
            android:layout_marginTop="20dp"
            android:layout_marginLeft="20dp"
            android:layout_width="wrap_content"
            android:layout_height="30dp"/>
    

    好了,就这样结束了,这里android:layout_width不管设什么值都是自适应的,因为在onMeasure中直接定死了。若要区分开来,可重写onMeasure做判断。

    相关文章

      网友评论

      • 琛宝老爸:请问,能不能扩展一下接口呢?
        比如动态设置字体大小、颜色、背景的颜色、形状等。
        谢谢!

      本文标题:Android自定义未读消息提示View

      本文链接:https://www.haomeiwen.com/subject/fsmldxtx.html