【Android 開(kāi)發(fā)】自定義View(中)——基本圖像繪制

內(nèi)容簡(jiǎn)概

一拖刃、畫(huà)線删壮、圓、扇形
二序调、扇形動(dòng)畫(huà)

具體內(nèi)容

一醉锅、畫(huà)線、圓发绢、扇形硬耍、圓弧

(一)創(chuàng)建一個(gè)類(lèi)(繼承View)用于測(cè)試

在這個(gè)類(lèi)中,我們放置線边酒、圓经柴、扇形、圓弧墩朦。

public class TestView extends View {
    // 實(shí)現(xiàn)View的兩個(gè)方法
    public TestView(Context context) {
        super(context);
    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    
    @Override
    protected void onDraw(Canvas canvas) {
        // 畫(huà)線
        // 1. 準(zhǔn)備畫(huà)筆 抗鋸齒
        Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextSize(70);
        mPaint.setColor(Color.BLACK); // 設(shè)置畫(huà)筆顏色
        mPaint.setStrokeWidth(20); // 設(shè)置畫(huà)筆粗細(xì)

        // 2.在畫(huà)布上畫(huà)線
        canvas.drawLine(50,50,300,400,mPaint);
        // x,y為開(kāi)頭文字左下角左標(biāo)
        canvas.drawText("↑",200,600,mPaint);
        canvas.drawText("drawLine",50,700,mPaint);

        //3.畫(huà)圓
        // 這里的top是圓心坐標(biāo)坯认,
        canvas.drawArc(600,50,1000,450,0,300,true,mPaint);
        canvas.drawText("↑",770,600,mPaint);
        canvas.drawText("drawArc",650,700,mPaint);

        // useCenter = false
        canvas.drawArc(50,800,450,1200,0,300,false,mPaint);
        canvas.drawText("↑",200,1300,mPaint);
        canvas.drawText("drawArc",50,1400,mPaint);
        canvas.drawText("useCenter=false",50,1500,mPaint);
        // 畫(huà)圓的另一種方法
        canvas.drawCircle(800,1000,200,mPaint);
        canvas.drawText("↑",770,1300,mPaint);
        canvas.drawText("drawCircle",650,1400,mPaint);
    }
}

這里的圓是實(shí)心的,如果想要畫(huà)空心的圓或者圓弧怎么辦呢氓涣?只要多加一句mPaint.setStyle(Paint.Style.STROKE);就可以了牛哺,系統(tǒng)默認(rèn)的style為FILL(實(shí)心)。

(二) xml(使用RelativeLayout)
<com.example.test.TestView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
(三)運(yùn)行結(jié)果圖

左邊為實(shí)心劳吠,右邊為空心引润。空心就是描繪外輪廓痒玩。(請(qǐng)忽略空心的丑陋文字)淳附。

二、扇形動(dòng)畫(huà)

扇形動(dòng)畫(huà)是扇形的半徑不變蠢古,轉(zhuǎn)的角度在變奴曙。下面我用兩個(gè)類(lèi)分別實(shí)現(xiàn)兩種動(dòng)畫(huà),一種是點(diǎn)擊展開(kāi)的扇形草讶,一種是自動(dòng)展開(kāi)的扇形洽糟。前者可以用onTouchEvent方法實(shí)現(xiàn),后者可以用Timer(定時(shí)器)或?qū)傩詣?dòng)畫(huà)實(shí)現(xiàn)。

(一)點(diǎn)擊展開(kāi)的扇形

規(guī)定扇形完全展開(kāi)后就固定為圓形脊框,不再變化颁督。

public class FanAnimation extends View {
    int angle; //每次增長(zhǎng)之后的值
    int speed = 20; //增長(zhǎng)速度

    public FanAnimation(Context context) {
        super(context);
    }

    public FanAnimation(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawFanChart(canvas,Color.BLACK, (float) (angle/360.0),"點(diǎn)擊展開(kāi)的扇形");
    }

    // onDraw方法不能滿足需求,所以自己寫(xiě)一個(gè)方法
    private void drawFanChart(Canvas canvas,int color,float rate,String text){
        //畫(huà)筆
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setTextSize(70);
        paint.setColor(color);

        //畫(huà)扇形
        int endAngle = (int) (360*rate);// 新繪制的扇形endAngle都在增大
        canvas.drawArc(50,100,450,500, 0,endAngle, true,paint);
        canvas.drawText(text,550,300,paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN){
            // 點(diǎn)擊屏幕 畫(huà)一點(diǎn) 這里的angle就是上面的rate
            angle += speed;
            // 控制最大值
            if (angle>360){
                angle = 360;
            }
            // 刷新
            invalidate();
        }
        return true;
    }
}
(二)自動(dòng)展開(kāi)的扇形——Timer
public class AutoFanAnimation extends View {
    int angle; //每次增長(zhǎng)之后的值
    int speed = 5; //增長(zhǎng)速度
    public AutoFanAnimation(Context context) {
        super(context);
    }

    public AutoFanAnimation(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 創(chuàng)建定時(shí)器 每個(gè)0.5s 畫(huà)一次
        final Timer t = new Timer();
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                angle += speed;
                if (angle > 360){
                    angle = 0; // 重新開(kāi)始
//                    t.cancel();// 關(guān)閉定時(shí)器
                }
                invalidate(); // 通知系統(tǒng)調(diào)用ondraw
                postInvalidate(); // 子進(jìn)程里面
            }
        },0,100);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        drawFanChart(canvas, Color.BLACK, (float) (angle/360.0),"自動(dòng)展開(kāi)的扇形");
    }

    // onDraw方法不能滿足需求浇雹,所以自己寫(xiě)一個(gè)方法
    private void drawFanChart(Canvas canvas,int color,float rate,String text){
        //畫(huà)筆
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setTextSize(70);
        paint.setColor(color);

        //畫(huà)扇形
        int endAngle = (int) (360*rate);
        canvas.drawArc(50,0,450,400, 0,endAngle, true,paint);
        canvas.drawText(text,550,300,paint);
    }
}
(三)自動(dòng)展開(kāi)的扇形——valueAnimator屬性動(dòng)畫(huà)

和自動(dòng)展開(kāi)的扇形唯一不同的就是onSizeChanged沉御。

public class ValueAnimator extends View {
    int angle; //每次增長(zhǎng)之后的值
    int speed = 20; //增長(zhǎng)速度
    public ValueAnimator(Context context) {
        super(context);
    }

    public ValueAnimator(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 創(chuàng)建ValueAnimator對(duì)象 設(shè)置范圍0-360
        android.animation.ValueAnimator va = android.animation.ValueAnimator.ofInt(0,360);
        va.setDuration(3000); // 動(dòng)畫(huà)時(shí)間
        va.setRepeatCount(android.animation.ValueAnimator.INFINITE);
        // 設(shè)置監(jiān)聽(tīng)器 監(jiān)聽(tīng)值的變化
        va.addUpdateListener(new android.animation.ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(android.animation.ValueAnimator valueAnimator) {
                // 獲取某一刻的值
                angle = (int) valueAnimator.getAnimatedValue();
                // 刷新
                invalidate();
            }
        });
        // 啟動(dòng)
        va.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawFanChart(canvas, Color.BLACK, (float) (angle/360.0),"屬性動(dòng)畫(huà)展開(kāi)的扇形");
    }
    private void drawFanChart(Canvas canvas,int color,float rate,String text){
        //畫(huà)筆
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setTextSize(57);
        paint.setColor(color);

        //畫(huà)扇形
        int endAngle = (int) (360*rate);// 新繪制的扇形endAngle都在增大
        canvas.drawArc(50,0,450,400, 0,endAngle, true,paint);
        canvas.drawText(text,550,300,paint);
    }
}
(四)xml(使用LinearLayout)
<com.example.test.FanAnimation
        android:id="@+id/click"
        android:layout_width="wrap_content"
        android:layout_height="250dp"/>

    <com.example.test.AutoFanAnimation
        android:layout_width="wrap_content"
        android:layout_height="200dp"/>

    <com.example.test.ValueAnimator
        android:layout_width="wrap_content"
        android:layout_height="220dp"/>

(五)運(yùn)行結(jié)果圖

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昭灵,隨后出現(xiàn)的幾起案子吠裆,更是在濱河造成了極大的恐慌,老刑警劉巖烂完,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件试疙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡抠蚣,警方通過(guò)查閱死者的電腦和手機(jī)祝旷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嘶窄,“玉大人怀跛,你說(shuō)我怎么就攤上這事”澹” “怎么了吻谋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)现横。 經(jīng)常有香客問(wèn)我漓拾,道長(zhǎng),這世上最難降的妖魔是什么戒祠? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任骇两,我火速辦了婚禮,結(jié)果婚禮上姜盈,老公的妹妹穿的比我還像新娘脯颜。我一直安慰自己,他們只是感情好贩据,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著闸餐,像睡著了一般饱亮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舍沙,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天近上,我揣著相機(jī)與錄音,去河邊找鬼拂铡。 笑死壹无,一個(gè)胖子當(dāng)著我的面吹牛葱绒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斗锭,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼地淀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了岖是?” 一聲冷哼從身側(cè)響起帮毁,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎豺撑,沒(méi)想到半個(gè)月后烈疚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡聪轿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年爷肝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陆错。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡灯抛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出危号,到底是詐尸還是另有隱情牧愁,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布外莲,位于F島的核電站猪半,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏偷线。R本人自食惡果不足惜磨确,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望声邦。 院中可真熱鬧乏奥,春花似錦、人聲如沸亥曹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)媳瞪。三九已至骗炉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛇受,已是汗流浹背句葵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乍丈。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓剂碴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親轻专。 傳聞我的和親對(duì)象是個(gè)殘疾皇子忆矛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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