簡(jiǎn)介
常用函數(shù)介紹
1.onMeasure()
//該函數(shù)為測(cè)量函數(shù),可以獲取長(zhǎng)寬等參數(shù),進(jìn)行設(shè)置
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMeasureSpec == MeasureSpec.AT_MOST) {//wrap_content
}
if (widthMeasureSpec == MeasureSpec.EXACTLY) {//一個(gè)確切的值 match_parent fill_parent
}
if (widthMeasureSpec == MeasureSpec.UNSPECIFIED) {//盡可能的大 很少用到 listview scrollview
}
}
2.onDraw()
注:viewgroup不執(zhí)行該方法,但會(huì)執(zhí)行dispatchDraw(Canvas canvas)方法。
如果繼承ViewGroup,想要繪制有如下方法:
思路:改變mPrivateFlags
(1)繼承dispatchDraw(Canvas canvas)代替ondraw()
(2)設(shè)置透明背景 setBackgroundColor(Color.TRANSPARENT);
(3)setWillNotDraw()
基線(xiàn)圖:
image.png
//該函數(shù)為繪制函數(shù),能根據(jù)需求繪制不同的文本或者圖形
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//畫(huà)文本
canvas.drawText();
//畫(huà)弧
canvas.drawArc();
//畫(huà)圓
canvas.drawCircle();
}
3.onTouchEvent
//該函數(shù)處理的是事件分發(fā),通俗說(shuō)就是對(duì)屏幕的操作
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
//手指抬起
break;
case MotionEvent.ACTION_DOWN:
//手指按下
break;
case MotionEvent.ACTION_MOVE:
//手指移動(dòng)
break;
}
return super.onTouchEvent(event);
}
編寫(xiě)步驟
1.創(chuàng)建自定義TextView類(lèi)
(1)繼承View類(lèi)
定義所需屬性值,并賦初始值:
private String mText;
private int mTextSize = 15;
private int mTextColor = Color.BLACK;
(2)重載構(gòu)造函數(shù)
通常情況下將各個(gè)構(gòu)造函數(shù)都引用到 public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
該構(gòu)造函數(shù)上來(lái),獲取控件屬性值并初始化
public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
//獲取自定義屬性
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.TextView);
mText = array.getString(R.styleable.TextView_MyText);
mTextColor = array.getColor(R.styleable.TextView_MyTextColor,mTextColor);
mTextSize = array.getDimensionPixelSize(R.styleable.TextView_MyTextSize,mTextSize);
//回收
array.recycle();
}
2.自定義屬性
(1)在res/values中創(chuàng)建attrs.xml文件,自定義所需屬性名以及對(duì)應(yīng)參數(shù)
/**
* dimension:對(duì)應(yīng)的是像素
* reference:對(duì)應(yīng)是引用
* enum:標(biāo)簽定義的是枚舉類(lèi)型
**/
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextView">
<attr name="MyText" format="string" />
<attr name="MyTextColor" format="color" />
<attr name="MyTextSize" format="dimension" />
<attr name="MyMaxLength" format="integer" />
<!-- background 自定義view都是繼承自view,背景是由view管理的-->
<!-- <attr name="MyBackground" format="reference|color" />-->
<attr name="MyInputType">
<enum name="number" value="1"/>
<enum name="text" value="2"/>
<enum name="password" value="3"/>
</attr>
</declare-styleable>
</resources>
3.使用自定義控件
<com.incall.apps.textview.TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:MyText="安卓"
app:MyTextSize="18sp"
app:MyTextColor="@color/teal_200"
app:MyInputType="number"/>
常見(jiàn)問(wèn)題解答
1.為什么不能在子線(xiàn)程更新ui
開(kāi)了線(xiàn)程,跟新ui會(huì)到viewRootImpl checkThread()
中
void checkThread() {
// Thread.currentThread()是子線(xiàn)程,mThread 是構(gòu)造函數(shù)初始化時(shí)的主線(xiàn)程
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
2.ui繪制流程
三個(gè)重要方法
performTraversals()
performMeasure()
-
performDraw()
invlidate()流程:一路往上跑,跑到最外層draw()->dispatchDraw()
一路往下畫(huà) 最終畫(huà)到當(dāng)前調(diào)用invaldate的onDraw方法