自定义View实现雨点洒落效果
2016-01-15 16:56
218 查看
自定义View实现雨点洒落效果
最近事情不多,想着写点东西,又不知道写什么好,实现个小效果,娱乐一下,顺带自己也再熟练下自定义view的绘制的相关知识,不说废话,先上图:一、前期分析
很明显,上面场景是又一个居中的TextView以及一个个小红点和散开的圆圈构成。在点击上面文本框的时候文本框出现抖动并产生一个小红点,下红点沿预定路径下落,在下落到指定高度时显示散开的波浪效果,同时伴有透明度的变化。好了,效果分析完,咱开始代码实现吧。
二、文本框抖动的实现
文本框抖动很简单,一个平移效果的动画,加上循环差值器,xml如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#fff"> <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="50dp" android:layout_marginTop="30dp" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:background="#f60" android:clickable="true" android:textColor="#fff" android:gravity="center" android:text="hahaha" /> <com.example.test.CustomView android:id="@+id/v" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
private TextView tv; tv=(TextView) findViewById(R.id.tv); final TranslateAnimation animation = (TranslateAnimation)AnimationUtils.loadAnimation(this, R.anim.animation); tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { tv.startAnimation(animation); } });
animation.xml:
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fromXDelta="0" android:interpolator="@anim/cycle" android:toXDelta="10" > </translate>
cycle.xml:
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="5" />
这个实现很简单,大家看一下应该都能明白,我们继续。
三、圆点生成以及散开效果
ok,我们的圆点生成器已经完成,我们要制作圆点了,动手之前,我们再次观察一下,我**每点击一次**就**生成一个**小圆点,而且小圆点是按照**自己的轨迹**掉落下来,最后自己散开。 聪明的小伙伴应该已经猜到了,每个小圆点应该都是独立的,按照面向对象的思想,每个小圆点应该都做为一个独立的对象存在,那我们就先来创建小圆点的对象吧。
class Circle{ //x轴的 的坐标 int x; //y轴的坐标 int y; //画笔的透明度值 int alpha; //掉落后圆环的宽度 float width; //圆环的半径 float radius; //绘制散开圆环的画笔 Paint paint; }
在产生小圆点以及小圆点散开的过程中,我们就是要不断的绘制我们的界面,这里呢,我们自定义一个View来实现这个效果。
public class CustomView extends View { //画小圆点的画笔 private Paint paint; private List<Circle> list = new ArrayList<CustomView.Circle>(); //x初始值 //圆环的画笔 private Paint Circlepaint; public CustomView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); Circlepaint = new Paint(paint); Circlepaint.setStyle(Paint.Style.STROKE); } @Override protected void onDraw(Canvas canvas) { for(Circle circle:list){ if(circle.alpha<15){ circle.alpha = 0; } circle.paint.setAlpha(circle.alpha); if(circle.y >= dp2px(300)){ circle.paint.setStrokeWidth(circle.width); canvas.drawCircle(circle.x, dp2px(300), circle.radius, circle.paint); }else{ canvas.drawCircle(circle.x, circle.y, circle.radiusSamll, paint); } } } //外部刷新view public void refresh(int y){ int x = dp2px(150); int cishu = new Random().nextInt(4); switch (cishu) { case 0: x-=dp2px(30); break; case 1: x+=dp2px(30); break; case 2: x-=dp2px(10); break; case 3: x+=dp2px(10); break; } Circle circle = new Circle(); circle.x = x; circle.y = y; circle.radius = dp2px(60f); circle.alpha = 255; circle.radiusSamll = dp2px(10); circle.width = dp2px(60f); circle.paint = Circlepaint;//画圆的paint list.add(circle); invalidate(); } private List<Circle> tempList = new ArrayList<CustomView.Circle>(); @Override public void computeScroll() { for(Circle circle:list){ if(circle.y <dp2px(300)){ circle.y+=dp2px(8); invalidate(); }else{ if(circle.alpha >= 0){ circle.radius+=dp2px(28); circle.alpha-=10; circle.width-=dp2px(15); if(circle.width<0){ circle.width = 0; circle.radius = 0; } invalidate(); }else{ //将alpha值小于0的对象保存在临时集合中 tempList.add(circle); } } } //从集合中去除看不见的对象 list.removeAll(tempList); } class Circle{ //x轴的坐标 int x; //y轴的坐标 int y; //画笔的透明度值 int alpha; //掉落后圆环的宽度 float width; //散落下圆环的半径 float radius; //小圆点的半径 float radiusSamll; //绘制散开圆环的画笔 Paint paint; } public int dp2px(float value){ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics()); } }
private TextView tv; private CustomView cv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); cv = (CustomView) findViewById(R.id.v); tv=(TextView) findViewById(R.id.tv); final TranslateAnimation animation = (TranslateAnimation)AnimationUtils.loadAnimation(this, R.anim.animation); tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { tv.startAnimation(animation); // 刷新 界面 cv.refresh(0); } }); }
其中核心就是每点击一次就创建一个圆点对象,并存储在集合中,在每次onDraw调用时,遍历集合中每一个对象绘制在界面上,invalidate方法会触发computeScroll方法,在computeScroll方法调用时,遍历判断每个对象的透明值是否小于0,即是否可见,如果不可见,我们就将其从集合中移除出去,注意集合在遍历时不允许进行增删操作,所以这里我们先放进一个临时集合中,在遍历结束之后统一移除。
四、总结
自定义view最主要的就是根据状态赋予不同的变量值,从而不断的显示不同的效果,Paint,Canvas是两个很强大的类,有很多有趣的功能等着我们探索,加油吧。
相关文章推荐
- MySQL 中文显示乱码
- 在popupWindow里响应硬件的back按键的事件
- 【菜鸟学Java】8:List实体集合中保证产品名称不重复
- T-SQL查询进阶--详解公用表表达式(CTE)
- 统计网站浏览量
- MTK android 重启测试脚本
- Sphinx之配置文件
- lua 怎么写两个字符串相加
- 时尚仪表盘 Android 自定义View
- java接口与抽象类学习总结
- Java/Android的观察者模式
- e8000051
- Unity3D游戏开发中制作场景
- Oracle 12cR1中性能优化新特性之全数据库缓冲模式
- 设计模式:依赖倒转原则
- iOS NSData 转换成 NSDictionary
- Java——String.valueOf() 方法的使用
- Rails 4中document.ready失效
- sql语句in超过1000时的写法
- The type org.apache.http.HttpEntity cannot be resolved.错误的解决