介面無小事(一): RecyclerView+CardView瞭解一下
介面無小事(二): 讓RecyclerView展示更多不同檢視
介面無小事(三):用RecyclerView + Toolbar做個檔案選擇器
目錄
- 效果圖
- 前言
- 自定義屬性
- 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_parent和wrap_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);
}
複製程式碼
最後
這樣可以自定義一些簡單的檢視類了, 如果要更復雜的, 還需要去處理更多的引數, 特別是構造方法那個四引數的. 有意見或者建議評論區見, 喜歡記得點贊或者關注我哦~