android显示绘图动画,Android自定义View绘图实现渐隐动画

实现了一个有趣的小东西:使用自定义view绘图,一边画线,画出的线条渐渐变淡,直到消失。效果如下图所示:

d7b38b8a19a75b794a20139ad4b54754.gif

用属性动画或者渐变填充(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 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() ;

}

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

}

}

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339187.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

csrf spring_无状态Spring安全性第1部分:无状态CSRF保护

csrf spring如今&#xff0c;随着RESTful架构变得越来越标准&#xff0c;可能值得花一些时间重新考虑当前的安全方法。 在这一小系列博客文章中&#xff0c;我们将探索以无状态方式解决与Web相关的安全性问题的几种相对较新的方法。 这第一篇文章是关于保护您的网站免受跨站请求…

python网络编程项目_python网络编程详解

最近在看《UNIX网络编程 卷1》和《FREEBSD操作系统设计与实现》这两本书&#xff0c;我重点关注了TCP协议相关的内容&#xff0c;结合自己后台开发的经验&#xff0c;写下这篇文章&#xff0c;一方面是为了帮助有需要的人&#xff0c;更重要的是方便自己整理思路&#xff0c;加…

C - 指针总结

指针是什么&#xff1f;指针是一变量或函数的内存地址&#xff0c;是一个无符号整数&#xff0c;它是以系统寻址范围为取值范围&#xff0c;32位&#xff0c;4字节。指针变量&#xff1a;存放地址的变量。在C 中&#xff0c;指针变量只有有了明确的指向才有意义。指针类型int* …

android网络转圈,android基于dialog加载时转圈圈很好的demo

【实例简介】这是一个android基于dialog加载时转圈圈很好的完整demo&#xff0c;很适合新手学习&#xff0c;希望对有需要的朋友能得到帮助【实例截图】【核心代码】dialog_anim└── dialog_anim├── AndroidManifest.xml├── bin│ ├── AndroidManifest.xml│ ├…

spring期刊状态_无状态Spring安全性第2部分:无状态认证

spring期刊状态Spring Stateless Security系列的第二部分是关于以无状态方式探索身份验证的方法。 如果您错过了有关CSRF的第一部分&#xff0c;可以在这里找到。 因此&#xff0c;在谈论身份验证时&#xff0c;其全部内容就是让客户端以可验证的方式向服务器标识自己。 通常&…

分享10个值得关注的C语言开源项目

来源于网络&#xff0c;如有侵权&#xff0c;告知必删。

python3 x默认使用的编码_python3默认使用什么编码

python3默认编码为unicode&#xff0c;由str类型进行表示。二进制数据使用byte类型表示。 字符串通过编码转换成字节码&#xff0c;字节码通过解码成为字符串encode&#xff1a;str --> bytes&#xff08;推荐学习&#xff1a;Python视频教程&#xff09; decode&#xff1a…

html中写css代码,开发DIV CSS时 先写CSS代码还是先写HTML代码

相信良多&#xff2c;&#xff2f;&#xff36;&#xff25;用DIVCSS技术启示重构网页的爱好者友好&#xff0c;在起源学习DIVCSS的时分都邑想一个标题&#xff0c;想晓得DIVCSS妙手或有教育者在开发制作html页面的时刻&#xff0c;下场是先写html照样先写css&#xff1f;带着这…

象棋子 设计模式_通过设计国际象棋游戏了解策略模式

象棋子 设计模式今天&#xff0c;我们将借助一个示例来尝试了解策略模式。 我们将考虑的示例是国际象棋游戏。 这里的目的是解释策略模式&#xff0c;而不是构建全面的国际象棋游戏解决方案。 策略模式&#xff1a;策略模式被称为行为模式–用于管理对象之间的算法&#xff0…

入门C语言10问10答

1 如何理解变量与常量?变量与常量相当于数据的可读可写与只读&#xff0c;常量是数据的一种保护机制。在内存分配给程序的内存块中有专门的常量&#xff08;只读&#xff09;存储区。2 整型数据的溢出问题任何一种数据类型的数据在计算机中都有它确定的数值表示范围&#xff0…

mac json格式化工具_简洁好用的工具都是相似的

大家好&#xff0c;我是你们的章鱼猫。不知道大家了不了解 jq 这个工具呢&#xff1f;指的不是 JQuery&#xff0c;而是一个命令行工具。jq 是一个轻量级而且灵活的命令行 JSON 解析器&#xff0c;类似用于 JSON 数据的 sed 工具。我们来看一下使用 jq 处理 json 的基本用法(更…

android 撑满剩余空间,怎么让LinearLayout占据父布局的所有剩余空间

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼xmlns:tools"http://schemas.android.com/tools"android:layout_width"match_parent"android:layout_height"match_parent"android:paddingBottom"dimen/activity_vertical_margin"androi…

战神4 幕后花絮 概念艺术_Java 9幕后花絮:新功能从何而来?

战神4 幕后花絮 概念艺术找出Java幕后发生的事情&#xff0c;以及新功能如何实现 在上一篇文章中&#xff0c;我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能&#xff0c;并简要提到了将新功能添加到下一个版本之前要经历的过程。 由于此过程几乎影响了所有Java开发人…

ID生成器 雪花算法

背景&#xff1a;在很多业务场景下&#xff0c;我们都需要一个唯一的 ID 来进行一些数据的交互&#xff0c;那么如何生成这个唯一的 ID 呢&#xff1f;如果在单机的情况下&#xff0c;生成唯一ID&#xff0c;可以利用机器内存的特点&#xff0c;通过内存分配即可。但我们线上的…

2014 android 机型排行,2014年10月十佳Android系统智能安卓手机排行榜单 Note 4第一名...

Android系统手机经过几年的发展&#xff0c;如今已经成了大家购机的首选。但在市面上数量众多的Android家族成员中&#xff0c;那些才是真正值得期待和拥有的机型&#xff0c;或许每个人会有不同的答案。如果你还在几款机型的选择上纠结&#xff0c;那么不妨借助国外媒体Androi…

python anaconda安装_Python - 安装并配置Anaconda环境

$ py --version # 当前默认python版本 Python 3.7.1 $ conda create --name testpy2 python2.7 pandas # 创建名为testpy2的运行环境&#xff0c;并安装pandas包及其依赖包 Solving environment: done ## Package Plan ## environment location: D:\DownLoadFiles\anaconda3\en…

jstack调试_增压的jstack:如何以100mph的速度调试服务器

jstack调试使用jstack调试实时Java生产服务器的指南 jstack就像U2一样-从时间的黎明就一直在我们身边&#xff0c;我们似乎无法摆脱它 。 除了笑话&#xff0c;到目前为止&#xff0c;jstack是您的工具库中用于调试实时生产服务器的最方便的工具之一。 即便如此&#xff0c;我仍…

C/C 输入输出缓冲区

【导读】&#xff1a;本文介绍C与C 输入输出缓冲的一些操作与特性。以下是正文&#xff08;1&#xff09;c 中cin、cout&#xff0c;cerr和c的stdin、stdout、stderr都是同步的&#xff0c;即iostream 对象和 and cstdio流是同步的&#xff0c;同步关系如下&#xff1a;同步即表…

android 活动销毁不了,即使活动已经销毁,AsyncTask也不会停止

我想添加一个信息补充&#xff0c;并给出一个指向库或2的指针&#xff0c;可以用于长时间运行的AsyncTask&#xff0c;甚至可以用于面向网络的asynctasks。AsyncTasks专为在后台执行操作而设计。是的&#xff0c;您可以使用该cancel方法停止它。当您从Internet下载内容时&#…

python输入input数组_python怎么输入数组

python怎么输入数组&#xff1f; python输入数组 一维数组&#xff1a;arr input("") //输入一个一维数组&#xff0c;每个数之间使空格隔开 num [int(n) for n in arr.split()] //将输入每个数以空格键隔开做成数组 print(num) //打印数组 一维数组输入输出示例&a…