自定義view單位的轉化、狀態儲存等
阿新 • • 發佈:2019-01-31
自定義view單位的轉化
//dp轉px
int minWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120,
getContext().getResources().getDisplayMetrics());
//sp轉px
int minHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 80,
getContext().getResources().getDisplayMetrics());
/**
* 根據手機的解析度從 dp 的單位 轉成為 px(畫素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
工具類:
public class DensityUtils {
private DensityUtils() {
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
public static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
public static float px2dp(Context context, float pxVal) {
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}
自定義view狀態的儲存
private static final String STATE_INSTANCE = "state_instance";
private static final String STATE_TYPE = "state_type";
private static final String STATE_BORDER_RADIUS = "state_border_radius";
private int type;
private int mBorderRadius;
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());
bundle.putInt(STATE_TYPE, type);
bundle.putInt(STATE_BORDER_RADIUS, mBorderRadius);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
super.onRestoreInstanceState(((Bundle) state).getParcelable(STATE_INSTANCE));
this.type = bundle.getInt(STATE_TYPE);
this.mBorderRadius = bundle.getInt(STATE_BORDER_RADIUS);
} else {
super.onRestoreInstanceState(state);
}
}
自定義view的常用的onmeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight()/2);
}
系統預設:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
系統預設wrap_content和match_parent效果一樣,測量寬高都是specSize,而這個specSize正是父控制元件剩餘的寬高,所以預設onMeasure方法中wrap_content 和match_parent 的效果是一樣的,都是填充剩餘的空間。
考慮wrap_content:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec); //獲取寬的模式
int heightMode = MeasureSpec.getMode(heightMeasureSpec); //獲取高的模式
int widthSize = MeasureSpec.getSize(widthMeasureSpec); //獲取寬的尺寸
int heightSize = MeasureSpec.getSize(heightMeasureSpec); //獲取高的尺寸
int width;
int height ;
if (widthMode == MeasureSpec.EXACTLY) {
//如果match_parent或者具體的值,直接賦值
width = widthSize;
} else {
//如果是wrap_content,我們要得到控制元件需要多大的尺寸
float textWidth = mBound.width(); //文字的寬度
//控制元件的寬度就是文字的寬度加上兩邊的內邊距。內邊距就是padding值,在構造方法執行完就被賦值
width = (int) (getPaddingLeft() + textWidth + getPaddingRight());
}
//高度跟寬度處理方式一樣
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
float textHeight = mBound.height();
height = (int) (getPaddingTop() + textHeight + getPaddingBottom());
}
//儲存測量寬度和測量高度
setMeasuredDimension(width, height);
}
介面的定義示例:
private OnLoadingCompleteListenter onLoadingCompleteListenter;
interface OnLoadingCompleteListenter {
void onComplete();
}
public OnLoadingCompleteListenter getOnLoadingCompleteListenter() {
return onLoadingCompleteListenter;
}
public void setOnLoadingCompleteListenter(OnLoadingCompleteListenter onLoadingCompleteListenter) {
this.onLoadingCompleteListenter = onLoadingCompleteListenter;
}