两种方式实现类似水波扩散效果,先上图为敬
- 自定义view实现
- 动画实现
自定义view实现
思路分析:通过canvas画圆,每次改变圆半径和透明度,当半径达到一定程度,再次从中心开始绘圆,达到不同层级的效果,通过不断绘制达到view扩散效果
1
2
3
4
5
6
7
8
9
10
|
private Paint centerPaint; //中心圆paint
private int radius = 100 ; //中心圆半径
private Paint spreadPaint; //扩散圆paint
private float centerX; //圆心x
private float centerY; //圆心y
private int distance = 5 ; //每次圆递增间距
private int maxRadius = 80 ; //最大圆半径
private int delayMilliseconds = 33 ; //扩散延迟间隔,越大扩散越慢
private List<Integer> spreadRadius = new ArrayList<>(); //扩散圆层级数,元素为扩散的距离
private List<Integer> alphas = new ArrayList<>(); //对应每层圆的透明度
|
style文件里自定义属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<declare-styleable name= "SpreadView" >
<!--中心圆颜色-->
<attr name= "spread_center_color" format= "color" />
<!--中心圆半径-->
<attr name= "spread_radius" format= "integer" />
<!--扩散圆颜色-->
<attr name= "spread_spread_color" format= "color" />
<!--扩散间距-->
<attr name= "spread_distance" format= "integer" />
<!--扩散最大半径-->
<attr name= "spread_max_radius" format= "integer" />
<!--扩散延迟间隔-->
<attr name= "spread_delay_milliseconds" format= "integer" />
</declare-styleable>
|
初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public SpreadView(Context context) {
this (context, null , 0 );
}
public SpreadView(Context context, @Nullable AttributeSet attrs) {
this (context, attrs, 0 );
}
public SpreadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super (context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpreadView, defStyleAttr, 0 );
radius = a.getInt(R.styleable.SpreadView_spread_radius, radius);
maxRadius = a.getInt(R.styleable.SpreadView_spread_max_radius, maxRadius);
int centerColor = a.getColor(R.styleable.SpreadView_spread_center_color, ContextCompat.getColor(context, R.color.colorAccent));
int spreadColor = a.getColor(R.styleable.SpreadView_spread_spread_color, ContextCompat.getColor(context, R.color.colorAccent));
distance = a.getInt(R.styleable.SpreadView_spread_distance, distance);
a.recycle();
centerPaint = new Paint();
centerPaint.setColor(centerColor);
centerPaint.setAntiAlias( true );
//最开始不透明且扩散距离为0
alphas.add( 255 );
spreadRadius.add( 0 );
spreadPaint = new Paint();
spreadPaint.setAntiAlias( true );
spreadPaint.setAlpha( 255 );
spreadPaint.setColor(spreadColor);
}
|
确定圆心位置
1
2
3
4
5
6
7
|
@Override
protected void onSizeChanged( int w, int h, int oldw, int oldh) {
super .onSizeChanged(w, h, oldw, oldh);
//圆心位置
centerX = w / 2 ;
centerY = h / 2 ;
}
|
自定义view的绘制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@Override
protected void onDraw(Canvas canvas) {
super .onDraw(canvas);
for ( int i = 0 ; i < spreadRadius.size(); i++) {
int alpha = alphas.get(i);
spreadPaint.setAlpha(alpha);
int width = spreadRadius.get(i);
//绘制扩散的圆
canvas.drawCircle(centerX, centerY, radius + width, spreadPaint);
//每次扩散圆半径递增,圆透明度递减
if (alpha > 0 && width < 300 ) {
alpha = alpha - distance > 0 ? alpha - distance : 1 ;
alphas.set(i, alpha);
spreadRadius.set(i, width + distance);
}
}
//当最外层扩散圆半径达到最大半径时添加新扩散圆
if (spreadRadius.get(spreadRadius.size() - 1 ) > maxRadius) {
spreadRadius.add( 0 );
alphas.add( 255 );
}
//超过8个扩散圆,删除最先绘制的圆,即最外层的圆
if (spreadRadius.size() >= 8 ) {
alphas.remove( 0 );
spreadRadius.remove( 0 );
}
//中间的圆
canvas.drawCircle(centerX, centerY, radius, centerPaint);
//TODO 可以在中间圆绘制文字或者图片
//延迟更新,达到扩散视觉差效果
postInvalidateDelayed(delayMilliseconds);
}
|
xml样式
1
2
3
4
5
6
7
8
9
10
|
<com.airsaid.diffuseview.widget.SpreadView
android:id= "@+id/spreadView"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
app:spread_center_color= "@color/colorAccent"
app:spread_delay_milliseconds= "35"
app:spread_distance= "5"
app:spread_max_radius= "90"
app:spread_radius= "100"
app:spread_spread_color= "@color/colorAccent" />
|
效果图
中心圆处可以自定义写文字,画图片等等...
动画实现
思路分析:通过动画实现,imageView不停做动画缩放+渐变
最中心的imageView保持不变
中间一层imageView从原始放大到1.4倍,同时从不透明变为半透明
最外层的imageView从1.4倍放大到1.8倍,同时从半透明变为全透明
利用shape画一个圆,作为动画基础视图
1
2
3
4
5
|
<?xml version= "1.0" encoding= "utf-8" ?>
<shape xmlns:android= "http://schemas.android.com/apk/res/android" >
<corners android:radius= "65dp" />
<solid android:color= "@color/colorAccent" />
</shape>
|
布局视图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<FrameLayout
android:layout_width= "match_parent"
android:layout_height= "match_parent" >
<!--中心imageView-->
<ImageView
android:id= "@+id/iv_wave"
android:layout_width= "130dp"
android:layout_height= "130dp"
android:layout_gravity= "center"
android:background= "@drawable/shape_circle" />
<!--中间的imageView-->
<ImageView
android:id= "@+id/iv_wave_1"
android:layout_width= "130dp"
android:layout_height= "130dp"
android:layout_gravity= "center"
android:background= "@drawable/shape_circle" />
<!--最外层imageView-->
<ImageView
android:id= "@+id/iv_wave_2"
android:layout_width= "130dp"
android:layout_height= "130dp"
android:layout_gravity= "center"
android:background= "@drawable/shape_circle" />
</FrameLayout>
|
中间imageView的动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private void setAnim1() {
AnimationSet as = new AnimationSet( true );
//缩放动画,以中心从原始放大到1.4倍
ScaleAnimation scaleAnimation = new ScaleAnimation( 1 .0f, 1 .4f, 1 .0f, 1 .4f,
ScaleAnimation.RELATIVE_TO_SELF, 0 .5f,
ScaleAnimation.RELATIVE_TO_SELF, 0 .5f);
//渐变动画
AlphaAnimation alphaAnimation = new AlphaAnimation( 1 .0f, 0 .5f);
scaleAnimation.setDuration( 800 );
scaleAnimation.setRepeatCount(Animation.INFINITE);
alphaAnimation.setRepeatCount(Animation.INFINITE);
as.setDuration( 800 );
as.addAnimation(scaleAnimation);
as.addAnimation(alphaAnimation);
iv1.startAnimation(as);
}
|
最外层imageView的动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private void setAnim2() {
AnimationSet as = new AnimationSet( true );
//缩放动画,以中心从1.4倍放大到1.8倍
ScaleAnimation scaleAnimation = new ScaleAnimation( 1 .4f, 1 .8f, 1 .4f, 1 .8f,
ScaleAnimation.RELATIVE_TO_SELF, 0 .5f,
ScaleAnimation.RELATIVE_TO_SELF, 0 .5f);
//渐变动画
AlphaAnimation alphaAnimation = new AlphaAnimation( 0 .5f, 0 .1f);
scaleAnimation.setDuration( 800 );
scaleAnimation.setRepeatCount(Animation.INFINITE);
alphaAnimation.setRepeatCount(Animation.INFINITE);
as.setDuration( 800 );
as.addAnimation(scaleAnimation);
as.addAnimation(alphaAnimation);
iv2.startAnimation(as);
}
|
效果图
相比较而言,自定义view的效果更好点,动画实现起来更方便点。
两种方式实现的扩散效果介绍完毕,具体项目里还是要按需变动的。
总结
以上所述是小编给大家介绍的Android 实现圆圈扩散水波动画效果两种方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:https://www.cnblogs.com/taixiang/archive/2018/05/27/9095464.html