兩種方式實現(xiàn)類似水波擴(kuò)散效果,先上圖為敬
- 自定義view實現(xiàn)
- 動畫實現(xiàn)
自定義view實現(xiàn)
思路分析:通過canvas畫圓,每次改變圓半徑和透明度,當(dāng)半徑達(dá)到一定程度,再次從中心開始繪圓,達(dá)到不同層級的效果,通過不斷繪制達(dá)到view擴(kuò)散效果
1
2
3
4
5
6
7
8
9
10
|
private Paint centerPaint; //中心圓paint private int radius = 100 ; //中心圓半徑 private Paint spreadPaint; //擴(kuò)散圓paint private float centerX; //圓心x private float centerY; //圓心y private int distance = 5 ; //每次圓遞增間距 private int maxRadius = 80 ; //最大圓半徑 private int delayMilliseconds = 33 ; //擴(kuò)散延遲間隔,越大擴(kuò)散越慢 private List<Integer> spreadRadius = new ArrayList<>(); //擴(kuò)散圓層級數(shù),元素為擴(kuò)散的距離 private List<Integer> alphas = new ArrayList<>(); //對應(yīng)每層圓的透明度 |
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" /> <!--擴(kuò)散圓顏色--> <attr name= "spread_spread_color" format= "color" /> <!--擴(kuò)散間距--> <attr name= "spread_distance" format= "integer" /> <!--擴(kuò)散最大半徑--> <attr name= "spread_max_radius" format= "integer" /> <!--擴(kuò)散延遲間隔--> <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 ); //最開始不透明且擴(kuò)散距離為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); //繪制擴(kuò)散的圓 canvas.drawCircle(centerX, centerY, radius + width, spreadPaint); //每次擴(kuò)散圓半徑遞增,圓透明度遞減 if (alpha > 0 && width < 300 ) { alpha = alpha - distance > 0 ? alpha - distance : 1 ; alphas.set(i, alpha); spreadRadius.set(i, width + distance); } } //當(dāng)最外層擴(kuò)散圓半徑達(dá)到最大半徑時添加新擴(kuò)散圓 if (spreadRadius.get(spreadRadius.size() - 1 ) > maxRadius) { spreadRadius.add( 0 ); alphas.add( 255 ); } //超過8個擴(kuò)散圓,刪除最先繪制的圓,即最外層的圓 if (spreadRadius.size() >= 8 ) { alphas.remove( 0 ); spreadRadius.remove( 0 ); } //中間的圓 canvas.drawCircle(centerX, centerY, radius, centerPaint); //TODO 可以在中間圓繪制文字或者圖片 //延遲更新,達(dá)到擴(kuò)散視覺差效果 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" /> |
效果圖
中心圓處可以自定義寫文字,畫圖片等等...
動畫實現(xiàn)
思路分析:通過動畫實現(xiàn),imageView不停做動畫縮放+漸變
最中心的imageView保持不變
中間一層imageView從原始放大到1.4倍,同時從不透明變?yōu)榘胪该?/p>
最外層的imageView從1.4倍放大到1.8倍,同時從半透明變?yōu)槿该?/p>
利用shape畫一個圓,作為動畫基礎(chǔ)視圖
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的效果更好點,動畫實現(xiàn)起來更方便點。
兩種方式實現(xiàn)的擴(kuò)散效果介紹完畢,具體項目里還是要按需變動的。
總結(jié)
以上所述是小編給大家介紹的Android 實現(xiàn)圓圈擴(kuò)散水波動畫效果兩種方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對服務(wù)器之家網(wǎng)站的支持!
原文鏈接:https://www.cnblogs.com/taixiang/archive/2018/05/27/9095464.html