介面無小事(五):自定義TextView

Sorrower發表於2018-07-19

介面無小事(一): RecyclerView+CardView瞭解一下

介面無小事(二): 讓RecyclerView展示更多不同檢視

介面無小事(三):用RecyclerView + Toolbar做個檔案選擇器

介面無小事(四):來寫個滾動選擇器吧!

介面無小事(五):自定義TextView

介面無小事(六):來做個好看得側拉選單!

github傳送門


目錄

  • 效果圖
  • 前言
  • 自定義屬性
  • MeasureSpec類
  • 顏色解析
  • 字號轉換
  • 最後

效果圖

不多廢話, 直接上圖, 如果感興趣再看下去.

效果圖


前言

寫第四篇滾動選擇器的時候, 在自定義檢視這裡含糊了, 有些地方沒說清楚, 這次補上關於自定義檢視的部分.


自定義屬性

自定義檢視的一個要點就是新增自定義屬性. 這裡我們填上三個常用的, 文字, 顏色, 字號. 然後在佈局檔案中就可以使用了. 最後在自定義類中獲取屬性並賦值.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTextView">
        <attr name="text" format="string" />
        <attr name="color" format="color" />
        <attr name="size" format="dimension" />
    </declare-styleable>
</resources>
複製程式碼
xmlns:app="http://schemas.android.com/apk/res-auto"
複製程式碼
<com.so.mytextview.ui.view.MyTextView
    android:id="@+id/mtv_test"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    app:color="@color/colorAccent"
    app:size="60sp"
    app:text="hello world" />
複製程式碼
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
    // 獲取自定義屬性
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);

    mSize = ta.getDimension(R.styleable.MyTextView_size, 16);
    mText = ta.getString(R.styleable.MyTextView_text);
    mColor = ta.getColor(R.styleable.MyTextView_color, Color.BLACK);

    ta.recycle();

    // 設定畫筆
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setTextSize(mSize);

    // 設定背景顏色
    mBkColor = Color.BLUE;
}
複製程式碼

MeasureSpec類

MeasureSpec類官方文件 關於onMeasure方法, 最重要的就是就是MeasureSpec類的使用了. 其實主要也就是要算好match_parentwrap_content. match_parent和具體數值都是EXACTLY. wrap_content是AT_MOST. ScrollView或者是ListView就會是UNSPECIFIED.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int width = 0;
    int height = 0;

    int specMode = MeasureSpec.getMode(widthMeasureSpec);
    int specSize = MeasureSpec.getSize(widthMeasureSpec);

    switch (specMode) {
        case MeasureSpec.EXACTLY:
            width = getPaddingLeft() + getPaddingRight() + specSize;
            break;

        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            width = (int) (getPaddingLeft() + getPaddingRight()
                    + mPaint.measureText(mText));
            break;
    }

    specMode = MeasureSpec.getMode(heightMeasureSpec);
    specSize = MeasureSpec.getSize(heightMeasureSpec);

    switch (specMode) {
        case MeasureSpec.EXACTLY:
            height = getPaddingTop() + getPaddingBottom() + specSize;
            break;

        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            Paint.FontMetrics fmi = mPaint.getFontMetrics();
            float textHeight = Math.abs(fmi.bottom - fmi.top);
            height = (int) (getPaddingTop() + getPaddingBottom() + textHeight);
            break;
    }

    setMeasuredDimension(width, height);
}
複製程式碼

有兩個要點, 就是算字串的寬度和高度, 寬度用Paint例項的measureText方法即可. 高度涉及到我在第四篇寫的Paint.FontMetrics類, 就是用底部減去頂部取絕對值.


顏色解析

Color是個要處理的類, 當你用getColor函式獲取到函式, 它是一個int值, 如果我們需要重新在原有顏色基礎上變化, 就需要解析這個int, 將它還原成RGB.

/**
 * 依據顏色值獲取rgb值
 *
 * @param color 顏色值
 * @return rgb值
 */
public int[] setColor(int color) {
    int[] rgb = new int[3];
    rgb[0] = (color & 0x00ff0000) >> 16;
    rgb[1] = (color & 0x0000ff00) >> 8;
    rgb[2] = (color & 0x000000ff);
    return rgb;
}
複製程式碼

字號轉換

要處理好字號問題, 最重要的就是轉換, 程式碼中都是用px的, 但是佈局檔案一般用sp.

/**
 * sp轉px
 */
public static int sp2px(float spVal) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
            spVal, getContext().getResources().getDisplayMetrics());
}

/**
 * px轉sp
 */
public static float px2sp(float pxVal) {
    return (pxVal / getContext().getResources().getDisplayMetrics().scaledDensity);
}
複製程式碼

最後

這樣可以自定義一些簡單的檢視類了, 如果要更復雜的, 還需要去處理更多的引數, 特別是構造方法那個四引數的. 有意見或者建議評論區見, 喜歡記得點贊或者關注我哦~


相關文章