[Android筆記]自定義控件系列一

  • 繼承View必須要重寫構(gòu)造方法
  • 構(gòu)造方法中必須有繼承一個(gè)和第二個(gè)
    第二個(gè)構(gòu)造方法中有AttributeSet參數(shù)瘩燥,如果沒有這個(gè)參數(shù)則會(huì)報(bào)RutimeException異常锨天;
    AttributeSet是用來解析android自帶的layout_width、layout_height、id辫塌、padding原押、margin等屬性的
  • 筆 Paint
    需要new Paint paint = new Patin();
  • 紙 Canvas(畫布)
    紙?jiān)趏nDraw(Canvas canvas)方法中傳遞進(jìn)來
  • 不要在draw和layout的過程中去實(shí)例化對(duì)象
    故不要在onDraw()方法中去實(shí)例化對(duì)象分冈,一般在構(gòu)造函數(shù)去實(shí)例化圾另;
    draw和layout很可能是一個(gè)頻繁重復(fù)執(zhí)行的過程,new是需要分配內(nèi)存的雕沉,這樣操作浪費(fèi)內(nèi)存集乔,甚至爆掉
  • Paint 各種屬性
    setAntiAlias(true) 抗鋸齒
    setColor() 設(shè)置畫筆顏色
    setStrokeWidth() 設(shè)置描邊線條
    setStyle()設(shè)置畫筆樣式
    ...
paint方法.png
  • Canvas 各種屬性
    drawCircle() 繪制圓
    drawArc() 繪制圓弧
    drawBitmap() 繪制位圖
    ...
canvas方法.png
  • 繪制一個(gè)圓環(huán)

  • 測(cè)量工具類

public class MeasureUtil {

    /**
     *  獲取屏幕尺寸
     * @param activity
     * @return 屏幕尺寸像素值,下標(biāo)為0的值為寬度坡椒,下標(biāo)為1的值為高
     */
    public static int[] getScreenSize(Activity activity) {
        DisplayMetrics metrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        return new int[]{metrics.widthPixels, metrics.heightPixels};
    }
}
  • 初始化畫筆
    private void initPaint() {
        mPaint = new Paint();

        mPaint.setAntiAlias(true); // 抗鋸齒
        /**
         *  設(shè)置畫筆樣式
         *   1. Paint.Style.STROKE: 描邊
         *   2. Paint.Style.FILL_AND_STROKE: 描邊并填充
         *   3. Paint.Style.FILL: 填充
         */
        mPaint.setStyle(Paint.Style.STROKE);

        mPaint.setColor(Color.GREEN); // 設(shè)置畫筆顏色

        /**
         *  設(shè)置畫筆寬度扰路,單位像素
         *  setStrokeWidth(0)的時(shí)候?qū)挾炔⒉粸?,為一個(gè)像素
         */
        mPaint.setStrokeWidth(10);
    }
  • 繪制圓
// 繪制圓
        canvas.drawCircle(MeasureUtil.getScreenSize(((Activity) mContext))[0] / 2,
                MeasureUtil.getScreenSize((Activity) mContext)[1] / 2, 200, mPaint);
circle.png

圓已經(jīng)出來了倔叼,現(xiàn)在我們來整個(gè)動(dòng)態(tài)變換半徑大小的怎么樣汗唱,說干就干,不能慫丈攒。
其實(shí)要?jiǎng)討B(tài)的圓很簡單哩罪,我們只要更改其半徑的大小,然后重繪就行巡验,Android中給我們提供了invalidate()和postInvalidate()方法可以重繪我們的View际插,它們兩者的區(qū)別我等下在下面敘述,我們先來看代碼深碱。

public class SimpleView extends View implements Runnable {

    private Paint mPaint;
    private Context mContext;
    private int radius; // 半徑

    public SimpleView(Context context) {
        this(context, null);
    }

    public SimpleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        initPaint();
    }

    /**
     * 初始化畫筆
     */
    private void initPaint() {
        mPaint = new Paint();

        mPaint.setAntiAlias(true); // 抗鋸齒
        /**
         *  設(shè)置畫筆樣式
         *   1. Paint.Style.STROKE: 描邊
         *   2. Paint.Style.FILL_AND_STROKE: 描邊并填充
         *   3. Paint.Style.FILL: 填充
         */
        mPaint.setStyle(Paint.Style.STROKE);

        mPaint.setColor(Color.GREEN); // 設(shè)置畫筆顏色

        /**
         *  設(shè)置畫筆寬度腹鹉,單位像素
         *  setStrokeWidth(0)的時(shí)候?qū)挾炔⒉粸?,為一個(gè)像素
         */
        mPaint.setStrokeWidth(10);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 繪制圓
        canvas.drawCircle(MeasureUtil.getScreenSize(((Activity) mContext))[0] / 2,
                MeasureUtil.getScreenSize((Activity) mContext)[1] / 2, radius, mPaint);

    }

    @Override
    public void run() {
        /**
         *  不斷刷新界面
         */
        while (true) {
            try {
                /**
                 *  半徑小于等于300則自動(dòng)放大
                 */
                if(radius <= 300) {
                    radius += 20;
                    // 刷新view
                    postInvalidate();
                } else {
                    radius = 0;
                }
                // 每100毫秒刷新一次
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

MainActivity中很簡單敷硅,開個(gè)線程就行

simpleView = (SimpleView) findViewById(R.id.main_simpleview);
new Thread(simpleView).start();
dynamic.gif

如果我們把上面的postInvalidate改成invalidate就會(huì)報(bào)下面這個(gè)錯(cuò),


Error1.png

這是為什么呢愉阎,因?yàn)槲覀冊(cè)诜荱I線程中更新UI绞蹦,而我們都知道在Android中非UI線程是不能更新UI的,故我們用postInvalidate榜旦。

postInvalidate()和invalidate()的區(qū)別:

invalidate()必須在主線程中調(diào)用幽七,而postInvalidate()內(nèi)部是由Handler的消息機(jī)制實(shí)現(xiàn)的,所以在任何線程中都可以調(diào)用溅呢,但實(shí)時(shí)性沒有invalidate()強(qiáng)澡屡,一般為了保險(xiǎn)起見,均使用postInvalidate()來刷新界面咐旧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驶鹉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铣墨,更是在濱河造成了極大的恐慌室埋,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異姚淆,居然都是意外死亡孕蝉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門腌逢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來降淮,“玉大人,你說我怎么就攤上這事搏讶〖驯睿” “怎么了?”我有些...
    開封第一講書人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵窍蓝,是天一觀的道長腋颠。 經(jīng)常有香客問我,道長吓笙,這世上最難降的妖魔是什么淑玫? 我笑而不...
    開封第一講書人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮面睛,結(jié)果婚禮上絮蒿,老公的妹妹穿的比我還像新娘。我一直安慰自己叁鉴,他們只是感情好土涝,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幌墓,像睡著了一般但壮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上常侣,一...
    開封第一講書人閱讀 52,184評(píng)論 1 308
  • 那天蜡饵,我揣著相機(jī)與錄音,去河邊找鬼胳施。 笑死溯祸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的舞肆。 我是一名探鬼主播焦辅,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼椿胯!你這毒婦竟也來了筷登?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤压状,失蹤者是張志新(化名)和其女友劉穎仆抵,沒想到半個(gè)月后跟继,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镣丑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年舔糖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莺匠。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡金吗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趣竣,到底是詐尸還是另有隱情摇庙,我是刑警寧澤,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布遥缕,位于F島的核電站卫袒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏单匣。R本人自食惡果不足惜夕凝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望户秤。 院中可真熱鬧码秉,春花似錦、人聲如沸鸡号。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鲸伴。三九已至府蔗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間汞窗,已是汗流浹背礁竞。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杉辙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓捶朵,卻偏偏與公主長得像蜘矢,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子综看,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容