自定义View-----汽泡效果
先来看一下这次要实现的最终效果:
首先来实现效果一,为实现效果二做充足的准备,下面开始:
新建工程,并定义一个自定义View,然后将其定义在布局文件中,里面是空实现,之后会一步步来填充代码:
MyRing.java:
public class MyRing extends View { public MyRing(Context context, AttributeSet attrs) {
super(context, attrs);
} }
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" > <com.example.waveview.MyRing
android:layout_width="match_parent"
android:layout_height="match_parent"
/> </RelativeLayout>
接下来一步步来实现第一张效果图所示的效果,先重写父类的某些方法:
public class MyRing extends View { public MyRing(Context context, AttributeSet attrs) {
super(context, attrs);
} /**
* 大小的测量按系统的默认规则
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} /**
* 绘制我们的内容
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
在点击时需要画一个圆,这是第一步,所以需要监听触摸事件:
public class MyRing extends View { /**
* 圆环圆心的X坐标
*/
private int cx; /**
* 圆环圆心的Y坐标
*/
private int cy;
private Paint paint;
/**
* 线条的厚度
*/
private float strokeWidth; public MyRing(Context context, AttributeSet attrs) {
super(context, attrs);
// 初始化paint
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE); // 刻画,画线条
paint.setStrokeWidth(strokeWidth); // 设置条线的厚度
} /**
* 大小的测量按系统的默认规则
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} /**
* 绘制我们的内容
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 绘制圆环,为了看到效果先将半径写死
*/
canvas.drawCircle(cx, cy, 100, paint);
} @Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // 点击,获得圆环的中心
cx = (int) event.getX();
cy = (int) event.getY();
invalidate();
break;
}
return true;
}
}
效果如下:
默认圆画在(0,0)的位置,有了第一步之后,接下来则要让这个圆进行动态渐变,半径、圆边线的粗度都得动态去改变,具体代码如下:
public class MyRing extends View { /**
* 圆环圆心的X坐标
*/
private int cx; /**
* 圆环圆心的Y坐标
*/
private int cy;
private Paint paint;
/**
* 线条的厚度
*/
private float strokeWidth;
/**
* 圆环的半径
*/
private float radius;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
flushState();
// 刷新页面 执行onDraw()方法
invalidate();
if (paint.getAlpha() != 0) {
handler.sendEmptyMessageDelayed(0, 100);
}
};
}; public MyRing(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
} private void initView() {
// 初始化paint
paint = new Paint();
paint.setAntiAlias(true); // 抗矩齿
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE); // 刻画,画线条
paint.setStrokeWidth(strokeWidth); // 设置条线的厚度
paint.setAlpha(255); // 设置透明度 ,0--255 0代表完全透明 //
this.radius = 0;
strokeWidth = 0;
} /**
* 大小的测量按系统的默认规则
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} /**
* 绘制我们的内容
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 绘制圆环
*/
canvas.drawCircle(cx, cy, radius, paint);
} @Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // 点击,获得圆环的中心
cx = (int) event.getX();
cy = (int) event.getY();
// 初始化画笔
initView();
handler.sendEmptyMessage(0);
break;
}
return true;
} /*
* 刷新状态
*/
private void flushState() {
this.radius += 10;
this.strokeWidth = radius / 4;
paint.setStrokeWidth(strokeWidth); int nextAlpha = paint.getAlpha() - 20;
if (nextAlpha <= 20) {
nextAlpha = 0;
}
paint.setAlpha(nextAlpha); }
}
这时就是图一的效果了,有了这个基础,要实现图二的效果也就不难了,下面来试一下:
由于是多个圆,所以肯定是需要一个集合来存储,另外需要用一个实体来表示一个圆的多个属性,如下:
/**
* 定义一个波浪
* @author leo
*/
private class Wave {
//圆心
int cx;
int cy; //画笔
Paint p;
//半径
int r;
}
然后在按下或滑动时,则把相应的点给添加到集合中,并且需要点与点之间有一定的距离才行,挨得太近则不添加,具体逻辑如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE: int x = (int) event.getX();
int y = (int) event.getY(); addPoint(x,y); break; default:
break;
} return true; }
而添加的方法如下:
/**
* 添加新的波浪中心点
* @param x
* @param y
*/
private void addPoint(int x, int y) {
if(wList.size() == 0){
addPoint2List(x,y);
/*
* 第一次启动动画
*/
isRunning = true;
handler.sendEmptyMessage(0);
}else{
Wave w = wList.get(wList.size()-1); if(Math.abs(w.cx - x)>DIS_SOLP || Math.abs(w.cy-y)>DIS_SOLP){
addPoint2List(x,y);
} }; } /**
* 添加新的波浪
* @param x
* @param y
*/
private void addPoint2List(int x, int y) {
Wave w = new Wave();
w.cx = x;
w.cy=y;
Paint pa=new Paint();
pa.setColor(colors[(int)(Math.random()*4)]);
pa.setAntiAlias(true);
pa.setStyle(Style.STROKE); w.p = pa; wList.add(w);
}
其中当一第一次添加时,则会开启handler去跑圆环动画,其它的则相继往集合中添加,而handler的写法跟一个圆环的写法差不多,这里就不多解释,直接把整个代码贴上来,都比较好理解:
/**
* 水波纹效果
*
*/
public class MyRingWave extends View{ /**
* 二个相临波浪中心点的最小距离
*/
private static final int DIS_SOLP = 13; protected boolean isRunning = false; private ArrayList<Wave> wList; public MyRingWave(Context context, AttributeSet attrs) {
super(context, attrs);
wList = new ArrayList<MyRingWave.Wave>();
} private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) { //刷新数据
flushData();
//刷新页面
invalidate();
//循环动画
if (isRunning) {
handler.sendEmptyMessageDelayed(0, 50);
} };
}; @Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < wList.size(); i++) {
Wave wave = wList.get(i);
canvas.drawCircle(wave.cx, wave.cy, wave.r, wave.p);
}
} @Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE: int x = (int) event.getX();
int y = (int) event.getY(); addPoint(x,y); break; default:
break;
} return true; } /**
* 添加新的波浪中心点
* @param x
* @param y
*/
private void addPoint(int x, int y) {
if(wList.size() == 0){
addPoint2List(x,y);
/*
* 第一次启动动画
*/
isRunning = true;
handler.sendEmptyMessage(0);
}else{
Wave w = wList.get(wList.size()-1); if(Math.abs(w.cx - x)>DIS_SOLP || Math.abs(w.cy-y)>DIS_SOLP){
addPoint2List(x,y);
} }; } /**
* 添加新的波浪
* @param x
* @param y
*/
private void addPoint2List(int x, int y) {
Wave w = new Wave();
w.cx = x;
w.cy=y;
Paint pa=new Paint();
pa.setColor(colors[(int)(Math.random()*4)]);
pa.setAntiAlias(true);
pa.setStyle(Style.STROKE); w.p = pa; wList.add(w);
} private int [] colors = new int[]{Color.BLUE,Color.RED,Color.YELLOW,Color.GREEN};
/**
* 刷新数据
*/
private void flushData() { for (int i = 0; i < wList.size(); i++) { Wave w = wList.get(i); //如果透明度为 0 从集合中删除
int alpha = w.p.getAlpha();
if(alpha == 0){
wList.remove(i); //删除i 以后,i的值应该再减1 否则会漏掉一个对象,不过,在此处影响不大,效果上看不出来。
continue;
} alpha-=5;
if(alpha<5){
alpha =0;
}
//降低透明度
w.p.setAlpha(alpha); //扩大半径
w.r = w.r+3;
//设置半径厚度
w.p.setStrokeWidth(w.r/3);
} /*
* 如果集合被清空,就停止刷新动画
*/
if(wList.size() == 0){
isRunning = false;
}
} /**
* 定义一个波浪
* @author leo
*/
private class Wave {
//圆心
int cx;
int cy; //画笔
Paint p;
//半径
int r;
}
}
对于这个自定义效果倒不是很复杂,但效果还是挺炫滴,以后坚持收集学习好的UI效果。
自定义View-----汽泡效果的更多相关文章
- android自定义view实现公章效果
上次去一个公司面试,面试官问了一个题,怎么用android的自定义view实现一个公章的效果,据说这是华为之前的面试题,我想了下,要是公章的效果,最外层是一个圆,里面是一个五角星,但是这文字怎么画呢, ...
- 自定义View实现钟摆效果进度条PendulumView
转载请注明出处:http://blog.csdn.net/fightlei/article/details/52556755 在网上看到了一个IOS组件PendulumView,实现了钟摆的动画效果. ...
- Android 自定义View跑马灯效果(一)
今天通过书籍重新复习了一遍自定义VIew,为了加强自己的学习,我把它写在博客里面,有兴趣的可以看一下,相互学习共同进步: 通过自定义一个跑马灯效果,来诠释一下简单的效果: 一.创建一个类继承View, ...
- android 自定义view之侧滑效果
效果图: 看网上的都是两个view拼接,默认右侧的不显示,水平移动的时候把右侧的view显示出来.但是看最新版QQ上的效果不是这样的,但给人的感觉却很好,所以献丑来一发比较高仿的. 知识点: 1.Vi ...
- HTML5 汽泡效果
又到了晚上了,精神只有在晚上的时候才能爆发,可能程序员的命吧.废话就不多说了,今天我为大家带来的是一个气泡的效果. 代码下载 下面请看效果图
- 在RecyclerView中集成QQ汽泡二
上次已经将GooView集成到RecyclerView当中了[http://www.cnblogs.com/webor2006/p/7787511.html],但是目前还有很多问题,下面先来运行看一下 ...
- 在RecyclerView中集成QQ汽泡一
上次已经实现了QQ汽泡的自定义View的效果[http://www.cnblogs.com/webor2006/p/7726174.html],接着再将它应用到列表当中,这样才算得上跟QQ的效果匹配, ...
- 分析自定义view的实现过程-实现雪花飞舞效果(转载有改动)
声明:本文源码出自实现雪花飞舞效果(有改动)主要通过这篇文来分析自定义view的实现过程. 没事时,比较喜欢上网看看一些新的东西,泡在网上的日子就是一个很不错的网站. 下面开始了,哈哈.^_^ 大家都 ...
- Android自定义View之圆环交替 等待效果
学习了前面两篇的知识,对于本篇实现的效果,相信大家都不会感觉太困难,我要实现的效果是什么样呢?下面请先看效果图: 看上去是不很炫的样子,它的实现上也不是很复杂,重点在与onDraw()方法的绘制. 首 ...
- Android自定义View 画弧形,文字,并增加动画效果
一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类 B ...
随机推荐
- 书.Windows网络与通信程序设计
1.PDF&源码 保存到了 我的网盘fivez79513-->"PDF&源码" 目录中 “Windows网络与通信程序设计(第2版) 完整带书签PDF+源码. ...
- FCM实现手机推送,推送的方式,真机调试
FCM实现手机 1 下载Androidstudio 3.2 版本,之后新建一个项目 2 创建完项目之后查找文件AndroidMainifest.xml 3 访问网站注册一个自己的firebase的 ...
- 【持续集成】jenkins安装部署从git获取代码
一:持续集成的概念: 1.1:总体的概括 持续集成Continuous Integration 持续交付Continuous Delivery 持续部署Continuous Deployment 1. ...
- jira使用一:如何给项目分组、sprint并行、禁止发送消息给atlassian
问题一:如何设置多个sprint并行? 问题二: 如何分组显示 设置泳道,并快速过滤 问题3:添加所属产品? 管理员登录Jira后台设置-问题-自定义字段找到:所属产品,进入 配置 界面在配置界面中, ...
- Machine Learning Stanford Univerisity (Week 1)
1. 机器学习是什么? "A computer program is said to learn from experience E with respect to some class o ...
- LeNet-5 pytorch+torchvision+visdom
# ====================LeNet-5_main.py=============== # pytorch+torchvision+visdom # -*- coding: utf- ...
- 提车应该检查哪?4S店都怕你检查这4个“雷区”,别等后悔才知道
https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_9381645601643691163% ...
- SQL入门经典(第四版)学习记录——SQL语法(二)
一.创建表 create table 表里包含什么类型的数据 表的名称是什么 主键 列的名称是什么 每一列的数据类型是什么 每一列的长度是多少 表里哪些列可以是空的 语法: create table ...
- SpringBoot使用thymeleaf的方式引用static中的静态资源
当我们在开发网站时为了快速完成,避免不了使用第三方的框架文件.这样我们就得引用框架中的各种资源文件.那么,在springboot中通过 thymeleaf如何在html中使用static文件夹下的静态 ...
- RecursiveSequence(HDU-5950)【矩阵快速幂】
题目链接: 题意:Si=S(i-1)+2*S(i-2)+i^4,求Sn. 思路:想到了矩阵快速幂,实在没想出来怎么构造矩阵.... 首先构造一个向量vec={a,b,16,8,4,2,1}. 在构造求 ...