当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义View绘图实现渐隐动画

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

2019年07月24日  | 移动技术网移动技术  | 我要评论

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

 

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

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

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网