您的位置:首页 > 其它

自定义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是两个很强大的类,有很多有趣的功能等着我们探索,加油吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: