自定义角标

 

自定义角标_第1张图片

 

在res/values下新建attrs.xml文件

 


    

    
        
        
        
        
        
        
    
    
    
    
    

    
    

创建自定义View

public class BitmapSubscriptView extends View {

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

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

    public BitmapSubscriptView(Context context,  AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BitmapSubscriptView);
        init(typedArray);
    }
}

初始化

    public static final  int TOP_RIGHT = 0;
    public static final  int BOTTOM_RIGHT = 1;
    public static final  int BOTTOM_CENTER = 2;
    public static final  int BOTTOM_LEFT = 3;
    public static final  int TOP_LEFT = 4;
    public static final  int TOP_CENTER = 5;

    /**
     * 默认类型
     */
    @IntDef({TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_CENTER, BOTTOM_LEFT, TOP_LEFT,TOP_CENTER})
    @Retention(RetentionPolicy.SOURCE)
    private  @interface SubscriptOrientation {
    }    

    //文字画笔
    private TextPaint textPaint;

    /**
     * 获取文字画笔
     */
    public Paint getTextPaint(){
        return textPaint;
    }

    //文字颜色
    private int textColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorWhite);

    /**
     * 设置角标中文字的颜色
     * @param textColor 文字颜色
     */
    public void setTextColor(int textColor){
        this.textColor = textColor;
        textPaint.setColor(textColor);
        invalidate();
    }

    //文字
    private String subscriptText = "0";

    /**
     * 设置角标中的文字
     * @param subscriptText 角标数字
     */
    public void setSubscriptText(String subscriptText){
        this.subscriptText = subscriptText;
        invalidate();
    }

    //角标画笔
    private Paint subscriptPaint;

    /**
     * 获取角标画笔
     */
    public Paint getSubscriptPaint(){
        return subscriptPaint;
    }

    //角标颜色
    private int subscriptColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorAccent);

    /**
     * 设置角标填充颜色
     * @param subscriptColor 角标颜色
     */
    public void setSubscriptColor(int subscriptColor){
        this.subscriptColor = subscriptColor;
        subscriptPaint.setColor(subscriptColor);
        invalidate();
    }

    //角标半径
    private float subscriptRadius ;

    /**
     * 设置角标半径
     * @param subscriptRadius 半径
     */
    public void setSubscriptRadius(float subscriptRadius){
        if (blankBitmap != null){
            blankBitmap = null;
        }
        this.subscriptRadius = subscriptRadius;
        invalidate();
    }

    //角标X轴偏移量
    private float angularOffsetX = 0 ;

    /**
     * 设置角标X轴偏移量
     * @param angularOffsetX 正数:向右;负数:向左
     */
    public void setAngularOffsetX(float angularOffsetX){
        this.angularOffsetX = angularOffsetX;
        invalidate();
    }

    //角标Y轴偏移量
    private float angularOffsetY = 0 ;

    /**
     * 设置角标Y轴偏移量
     * @param angularOffsetY 正数:向下;负数:向上
     */
    public void setAngularOffsetY(float angularOffsetY){
        this.angularOffsetY = angularOffsetY;
        invalidate();
    }

    //角标位置
    private int subscriptOrientation;

    /**
     * 设置角标位置
     * @param subscriptOrientation 右上,右下,中下,左下,左上,左中
     */
    public void setSubscriptOrientation(@SubscriptOrientation int subscriptOrientation){
        this.subscriptOrientation = subscriptOrientation;
        invalidate();
    }

    //空白位图
    private Bitmap blankBitmap;

    //位图
    private Bitmap bitmap;

    /**
     * 设置位图
     * @param id id
     * @param isRGB 是否使用RGB_565压缩图片
     */
    public void setBitmap(@DrawableRes int id,boolean isRGB){
        if (blankBitmap != null){
            blankBitmap = null;
        }
        bitmap = getBitmapResources(getResources(), id, isRGB);
        invalidate();
    }

    /**
     * 设置位图
     * @param bitmap bitmap
     */
    public void setBitmap(Bitmap bitmap) {
        if (blankBitmap != null){
            blankBitmap = null;
        }
        this.bitmap = bitmap;
        invalidate();
    }

    //屏幕宽高
    private int width;
    private int height;

    private void init(TypedArray typedArray) {
        subscriptOrientation = typedArray.getInt(R.styleable.BitmapSubscriptView_subscript_orientation,0);
        angularOffsetX = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_x,angularOffsetX);
        angularOffsetY = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_y,angularOffsetY);
        subscriptRadius = typedArray.getDimension(R.styleable.BitmapSubscriptView_subscript_radius,0);
        subscriptColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_color,subscriptColor);
        subscriptText = typedArray.getString(R.styleable.BitmapSubscriptView_subscript_text);
        textColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_text_color,textColor);
        int id = typedArray.getResourceId(R.styleable.BitmapSubscriptView_subscript_bitmap,R.drawable.ic_launcher);
        bitmap = getBitmapResources(getResources(),id,false);

        typedArray.recycle();

        if (subscriptText == null){
            subscriptText = "0";
        }

        subscriptPaint = new Paint();
        subscriptPaint.setColor(subscriptColor);
        subscriptPaint.setStyle(Paint.Style.FILL);
        subscriptPaint.setAntiAlias(true);

        textPaint = new TextPaint();
        textPaint.setColor(textColor);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setAntiAlias(true);

        screenWidth();
    }

    /**
     * 读取资源文件夹下图片
     *
     * @param res   getResources
     * @param id    文件id
     * @param isRGB 是否使用RGB_565压缩图片
     * @return bitmap
     */
    public Bitmap getBitmapResources(Resources res, int id, boolean isRGB) {
        TypedValue value = new TypedValue();
        InputStream is = res.openRawResource(id, value);
        if (isRGB) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            return BitmapFactory.decodeStream(new BufferedInputStream(is), null, options);
        }
        return BitmapFactory.decodeStream(new BufferedInputStream(is));
    }

    /**
     * 获取屏幕宽高
     */
    private void screenWidth() {
        WindowManager wm = (WindowManager) getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        if (wm != null) {
            Display display = wm.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            width = size.x;
            height = size.y;
        }
    }

绘制

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //最短边距
        int length = Math.min(getWidth(),getHeight());
        //如果没有设置角标半径,或者角标直径大于等于最短边距,那么subscriptRadius = 最短边距的6分之1
        if (subscriptRadius == 0){
            subscriptRadius = length/6f;
        }else if (2*subscriptRadius >= length){
            subscriptRadius = length/6f;
        }

        if (blankBitmap == null){
            //新图绘制区域高宽
            float width = getWidth() - 2*subscriptRadius;
            float height = getHeight() - 2*subscriptRadius;
            //缩放比例
            float scale = Math.min(width/bitmap.getWidth(),height/bitmap.getHeight());
            //新图大小
            int a = (int) (bitmap.getWidth()*scale);
            int b = (int) (bitmap.getHeight()*scale);
            //创建空白位图
            blankBitmap = Bitmap.createBitmap(a, b,Bitmap.Config.ARGB_8888);
            Canvas blankCanvas = new Canvas(blankBitmap);
            //将传入的图片绘制到空白位图上
            Matrix matrix = new Matrix();
            matrix.setScale(scale,scale);
            blankCanvas.drawBitmap(bitmap, matrix,subscriptPaint);
        }

        // 新图X坐标 =(控件宽 - 新图宽)/ 2
        float x = (getWidth() - blankBitmap.getWidth())/2f;
        float y = (getHeight() - blankBitmap.getHeight())/2f;
        //绘制新图
        canvas.drawBitmap(blankBitmap,x,y,subscriptPaint);

        // 角标X坐标 = (控件宽 + 新图宽)/2
        float subscriptX;
        float subscriptY;
        switch (subscriptOrientation){
            case BOTTOM_RIGHT:
                subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case BOTTOM_CENTER:
                subscriptX = getWidth()/2f + angularOffsetX;
                subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case BOTTOM_LEFT:
                subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case TOP_LEFT:
                subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case TOP_CENTER:
                subscriptX = getWidth()/2f + angularOffsetX;
                subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            default:
                subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
                break;
        }

        //绘制角标
        canvas.drawCircle(subscriptX ,  subscriptY , subscriptRadius ,subscriptPaint);

        textPaint.setTextSize(subscriptRadius/2);
        //绘制角标中的数字
        canvas.drawText(subscriptText,subscriptX, subscriptY - textPaint.ascent()/2f ,textPaint);
    }

测量

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
        int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
        int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
        int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);

        //限制控件大小不能大于屏幕宽高
        setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? Math.min(measureWidth, width) : Math.min(bitmap.getWidth(), width)
                , (measureHeightMode == MeasureSpec.EXACTLY) ? Math.min(measureHeight, height) : Math.min(bitmap.getHeight(), height));
    }

使用

//设置图片
bitmapSubscriptView.setBitmap(R.drawable.test,false)
bitmapSubscriptView.setBitmap(bitmap)
//设置角标颜色和半径
bitmapSubscriptView.setSubscriptColor(R.color.colorAccent)
bitmapSubscriptView.setSubscriptRadius(10f)
//设置角标方位和偏移量
bitmapSubscriptView.setSubscriptOrientation(BitmapSubscriptView.TOP_LEFT)
bitmapSubscriptView.setAngularOffsetX(100f)
bitmapSubscriptView.setAngularOffsetY(100f)
//设置角标文字和颜色
bitmapSubscriptView.setSubscriptText("1")
bitmapSubscriptView.setTextColor(R.color.colorWhite)
app:subscript_bitmap="@drawable/test"
app:subscript_radius="40dp"
app:subscript_orientation="bottom_right"
app:subscript_color="@color/colorAccent"
app:subscript_text="1"
app:subscript_text_color="@color/colorWhite"
app:angular_offset_x="-10dp"
app:angular_offset_y="10dp"

完整代码

public class BitmapSubscriptView extends View {

    public static final  int TOP_RIGHT = 0;
    public static final  int BOTTOM_RIGHT = 1;
    public static final  int BOTTOM_CENTER = 2;
    public static final  int BOTTOM_LEFT = 3;
    public static final  int TOP_LEFT = 4;
    public static final  int TOP_CENTER = 5;

    /**
     * 默认类型
     */
    @IntDef({TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_CENTER, BOTTOM_LEFT, TOP_LEFT,TOP_CENTER})
    @Retention(RetentionPolicy.SOURCE)
    private  @interface SubscriptOrientation {
    }

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

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

    public BitmapSubscriptView(Context context,  AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BitmapSubscriptView);
        init(typedArray);
    }

    //文字画笔
    private TextPaint textPaint;

    /**
     * 获取文字画笔
     */
    public Paint getTextPaint(){
        return textPaint;
    }

    //文字颜色
    private int textColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorWhite);

    /**
     * 设置角标中文字的颜色
     * @param textColor 文字颜色
     */
    public void setTextColor(int textColor){
        this.textColor = textColor;
        textPaint.setColor(textColor);
        invalidate();
    }

    //文字
    private String subscriptText = "0";

    /**
     * 设置角标中的文字
     * @param subscriptText 角标数字
     */
    public void setSubscriptText(String subscriptText){
        this.subscriptText = subscriptText;
        invalidate();
    }

    //角标画笔
    private Paint subscriptPaint;

    /**
     * 获取角标画笔
     */
    public Paint getSubscriptPaint(){
        return subscriptPaint;
    }

    //角标颜色
    private int subscriptColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorAccent);

    /**
     * 设置角标填充颜色
     * @param subscriptColor 角标颜色
     */
    public void setSubscriptColor(int subscriptColor){
        this.subscriptColor = subscriptColor;
        subscriptPaint.setColor(subscriptColor);
        invalidate();
    }

    //角标半径
    private float subscriptRadius ;

    /**
     * 设置角标半径
     * @param subscriptRadius 半径
     */
    public void setSubscriptRadius(float subscriptRadius){
        this.subscriptRadius = subscriptRadius;
        invalidate();
    }

    //角标X轴偏移量
    private float angularOffsetX = 0 ;

    /**
     * 设置角标X轴偏移量
     * @param angularOffsetX 正数:向右;负数:向左
     */
    public void setAngularOffsetX(float angularOffsetX){
        this.angularOffsetX = angularOffsetX;
        invalidate();
    }

    //角标Y轴偏移量
    private float angularOffsetY = 0 ;

    /**
     * 设置角标Y轴偏移量
     * @param angularOffsetY 正数:向下;负数:向上
     */
    public void setAngularOffsetY(float angularOffsetY){
        this.angularOffsetY = angularOffsetY;
        invalidate();
    }

    //角标位置
    private int subscriptOrientation;

    /**
     * 设置角标位置
     * @param subscriptOrientation 右上,右下,中下,左下,左上,左中
     */
    public void setSubscriptOrientation(@SubscriptOrientation int subscriptOrientation){
        this.subscriptOrientation = subscriptOrientation;
        invalidate();
    }

    //空白位图
    private Bitmap blankBitmap;

    //位图
    private Bitmap bitmap;

    /**
     * 设置位图
     * @param id id
     * @param isRGB 是否使用RGB_565压缩图片
     */
    public void setBitmap(@DrawableRes int id,boolean isRGB){
        bitmap = getBitmapResources(getResources(), id, isRGB);
        invalidate();
    }

    /**
     * 设置位图
     * @param bitmap bitmap
     */
    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
        invalidate();
    }

    //屏幕宽高
    private int width;
    private int height;

    private void init(TypedArray typedArray) {
        subscriptOrientation = typedArray.getInt(R.styleable.BitmapSubscriptView_subscript_orientation,0);
        angularOffsetX = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_x,angularOffsetX);
        angularOffsetY = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_y,angularOffsetY);
        subscriptRadius = typedArray.getDimension(R.styleable.BitmapSubscriptView_subscript_radius,0);
        subscriptColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_color,subscriptColor);
        subscriptText = typedArray.getString(R.styleable.BitmapSubscriptView_subscript_text);
        textColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_text_color,textColor);
        int id = typedArray.getResourceId(R.styleable.BitmapSubscriptView_subscript_bitmap,R.drawable.ic_launcher);
        bitmap = getBitmapResources(getResources(),id,false);

        typedArray.recycle();

        if (subscriptText == null){
            subscriptText = "0";
        }

        subscriptPaint = new Paint();
        subscriptPaint.setColor(subscriptColor);
        subscriptPaint.setStyle(Paint.Style.FILL);
        subscriptPaint.setAntiAlias(true);

        textPaint = new TextPaint();
        textPaint.setColor(textColor);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setAntiAlias(true);

        screenWidth();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //最短边距
        int length = Math.min(getWidth(),getHeight());
        //如果没有设置角标半径,或者角标直径大于等于最短边距,那么subscriptRadius = 最短边距的6分之1
        if (subscriptRadius == 0){
            subscriptRadius = length/6f;
        }else if (2*subscriptRadius >= length){
            subscriptRadius = length/6f;
        }

        if (blankBitmap == null){
            //新图绘制区域高宽
            float width = getWidth() - 2*subscriptRadius;
            float height = getHeight() - 2*subscriptRadius;
            //缩放比例
            float scale = Math.min(width/bitmap.getWidth(),height/bitmap.getHeight());
            //新图大小
            int a = (int) (bitmap.getWidth()*scale);
            int b = (int) (bitmap.getHeight()*scale);
            //创建空白位图
            blankBitmap = Bitmap.createBitmap(a, b,Bitmap.Config.ARGB_8888);
            Canvas blankCanvas = new Canvas(blankBitmap);
            //将传入的图片绘制到空白位图上
            Matrix matrix = new Matrix();
            matrix.setScale(scale,scale);
            blankCanvas.drawBitmap(bitmap, matrix,subscriptPaint);
        }

        // 新图X坐标 =(控件宽 - 新图宽)/ 2
        float x = (getWidth() - blankBitmap.getWidth())/2f;
        float y = (getHeight() - blankBitmap.getHeight())/2f;
        //绘制新图
        canvas.drawBitmap(blankBitmap,x,y,subscriptPaint);

        // 角标X坐标 = (控件宽 + 新图宽)/2
        float subscriptX;
        float subscriptY;
        switch (subscriptOrientation){
            case BOTTOM_RIGHT:
                subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case BOTTOM_CENTER:
                subscriptX = getWidth()/2f + angularOffsetX;
                subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case BOTTOM_LEFT:
                subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case TOP_LEFT:
                subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            case TOP_CENTER:
                subscriptX = getWidth()/2f + angularOffsetX;
                subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
                break;
            default:
                subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
                subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
                break;
        }

        //绘制角标
        canvas.drawCircle(subscriptX ,  subscriptY , subscriptRadius ,subscriptPaint);

        textPaint.setTextSize(subscriptRadius/2);
        //绘制角标中的数字
        canvas.drawText(subscriptText,subscriptX, subscriptY - textPaint.ascent()/2f ,textPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
        int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
        int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
        int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);

        //限制控件大小不能大于屏幕宽高
        setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? Math.min(measureWidth, width) : Math.min(bitmap.getWidth(), width)
                , (measureHeightMode == MeasureSpec.EXACTLY) ? Math.min(measureHeight, height) : Math.min(bitmap.getHeight(), height));
    }

    /**
     * 读取资源文件夹下图片
     *
     * @param res   getResources
     * @param id    文件id
     * @param isRGB 是否使用RGB_565压缩图片
     * @return bitmap
     */
    public Bitmap getBitmapResources(Resources res, int id, boolean isRGB) {
        TypedValue value = new TypedValue();
        InputStream is = res.openRawResource(id, value);
        if (isRGB) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            return BitmapFactory.decodeStream(new BufferedInputStream(is), null, options);
        }
        return BitmapFactory.decodeStream(new BufferedInputStream(is));
    }

    /**
     * 获取屏幕宽高
     */
    private void screenWidth() {
        WindowManager wm = (WindowManager) getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        if (wm != null) {
            Display display = wm.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            width = size.x;
            height = size.y;
        }
    }
}

 

 

 

 

 

 

 

你可能感兴趣的:(安卓基础,自定义View)