編輯:關於Android編程
介紹:水波紋散開效果的控件在 App 裡面還是比較常見的,例如 網易雲音樂歌曲識別,附近搜索場景。
看下實現的效果:

實現思路: 先將最大圓半徑與最小圓半徑間距分成幾等份,從內到外,Paint 透明度依次遞減,繪制出同心圓,然後不斷的改變這些同心圓的半徑大小,延遲一定時間重繪,便達到了想外散開的動畫效果了。
public class WaveView extends View {
private static final String TAG = "WaveView";
private int waveColor;
private int waveCount;
private Bitmap waveCenterIcon;
private Paint paint;
private int mWidth;
private int mHeight;
private int centerX;
private int centerY;
private float radius; // 最外圓半徑,即最大半徑
private float innerRadius; // 最內圓的半徑,即最小半徑
private int centerIconWidth;
private int centerIconHeight;
private float[] waveDegreeArr;
private boolean isRunning = true;
public WaveView(Context context) {
this(context, null);
}
public WaveView(Context context, AttributeSet attrs) {
super(context, attrs);
readAttrs(context, attrs);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(waveColor);
paint.setStyle(Paint.Style.FILL);
waveDegreeArr = new float[waveCount];
// 設置中間 drawable 點擊事件
}
private void readAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaveView);
try {
waveColor = typedArray.getColor(R.styleable.WaveView_waveColor, 0xffff0000);
waveCount = typedArray.getInt(R.styleable.WaveView_waveCount, 4);
Drawable centerDrawable = typedArray.getDrawable(R.styleable.WaveView_waveCenterIcon);
waveCenterIcon = ((BitmapDrawable) centerDrawable).getBitmap();
} catch (Exception e) {
} finally {
typedArray.recycle();
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
centerX = mWidth / 2;
centerY = mHeight / 2;
radius = Math.min(mWidth, mHeight) / 2f;
centerIconWidth = waveCenterIcon.getWidth();
centerIconHeight = waveCenterIcon.getHeight();
innerRadius = Math.max(centerIconWidth, centerIconHeight) * 1.2f;
for (int i = 0; i < waveCount; i++) {
waveDegreeArr[i] = innerRadius + (radius - innerRadius) / waveCount * i;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.AT_MOST) {
widthMeasureSpec = MeasureSpec.makeMeasureSpec(dp2Px(120), MeasureSpec.EXACTLY);
}
if (heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(dp2Px(120), MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
drawWave(canvas);
drawCenterCircle(canvas);
drawCenterIcon(canvas);
}
private void drawCenterCircle(Canvas canvas) {
canvas.drawCircle(centerX, centerY, innerRadius, paint);
}
private void drawWave(Canvas canvas) {
for (int i = 0; i < waveCount; i++) {
paint.setAlpha((int) (255 - 255 * waveDegreeArr[i] / radius));
canvas.drawCircle(centerX, centerY, waveDegreeArr[i], paint);
}
for (int i = 0; i < waveDegreeArr.length; i++) {
if ((waveDegreeArr[i] += 4) > radius) {
waveDegreeArr[i] = innerRadius;
}
}
if (isRunning) {
postInvalidateDelayed(50);
}
}
private void drawCenterIcon(Canvas canvas) {
paint.setAlpha(255);
int left = centerX - centerIconWidth / 2;
int top = centerY - centerIconHeight / 2;
canvas.drawBitmap(waveCenterIcon, left, top, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 處理事件邏輯
handleEvent(event);
return true;
}
return true;
}
private void handleEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
Log.i(TAG, "handleEvent: " + "(" + touchX + "," + touchY + ")");
float distanceX = Math.abs(touchX - centerX);
float distanceY = Math.abs(touchY - centerY);
// 計算觸摸點距離中心點的距離
float distance = (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY);
// 當點擊的點距離中心點距離小於最內圓半徑時,認為是點擊有效,否則無效
if (distance < innerRadius) {
if (listener != null) {
listener.onCenterWaveClick();
}
}
}
OnCenterWaveClickListener listener;
public interface OnCenterWaveClickListener {
void onCenterWaveClick();
}
public void setOnCenterWaveClickListener(OnCenterWaveClickListener listener) {
this.listener = listener;
}
public void toggle() {
isRunning = !isRunning;
invalidate();
}
public boolean isWaveRunning() {
return isRunning;
}
private int dp2Px(int dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, getResources().getDisplayMetrics());
}
}
github地址:https://github.com/xing16/WaveView
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
Android逆向分析案例——某酒店APP的登陸請求分析
為了練練手,增長逆向分析的知識,本次博客打算分析一下某酒店APP的登陸請求。這次的逆向分析還是以網絡請求為例,通過分析其登陸請求數據的加解密原理,將請求數據從密文轉換成明
Android 7.1 快捷方式 Shortcuts
前些天就看到相關內容了,但是最近吸毒比較深(wow),所以沒有緊跟潮流,今天補一篇。https://github.com/ddwhan0123/Useful-Open-S
android ListView 實現3級節點 (可拓展N級)
ListView實現二級節點想必大家都知道可以用ExpandableListView 就可以輕松實現,但是要實現3級甚至多級菜單怎麼實現呢? 再利用ExpandableL
android 從源碼分析view事件分發機制
一直對View的事件分發機制不太明白,在項目開發中也遇到過,在網上也找到一些解決問題方法,但是其原理並不太了解,現在辭職了有時間,今天寫寫View的事件分發,結合andr