首页 > 系统 > Android > 正文

Android自定义View绘图实现渐隐动画

2019-12-12 05:21:36
字体:
来源:转载
供稿:网友

实现了一个有趣的小东西:使用自定义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);  }}
 

这个示例还可以添加一些效果,比如让线条一边变淡一边变细。

目前还有一些问题,线条粗的话,可以明显看到线段与线段之间有缝隙或裂口,哪位想到怎么优化?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表