Skip to content

Commit 79385ef

Browse files
committed
Add Code Source
1 parent c36947f commit 79385ef

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/**
2+
* Author: GcsSloop
3+
* <p>
4+
* Created Date: 16/5/31
5+
* <p>
6+
* Copyright (C) 2016 GcsSloop.
7+
* <p>
8+
* GitHub: https://github.com/GcsSloop
9+
*/
10+
public class SearchView extends View {
11+
12+
// 画笔
13+
private Paint mPaint;
14+
15+
// View 宽高
16+
private int mViewWidth;
17+
private int mViewHeight;
18+
19+
// 这个视图拥有的状态
20+
public static enum State {
21+
NONE,
22+
STARTING,
23+
SEARCHING,
24+
ENDING
25+
}
26+
27+
// 当前的状态(非常重要)
28+
private State mCurrentState = State.NONE;
29+
30+
// 放大镜与外部圆环
31+
private Path path_srarch;
32+
private Path path_circle;
33+
34+
// 测量Path 并截取部分的工具
35+
private PathMeasure mMeasure;
36+
37+
// 默认的动效周期 2s
38+
private int defaultDuration = 2000;
39+
40+
// 控制各个过程的动画
41+
private ValueAnimator mStartingAnimator;
42+
private ValueAnimator mSearchingAnimator;
43+
private ValueAnimator mEndingAnimator;
44+
45+
// 动画数值(用于控制动画状态,因为同一时间内只允许有一种状态出现,具体数值处理取决于当前状态)
46+
private float mAnimatorValue = 0;
47+
48+
// 动效过程监听器
49+
private ValueAnimator.AnimatorUpdateListener mUpdateListener;
50+
private Animator.AnimatorListener mAnimatorListener;
51+
52+
// 用于控制动画状态转换
53+
private Handler mAnimatorHandler;
54+
55+
// 判断是否已经搜索结束
56+
private boolean isOver = false;
57+
58+
private int count = 0;
59+
60+
public SearchView(Context context) {
61+
super(context);
62+
63+
initPaint();
64+
65+
initPath();
66+
67+
initListener();
68+
69+
initHandler();
70+
71+
initAnimator();
72+
73+
// 进入开始动画
74+
mCurrentState = State.STARTING;
75+
mStartingAnimator.start();
76+
77+
}
78+
79+
private void initPaint() {
80+
mPaint = new Paint();
81+
mPaint.setStyle(Paint.Style.STROKE);
82+
mPaint.setColor(Color.WHITE);
83+
mPaint.setStrokeWidth(15);
84+
mPaint.setStrokeCap(Paint.Cap.ROUND);
85+
mPaint.setAntiAlias(true);
86+
}
87+
88+
private void initPath() {
89+
path_srarch = new Path();
90+
path_circle = new Path();
91+
92+
mMeasure = new PathMeasure();
93+
94+
// 注意,不要到360度,否则内部会自动优化,测量不能取到需要的数值
95+
RectF oval1 = new RectF(-50, -50, 50, 50); // 放大镜圆环
96+
path_srarch.addArc(oval1, 45, 359.9f);
97+
98+
RectF oval2 = new RectF(-100, -100, 100, 100); // 外部圆环
99+
path_circle.addArc(oval2, 45, -359.9f);
100+
101+
float[] pos = new float[2];
102+
103+
mMeasure.setPath(path_circle, false); // 放大镜把手的位置
104+
mMeasure.getPosTan(0, pos, null);
105+
106+
path_srarch.lineTo(pos[0], pos[1]); // 放大镜把手
107+
108+
Log.i("TAG", "pos=" + pos[0] + ":" + pos[1]);
109+
}
110+
111+
private void initListener() {
112+
mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
113+
@Override
114+
public void onAnimationUpdate(ValueAnimator animation) {
115+
mAnimatorValue = (float) animation.getAnimatedValue();
116+
invalidate();
117+
}
118+
};
119+
120+
mAnimatorListener = new Animator.AnimatorListener() {
121+
@Override
122+
public void onAnimationStart(Animator animation) {
123+
124+
}
125+
126+
@Override
127+
public void onAnimationEnd(Animator animation) {
128+
// getHandle发消息通知动画状态更新
129+
mAnimatorHandler.sendEmptyMessage(0);
130+
}
131+
132+
@Override
133+
public void onAnimationCancel(Animator animation) {
134+
135+
}
136+
137+
@Override
138+
public void onAnimationRepeat(Animator animation) {
139+
140+
}
141+
};
142+
}
143+
144+
private void initHandler() {
145+
mAnimatorHandler = new Handler() {
146+
@Override
147+
public void handleMessage(Message msg) {
148+
super.handleMessage(msg);
149+
switch (mCurrentState) {
150+
case STARTING:
151+
// 从开始动画转换好搜索动画
152+
isOver = false;
153+
mCurrentState = State.SEARCHING;
154+
mStartingAnimator.removeAllListeners();
155+
mSearchingAnimator.start();
156+
break;
157+
case SEARCHING:
158+
if (!isOver) { // 如果搜索未结束 则继续执行搜索动画
159+
mSearchingAnimator.start();
160+
Log.e("Update", "RESTART");
161+
162+
count++;
163+
if (count>2){ // count大于2则进入结束状态
164+
isOver = true;
165+
}
166+
} else { // 如果搜索已经结束 则进入结束动画
167+
mCurrentState = State.ENDING;
168+
mEndingAnimator.start();
169+
}
170+
break;
171+
case ENDING:
172+
// 从结束动画转变为无状态
173+
mCurrentState = State.NONE;
174+
break;
175+
}
176+
}
177+
};
178+
}
179+
180+
private void initAnimator() {
181+
mStartingAnimator = ValueAnimator.ofFloat(0, 1).setDuration(defaultDuration);
182+
mSearchingAnimator = ValueAnimator.ofFloat(0, 1).setDuration(defaultDuration);
183+
mEndingAnimator = ValueAnimator.ofFloat(1, 0).setDuration(defaultDuration);
184+
185+
mStartingAnimator.addUpdateListener(mUpdateListener);
186+
mSearchingAnimator.addUpdateListener(mUpdateListener);
187+
mEndingAnimator.addUpdateListener(mUpdateListener);
188+
189+
mStartingAnimator.addListener(mAnimatorListener);
190+
mSearchingAnimator.addListener(mAnimatorListener);
191+
mEndingAnimator.addListener(mAnimatorListener);
192+
}
193+
194+
195+
@Override
196+
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
197+
super.onSizeChanged(w, h, oldw, oldh);
198+
mViewWidth = w;
199+
mViewHeight = h;
200+
}
201+
202+
@Override
203+
protected void onDraw(Canvas canvas) {
204+
super.onDraw(canvas);
205+
206+
drawSearch(canvas);
207+
}
208+
209+
private void drawSearch(Canvas canvas) {
210+
211+
mPaint.setColor(Color.WHITE);
212+
213+
214+
canvas.translate(mViewWidth / 2, mViewHeight / 2);
215+
216+
canvas.drawColor(Color.parseColor("#0082D7"));
217+
218+
switch (mCurrentState) {
219+
case NONE:
220+
canvas.drawPath(path_srarch, mPaint);
221+
break;
222+
case STARTING:
223+
mMeasure.setPath(path_srarch, false);
224+
Path dst = new Path();
225+
mMeasure.getSegment(mMeasure.getLength() * mAnimatorValue, mMeasure.getLength(), dst, true);
226+
canvas.drawPath(dst, mPaint);
227+
break;
228+
case SEARCHING:
229+
mMeasure.setPath(path_circle, false);
230+
Path dst2 = new Path();
231+
float stop = mMeasure.getLength() * mAnimatorValue;
232+
float start = (float) (stop - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * 200f));
233+
mMeasure.getSegment(start, stop, dst2, true);
234+
canvas.drawPath(dst2, mPaint);
235+
break;
236+
case ENDING:
237+
mMeasure.setPath(path_srarch, false);
238+
Path dst3 = new Path();
239+
mMeasure.getSegment(mMeasure.getLength() * mAnimatorValue, mMeasure.getLength(), dst3, true);
240+
canvas.drawPath(dst3, mPaint);
241+
break;
242+
}
243+
}
244+
}

0 commit comments

Comments
 (0)