Android custom message prompts container

8901031-7b191d089b461c7c.png
night_rain.png

Custom View, first, in order to meet the design requirements, and second, one of the developers advanced signs. I waited casual is the goal of fighting! ! !

effect

8901031-4dc1fc0fb3974694.gif
Renderings

Implementation logic

  • Knowledge points
    1, dispatchDraw(Canvas canvas)drawing the sub-View, where the upper drawing can ensure its child View of
    2, TextPaintthe default text begin from the bottom of the drawing, setTextAlign()the alignment of the text may be provided to draw

  • Realization of ideas
    1, confirm the height of the drawing background, because regardless of whether or not to open an adaptive, height is always the same. Code embodied in countDefaultTextBackgroundSize()the
    2, in accordance with custom properties, the drawing area is determined. Code embodied in countHintTextPosition()the
    3 position determination to get started painting the background and numbers.dispatchDraw()

All codes

/**
 * 自定义消息提示容器
 * {@link #countHintTextPosition() 计算绘制位置}
 * {@link #countDefaultTextBackgroundSize() 计算背景高度}
 *
 * @attr customHintTextColor         //消息数字颜色
 * @attr customHintTextSize          //消息数字尺寸
 * @attr customHintTextBackground    //消息背景颜色
 * @attr customSelfAdaption          //背景是否自适应数字大小
 * @attr customHintTextMarginLeft    //距离容器左侧外边距
 * @attr customHintTextMarginRight   //距离容器右侧外边距
 * @attr customHintTextMarginTop     //距离容器顶部外边距
 * @attr customHintTextMarginBottom  //距离容器底部外边距
 * @attr customHintPosition          //消息提示相对容器位置
 */
public class CustomMessageHintContainerView extends LinearLayout {
    private static final String TAG = "CustomMessageHintContai";
    //提示文字默认长度
    private final int DEFAULT_LENGTH = 3;
    //左上
    public static final int POSITION_TOP_LIFT = 101;
    //左下
    public static final int POSITION_BOTTOM_LIFT = 102;
    //右上
    public static final int POSITION_TOP_RIGHT = 103;
    //右下
    public static final int POSITION_BOTTOM_RIGHT = 104;
    /**
     * 提示文字内容
     */
    private String mMessageHintTextContent;
    //绘制提示文字背景的画笔
    private Paint mPaint;
    //绘制提示文字的画笔
    private TextPaint mTextPaint;
    //提示文字的颜色
    private int mMessageHintTextColor;
    //提示文字的尺寸
    private float mMessageHintTextSize;
    //提示文字的背景颜色
    private int mMessageHintBackgroundColor;
    //提示内容相对容器的位置
    private int mMessageHintPosition;
    //是否根据文字自适应背景大小
    private boolean isSelfAdaption;
    //提示文字外边距
    private float mMessageHintMarginLeft;
    private float mMessageHintMarginTop;
    private float mMessageHintMarginRight;
    private float mMessageHintMarginBottom;
    //默认背景的高度
    private float mDefaultBackgroundHeight = 0;


    public CustomMessageHintContainerView(Context context) {
        this(context, null);
    }

    public CustomMessageHintContainerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomMessageHintContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始默认属性
        initDefaultAttrs();
        //初始自定义属性
        initAttrs(context, attrs);
        //初始画笔
        initPaint();
        //计算默认情况下需要的背景尺寸
        countDefaultTextBackgroundSize();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        RectF mRectF = countHintTextPosition();
        if (mRectF != null) {
            float backgroundWidth = mRectF.width();
            float backgroundHeight = mRectF.height();
            float radius = backgroundHeight / 2.0F;
            //绘制背景
            canvas.drawRoundRect(mRectF, radius, radius, mPaint);
            Rect measureTextSize = measureTextSize("8");
            //绘制文字
            if (!isSelfAdaption) {
                if (Integer.parseInt(mMessageHintTextContent) > 99) {
                    canvas.drawText("99+", backgroundWidth / 2.0F + mRectF.left, radius + mRectF.top + measureTextSize.height() / 2.0F, mTextPaint);
                } else {
                    canvas.drawText(mMessageHintTextContent, backgroundWidth / 2.0F + mRectF.left, radius + mRectF.top + measureTextSize.height() / 2.0F, mTextPaint);
                }
            } else {
                canvas.drawText(mMessageHintTextContent, backgroundWidth / 2.0F + mRectF.left, radius + mRectF.top + measureTextSize.height() / 2.0F, mTextPaint);
            }


        }
    }


    /**
     * 计算默认背景尺寸
     */
    private void countDefaultTextBackgroundSize() {
        if (!TextUtils.isEmpty(mMessageHintTextContent)) {
            StringBuffer mStringBuffer = new StringBuffer();
            for (int i = 0; i < DEFAULT_LENGTH; i++) {
                mStringBuffer.append("8");
            }
            Rect mDefaultTextRect = measureTextSize(mStringBuffer.toString());
            mDefaultBackgroundHeight = (float) Math.ceil(Math.sqrt((Math.pow(mDefaultTextRect.width(), 2) + Math.pow(mDefaultTextRect.height(), 2))));

        }
    }

    /**
     * 计算提示文字显示位置
     */
    private RectF countHintTextPosition() {

        RectF mRectF = null;
        if (!TextUtils.isEmpty(mMessageHintTextContent)) {
            if (mDefaultBackgroundHeight == 0) {
                countDefaultTextBackgroundSize();
            }
            //显示内容的文字尺寸
            Rect mTextContentRect = measureTextSize(mMessageHintTextContent);
            int mMeasuredWidth = this.getMeasuredWidth();
            int mMeasuredHeight = this.getMeasuredHeight();
            mRectF = new RectF();
            switch (mMessageHintPosition) {
                case POSITION_TOP_LIFT:
                    mRectF.top = mMessageHintMarginTop;
                    mRectF.bottom = mMessageHintMarginTop + mDefaultBackgroundHeight;
                    mRectF.left = mMessageHintMarginLeft;
                    if (isSelfAdaption) {
                        if (mMessageHintTextContent.length() <= DEFAULT_LENGTH) {
                            mRectF.right = mMessageHintMarginLeft + mDefaultBackgroundHeight;
                        } else {
                            mRectF.right = mMessageHintMarginLeft + mTextContentRect.width() + mDefaultBackgroundHeight / 2;
                        }
                    } else {
                        mRectF.right = mMessageHintMarginLeft + mDefaultBackgroundHeight;
                    }
                    break;
                case POSITION_BOTTOM_LIFT:
                    mRectF.left = mMessageHintMarginLeft;
                    mRectF.bottom = mMeasuredHeight - mMessageHintMarginBottom;
                    mRectF.top = mMeasuredHeight - mMessageHintMarginBottom - mDefaultBackgroundHeight;
                    if (isSelfAdaption) {
                        if (mMessageHintTextContent.length() <= DEFAULT_LENGTH) {
                            mRectF.right = mMessageHintMarginLeft + mDefaultBackgroundHeight;
                        } else {
                            mRectF.right = mMessageHintMarginLeft + mTextContentRect.width() + mDefaultBackgroundHeight / 2;
                        }
                    } else {
                        mRectF.right = mMessageHintMarginLeft + mDefaultBackgroundHeight;
                    }
                    break;
                case POSITION_TOP_RIGHT:
                    mRectF.top = mMessageHintMarginTop;
                    mRectF.bottom = mMessageHintMarginTop + mDefaultBackgroundHeight;
                    mRectF.right = mMeasuredWidth - mMessageHintMarginRight;
                    if (isSelfAdaption) {
                        if (mMessageHintTextContent.length() <= DEFAULT_LENGTH) {
                            mRectF.left = mMeasuredWidth - (mMessageHintMarginRight + mDefaultBackgroundHeight);
                        } else {
                            mRectF.left = mMeasuredWidth - (mMessageHintMarginRight + mTextContentRect.width() + mDefaultBackgroundHeight / 2);
                        }
                    } else {
                        mRectF.left = mMeasuredWidth - (mMessageHintMarginRight + mDefaultBackgroundHeight);
                    }
                    break;
                case POSITION_BOTTOM_RIGHT:
                    mRectF.right = mMeasuredWidth - mMessageHintMarginRight;
                    mRectF.bottom = mMeasuredHeight - mMessageHintMarginBottom;
                    mRectF.top = mMeasuredHeight - mMessageHintMarginBottom - mDefaultBackgroundHeight;
                    if (isSelfAdaption) {
                        if (mMessageHintTextContent.length() <= DEFAULT_LENGTH) {
                            mRectF.left = mMeasuredWidth - mMessageHintMarginRight - mDefaultBackgroundHeight;
                        } else {
                            mRectF.left = mMeasuredWidth - mMessageHintMarginRight - mTextContentRect.width() - mDefaultBackgroundHeight / 2;
                        }
                    } else {
                        mRectF.left = mMeasuredWidth - mMessageHintMarginRight - mDefaultBackgroundHeight;

                    }
                    break;
                default:
                    mRectF.top = mMessageHintMarginTop;
                    mRectF.bottom = mMessageHintMarginTop + mDefaultBackgroundHeight;
                    mRectF.right = mMeasuredWidth - mMessageHintMarginRight;
                    if (isSelfAdaption) {
                        if (mMessageHintTextContent.length() <= DEFAULT_LENGTH) {
                            mRectF.left = mMeasuredWidth - (mMessageHintMarginRight + mDefaultBackgroundHeight);
                        } else {
                            mRectF.left = mMeasuredWidth - (mMessageHintMarginRight + mTextContentRect.width() + mDefaultBackgroundHeight / 2);
                        }
                    } else {
                        mRectF.left = mMeasuredWidth - (mMessageHintMarginRight + mDefaultBackgroundHeight);
                    }
            }
        }
        return mRectF;
    }


    //初始化画笔
    private void initPaint() {
        //绘制背景画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setColor(mMessageHintBackgroundColor);
        //绘制文字画笔
        mTextPaint = new TextPaint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(mMessageHintTextColor);
        mTextPaint.setTextSize(mMessageHintTextSize);
        mTextPaint.setTextAlign(TextPaint.Align.CENTER);
    }


    /**
     * 初始默认属性
     */
    private void initDefaultAttrs() {
        //默认文字颜色为白色
        mMessageHintTextColor = Color.WHITE;
        //默认文字大小12SP
        mMessageHintTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());
        //默认提示文字背景颜色红色
        mMessageHintBackgroundColor = Color.RED;
        //默认提示文字位置在右上角
        mMessageHintPosition = POSITION_TOP_RIGHT;
        //默认开启文字自适应
        isSelfAdaption = true;
        //默认外边距
        mMessageHintMarginLeft = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
        mMessageHintMarginRight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
        mMessageHintMarginTop = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
        mMessageHintMarginBottom = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
    }

    /**
     * 初始化自定义属性
     */
    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomMessageHintContainerView);
        isSelfAdaption = mTypedArray.getBoolean(R.styleable.CustomMessageHintContainerView_customSelfAdaption, isSelfAdaption);
        mMessageHintBackgroundColor = mTypedArray.getColor(R.styleable.CustomMessageHintContainerView_customHintTextBackground, mMessageHintBackgroundColor);
        mMessageHintTextColor = mTypedArray.getColor(R.styleable.CustomMessageHintContainerView_customHintTextColor, mMessageHintTextColor);
        mMessageHintTextSize = mTypedArray.getDimension(R.styleable.CustomMessageHintContainerView_customHintTextSize, mMessageHintTextSize);
        mMessageHintPosition = mTypedArray.getInt(R.styleable.CustomMessageHintContainerView_customHintPosition, mMessageHintPosition);
        mMessageHintMarginLeft = mTypedArray.getDimension(R.styleable.CustomMessageHintContainerView_customHintTextMarginLeft, mMessageHintMarginLeft);
        mMessageHintMarginRight = mTypedArray.getDimension(R.styleable.CustomMessageHintContainerView_customHintTextMarginRight, mMessageHintMarginRight);
        mMessageHintMarginTop = mTypedArray.getDimension(R.styleable.CustomMessageHintContainerView_customHintTextMarginTop, mMessageHintMarginTop);
        mMessageHintMarginBottom = mTypedArray.getDimension(R.styleable.CustomMessageHintContainerView_customHintTextMarginBottom, mMessageHintMarginBottom);
        mTypedArray.recycle();
    }


    /**
     * 测量文字的尺寸
     *
     * @return 一个汉字的矩阵
     */
    private Rect measureTextSize(String content) {
        Rect mRect = null;
        if (!TextUtils.isEmpty(content)) {
            if (mTextPaint != null) {
                mRect = new Rect();
                mTextPaint.getTextBounds(content, 0, content.length(), mRect);
            }
        }
        return mRect;
    }

    /**
     * 设置提示消息数
     *
     * @param number 提示数
     */
    public void setMessageNumber(int number) {
        this.mMessageHintTextContent = String.valueOf(number);
        invalidate();
    }

    /**
     * 设置背景根据内容自适应
     *
     * @param isSelfAdaption 是否开启自适应
     */
    public void setSelfAdaption(boolean isSelfAdaption) {
        this.isSelfAdaption = isSelfAdaption;
        invalidate();
    }

    /**
     * 设置消息相对容器的位置
     *
     * @param messageHintPosition 位置
     *                            <p> See
     *                            {@link #POSITION_TOP_RIGHT 右上角},
     *                            {@link #POSITION_BOTTOM_LIFT 左下角},
     *                            {@link #POSITION_BOTTOM_RIGHT 右下角},
     *                            {@link #POSITION_TOP_LIFT 左上角}
     */
    public void setMessageHintPosition(int messageHintPosition) {
        this.mMessageHintPosition = messageHintPosition;
        invalidate();
    }

    /**
     * 获取提示消息数
     *
     * @return 消息数
     */
    public int getMessageHintCount() {
        if (TextUtils.isEmpty(mMessageHintTextContent)) {
            return 0;
        }
        return Integer.parseInt(mMessageHintTextContent);
    }

    /**
     * 获取自适应状态
     *
     * @return 状态
     */
    public boolean getSelfAdaptionStatus() {
        return isSelfAdaption;
    }
}

Custom Attributes

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomMessageHintContainerView">
        <attr name="customHintTextColor" format="color" />
        <attr name="customHintTextSize" format="dimension" />
        <attr name="customHintTextBackground" format="color" />
        <attr name="customSelfAdaption" format="boolean" />
        <attr name="customHintTextMarginLeft" format="dimension" />
        <attr name="customHintTextMarginRight" format="dimension" />
        <attr name="customHintTextMarginTop" format="dimension" />
        <attr name="customHintTextMarginBottom" format="dimension" />
        <attr name="customHintPosition">
            <enum name="top_left" value="101" />
            <enum name="bottom_left" value="102" />
            <enum name="top_right" value="103" />
            <enum name="bottom_right" value="104" />
        </attr>
    </declare-styleable>
</resources>

Reproduced in: https: //www.jianshu.com/p/9d34b8370034

Guess you like

Origin blog.csdn.net/weixin_34364135/article/details/91073487