|
| 1 | +package com.lwp.customviewtest.CustomViews; |
| 2 | + |
| 3 | +import android.content.Context; |
| 4 | +import android.content.res.ColorStateList; |
| 5 | +import android.content.res.TypedArray; |
| 6 | +import android.graphics.Canvas; |
| 7 | +import android.graphics.Color; |
| 8 | +import android.graphics.Paint; |
| 9 | +import android.graphics.Rect; |
| 10 | +import android.text.style.DynamicDrawableSpan; |
| 11 | +import android.util.AttributeSet; |
| 12 | +import android.util.TypedValue; |
| 13 | +import android.view.View; |
| 14 | +import android.view.ViewGroup; |
| 15 | +import android.widget.LinearLayout; |
| 16 | + |
| 17 | +import com.lwp.customviewtest.R; |
| 18 | + |
| 19 | +/** |
| 20 | + * <pre> |
| 21 | + * author : 李蔚蓬(简书_凌川江雪) |
| 22 | + * time : 2020/8/17 2:21 |
| 23 | + * desc : |
| 24 | + * </pre> |
| 25 | + */ |
| 26 | +public class TextView extends LinearLayout { |
| 27 | + |
| 28 | + private String mText; |
| 29 | + private int mTextSize = 15; |
| 30 | + private int mTextColor = Color.BLACK; |
| 31 | + |
| 32 | + //写字用的画笔 |
| 33 | + private Paint mPaint; |
| 34 | + |
| 35 | + //这个构造函数 会在代码里面 new的时候 调用 |
| 36 | + //TextView textView = new TextView(this); |
| 37 | + public TextView(Context context) { |
| 38 | + this(context,null); |
| 39 | + } |
| 40 | + |
| 41 | + //这个构造函数 在布局layout中使用时候 调用 |
| 42 | +// <com.lwp.customviewtest.CustomViews.TextView |
| 43 | +// android:layout_width="wrap_content" |
| 44 | +// android:layout_height="wrap_content" /> |
| 45 | + public TextView(Context context, AttributeSet attrs) { |
| 46 | + this(context, attrs, 0); |
| 47 | + } |
| 48 | + |
| 49 | + //这个构造函数 在布局layout中使用 并且有style的时候 调用 |
| 50 | + // 【Refactor -- Extract -- style】 |
| 51 | +// <com.lwp.customviewtest.CustomViews.TextView |
| 52 | +// android:text="6666666666666666666" |
| 53 | +// style="@style/cstyle" /> |
| 54 | +// style可以提取重复的属性 |
| 55 | + public TextView(Context context, AttributeSet attrs, int defStyleAttr) { |
| 56 | + super(context, attrs, defStyleAttr); |
| 57 | + |
| 58 | + // 获取自定义属性列表 TypedArray |
| 59 | + TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.TextView); |
| 60 | + // 获取文本 有时候可能会找不到我们自定义的属性 如TextView_lwpMaxLength,这个时候Rebuild一下,或者重启AS即可 |
| 61 | + mText = (String) typedArray.getText(R.styleable.TextView_lwpText); |
| 62 | + // 获取文字颜色 |
| 63 | + mTextColor = typedArray.getColor(R.styleable.TextView_lwpTextColor, mTextColor); |
| 64 | + // 获取文字大小 |
| 65 | + mTextSize = typedArray.getDimensionPixelSize(R.styleable.TextView_lwpTextSize, sp2px(mTextSize)); |
| 66 | + |
| 67 | + // 回收 |
| 68 | + typedArray.recycle(); |
| 69 | + |
| 70 | + mPaint = new Paint(); |
| 71 | + //抗锯齿 画的时候不会那么模糊 |
| 72 | + mPaint.setAntiAlias(true); |
| 73 | + //设置 字体的大小和颜色!! |
| 74 | + mPaint.setTextSize(mTextSize); |
| 75 | + mPaint.setColor(mTextColor); |
| 76 | + |
| 77 | + //思路2:默认给一个背景 |
| 78 | +// setBackgroundColor(Color.TRANSPARENT); |
| 79 | + |
| 80 | + //思路3: |
| 81 | + setWillNotDraw(false); |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * 自定义View的测量方法 |
| 86 | + * @param widthMeasureSpec |
| 87 | + * @param heightMeasureSpec |
| 88 | + */ |
| 89 | + @Override |
| 90 | + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
| 91 | + super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
| 92 | + //布局的 宽高 都是由这个方法指定 |
| 93 | + //指定控件的宽高 需要测量 |
| 94 | + |
| 95 | + //获取宽高的模式 widthMeasureSpec的前两位 |
| 96 | + int widthMode = MeasureSpec.getMode(widthMeasureSpec); |
| 97 | + int heightMode = MeasureSpec.getMode(heightMeasureSpec); |
| 98 | + |
| 99 | + Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt(); |
| 100 | + |
| 101 | + //1.确定的值,这个时候 不需要计算,给的多少就是多少 |
| 102 | + //获取宽高的值 widthMeasureSpec的后30位 |
| 103 | + int widthSize = MeasureSpec.getSize(widthMeasureSpec); |
| 104 | + int heightSize = MeasureSpec.getSize(heightMeasureSpec); |
| 105 | + |
| 106 | + |
| 107 | + //2.给的是wrap_content,需要计算 |
| 108 | + if (widthMode == MeasureSpec.AT_MOST) { |
| 109 | + //计算的宽度 与 字体的长度、大小 有关 用画笔来测量 |
| 110 | + Rect bounds = new Rect(); |
| 111 | + //获取文本的 Rect |
| 112 | + mPaint.getTextBounds(mText, 0, mText.length(), bounds); |
| 113 | + //拿到文本的宽度 |
| 114 | + widthSize = bounds.width() + getPaddingLeft() + getPaddingRight(); |
| 115 | + } |
| 116 | + if (heightMode == MeasureSpec.AT_MOST) { |
| 117 | + |
| 118 | + int x = getPaddingLeft(); |
| 119 | + //计算的宽度 与 字体的长度、大小 有关 用画笔来测量 |
| 120 | + Rect bounds = new Rect(); |
| 121 | + //获取文本的 Rect |
| 122 | + mPaint.getTextBounds(mText, x, mText.length(), bounds); |
| 123 | + //拿到文本的高度 |
| 124 | + heightSize = bounds.height() + getPaddingTop() + getPaddingBottom() - |
| 125 | + fontMetricsInt.ascent + fontMetricsInt.descent; |
| 126 | + } |
| 127 | + |
| 128 | + //设置控件的宽高 |
| 129 | + setMeasuredDimension(widthSize, heightSize); |
| 130 | + } |
| 131 | + |
| 132 | + @Override |
| 133 | + protected void onDraw(Canvas canvas) { |
| 134 | + super.onDraw(canvas); |
| 135 | + |
| 136 | + //***********************************计算基线************************************ |
| 137 | + //画文字 四个参数:text内容 x y paint画笔 |
| 138 | + //x 开始的位置 0 y 基线 |
| 139 | + //dy 代表的是:高度的一半到 baseline的距离 |
| 140 | + Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt(); |
| 141 | + int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom; |
| 142 | + int baseline = getHeight() / 2 + dy; |
| 143 | + //******************************************************************************* |
| 144 | + |
| 145 | +// canvas.drawText(mText, 0, getHeight() / 2, mPaint); |
| 146 | + canvas.drawText(mText, 0, baseline, mPaint); |
| 147 | + } |
| 148 | + |
| 149 | + //sp转px |
| 150 | + private int sp2px(int sp) { |
| 151 | + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics()); |
| 152 | + } |
| 153 | +} |
0 commit comments