自定義view(三)之滴滴loading

公司有個(gè)福利,就是每天晚上加班之后可以打車,然后每個(gè)月報(bào)銷一次,感覺生活的幸福感都提升了,有木有,加班之后那么累正好打車,但是我住的比較偏呀,有時(shí)候看著滴滴那個(gè)轉(zhuǎn)啊轉(zhuǎn)就是沒有車,老煩了,你就不能給我多通知幾個(gè)車嗎。正好學(xué)了自定義view那么自己手?jǐn)]一個(gè),嘿嘿。
先上個(gè)圖看看效果怎么樣

滴滴的圖

看看是不是特別像滴滴的呢,除了車通知的太多了[捂臉],到了上大餐的時(shí)候了,先說一下思路:

  • 大概分成四部分:
    1. 不動(dòng)的字比如:正在為您叫車,為您優(yōu)先叫車,這個(gè)是可以用textView直接寫的
    2. 需要在畫布上寫的,比如:已通知出租車,通知多少輛,“輛”,這些雖然可以用textView寫然后套framelayout,但是這樣需要調(diào)的地方比較多,所以還是自定義
    3. 基礎(chǔ)的灰色的圓,轉(zhuǎn)的橙色的圓
    4. 在圓上邊一直轉(zhuǎn)的那個(gè)圓

開始上代碼了
mCirclePaint = new Paint();
mCirclePaint.setStrokeWidth(5);
mCirclePaint.setColor(Color.parseColor("#E3E4E7"));
mCirclePaint.setAntiAlias(true);
mCirclePaint.setStyle(Paint.Style.STROKE);

    mTextPaint = new Paint();
    mTextPaint.setStrokeWidth(1);
    mTextPaint.setColor(Color.parseColor("#8B8C8F"));
    mTextPaint.setAntiAlias(true);
    mTextPaint.setTextSize(20);
    mTextPaint.setStyle(Paint.Style.FILL);


    mTextCountPaint = new Paint();
    mTextCountPaint.setStrokeWidth(1);
    mTextCountPaint.setColor(Color.parseColor("#EC9B70"));
    mTextCountPaint.setAntiAlias(true);
    mTextCountPaint.setTextSize(40);
    mTextCountPaint.setStyle(Paint.Style.FILL);


    mTextUnitPaint = new Paint();
    mTextUnitPaint.setStrokeWidth(1);
    mTextUnitPaint.setColor(Color.parseColor("#EC9B70"));
    mTextUnitPaint.setAntiAlias(true);
    mTextUnitPaint.setTextSize(20);
    mTextUnitPaint.setStyle(Paint.Style.FILL);

    mDrawArcPaint = new Paint();
    mDrawArcPaint.setStrokeWidth(5);
    mDrawArcPaint.setAntiAlias(true);
    mDrawArcPaint.setStyle(Paint.Style.STROKE);

    pos = new float[2];
    tan = new float[2];
    BitmapFactory.Options options = new BitmapFactory.Options();//通過bitmapFactory獲取圖片資源
    mBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.point,options);//獲取資源
    mMatrix = new Matrix();

這次我先設(shè)置了多個(gè)畫筆,這樣就不用每次繪制不同的寬度或顏色的圖形就要重新設(shè)置畫筆了,但是這樣就有一個(gè)問題,成員變量太多了,會(huì)占用比較大的內(nèi)存(這里我要吐槽一下我,我有一個(gè)A同事,還有一個(gè)B同事,A同事說你為啥方法里用局部變量不用成員變量,B同事說我這個(gè)只是在方法中調(diào)用,所以用局部變量,A同事說你這個(gè)寫的不對(duì),真是不知道怎么說這個(gè)A同事了),如果項(xiàng)目中還是盡量少寫成員變量,而選擇的用局部變量。

現(xiàn)在就是開始畫了圓了

@Override
protected void onDraw(Canvas canvas) {
    canvas.translate(mWidth/2,mHeight/2);//把畫布移到屏幕的中心
    rectF = new RectF(-mWidth/2+50,-mWidth/2+50,mWidth/2-50,mWidth/2-50);

    Path path = new Path();
    path.addCircle(0,0,(mWidth-100)/2, Path.Direction.CW);//cw是順時(shí)針
    canvas.drawPath(path,mCirclePaint);//順時(shí)針的畫一個(gè)圓


    PathMeasure measure = new PathMeasure(path, false);     // 創(chuàng)建 PathMeasure,這是測(cè)試path的

    BigDecimal bigDecimal1 = BigDecimal.valueOf(sweepAngle);
    BigDecimal b2 = BigDecimal.valueOf(360);
    float rad = bigDecimal1.divide(b2,MathContext.DECIMAL32).floatValue();//通過bigdecimal來獲取黃線在灰色圓上的位置,在放黃色的小球
    measure.getPosTan(measure.getLength() * rad +10, pos, tan);// 獲取當(dāng)前位置的坐標(biāo)以及趨勢(shì)

    mMatrix.reset();                                                        // 重置Matrix
    float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI); // 計(jì)算圖片旋轉(zhuǎn)角度

    mMatrix.postRotate(degrees, mBitmap.getWidth() / 2, mBitmap.getHeight() / 2);   // 旋轉(zhuǎn)圖片
    mMatrix.postTranslate(pos[0] - mBitmap.getWidth() / 2, pos[1] - mBitmap.getHeight() / 2);   // 將圖片繪制中心調(diào)整到與當(dāng)前點(diǎn)重合

    Rect rect = new Rect();
    mTextPaint.getTextBounds(notification,0,notification.length(),rect);
    canvas.drawText(notification,-(rect.left+rect.right)/2,rect.bottom,mTextPaint);//寫通知的字

    Rect rectCount = new Rect();
    mTextCountPaint.getTextBounds(String.valueOf(sweepAngle),0,String.valueOf(sweepAngle).length(),rectCount);
    canvas.drawText(String.valueOf(sweepAngle),-(rect.left+rect.right)/2,rect.bottom-rect.top-rect.bottom-rectCount.top/*-rectCount.bottom*/,mTextCountPaint);//寫車的數(shù)量

    canvas.drawText(unit,(rect.left-rect.right)/2+100,rect.bottom-rect.top-rect.bottom-rectCount.top/*-rectCount.bottom*/,mTextUnitPaint);//寫車的單位
//  Log.d(TAG, "onDraw: y=  "+(-rect.top-rectCount.top-rectCount.bottom));
//  Log.d(TAG, "onDraw: rect.top "+rect.top);
//  Log.d(TAG, "onDraw: rectCount.top "+rectCount.top);
//  Log.d(TAG, "onDraw: rectCount.bottom "+rectCount.bottom);

    mMatrix.postRotate(-90);
    canvas.drawBitmap(mBitmap, mMatrix, mDrawArcPaint);
    canvas.drawArc(rectF,-90,sweepAngle,false, mDrawArcPaint);
}

思路也寫到注釋里邊了,哈哈,注意看代碼就可以了,然后這時(shí)候還不能動(dòng)哩,要設(shè)置動(dòng)怎么辦呢,就是刷新,上次用了pos,這次用Timer+handler。

    final Timer timer = new Timer();
    TimerTask timeTask = new TimerTask() {
        @Override
        public void run() {
            if (i>=360) {
                i = 0;
            }
            Message message = new Message();
            message.what = 1;
            handler.sendMessage(message);
        }
    };
    timer.schedule(timeTask,1000,100);//每100毫秒時(shí)候刷新一下,第三個(gè)參數(shù)

}

Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        if (msg.what == 1) {
            diDiView.setData(i+=1);
        }
        super.handleMessage(msg);
    }
};

這就搞定了,然后你就看到通知了好多車就是沒人來接[尷尬]。代碼已經(jīng)上傳到我的git歡迎大家star和fork,也可以關(guān)注我的簡(jiǎn)書。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,781評(píng)論 25 709
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 7,295評(píng)論 0 17
  • 定時(shí)器工作方式控制寄存器的兩種啟動(dòng)方式? 純軟件啟動(dòng):GATE0/1=0 TR0/1=1 軟硬協(xié)同啟動(dòng):GATE...
    0220_喬紫荊閱讀 449評(píng)論 1 4
  • 在centos6版本如果你配置docker 的https_proxy 代理,只需要在/etc/sysconfig/...
    竹蓮心龍閱讀 429評(píng)論 0 0
  • 下班吃了晚飯倒頭就睡著了,約摸十一點(diǎn)的時(shí)候忽的醒來,就睡不著了。 刷了刷朋友圈,莫名的有些鬧騰,清一色的各種...
    三妄閱讀 3,769評(píng)論 0 3

友情鏈接更多精彩內(nèi)容