炫酷的環(huán)形調(diào)節(jié)器控件 : RegulatorView

又畫了一個(gè)圓骑丸,但這次這個(gè)帶了個(gè)觸摸,由于最近在搞智能家居類應(yīng)用恭取,所以可想而知有很多東西需要自定義如遙控器泰偿,調(diào)節(jié)器,還有一些帶動(dòng)畫效果的View蜈垮,畢竟叫智能產(chǎn)品嘛耗跛,不能就是開和關(guān)兩個(gè)選項(xiàng)加一些圖片吧,所以還是要自定義一些控件的攒发,今天這個(gè)是一個(gè)環(huán)形調(diào)節(jié)期调塌,可以適應(yīng)于空調(diào)或者熱水器的遠(yuǎn)程調(diào)節(jié)控件,我們主要是用于設(shè)備的調(diào)檔惠猿。

main.jpg

上次的寫的一個(gè)控件 炫酷的空氣凈化器控件 : AirPurgeLayoutView

1.主要功能

  • 背光燈漸變
  • 背光燈調(diào)色
  • 控制環(huán)的顏色
  • 控制環(huán)形的度數(shù)
  • 平滑實(shí)現(xiàn)調(diào)節(jié)
  • 里面所以參數(shù)都可以微調(diào)

2.背光燈效果

這里說的背光燈效果是第二個(gè)圓環(huán)的陰影背景這里實(shí)現(xiàn)還是非常簡單的羔砾,但需要主要一下記得關(guān)閉硬件加速,要不然就沒有效果了。

  1. setLayerType(LAYER_TYPE_SOFTWARE, null); //要關(guān)閉硬件加速
  2. mPaint.setShadowLayer(mCurShadowRadius, 0, 0, mSecondCircleShadowColor); //設(shè)置圓環(huán)陰影
  3. 實(shí)現(xiàn)動(dòng)畫效果
sweep.gif
private void onStartBacklightAnim() {
        if (mBacklightAnim != null && mBacklightAnim.isRunning()) {
            return;
        }
        mBacklightAnim = ObjectAnimator.ofFloat(this,"curShadowRadius",0,mSecondCircleShadowRadius);
        mBacklightAnim.setDuration(mBacklightAnimDurtion);
        mBacklightAnim.setRepeatCount(ValueAnimator.INFINITE);
        mBacklightAnim.setRepeatMode(ValueAnimator.REVERSE);
        mBacklightAnim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mCurShadowRadius = mSecondCircleShadowRadius;
            }
        });
        mBacklightAnim.start();
    }

3.實(shí)現(xiàn)外圓環(huán)環(huán)形漸變

這個(gè)實(shí)現(xiàn)也挺簡單的如果你知道android自定義view有三種常用漸變方法這個(gè)一看就知道(1. LinearGradient 線性漸變 2.RadialGradient 輻射漸變 3.SweepGradient 環(huán)形漸變)其實(shí)還有一些但這三個(gè)比較常用不知道的google一下或者看下官網(wǎng)就ok了,這里用到的是SweepGradient 但有一個(gè)問題就是他是360°的顏色從0度開始到最后不能調(diào)節(jié)顏色開始角度姜凄,所以使用時(shí)最好在首位加多加一位顏色政溃。

//繪制顏色
if (mColors != null && mColors.length != 0) {
        canvas.save();
        canvas.rotate(90, mCenterX, mCenterY);
        if (mColors.length == 1) {
             mPaint.setColor(mColors[0]);
        } else if (mColors.length>1) {
             SweepGradient sweepGradient = new SweepGradient(mCenterX, mCenterY, mColors, null);
             mPaint.setShader(sweepGradient);
       ![sweep.gif](http://upload-images.jianshu.io/upload_images/2646598-5d1fbd181e0411b6.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
}
      canvas.drawArc(rectF, (360 - mThreeRingAngle) / 2, mThreeRingAngle, false, mPaint);
      mPaint.setShader(null);
      canvas.restore();
}

4. 滑動(dòng)控制

實(shí)現(xiàn)滑動(dòng)控制主要是監(jiān)聽下view的onTouchEvent方法,這里主要控件的邏輯大致是态秧,當(dāng)用戶手指按下這個(gè)控件時(shí)會(huì)判斷是否單機(jī)控件的第三個(gè)控制圓環(huán)董虱,如果有出發(fā)控制,如果沒有不處理觸摸申鱼。

slide.gif

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (isForbidSlide) return false;

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                onStopAutoFlingAnim();  //有動(dòng)畫立刻停止
                boolean isTakeOver = isTakeOverTouch(event.getX(),event.getY()); //第一次單機(jī)在圓環(huán)上才接管觸摸
                if (isTakeOver) {
                    mPreX = (int) event.getX();
                    mPreY = (int) event.getY();
                    refreshAngle(mPreX,mPreY,true);
                    return true;
                } else {
                    return false;
                }
            case MotionEvent.ACTION_MOVE:
                refreshAngle((int) event.getX(),(int) event.getY(),false);
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true; //consumption
    }

      /**
      * 判斷是否接管觸摸 兩種情況
      */
    private boolean isTakeOverTouch(float downX,float downY) {

        //加個(gè)0.5防止有些人眼神或手不好點(diǎn)不到圓弧上
        float minRadius = mThreeCircleRadius - mThreeCircleWidth/2f - 0.5f;
        float maxRadius = mThreeCircleRadius + mThreeCircleWidth/2f + 0.5f;

        //到按下點(diǎn)到圓心的距離
        float distanceCircle = (float) Math.abs(Math.sqrt((downX-mCenterX)*(downX-mCenterX)+(downY-mCenterY)*(downY-mCenterY)));
        if (distanceCircle >= minRadius && distanceCircle <= maxRadius) {
            if (mThreeRingAngle > 180 && downY > mCenterY) {
                float angle = (float) (Math.atan(Math.abs(downX-mCenterX)/Math.abs(downY-mCenterY))*180/Math.PI);
                if ((360-mThreeRingAngle)/2f > angle) {
                    return false;
                }
            } else if (mThreeRingAngle <= 180) {
                if (downY>mCenterY) {
                    return false;
                } else {
                    float angle = (float) (Math.atan(Math.abs(downX-mCenterX)/Math.abs(downY-mCenterY))*180/Math.PI);
                    if (angle > (360-mThreeRingAngle)/2f) {
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }

5.實(shí)現(xiàn)代碼滑動(dòng)

這個(gè)也很簡單主要是現(xiàn)實(shí)根據(jù)進(jìn)度實(shí)現(xiàn)動(dòng)畫性的改變進(jìn)度愤诱,但需要注意的是當(dāng)觸摸時(shí)立刻停止動(dòng)畫,如果動(dòng)畫在運(yùn)行的捐友。

control.gif
private ValueAnimator mAutoFlingAnim;
    public void setCurAngle(float progress,boolean isWantAnim) {
        if (isWantAnim) {
            if (mAutoFlingAnim != null && mAutoFlingAnim.isRunning()) {
                mAutoFlingAnim.cancel();
                mAutoFlingAnim.removeAllUpdateListeners();
                mAutoFlingAnim = null;
            }
            mAutoFlingAnim = new ValueAnimator();
            float curProgress = ((mCurAngle+90+mThreeRingAngle/2f)%360)/mThreeRingAngle;
            mAutoFlingAnim.setFloatValues(curProgress,progress);
            mAutoFlingAnim.setDuration((long) (Math.abs(progress-curProgress)*2000));
            mAutoFlingAnim.setInterpolator(new LinearInterpolator());
            mAutoFlingAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    float value = (float) valueAnimator.getAnimatedValue();
                    int angle = (int) (value*mThreeRingAngle + (360-mThreeRingAngle)/2f+90)%360;
                    if (mCurAngle != angle) {
                        mCurAngle = angle;
                        invalidate();
                    }
                }
            });
            mAutoFlingAnim.start();
        } else {
            this.mCurAngle = (int) (progress*mThreeRingAngle + (360-mThreeRingAngle)/2f+90)%360;
            invalidate();
        }
    }

6.感想

最近開發(fā)智能家居產(chǎn)品淫半,需要時(shí)不時(shí)定義一些view,但如果你完整的看完過android view的api時(shí)匣砖,你會(huì)發(fā)現(xiàn)其實(shí)真的不難撮慨,很多google都給你封裝好了,像什么漸變啊脆粥,貝塞爾曲線砌溺,圖片剪切,動(dòng)畫变隔,觸摸滑動(dòng)规伐,布局填充等,你只要學(xué)會(huì)拼接就可以匣缘,所以如果項(xiàng)目需要大量使用自定義控件的可以去系統(tǒng)的看一遍view的api猖闪。

7. RegulatorView的源碼地址

8. 空氣凈化器控件 : AirPurgeLayoutView

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市肌厨,隨后出現(xiàn)的幾起案子培慌,更是在濱河造成了極大的恐慌,老刑警劉巖柑爸,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吵护,死亡現(xiàn)場離奇詭異,居然都是意外死亡表鳍,警方通過查閱死者的電腦和手機(jī)馅而,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來譬圣,“玉大人瓮恭,你說我怎么就攤上這事±迨欤” “怎么了屯蹦?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵维哈,是天一觀的道長。 經(jīng)常有香客問我登澜,道長阔挠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任帖渠,我火速辦了婚禮,結(jié)果婚禮上竭宰,老公的妹妹穿的比我還像新娘空郊。我一直安慰自己,他們只是感情好切揭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布狞甚。 她就那樣靜靜地躺著,像睡著了一般廓旬。 火紅的嫁衣襯著肌膚如雪哼审。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天孕豹,我揣著相機(jī)與錄音涩盾,去河邊找鬼。 笑死励背,一個(gè)胖子當(dāng)著我的面吹牛春霍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叶眉,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼址儒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了衅疙?” 一聲冷哼從身側(cè)響起莲趣,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饱溢,沒想到半個(gè)月后喧伞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绩郎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年絮识,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗽上。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡次舌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兽愤,到底是詐尸還是另有隱情彼念,我是刑警寧澤挪圾,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站逐沙,受9級(jí)特大地震影響哲思,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吩案,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一棚赔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧徘郭,春花似錦靠益、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至抱环,卻和暖如春壳快,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镇草。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國打工眶痰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梯啤。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓凛驮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親条辟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子黔夭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,089評(píng)論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,756評(píng)論 22 665
  • 原文鏈接:https://github.com/opendigg/awesome-github-android-u...
    IM魂影閱讀 32,931評(píng)論 6 472
  • 看過日出 走過夕陽 山溪里的鯽魚肥了又瘦 屋檐下的燕子來了又回 那棵楊柳,越來越高 那只黑貓羽嫡,越來越老 我一直在這...
    ivy_y閱讀 183評(píng)論 0 0
  • 2017年10.3日本姥,全家總動(dòng)員去外婆家送節(jié),老爸本來不太想去杭棵,我說晚上還有安排婚惫,大家一起聚聚的,老爸就去了魂爪,這個(gè)...
    榮小婷閱讀 183評(píng)論 0 0