Android自訂View繪圖實現漸隱動畫_Android

來源:互聯網
上載者:User

實現了一個有趣的小東西:使用自訂View繪圖,一邊畫線,畫出的線條漸漸層淡,直到消失。效果如下圖所示:

用屬性動畫或者漸層填充(Shader)可以做到一筆一筆的變化,但要想一筆漸層(手指不抬起邊畫邊漸隱),沒在Android中找到現成的API可用。所以,自己做了一個。

基本的想法是這樣的:

•在View的onTouchEvent中記錄觸摸點,產生一條一條的線LineElement,放在一個List中。給每個LineElement配置一個Paint執行個體。
•在onDraw中繪製線段。
•變換LineElement的Paint執行個體的Alpha值。
•根據Alpha值重組線段列表 

別的不說了,上代碼:

package com.example.disappearinglines;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.RectF;import android.os.Handler;import android.os.Message;import android.os.SystemClock;import android.support.annotation.NonNull;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import java.util.List;import java.util.ListIterator;public class DisappearingDoodleView extends View {  final static String TAG = "DoodleView";  class LineElement {    static final public int ALPHA_STEP = 5;    static final public int SUBPATH_DIMENSION = 8;    public LineElement(){      mPaint = new Paint();      mPaint.setARGB(255, 255, 0, 0);      mPaint.setAntiAlias(true);      mPaint.setStrokeWidth(16);      mPaint.setStrokeCap(Paint.Cap.BUTT);      mPaint.setStyle(Paint.Style.STROKE);    }    public LineElement(Paint paint){      mPaint = paint;    }    public void setPaint(Paint paint){      mPaint = paint;    }    public void setAlpha(int alpha){      mPaint.setAlpha(alpha);    }    public float mStartX = -1;    public float mStartY = -1;    public float mEndX = -1;    public float mEndY = -1;    public Paint mPaint;  }  private LineElement mCurrentLine = null;  private List<LineElement> mLines = null;  private long mElapsed = 0;  private Handler mHandler = new Handler(){    @Override    public void handleMessage(Message msg){      DisappearingDoodleView.this.invalidate();    }  };  public DisappearingDoodleView(Context context){    super(context);  }  public DisappearingDoodleView(Context context, AttributeSet attrs){    super(context, attrs);  }  @Override  protected void onDraw(Canvas canvas){    mElapsed = SystemClock.elapsedRealtime();    if(mLines != null) {      for (LineElement e : mLines) {        if(e.mStartX < 0 || e.mEndY < 0) continue;        canvas.drawLine(e.mStartX, e.mStartY, e.mEndX, e.mEndY, e.mPaint);      }      compactPaths();    }  }  @Override  public boolean onTouchEvent(MotionEvent event){    float x = event.getX();    float y = event.getY();    int action = event.getAction();    if(action == MotionEvent.ACTION_UP){// end one line after finger release      mCurrentLine.mEndX = x;      mCurrentLine.mEndY = y;      mCurrentLine = null;      invalidate();      return true;    }    if(action == MotionEvent.ACTION_DOWN){      mCurrentLine = new LineElement();      addToPaths(mCurrentLine);      mCurrentLine.mStartX = x;      mCurrentLine.mStartY = y;      return true;    }    if(action == MotionEvent.ACTION_MOVE) {      mCurrentLine.mEndX = x;      mCurrentLine.mEndY = y;      mCurrentLine = new LineElement();      addToPaths(mCurrentLine);      mCurrentLine.mStartX = x;      mCurrentLine.mStartY = y;    }    if(mHandler.hasMessages(1)){      mHandler.removeMessages(1);    }    Message msg = new Message();    msg.what = 1;    mHandler.sendMessageDelayed(msg, 0);    return true;  }  private void addToPaths(LineElement element){    if(mLines == null) {      mLines = new ArrayList<LineElement>() ;    }    mLines.add(element);  }  public void compactPaths(){    int size = mLines.size();    int index = size - 1;    if(size == 0) return;    int baseAlpha = 255 - LineElement.ALPHA_STEP;    int itselfAlpha;    LineElement line;    for(; index >=0 ; index--, baseAlpha -= LineElement.ALPHA_STEP){      line = mLines.get(index);      itselfAlpha = line.mPaint.getAlpha();      if(itselfAlpha == 255){        if(baseAlpha <= 0){          ++index;          break;        }        line.setAlpha(baseAlpha);      }else{        itselfAlpha -= LineElement.ALPHA_STEP;        if(itselfAlpha <= 0){          ++index;          break;        }        line.setAlpha(itselfAlpha);      }    }    if(index >= size){      // all sub-path should disappear      mLines = null;    }    else if(index >= 0){      //Log.i(TAG, "compactPaths from " + index + " to " + (size - 1));      mLines = mLines.subList(index, size);    }else{      // no sub-path should disappear    }    long interval = 40 - SystemClock.elapsedRealtime() + mElapsed;    if(interval < 0) interval = 0;    Message msg = new Message();    msg.what = 1;    mHandler.sendMessageDelayed(msg, interval);  }}
 

這個樣本還可以添加一些效果,比如讓線條一邊變淡一邊變細。

目前還有一些問題,線條粗的話,可以明顯看到線段與線段之間有縫隙或裂口,哪位想到怎麼最佳化?

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.