Android自定义View绘图实现渐隐动画
程序员文章站
2024-03-06 22:48:26
实现了一个有趣的小东西:使用自定义view绘图,一边画线,画出的线条渐渐变淡,直到消失。效果如下图所示:
用属性动画或者渐变填充(shader)可以做到一笔一笔的变化...
实现了一个有趣的小东西:使用自定义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); } }
这个示例还可以添加一些效果,比如让线条一边变淡一边变细。
目前还有一些问题,线条粗的话,可以明显看到线段与线段之间有缝隙或裂口,哪位想到怎么优化?
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。