CirclePoint.java
6.61 KB
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package com.cnlive.goldenline.ui.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import com.cnlive.goldenline.R;
public class CirclePoint extends View {
private float normalRadius = 3; //普通点的半径
private float selectedRadius = 4; //选择点的半径
private int normalRadiusColor = 0xDD333333; //普通点的颜色
private int selectedRadiusColor = 0xAAFF0000; //选中点的颜色
private float dotPadding = 10; //每个点之间的距离
private boolean isStroke = true; //是否是空心圆
private float normalStrokeWidth = 1; //空心圆的线宽
private boolean isBlink = false; //是否是以闪现的方式滑动
private int dotNum; //要展示的点的数量,默认按照Adapter的Count,如果设置Num,以设置的为准
private Paint mNormalPaint;
private Paint mSelectedPaint;
private float mCx; //第一个圆心的X坐标
private float mCy; //第一个圆心的Y坐标
private ViewPager mViewPager;
private MyOnPageChangeListener mListener;
private float mTranslationX; //移动的偏移量
private boolean isDetached; //是否被回收过
public CirclePoint(Context context) {
this(context, null);
}
public CirclePoint(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CirclePoint(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
normalRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, normalRadius, getResources().getDisplayMetrics());
selectedRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, selectedRadius, getResources().getDisplayMetrics());
dotPadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dotPadding, getResources().getDisplayMetrics());
normalStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, normalStrokeWidth, getResources().getDisplayMetrics());
TypedArray a = getResources().obtainAttributes(attrs, R.styleable.CircleIndicator);
normalRadius = a.getDimension(R.styleable.CircleIndicator_ci_normalRadius, normalRadius);
selectedRadius = a.getDimension(R.styleable.CircleIndicator_ci_selectedRadius, selectedRadius);
normalRadiusColor = a.getColor(R.styleable.CircleIndicator_ci_normalRadiusColor, normalRadiusColor);
selectedRadiusColor = a.getColor(R.styleable.CircleIndicator_ci_selectedRadiusColor, selectedRadiusColor);
dotPadding = a.getDimension(R.styleable.CircleIndicator_ci_dotPadding, dotPadding);
isStroke = a.getBoolean(R.styleable.CircleIndicator_ci_isStroke, isStroke);
normalStrokeWidth = a.getDimension(R.styleable.CircleIndicator_ci_normalStrokeWidth, normalStrokeWidth);
isBlink = a.getBoolean(R.styleable.CircleIndicator_ci_isBlink, isBlink);
a.recycle();
initPaint();
}
/**
* 各个方法执行顺序
* CircleIndicator
* onFinishInflate
* setXXX
* onSizeChanged
* onDraw
*/
private void initPaint() {
mNormalPaint = new Paint();
mNormalPaint.setAntiAlias(true);
mNormalPaint.setColor(normalRadiusColor);
mNormalPaint.setStrokeWidth(normalStrokeWidth);
if (isStroke)
mNormalPaint.setStyle(Paint.Style.STROKE);
else mNormalPaint.setStyle(Paint.Style.FILL);
mSelectedPaint = new Paint();
mSelectedPaint.setAntiAlias(true);
mSelectedPaint.setColor(selectedRadiusColor);
}
/**
* 计算第一个圆的圆心位置
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
float maxRadius = Math.max(normalRadius, selectedRadius);
float availableWidth = w - getPaddingLeft() - getPaddingRight();
float availableHeight = h - getPaddingTop() - getPaddingBottom();
float drawWidth = (dotNum - 1) * dotPadding + maxRadius * 2;
if (dotNum == 1)
drawWidth = maxRadius * 2;
if (dotNum <= 0)
drawWidth = 0;
mCx = (availableWidth - drawWidth) / 2 + maxRadius + getPaddingLeft();
mCy = availableHeight / 2 + getPaddingTop();
}
@Override
protected void onDraw(Canvas canvas) {
if (dotNum > 0) {
for (int i = 0; i < dotNum; i++) {
//绘制普通的圆
canvas.drawCircle(mCx + i * dotPadding, mCy, normalRadius, mNormalPaint);
}
//绘制选中的圆
canvas.drawCircle(mCx + mTranslationX, mCy, selectedRadius, mSelectedPaint);
}
}
public CirclePoint setViewPager(ViewPager viewPager) {
mViewPager = viewPager;
if (mViewPager == null || mViewPager.getAdapter() == null) {
throw new IllegalStateException("ViewPager不能为空或者ViewPager没有设置Adapter!");
}
dotNum = mViewPager.getAdapter().getCount();
mListener = new MyOnPageChangeListener();
mViewPager.addOnPageChangeListener(mListener);
return this;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (isDetached && mViewPager != null && mListener != null) {
mViewPager.addOnPageChangeListener(mListener);
isDetached = false;
}
}
/**
* 移除监听
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mViewPager != null && mListener != null)
mViewPager.removeOnPageChangeListener(mListener);
isDetached = true;
}
private class MyOnPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (dotNum > 0) {
if (isBlink) {
if (positionOffset == 0)
mTranslationX = position * dotPadding;
} else {
//对循环滑动的ViewPager做特殊的处理,滑动到边界的时候,继续滑动,小点应该返回
if ((position == dotNum - 1) && positionOffset > 0)
mTranslationX = (dotNum - 1) * dotPadding * (1 - positionOffset);
else
mTranslationX = (position + positionOffset) * dotPadding;
}
invalidate();
}
}
}
}