標籤:change int type parent get rem 放大 odi 最大
原文連結 https://mp.weixin.qq.com/s/M19tp_ShOO6esKdozi7Nlg
兩種方式實作類別似水波擴散效果,先為敬
- 自訂view實現
- 動畫實現
自訂view實現
思路分析:通過canvas畫圓,每次改變圓半徑和透明度,當半徑達到一定程度,再次從中心開始繪圓,達到不同層級的效果,通過不斷繪製達到view擴散效果
private Paint centerPaint; //中心圓paintprivate int radius = 100; //中心圓半徑private Paint spreadPaint; //擴散圓paintprivate float centerX;//圓心xprivate float centerY;//圓心yprivate int distance = 5; //每次圓遞增間距private int maxRadius = 80; //最大圓半徑private int delayMilliseconds = 33;//擴散延遲間隔,越大擴散越慢private List<Integer> spreadRadius = new ArrayList<>();//擴散圓層級數,元素為擴散的距離private List<Integer> alphas = new ArrayList<>();//對應每層圓的透明度
style檔案裡自訂屬性
<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>
初始化
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);}
確定圓心位置
@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //圓心位置 centerX = w / 2; centerY = h / 2;}
自訂view的繪製
@Overrideprotected 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樣式
<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畫一個圓,作為動畫基礎視圖
<?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>
布局視圖
<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
的動畫
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
的動畫
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的效果更好點,動畫實現起來更方便點。
兩種方式實現的擴散效果介紹完畢,具體項目裡還是要按需變動的。
歡迎關注我的部落格:https://blog.manjiexiang.cn/
同時歡迎關注公眾號
Android 兩種方式實作類別似水波擴散效果