倾斜的角标 android倾斜角标实现

android倾斜角标实现_android 图片角标如何制作-CSDN博客

复制代码
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;

import com.feishi.pettyloan.R;

/**
 * @author qiaoshi
 * @name IndexText
 * @class name:com.example.mylibrary
 * @time 2019/10/12 14:40
 */
public class SlantedTextView extends View {
    public static final int TAG_LEFT = 0x00000000;
    public static final int TAG_Right = 0x00000001;
    public static final int TAG_LEFT_BOTTOM = 0x00000002;
    public static final int TAG_RIGHT_BOTTOM = 0x00000003;
    public static final int TAG_LEFT_BAR = 0x00000004;
    public static final int TAG_RIGHT_BAR = 0x00000005;
    public static final int TAG_LEFT_BOTTOM_BAR = 0x00000006;
    public static final int TAG_RIGHT_BOTTOM_BAR = 0x00000007;
    public static final int TAG_LEFT_ANGLE = 0x00000008;


    private int myBackgroundColor = Color.WHITE;//默认白色
    private int TAG_Mode = TAG_LEFT;
    private Paint mPaint;//绘制背景色

    private TextPaint mTextPaint;
    private String myText = "";
    private float myTextSize = 14;
    private float mySlantedHeight = 40;//倾斜高度
    private int myTextColor = Color.BLACK;
    private int ROTATE_ANGLE = 45;//默认倾斜角度
    private float PADDING_TOP = 0;//全角到底部距离


    public SlantedTextView(Context context) {
        super(context);
    }

    public SlantedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public SlantedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public SlantedTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs);
    }

    /**
     * 初始化相关方法
     */
    private void init(AttributeSet attrs) {
        //加载默认属性
        TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.SlantedTextViewAtt);
        myBackgroundColor = array.getColor(R.styleable.SlantedTextViewAtt_myBackgroundColor, myBackgroundColor);
        myTextSize = array.getDimension(R.styleable.SlantedTextViewAtt_myTextSize, myTextSize);
        myTextColor = array.getColor(R.styleable.SlantedTextViewAtt_myTextColor, myTextColor);
        PADDING_TOP = array.getDimension(R.styleable.SlantedTextViewAtt_myPaddingTop, PADDING_TOP);
        mySlantedHeight = array.getDimension(R.styleable.SlantedTextViewAtt_mySlantedHeight, mySlantedHeight);

        if (array.hasValue(R.styleable.SlantedTextViewAtt_tagModel))//判断用户是否设置该方法
            TAG_Mode = array.getInt(R.styleable.SlantedTextViewAtt_tagModel, TAG_LEFT);
        if (array.hasValue(R.styleable.SlantedTextViewAtt_myText))
            myText = array.getString(R.styleable.SlantedTextViewAtt_myText);

        array.recycle();//设置完回收
        //初始化背景颜色画笔
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));//设置绘制模式这里表示显示在上面
        mPaint.setAntiAlias(true);
        mPaint.setColor(myBackgroundColor);

        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(myTextColor);
        mTextPaint.setTextSize(myTextSize);
        mTextPaint.setAntiAlias(true);


    }

    /**
     * 绘制字体颜色和背景颜色
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBackgroundColor(canvas);
        drawText(canvas);
    }

    //绘制背景颜色
    private void drawBackgroundColor(Canvas canvas) {
        //通过path绘制路径
        Path path = new Path();
        int mWidth = getWidth();
        int mHeight = getHeight();
        if (mWidth != mHeight) throw new IllegalStateException("设置的布局高和宽度必须一致");
        switch (TAG_Mode) {//设置具体模式
            case TAG_LEFT:
                path.lineTo(0, mHeight);
                path.lineTo(mWidth, 0);
                break;
            case TAG_Right:
                path.lineTo(mWidth, 0);
                path.lineTo(mWidth, mHeight);
                break;
            case TAG_LEFT_BOTTOM:
                path.lineTo(mWidth, mHeight);
                path.lineTo(0, mHeight);
                break;
            case TAG_RIGHT_BOTTOM:
                path.moveTo(0, mHeight);//移动坐标原点位置
                path.lineTo(mWidth, mHeight);
                path.lineTo(mWidth, 0);
                break;
            case TAG_LEFT_BAR:
                path.moveTo(mWidth, 0);
                path.lineTo(0, mHeight);
                path.lineTo(0, mHeight - mySlantedHeight);
                path.lineTo(mWidth - mySlantedHeight, 0);
                break;
            case TAG_RIGHT_BAR:
                path.lineTo(mWidth, mHeight);
                path.lineTo(mWidth, mHeight - mySlantedHeight);
                path.lineTo(mySlantedHeight, 0);
                break;
            case TAG_LEFT_BOTTOM_BAR:
                path.lineTo(mWidth, mHeight);
                path.lineTo(mWidth - mySlantedHeight, mHeight);
                path.lineTo(0, mySlantedHeight);
                break;
            case TAG_RIGHT_BOTTOM_BAR:
                path.moveTo(0, mHeight);
                path.lineTo(mySlantedHeight, mHeight);
                path.lineTo(mWidth, mySlantedHeight);
                path.lineTo(mWidth, 0);
                break;
            case TAG_LEFT_ANGLE:
                //绘制两个角度
             /*   path.reset();
                path.moveTo(mWidth-pointWidth,0);
                path.lineTo(mWidth,pointHeight);
                path.lineTo(mWidth-pointWidth-26,pointHeight);*/

                // path.reset();
               /* path.moveTo(0,mHeight-pointWidth);
                path.lineTo(pointHeight,mHeight);
                path.lineTo(pointHeight,mHeight-pointWidth-26);*/
                /*
                path.moveTo(mWidth - 100 - pointWidth, 0);
                path.lineTo(mWidth - pointWidth, 0);
                path.lineTo(0, mHeight - pointWidth);
                path.lineTo(0, mHeight - 100 - pointWidth);*/
                break;
        }
        path.close();
        canvas.drawPath(path, mPaint);
        canvas.save();
    }

    //绘制字体(从中间开始设置字体)
    private void drawText(Canvas canvas) {
        int w = (int) (canvas.getWidth() - mySlantedHeight / 2);
        int h = (int) (canvas.getHeight() - mySlantedHeight / 2);
        float[] xy = calculateXY(w, h);
        float toX = xy[0];
        float toY = xy[1];
        float centerX = xy[2];
        float centerY = xy[3];
        float angle = xy[4];
        canvas.rotate(angle, centerX, centerY);
        canvas.drawText(myText, toX, toY + PADDING_TOP, mTextPaint);
    }

    private float[] calculateXY(int w, int h) {
        float[] xy = new float[5];
        Rect rect;
        RectF rectF;
        int offset = (int) (mySlantedHeight / 2);
        //根据模式进行绘制
        switch (TAG_Mode) {
            case TAG_LEFT:
            case TAG_LEFT_BAR:


                rect = new Rect(0, 0, w, h);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(myText, 0, myText.length());
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();//Ascent: 字符顶部到baseLine的距离  Descent: 字符底部到baseLine的距离
                rectF.left += (rect.width() - rectF.right) / 2.0f;
                rectF.top += (rect.height() - rectF.bottom) / 2.0f;
                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2;
                xy[3] = h / 2;
                xy[4] = -ROTATE_ANGLE;
                break;
            case TAG_Right:
            case TAG_RIGHT_BAR:

                rect = new Rect(offset, 0, w + offset, h);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(myText, 0, myText.length());
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();
                rectF.left += (rect.width() - rectF.right) / 2.0f;
                rectF.top += (rect.height() - rectF.bottom) / 2.0f;
                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2 + offset;
                xy[3] = h / 2;
                xy[4] = ROTATE_ANGLE;
                break;
            case TAG_LEFT_BOTTOM:
            case TAG_LEFT_BOTTOM_BAR:

                rect = new Rect(0, offset, w, h + offset);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(myText, 0, myText.length());
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();
                rectF.left += (rect.width() - rectF.right) / 2.0f;
                rectF.top += (rect.height() - rectF.bottom) / 2.0f;
                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2;
                xy[3] = h / 2 + offset;
                xy[4] = ROTATE_ANGLE;
                break;

            case TAG_RIGHT_BOTTOM:
            case TAG_RIGHT_BOTTOM_BAR:
                rect = new Rect(offset, offset, w + offset, h + offset);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(myText, 0, myText.length());
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();
                rectF.left += (rect.width() - rectF.right) / 2.0f;
                rectF.top += (rect.height() - rectF.bottom) / 2.0f;
                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2 + offset;
                xy[3] = h / 2 + offset;
                xy[4] = -ROTATE_ANGLE;
                break;
        }
        return xy;
    }

    /**
     * 暴露设置的方法
     */
    public SlantedTextView setText(String text) {
        myText = text;
        postInvalidate();
        return this;
    }

    public SlantedTextView setText(int res) {
        String str = getResources().getString(res);
        if (str != null) {
            setText(str);
        }
        return this;
    }

    public String getText() {
        return myText;
    }

    // font color
    public SlantedTextView setTextColor(int color) {
        myTextColor = color;
        mTextPaint.setColor(myTextColor);
        postInvalidate();
        return this;
    }

    // font size

    public SlantedTextView setTextSize(int size) {
        this.myTextSize = size;
        mTextPaint.setTextSize(myTextSize);
        postInvalidate();
        return this;

    }

    //背景颜色
    public SlantedTextView setBackground(int color) {
        myBackgroundColor = color;
        mPaint.setColor(myBackgroundColor);
        postInvalidate();
        return this;

    }


    public SlantedTextView setMode(int mode) {
        if (TAG_Mode > TAG_RIGHT_BOTTOM_BAR || TAG_Mode < 0)
            throw new IllegalArgumentException(mode + "不存该模式");
        this.TAG_Mode = mode;
        postInvalidate();
        return this;
    }

    public int getMode() {
        return TAG_Mode;
    }

    public SlantedTextView setSlantedHeight(int length) {
        mySlantedHeight = length;
        postInvalidate();
        return this;
    }

    public SlantedTextView setPadding(int padding) {
        PADDING_TOP = padding;
        postInvalidate();
        return this;
    }


}

attrs.xml

复制代码
    <declare-styleable name="SlantedTextView">
        <attr name="slantedTextSize" format="dimension" />
        <attr name="slantedBackgroundColor" format="color" />
        <attr name="slantedText" format="string" />
        <attr name="slantedTextColor" format="color" />
        <attr name="slantedLength" format="dimension" />
        <attr name="slantedMode" format="enum">
            <enum name="left" value="0"></enum>
            <enum name="right" value="1"></enum>
            <enum name="left_bottom" value="2"></enum>
            <enum name="right_bottom" value="3"></enum>
            <enum name="left_triangle" value="4"></enum>
            <enum name="right_triangle" value="5"></enum>
            <enum name="left_bottom_triangle" value="6"></enum>
            <enum name="right_bottom_triangle" value="7"></enum>
        </attr>
    </declare-styleable>

    <!--提供布局调用属性(背景颜色)-->
    <declare-styleable name="SlantedTextViewAtt">
        <attr name="myBackgroundColor" format="color" />
        <attr name="tagModel" format="enum">
            <enum name="left" value="0"></enum>
            <enum name="right" value="1"></enum>
            <enum name="left_bottom" value="2"></enum>
            <enum name="right_bottom" value="3"></enum>
            <enum name="left_bar" value="4" />
            <enum name="right_bar" value="5" />
            <enum name="left_bottom_bar" value="6" />
            <enum name="right_bottom_bar" value="7" />
            <enum name="left_angle" value="8" />
        </attr>
        <attr name="myTextSize" format="dimension" />
        <attr name="myTextColor" format="color" />
        <attr name="myText" format="string" />
        <attr name="myPaddingTop" format="dimension" />
        <attr name="mySlantedHeight" format="dimension" />
    </declare-styleable>
相关推荐
三少爷的鞋13 分钟前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)4 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
晚风叙码6 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
传奇开心果编程6 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程9 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程10 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程11 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程11 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓11 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程11 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer