iterator = mCircleRadiusList.iterator();
131 | while (iterator.hasNext()) {
132 | Integer next = iterator.next();//获取这个值
133 | if (next >= mEndDiameter / 2) {//大于结束时半径并且包含则移除
134 | if (mCircleRadiusList.contains(next)) {
135 | iterator.remove();//使用迭代器来移除(否则有异常)
136 | }
137 | }
138 | }
139 | }
140 |
141 | /**
142 | * 开始动画
143 | */
144 | public void onStart() {
145 | mHandler.post(mRunnable);
146 | }
147 |
148 | /**
149 | * 开始动画
150 | *
151 | * @param loop
152 | */
153 | public void onStart(boolean loop) {
154 | isLoop = loop;
155 | mHandler.post(mRunnable);
156 | }
157 |
158 | /**
159 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
160 | */
161 | private int dp2px(float dpValue) {
162 | final float scale = mContext.getResources().getDisplayMetrics().density;
163 | return (int) (dpValue * scale + 0.5f);
164 | }
165 |
166 | /**
167 | * 设置RippleView开始显示时的直径
168 | *
169 | * @param startDiameterDp 直径(单位:dp)
170 | */
171 | public void setStartDiameter(int startDiameterDp) {
172 | mStartDiameter = dp2px(startDiameterDp);
173 | mCircleRadius = mStartDiameter / 2;
174 | mCircleRadiusList.clear();
175 | mCircleRadiusList.add(mCircleRadius);
176 | }
177 |
178 | /**
179 | * 设置RippleView结束显示时的直径
180 | *
181 | * @param endDiameter 直径(单位:px)
182 | */
183 | public void setEndDiameter(int endDiameter) {
184 | this.mRippleWidth = endDiameter;
185 | }
186 |
187 | /**
188 | * 设置RippleView线条的颜色
189 | *
190 | * @param rippleColor 颜色
191 | */
192 | public void setRippleColor(int rippleColor) {
193 | mCirclePaint.setColor(rippleColor);
194 | }
195 |
196 | /**
197 | * 设置是否循环显示动画
198 | *
199 | * @param loop
200 | */
201 | public void setLoop(boolean loop) {
202 | isLoop = loop;
203 | }
204 |
205 | public void setMode(Mode mode){
206 |
207 | }
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kince/rippleview/draw/HalfRippleView.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.kince.rippleview.draw;
5 |
6 | import android.content.Context;
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory;
9 | import android.graphics.Canvas;
10 | import android.graphics.Color;
11 | import android.graphics.Paint;
12 | import android.graphics.RectF;
13 | import android.os.Handler;
14 | import android.os.Message;
15 | import android.util.AttributeSet;
16 | import android.view.View;
17 |
18 | import com.kince.rippleview.R;
19 |
20 | /**
21 | * @author kince
22 | * @version v1.0.0
23 | * @category ²¨ÎÆ
24 | * @since 2014.8.9
25 | */
26 | public class HalfRippleView extends View {
27 |
28 | private int mScreenWidth;
29 | private int mScreenHeight;
30 |
31 | private Bitmap mRippleBitmap;
32 | private Paint mRipplePaint = new Paint();
33 |
34 | private int mBitmapWidth;
35 | private int mBitmapHeight;
36 |
37 | private boolean isStartRipple;
38 |
39 | private int heightPaddingTop;
40 | private int heightPaddingBottom;
41 | private int widthPaddingLeft;
42 | private int widthPaddingRight;
43 |
44 | private RectF mRect = new RectF();
45 |
46 | private int rippleFirstRadius = 0;
47 | private int rippleSecendRadius = -33;
48 | private int rippleThirdRadius = -66;
49 |
50 | private Paint textPaint = new Paint();
51 | private String mText = "µã»÷ÎÒ°É";
52 |
53 | private Handler handler = new Handler() {
54 | @Override
55 | public void handleMessage(Message msg) {
56 | // TODO Auto-generated method stub
57 | super.handleMessage(msg);
58 | invalidate();
59 | if (isStartRipple) {
60 | rippleFirstRadius++;
61 | if (rippleFirstRadius > 100) {
62 | rippleFirstRadius = 0;
63 | }
64 | rippleSecendRadius++;
65 | if (rippleSecendRadius > 100) {
66 | rippleSecendRadius = 0;
67 | }
68 | rippleThirdRadius++;
69 | if (rippleThirdRadius > 100) {
70 | rippleThirdRadius = 0;
71 | }
72 | sendEmptyMessageDelayed(0, 20);
73 | }
74 | }
75 | };
76 |
77 | /**
78 | * @param context
79 | */
80 | public HalfRippleView(Context context) {
81 | super(context);
82 | // TODO Auto-generated constructor stub
83 | init();
84 | }
85 |
86 | /**
87 | * @param context
88 | * @param attrs
89 | */
90 | public HalfRippleView(Context context, AttributeSet attrs) {
91 | super(context, attrs);
92 | // TODO Auto-generated constructor stub
93 | init();
94 | }
95 |
96 | /**
97 | * @param context
98 | * @param attrs
99 | * @param defStyleAttr
100 | */
101 | public HalfRippleView(Context context, AttributeSet attrs, int defStyleAttr) {
102 | super(context, attrs, defStyleAttr);
103 | // TODO Auto-generated constructor stub
104 | init();
105 | }
106 |
107 | private void init() {
108 | mRipplePaint.setColor(4961729);
109 | mRipplePaint.setAntiAlias(true);
110 | mRipplePaint.setStyle(Paint.Style.FILL);
111 |
112 | textPaint.setTextSize(30);
113 | textPaint.setAntiAlias(true);
114 | textPaint.setStyle(Paint.Style.FILL);
115 | textPaint.setColor(Color.WHITE);
116 |
117 | mRippleBitmap = BitmapFactory.decodeStream(getResources()
118 | .openRawResource(R.drawable.easy3d_ic_apply));
119 | mBitmapWidth = mRippleBitmap.getWidth();
120 | mBitmapHeight = mRippleBitmap.getHeight();
121 | }
122 |
123 | @Override
124 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
125 | // TODO Auto-generated method stub
126 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
127 | int mh = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
128 | int mw = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
129 | if (mBitmapWidth < 2 * mBitmapHeight) {
130 | mBitmapWidth = (2 * mBitmapHeight);
131 | }
132 | setMeasuredDimension(mBitmapWidth, mBitmapHeight);
133 | }
134 |
135 | @Override
136 | protected void onDraw(Canvas canvas) {
137 | // TODO Auto-generated method stub
138 | super.onDraw(canvas);
139 | if (isStartRipple) {
140 | float f1 = 3 * mBitmapHeight / 10;
141 | mRipplePaint.setAlpha(255);
142 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight,
143 | 7 * mBitmapHeight / 10, mRipplePaint);
144 | int i1 = (int) (220.0F - (220.0F - 0.0F) / 100.0F
145 | * rippleFirstRadius);
146 | mRipplePaint.setAlpha(i1);
147 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight, 7
148 | * mBitmapHeight / 10 + f1 * rippleFirstRadius / 100.0F,
149 | mRipplePaint);
150 | if (rippleSecendRadius >= 0) {
151 | int i3 = (int) (220.0F - (220.0F - 0.0F) / 100.0F
152 | * rippleSecendRadius);
153 | mRipplePaint.setAlpha(i3);
154 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight,
155 | 7 * mBitmapHeight / 10 + f1 * rippleSecendRadius
156 | / 100.0F, mRipplePaint);
157 | }
158 | if (rippleThirdRadius >= 0) {
159 | int i2 = (int) (220.0F - (220.0F - 0.0F) / 100.0F
160 | * rippleThirdRadius);
161 | mRipplePaint.setAlpha(i2);
162 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight, 7
163 | * mBitmapHeight / 10 + f1 * rippleThirdRadius / 100.0F,
164 | mRipplePaint);
165 | }
166 |
167 | }
168 | mRipplePaint.setAlpha(30);
169 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight, mBitmapHeight,
170 | mRipplePaint);
171 | mRipplePaint.setAlpha(120);
172 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight,
173 | 9 * mBitmapHeight / 10, mRipplePaint);
174 | mRipplePaint.setAlpha(180);
175 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight,
176 | 8 * mBitmapHeight / 10, mRipplePaint);
177 | mRipplePaint.setAlpha(255);
178 | canvas.drawCircle(mBitmapWidth / 2, mBitmapHeight,
179 | 7 * mBitmapHeight / 10, mRipplePaint);
180 | float length = textPaint.measureText(mText);
181 | canvas.drawText(mText, (mBitmapWidth - length) / 2,
182 | mBitmapHeight * 3 / 4, textPaint);
183 | }
184 |
185 | @Override
186 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
187 | // TODO Auto-generated method stub
188 | super.onSizeChanged(w, h, oldw, oldh);
189 | mScreenWidth = w;
190 | mScreenHeight = h;
191 | confirmSize();
192 | invalidate();
193 | }
194 |
195 | private void confirmSize() {
196 | int minScreenSize = Math.min(mScreenWidth, mScreenHeight);
197 | int widthOverSize = mScreenWidth - minScreenSize;
198 | int heightOverSize = mScreenHeight - minScreenSize;
199 | heightPaddingTop = (getPaddingTop() + heightOverSize / 2);
200 | heightPaddingBottom = (getPaddingBottom() + heightOverSize / 2);
201 | widthPaddingLeft = (getPaddingLeft() + widthOverSize / 2);
202 | widthPaddingRight = (getPaddingRight() + widthOverSize / 2);
203 |
204 | int width = getWidth();
205 | int height = getHeight();
206 |
207 | mRect = new RectF(widthPaddingLeft, heightPaddingTop, width
208 | - widthPaddingRight, height * 2 - heightPaddingBottom);
209 | }
210 |
211 | public void stratRipple() {
212 | isStartRipple = true;
213 | handler.sendEmptyMessage(0);
214 | }
215 |
216 | public void stopRipple() {
217 | isStartRipple = false;
218 | handler.removeMessages(0);
219 | }
220 |
221 | }
222 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kince/rippleview/draw/ObjectRippleView.java:
--------------------------------------------------------------------------------
1 | package com.kince.rippleview.draw;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.view.View;
9 | import android.view.animation.Interpolator;
10 | import android.view.animation.LinearInterpolator;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Iterator;
14 | import java.util.List;
15 |
16 | /**
17 | * 水波纹特效
18 | *
19 | * Created by fbchen2 on 2016/5/25.
20 | */
21 | public class ObjectRippleView extends View {
22 |
23 | private float mInitialRadius = 50; // 初始波纹半径
24 |
25 | private float mMaxRadius; // 最大波纹半径
26 |
27 | private long mDuration = 1000; // 一个波纹从创建到消失的持续时间
28 |
29 | private int mSpeed = 500; // 波纹的创建速度,每500ms创建一个
30 |
31 | private float mMaxRadiusRate = 0.85f;
32 |
33 | private boolean mMaxRadiusSet;
34 |
35 | private boolean mIsRunning;
36 |
37 | private long mLastCreateTime;
38 |
39 | private List mCircleList = new ArrayList();
40 |
41 | private Runnable mCreateCircle = new Runnable() {
42 |
43 | @Override
44 | public void run() {
45 | if (mIsRunning) {
46 | newCircle();
47 | postDelayed(mCreateCircle, mSpeed);
48 | }
49 | }
50 | };
51 |
52 | private Interpolator mInterpolator = new LinearInterpolator();
53 |
54 | private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
55 |
56 | public ObjectRippleView(Context context) {
57 | super(context);
58 | }
59 |
60 | public ObjectRippleView(Context context, AttributeSet attrs) {
61 | super(context, attrs);
62 | }
63 |
64 | public void setStyle(Paint.Style style) {
65 | mPaint.setStyle(style);
66 | }
67 |
68 | @Override
69 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
70 | if (!mMaxRadiusSet) {
71 | mMaxRadius = Math.min(w, h) * mMaxRadiusRate / 2.0f;
72 | }
73 | }
74 |
75 | public void setMaxRadiusRate(float maxRadiusRate) {
76 | mMaxRadiusRate = maxRadiusRate;
77 | }
78 |
79 | public void setColor(int color) {
80 | mPaint.setColor(color);
81 | }
82 |
83 | /**
84 | * 开始
85 | */
86 | public void start() {
87 | if (!mIsRunning) {
88 | mIsRunning = true;
89 | mCreateCircle.run();
90 | }
91 | }
92 |
93 | /**
94 | * 缓慢停止
95 | */
96 | public void stop() {
97 | mIsRunning = false;
98 | }
99 |
100 | /**
101 | * 立即停止
102 | */
103 | public void stopImmediately() {
104 | mIsRunning = false;
105 | mCircleList.clear();
106 | invalidate();
107 | }
108 |
109 | protected void onDraw(Canvas canvas) {
110 | Iterator iterator = mCircleList.iterator();
111 |
112 | while (iterator.hasNext()) {
113 | Circle circle = iterator.next();
114 | float radius = circle.getCurrentRadius();
115 |
116 | if (System.currentTimeMillis() - circle.mCreateTime < mDuration) {
117 | mPaint.setAlpha(circle.getAlpha());
118 | canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mPaint);
119 | } else {
120 | iterator.remove();
121 | }
122 | }
123 |
124 | if (mCircleList.size() > 0) {
125 | postInvalidateDelayed(10);
126 | }
127 | }
128 |
129 | public void setInitialRadius(float radius) {
130 | mInitialRadius = radius;
131 | }
132 |
133 | public void setDuration(long duration) {
134 | mDuration = duration;
135 | }
136 |
137 | public void setMaxRadius(float maxRadius) {
138 | mMaxRadius = maxRadius;
139 | mMaxRadiusSet = true;
140 | }
141 |
142 | public void setSpeed(int speed) {
143 | mSpeed = speed;
144 | }
145 |
146 | private void newCircle() {
147 | long currentTime = System.currentTimeMillis();
148 | if (currentTime - mLastCreateTime < mSpeed) {
149 | return;
150 | }
151 | Circle circle = new Circle();
152 | mCircleList.add(circle);
153 | invalidate();
154 | mLastCreateTime = currentTime;
155 | }
156 |
157 | private class Circle {
158 | private long mCreateTime;
159 |
160 | Circle() {
161 | mCreateTime = System.currentTimeMillis();
162 | }
163 |
164 | int getAlpha() {
165 | float percent = (getCurrentRadius() - mInitialRadius) / (mMaxRadius - mInitialRadius);
166 | return (int) (255 - mInterpolator.getInterpolation(percent) * 255);
167 | }
168 |
169 | float getCurrentRadius() {
170 | float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mDuration;
171 | Log.i("Kince","ss = "+(mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius)));
172 | return mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius);
173 | }
174 | }
175 |
176 | public void setInterpolator(Interpolator interpolator) {
177 | mInterpolator = interpolator;
178 | }
179 |
180 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/easy3d_ic_apply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-hdpi/easy3d_ic_apply.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/easy3d_ic_apply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-mdpi/easy3d_ic_apply.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/easy3d_ic_apply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-xhdpi/easy3d_ic_apply.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/easy3d_ic_apply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-xxhdpi/easy3d_ic_apply.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 | 64dp
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RippleView
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:2.3.1'
8 | }
9 | }
10 |
11 | allprojects {
12 | repositories {
13 | jcenter()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Apr 06 14:23:03 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/ripple.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HeroKince/RippleView/2c50679590d52ab161c866bb8643764c17f30fb7/ripple.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------