當(dāng)前位置:首頁(yè) > IT技術(shù) > 移動(dòng)平臺(tái) > 正文

Android自定義控件(一)---基礎(chǔ)篇
2021-09-16 11:44:33

談到 Android自定義控件 ,這是一個(gè)令人渴望又害怕的領(lǐng)域,是作為一個(gè)Android開(kāi)發(fā)人員的必經(jīng)之路。

鄙人也是一名初學(xué)者,懷著一顆分享的心,將自己所理解的知識(shí)點(diǎn)與君分享,不足之處望糾正

哈哈哈,說(shuō)的有點(diǎn)多了,下面直入正題吧!

一、自定義控件預(yù)備知識(shí)點(diǎn)

①構(gòu)造方法

package com.example.mytextview;

//import javax.swing.text.View;  這里別到錯(cuò)了包,這個(gè)包是錯(cuò)誤的 
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;        //這個(gè)是正確的包

import androidx.annotation.Nullable;

ppublic class TextView extends View {
    // 構(gòu)造函數(shù)會(huì)在代碼里面new的時(shí)候調(diào)用 : TextView tv = new TextView(this);
    // 用 this 的好處就是 不管你從哪個(gè)構(gòu)造函數(shù) 進(jìn)入, 都會(huì)走到第三個(gè)里面 進(jìn)行統(tǒng)一處理
    public TextView(Context context) {
        this(context,null);
    }

    // 在布局 layout 中使用(調(diào)用) :
    // <com.example.view_day01.TextView
    // android:layout_width="wrap_content"
    // android:layout_height="wrap_content"
    // android:text="Hello World!" />
    public TextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    // 在布局 layout 中使用(調(diào)用) 但是會(huì)有style:
    // <com.example.view_day01.TextView
    //  style="@style/myStyle"
    // android:text="Hello World!" />
    public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

系統(tǒng)為我們提供了 四種構(gòu)造方法 但是,第四種幾乎用不到,所有,為列出。

對(duì)于以上三種構(gòu)造方法,我們需要掌握的就是:①這幾個(gè)構(gòu)造方法在什么時(shí)候被調(diào)用,和Activity生命周期檢測(cè)一樣,可以通過(guò)打印Log來(lái)分辨,(調(diào)用時(shí)期已注解在旁邊,望知)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?②我們通常將前兩個(gè)構(gòu)造方法的 super 修改為 this,方便在第三個(gè)構(gòu)造方法里進(jìn)行統(tǒng)一處理。

②常用方法

onMeasure

/**
*自定義View的測(cè)量方法
*@Author yiqi
*@created 2021/2/22 14:04
*@param widthMeasureSpec || heightMeasureSpec 32位的值  前兩位是 model :MeasureSpec.AT_MOST
 *                        后三十位是 Integer.MAX_VALUE
*@return
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //這個(gè)可以解決 ScrollView 嵌套 ListView 顯示不全的問(wèn)題(面試常被問(wèn)及)
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2 , MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //布局的寬高都是由這個(gè)方法指定
    //指定控件的寬高,需要測(cè)量
    //獲取寬高的模式
    int widthMode = MeasureSpec.getMode(widthMeasureSpec); //獲取前兩位
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);

    //獲取寬高的值
    int widthSize = MeasureSpec.getSize(widthMeasureSpec); //獲取后面30位
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    // MeasureSpec.AT_MOST : 在布局中指定了wrap_content
    // MeasureSpec.EXACTLY : 在布局中指定了確切的值 100dp match_parent fill_parent
    // MeasureSpec.UNSPECIFIED : 盡可能的大 , 很少能用到 ListView ScrollView 在測(cè)量子布局的時(shí)候會(huì)用到 UNSPECIFIED
    if (widthMode == MeasureSpec.UNSPECIFIED){

    }
}

?對(duì)于onMeasure()這個(gè)方法,我們需要弄清楚一下幾點(diǎn):

? ? ? ???第一點(diǎn):widthMeasureSpec, heightMeasureSpec 都是 32位二進(jìn)制值,前兩位代表模式 可以通過(guò)?MeasureSpec.getMode 獲取,后30位代表最大寬高 可以通過(guò)?MeasureSpec.getSize 獲取

? ? ? ? ?第二點(diǎn):MeasureSpec.makeMeasureSpec() 這個(gè)方法可以用來(lái)設(shè)置 測(cè)量模式,(這個(gè)地方會(huì)牽扯一個(gè)面試問(wèn)題=》S從rollView里嵌套ListView ListView顯示不全問(wèn)題,后面章節(jié)進(jìn)行講解)

? ? ? ? ?第三點(diǎn):setMeasuredDimension()? 這個(gè)方法可以用來(lái)設(shè)置自定義控件的寬高

onDraw

/**
*用于繪制
*@Author yiqi 
*@created 2021/2/22 18:00
*@param 
*@return 
*/
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //畫(huà)文本
    canvas.drawText();
    //畫(huà)弧
    canvas.drawArc();
    //畫(huà)圓
    canvas.drawCircle();
}

?對(duì)于?onDraw() 方法 主要是掌握以上就差不多了,后面用到時(shí)會(huì)詳細(xì)講解

onTouchEvent

/**
*處理跟用戶(hù)交互的 手指觸摸等等
*@Author yiqi
*@created 2021/2/22 18:05
*@param
*@return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {

    switch(event.getAction()){
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_UP:
            break;
    }

    return super.onTouchEvent(event);
}

?對(duì)于?onTouchEvent() 方法,并非一言?xún)烧Z(yǔ)就能說(shuō)盡的,它也是得在實(shí)戰(zhàn)中體現(xiàn)其價(jià)值。

看到這里,就說(shuō)明你掌握基礎(chǔ)了,是不是覺(jué)得很簡(jiǎn)單呢?。?!,哈哈哈??墒莿e輕敵,前面輕松代表后面很苦哦

本文摘自 :https://blog.51cto.com/u

開(kāi)通會(huì)員,享受整站包年服務(wù)立即開(kāi)通 >