Android的學(xué)習(xí)與實(shí)踐11(波浪線與進(jìn)度的結(jié)合嫉戚,利用圖片來(lái)進(jìn)行“加載”的實(shí)現(xiàn))

1 收獲

說(shuō)實(shí)話今天沒(méi)有多少的新知識(shí)點(diǎn),但是今天做的東西是在昨天做的東西之上又實(shí)現(xiàn)了一些功能维贺,昨天最后的波浪時(shí)靜態(tài)的它掂,而今天我們將昨天做的最后一個(gè)靜態(tài)的波浪線是實(shí)現(xiàn)了動(dòng)態(tài),就在這里我們又重復(fù)用到了昨天學(xué)到的知識(shí)和以前學(xué)過(guò)的知識(shí)溯泣,包括自定義屬性虐秋,ObjectAnimator,ValueAnimator,RotateAnimation三種動(dòng)畫(huà)垃沦,這又給我們進(jìn)行復(fù)習(xí)的機(jī)會(huì)客给,說(shuō)實(shí)話我對(duì)于這些動(dòng)畫(huà)沒(méi)有了多大印象,除了ValueAnimator因?yàn)樽蛱觳艑W(xué)的肢簿,今天他們又出現(xiàn)在了我的眼前靶剑,我一定要好好的把握住他們蜻拨,不讓他們從我的手指間跑掉。這周又這樣結(jié)束了抬虽,時(shí)間轉(zhuǎn)瞬即逝官觅,好好珍惜眼下吧!2邸休涤!

2.技術(shù)

(1)ValueAnimator動(dòng)畫(huà)實(shí)現(xiàn)波浪線的動(dòng)畫(huà)
(2)利用畫(huà)筆繪制體格圓形和文本
(3)利用繼承ViewGroup實(shí)現(xiàn)布局和一些動(dòng)畫(huà)的組合
(4)利用ValueAnimator和RotateAnimation實(shí)現(xiàn)加載動(dòng)畫(huà)

3.技術(shù)實(shí)踐及其應(yīng)用

(1)ValueAnimator動(dòng)畫(huà)實(shí)現(xiàn)波浪線的動(dòng)畫(huà)
在利用ValueAnimator動(dòng)畫(huà)實(shí)現(xiàn)波浪線的動(dòng)畫(huà)之前為我們必須要做一些準(zhǔn)備工作
設(shè)置一些私有變量以及寫(xiě)出它們對(duì)應(yīng)的構(gòu)造方法,有利于外部對(duì)他們進(jìn)行設(shè)置

private ValueAnimator va;//動(dòng)畫(huà)
    private Paint paint;//畫(huà)筆
    private Path path;//路徑

    float density=getResources().getDisplayMetrics().density;//密度
    private int wavelength= (int) (100*density);//波長(zhǎng)
    private int wavecrest= (int) (100*density);//波峰

    private int speed;//變化動(dòng)畫(huà)的速度

    private int lineColor=Color.BLACK;//線條顏色
    private int linesize=20 ;//線條粗細(xì)

構(gòu)造方法

  //通過(guò)set方法來(lái)實(shí)現(xiàn)外部對(duì)屬性值的設(shè)置
    public void setWavelength(int wavelength) {
        this.wavelength = wavelength;
    }

    public void setWavecrest(int wavecrest) {
        this.wavecrest = wavecrest;
    }

    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
        paint.setColor(lineColor);
    }

    public void setLinesize(int linesize) {
        this.linesize = linesize;
        paint.setStrokeWidth(linesize);
    }

接下來(lái)就是在外部的設(shè)置(通過(guò)自定義屬性)
首先我們先要自定義屬性


image.png

image.png

我們屬性定義完后我們可以在xml中進(jìn)行設(shè)置值

<swu.xcf.waveloading.Waveview
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent"
        app:linecolor="@color/colorPrimaryDark"
        app:linesize="10"
        app:wavelength="50"
        app:wavecrest="50"
        />

當(dāng)外部傳來(lái)值時(shí)笛辟,內(nèi)部就要進(jìn)行對(duì)值進(jìn)行處理

private void initAttr(Context context, AttributeSet attrs){
        //讀取所有自定義屬性的值
        TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.Waveview);
        //讀取每一個(gè)屬性的值
        wavelength=typedArray.getInteger(R.styleable.Waveview_wavelength, (int) (100*density));
        wavecrest=typedArray.getInteger(R.styleable.Waveview_wavecrest,(int) (100*density));
        linesize=typedArray.getInteger(R.styleable.Waveview_linesize,10);
        lineColor=typedArray.getInteger(R.styleable.Waveview_linecolor,Color.BLACK);
    }

接下來(lái)就是進(jìn)行繪制圖形了功氨,首先我們還是要進(jìn)行對(duì)畫(huà)筆進(jìn)行初始化

 private void inite(){
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(lineColor);
        paint.setStrokeWidth(linesize);
        paint.setStyle(Paint.Style.STROKE);
    }

由于這個(gè)繪制的圖形并不是規(guī)則的,所以我們要明確繪制的路徑手幢,我們要對(duì)路徑進(jìn)行初始化

private void initpath() {
        //創(chuàng)造曲線
        path=new Path();
        //計(jì)算多少個(gè)周期(有幾個(gè)完整的波)
        int count=getWidth()/wavelength;
        //移動(dòng)設(shè)置起始點(diǎn) 距離x左邊的一個(gè)波長(zhǎng)
        path.moveTo(-wavelength+speed,getHeight()/2);
        //獲取中心的坐標(biāo)
        int ceterY= (int) getPivotY();
        //卻確定曲線的路徑
        for(int start=-wavelength+speed;start<getWidth();start+=wavelength){
            //畫(huà)上半周期
            path.cubicTo(start,ceterY,start+wavelength/4,ceterY-wavecrest,start+wavelength/2,ceterY);
            //畫(huà)下半周期
            path.cubicTo(start+wavelength/2,ceterY,start+(wavelength/4)*3,ceterY+wavecrest,start+wavelength,ceterY);
        }

    }

現(xiàn)在筆有了捷凄,路徑有了,接下來(lái)我們就是進(jìn)行繪制了

@Override
    protected void onDraw(Canvas canvas) {
        //開(kāi)始繪制
        initpath();
        canvas.drawPath(path,paint);
    }

但是當(dāng)我們運(yùn)行后發(fā)現(xiàn)這個(gè)波浪時(shí)靜態(tài)的围来,所以我們想到用一個(gè)動(dòng)畫(huà)來(lái)實(shí)現(xiàn)

//開(kāi)始動(dòng)畫(huà)
    public void startWave(){
        va=ValueAnimator.ofInt(0,wavelength);
        va.setDuration(400);//動(dòng)畫(huà)間隔時(shí)間
        va.setRepeatCount(ValueAnimator.INFINITE);//設(shè)置動(dòng)畫(huà)重復(fù)的次數(shù)
        va.setRepeatMode(ValueAnimator.RESTART);//設(shè)置動(dòng)畫(huà)的類(lèi)型
        va.setInterpolator(new LinearInterpolator());//使動(dòng)畫(huà)勻速
        //設(shè)置更新的監(jiān)聽(tīng)器
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //獲取當(dāng)前值
                speed= (int) valueAnimator.getAnimatedValue();
                //刷新
                invalidate();
            }
        });
        va.start();//開(kāi)始動(dòng)畫(huà)
    }

但是我們又發(fā)現(xiàn)當(dāng)我們我們進(jìn)度滿(mǎn)后跺涤,動(dòng)畫(huà)并沒(méi)有結(jié)束,所以我們寫(xiě)了一一個(gè)專(zhuān)門(mén)用來(lái)結(jié)束動(dòng)畫(huà)的函數(shù)

 //暫停動(dòng)畫(huà)
    public void stopWave(){
        if(va!=null){
            va.cancel();
        }
    

效果:

錄制_2019_10_28_00_00_24_864.gif

(2)利用畫(huà)筆繪制體格圓形和文本
在這里并沒(méi)有什么新的知識(shí)和技術(shù)监透,都是在昨天的講過(guò)的桶错,不知道的可以看上一篇推文,那片推文中有詳細(xì)的介紹胀蛮。
首先我們還是要一些我們需要的屬性以及他們的set方法院刁,方便外部對(duì)這些屬性進(jìn)行設(shè)置值

Paint circlepaint;//畫(huà)圓的畫(huà)筆
    Paint textcircle;//繪制文本的畫(huà)筆
    private int centerYSpace;//和中心線的距離
    private int linesize=20;//線條粗細(xì)
    private int linecolor=Color.BLACK;//線條顏色
    private int textcolor=Color.BLACK;//文本顏色
    private int textsize=50;//文本大小

    private float progress;//進(jìn)度

set方法

ublic void setLinesize(int linesize) {
        this.linesize = linesize;
        circlepaint.setStrokeWidth(linesize);
    }

    public void setLinecolor(int linecolor) {
        this.linecolor = linecolor;
        circlepaint.setColor(linecolor);
    }

    public void setTextcolor(int textcolor) {
        this.textcolor = textcolor;
        textcircle.setColor(textcolor);
    }

    public void setTextsize(int textsize) {
        this.textsize = textsize;
        textcircle.setTextSize(textsize);
    }

    public void setProgress(float progress) {
        this.progress = progress;
        //刷新
        invalidate();
    }

    public void setCenterYSpace(int centerYSpace) {
        this.centerYSpace = centerYSpace;
    }

然后對(duì)兩種畫(huà)筆進(jìn)行初始化

 private void inite() {
        circlepaint=new Paint(Paint.ANTI_ALIAS_FLAG);//創(chuàng)建畫(huà)筆
        circlepaint.setStrokeWidth(linesize);//畫(huà)筆的粗細(xì)
        circlepaint.setColor(linecolor);//畫(huà)筆的顏色
        circlepaint.setStyle(Paint.Style.STROKE);//畫(huà)筆的風(fēng)格(空心,實(shí)心)

        textcircle=new Paint(Paint.ANTI_ALIAS_FLAG);//創(chuàng)建畫(huà)筆
        textcircle.setStyle(Paint.Style.FILL);//畫(huà)筆的風(fēng)格(空心粪狼,實(shí)心)
        textcircle.setColor(textcolor);//畫(huà)筆的顏色
        textcircle.setTextSize(textsize);//畫(huà)筆的粗細(xì)

    }

在onDraw方法中進(jìn)行一些位置的設(shè)置退腥,然后開(kāi)始進(jìn)行繪制

protected void onDraw(Canvas canvas) {
        //確定半徑
        int radius=Math.min(getWidth(),getHeight());
        //畫(huà)圓
        canvas.drawCircle(getPivotX(),getPivotX(),radius/2-linesize,circlepaint);
        //畫(huà)文本
        String text=(int)(progress*100)+"%";
        //計(jì)算文本寬度
        int width= (int) textcircle.measureText(text);
        //獲取文字矩陣fontMetrics
        Paint.FontMetricsInt fm=textcircle.getFontMetricsInt();
        //開(kāi)始繪制
        canvas.drawText(text,getPivotX()-width/2,getPivotY()+(-fm.ascent)/2+centerYSpace,textcircle);
    }

效果:

image.png

(3)利用繼承ViewGroup實(shí)現(xiàn)布局和一些動(dòng)畫(huà)的組合
首先我們要先創(chuàng)建一個(gè)類(lèi),這個(gè)類(lèi)繼承于ViewGroup
image.png

image.png

創(chuàng)建后我們要實(shí)現(xiàn)ViewGroup里面的抽象方法
和自己的構(gòu)造方法(得到外部給自己的值)

//抽象方法
 @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
   
    }
//構(gòu)造方法
 public WaveLoadingView(Context context) {
        super(context);
    }

    public WaveLoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
public float getProgress() {
        return progress;
    }

然后我們需要?jiǎng)?chuàng)建兩個(gè)視圖類(lèi)(動(dòng)畫(huà))的對(duì)象和一個(gè)進(jìn)度屬性

 private Waveview wv;
    private float progress;
    private cricleview cv;

我們要實(shí)現(xiàn)具體類(lèi)的再榄,對(duì)類(lèi)的屬性進(jìn)行設(shè)置以及實(shí)現(xiàn)具體的布局
所以我們要在 onLayout() 抽象方法中去實(shí)現(xiàn)狡刘。

@Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        //創(chuàng)建原視圖
        cv=new cricleview(getContext());
        cv.setLinecolor(Color.RED);
        cv.setLinesize(50);
        cv.setTextcolor(Color.RED);
        cv.setTextsize(60);
        cv.setCenterYSpace(-50);
        //對(duì)子視圖進(jìn)行布局
        cv.layout(0,0,getWidth(),getHeight());
        //將子視圖添加到容器中
        addView(cv);

        //創(chuàng)建Waveview
        wv=new Waveview(getContext());
        wv.setLineColor(Color.RED);
        wv.setLinesize(5);
        wv.setWavecrest(30);
        wv.setWavelength(100);
        //布局
        wv.layout(getWidth()/4,getHeight()/2-30,getWidth()*3/4,getHeight()+30);
        //添加視圖
        addView(wv);
    }

效果:


錄制_2019_10_28_13_04_44_375.gif

(4)利用ValueAnimator和RotateAnimation實(shí)現(xiàn)加載動(dòng)畫(huà)
首先我們需要兩張圖片,我們將看兩張圖片引到在

image.png

然后我們對(duì)兩張圖片添加到容器中去

private void inite() {
        ImageView inner=new ImageView(getContext());
        inner.setImageResource(R.drawable.m);
        addView(inner);

        outer=new ImageView(getContext());
        outer.setImageResource(R.drawable.y);
        addView(outer);
    }

然后我們對(duì)里面的圖片進(jìn)行設(shè)置動(dòng)畫(huà)(兩種方式ValueAnimator和RotateAnimation)

 @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        /*
        RotateAnimation ra=new RotateAnimation(0,720,outer.getPivotX(),outer.getPivotY());
        ra.setDuration(300);
        ra.setRepeatCount(Animation.INFINITE);
        ra.setRepeatMode(Animation.RESTART);
        ra.setInterpolator(new LinearInterpolator());
        outer.startAnimation(ra);
        */
        ObjectAnimator oa=ObjectAnimator.ofFloat(outer,"rotation",0,360);
        oa.setDuration(1000);
        oa.setRepeatMode(ObjectAnimator.RESTART);
        oa.setRepeatCount(ObjectAnimator.INFINITE);
        oa.setInterpolator(new LinearInterpolator());
        oa.start();
    }

效果:


錄制_2019_10_28_00_40_45_649.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末困鸥,一起剝皮案震驚了整個(gè)濱河市嗅蔬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窝革,老刑警劉巖购城,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吕座,死亡現(xiàn)場(chǎng)離奇詭異虐译,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吴趴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)漆诽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事厢拭±加ⅲ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵供鸠,是天一觀的道長(zhǎng)畦贸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)楞捂,這世上最難降的妖魔是什么薄坏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮寨闹,結(jié)果婚禮上胶坠,老公的妹妹穿的比我還像新娘。我一直安慰自己繁堡,他們只是感情好沈善,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著椭蹄,像睡著了一般闻牡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上塑娇,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天澈侠,我揣著相機(jī)與錄音,去河邊找鬼埋酬。 笑死哨啃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的写妥。 我是一名探鬼主播拳球,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼珍特!你這毒婦竟也來(lái)了祝峻?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扎筒,失蹤者是張志新(化名)和其女友劉穎莱找,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體嗜桌,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奥溺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骨宠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浮定。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡相满,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桦卒,到底是詐尸還是另有隱情立美,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布方灾,位于F島的核電站建蹄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏裕偿。R本人自食惡果不足惜躲撰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望击费。 院中可真熱鬧拢蛋,春花似錦、人聲如沸蔫巩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)圆仔。三九已至垃瞧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坪郭,已是汗流浹背个从。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歪沃,地道東北人嗦锐。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像沪曙,于是被迫代替她去往敵國(guó)和親奕污。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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