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);    }}

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

目前還有一些問題,線條粗的話,可以明顯看到線段與線段之間有縫隙或裂口,哪位想到怎麼最佳化,可以告訴我,非常感謝。^_^。

Android繪圖之漸隱動畫

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.