1
1
package com .chiemy .cardview .view ;
2
2
3
3
import android .content .Context ;
4
- import android .content .res .TypedArray ;
5
4
import android .database .DataSetObserver ;
6
5
import android .graphics .Rect ;
7
6
import android .util .AttributeSet ;
7
+ import android .util .Log ;
8
8
import android .util .SparseArray ;
9
9
import android .view .MotionEvent ;
10
10
import android .view .View ;
11
11
import android .view .ViewConfiguration ;
12
+ import android .view .ViewGroup ;
13
+ import android .view .View .MeasureSpec ;
12
14
import android .view .animation .AccelerateInterpolator ;
13
15
import android .widget .FrameLayout ;
14
16
import android .widget .ListAdapter ;
15
17
16
- import com .chiemy .cardview .Utils ;
17
18
import com .nineoldandroids .animation .Animator ;
18
19
import com .nineoldandroids .animation .AnimatorListenerAdapter ;
19
20
import com .nineoldandroids .view .ViewHelper ;
20
21
import com .nineoldandroids .view .ViewPropertyAnimator ;
21
22
22
23
/**
23
24
* @author chiemy
24
- *
25
+ *
25
26
*/
26
- public class CardView extends FrameLayout {
27
+ public class CardView extends FrameLayout {
27
28
private static final int ITEM_SPACE = 40 ;
28
29
private static final int DEF_MAX_VISIBLE = 4 ;
29
- private static final int PADDING_TOP = 20 ;
30
-
30
+
31
31
private int mMaxVisible = DEF_MAX_VISIBLE ;
32
32
private int itemSpace = ITEM_SPACE ;
33
-
33
+
34
34
private float mTouchSlop ;
35
35
private ListAdapter mListAdapter ;
36
36
private int mNextAdapterPosition ;
37
37
private SparseArray <View > viewHolder = new SparseArray <View >();
38
38
private OnCardClickListener mListener ;
39
39
private int topPosition ;
40
40
private Rect topRect ;
41
-
42
- public interface OnCardClickListener {
43
- void onCardClick (View view ,int position );
41
+
42
+ public interface OnCardClickListener {
43
+ void onCardClick (View view , int position );
44
44
}
45
-
45
+
46
46
public CardView (Context context , AttributeSet attrs , int defStyle ) {
47
47
super (context , attrs , defStyle );
48
48
init ();
@@ -57,35 +57,35 @@ public CardView(Context context) {
57
57
super (context );
58
58
init ();
59
59
}
60
-
60
+
61
61
private void init () {
62
62
topRect = new Rect ();
63
63
ViewConfiguration con = ViewConfiguration .get (getContext ());
64
64
mTouchSlop = con .getScaledTouchSlop ();
65
65
}
66
-
66
+
67
67
public void setMaxVisibleCount (int count ) {
68
68
mMaxVisible = count ;
69
69
}
70
-
70
+
71
71
public int getMaxVisibleCount () {
72
- return mMaxVisible ;
72
+ return mMaxVisible ;
73
73
}
74
-
74
+
75
75
public void setItemSpace (int itemSpace ) {
76
76
this .itemSpace = itemSpace ;
77
77
}
78
-
78
+
79
79
public int getItemSpace () {
80
80
return itemSpace ;
81
81
}
82
-
82
+
83
83
public ListAdapter getAdapter () {
84
84
return mListAdapter ;
85
85
}
86
-
86
+
87
87
public void setAdapter (ListAdapter adapter ) {
88
- if (mListAdapter != null ){
88
+ if (mListAdapter != null ) {
89
89
mListAdapter .unregisterDataSetObserver (mDataSetObserver );
90
90
}
91
91
mNextAdapterPosition = 0 ;
@@ -94,56 +94,93 @@ public void setAdapter(ListAdapter adapter) {
94
94
removeAllViews ();
95
95
ensureFull ();
96
96
}
97
-
97
+
98
98
public void setOnCardClickListener (OnCardClickListener listener ) {
99
99
mListener = listener ;
100
100
}
101
-
101
+
102
102
private void ensureFull () {
103
103
while (mNextAdapterPosition < mListAdapter .getCount ()
104
104
&& getChildCount () < mMaxVisible ) {
105
105
int index = mNextAdapterPosition % mMaxVisible ;
106
106
View convertView = viewHolder .get (index );
107
- final View view = mListAdapter .getView (mNextAdapterPosition , convertView , this );
107
+ final View view = mListAdapter .getView (mNextAdapterPosition ,
108
+ convertView , this );
108
109
view .setOnClickListener (null );
110
+ // view.setOnTouchListener(null);
109
111
viewHolder .put (index , view );
110
-
111
- //添加剩余的View时,始终处在最后
112
+
113
+ // 添加剩余的View时,始终处在最后
112
114
index = Math .min (mNextAdapterPosition , mMaxVisible - 1 );
113
- ViewHelper .setScaleX (view , ((mMaxVisible - index - 1 )/ (float )mMaxVisible )* 0.2f + 0.8f );
114
- int topMargin = (mMaxVisible - index - 1 )* itemSpace + PADDING_TOP ;
115
+ ViewHelper .setScaleX (view ,((mMaxVisible - index - 1 ) / (float ) mMaxVisible ) * 0.2f + 0.8f );
116
+ int topMargin = (mMaxVisible - index - 1 ) * itemSpace ;
115
117
ViewHelper .setTranslationY (view , topMargin );
116
118
ViewHelper .setAlpha (view , mNextAdapterPosition == 0 ? 1 : 0.5f );
117
-
119
+
118
120
LayoutParams params = (LayoutParams ) view .getLayoutParams ();
119
- if (params == null ){
120
- params = new LayoutParams (LayoutParams .MATCH_PARENT , LayoutParams .WRAP_CONTENT );
121
+ if (params == null ) {
122
+ params = new LayoutParams (LayoutParams .MATCH_PARENT ,
123
+ LayoutParams .WRAP_CONTENT );
121
124
}
122
- addViewInLayout (view ,0 , params , true );
123
-
125
+ addViewInLayout (view , 0 , params );
126
+
124
127
mNextAdapterPosition += 1 ;
125
128
}
126
- requestLayout ();
129
+ // requestLayout();
130
+ }
131
+
132
+ @ Override
133
+ protected void onMeasure (int widthMeasureSpec , int heightMeasureSpec ) {
134
+ int widthMode = MeasureSpec .getMode (widthMeasureSpec );
135
+ int heightMode = MeasureSpec .getMode (heightMeasureSpec );
136
+ int widthSize = MeasureSpec .getSize (widthMeasureSpec );
137
+ int heightSize = MeasureSpec .getSize (heightMeasureSpec );
138
+
139
+ int childCount = getChildCount ();
140
+ int maxHeight = 0 ;
141
+ int maxWidth = 0 ;
142
+ for (int i = 0 ; i < childCount ; i ++) {
143
+ View child = getChildAt (i );
144
+ this .measureChild (child , widthMeasureSpec , heightMeasureSpec );
145
+ int height = child .getMeasuredHeight ();
146
+ int width = child .getMeasuredWidth ();
147
+ if (height > maxHeight ) {
148
+ maxHeight = height ;
149
+ }
150
+ if (width > maxWidth ) {
151
+ maxWidth = width ;
152
+ }
153
+ }
154
+ int desireWidth = widthSize ;
155
+ int desireHeight = heightSize ;
156
+ if (widthMode == MeasureSpec .AT_MOST ) {
157
+ desireWidth = maxWidth + getPaddingLeft () + getPaddingRight ();
158
+ }
159
+ if (heightMode == MeasureSpec .AT_MOST ) {
160
+ desireHeight = maxHeight + (mMaxVisible - 1 ) * itemSpace + getPaddingTop () + getPaddingBottom ();
161
+ }
162
+ setMeasuredDimension (desireWidth , desireHeight );
127
163
}
128
-
164
+
129
165
@ Override
130
166
protected void onLayout (boolean changed , int left , int top , int right ,
131
167
int bottom ) {
132
168
super .onLayout (changed , left , top , right , bottom );
133
- View topView = getChildAt (getChildCount ()- 1 );
134
- if (topView != null ){
169
+ View topView = getChildAt (getChildCount () - 1 );
170
+ if (topView != null ) {
135
171
topView .setOnClickListener (listener );
136
172
}
137
173
}
138
-
139
- float downX ,downY ;
174
+
175
+ float downX , downY ;
140
176
boolean remove = false ;
177
+
141
178
@ Override
142
179
public boolean onTouchEvent (MotionEvent event ) {
143
- switch (event .getAction ()){
180
+ switch (event .getAction ()) {
144
181
case MotionEvent .ACTION_MOVE :
145
- if (!remove ){
146
- if (goDown ()){
182
+ if (!remove ) {
183
+ if (goDown ()) {
147
184
downY = -1 ;
148
185
remove = true ;
149
186
}
@@ -152,98 +189,103 @@ public boolean onTouchEvent(MotionEvent event) {
152
189
}
153
190
return super .onTouchEvent (event );
154
191
}
155
-
192
+
156
193
/**
157
194
* 下移所有视图
158
195
*/
159
196
private boolean goDown () {
160
197
final View topView = getChildAt (getChildCount () - 1 );
161
- //topView.getHitRect(topRect); 在4.3以前有bug,用以下方法代替
198
+ // topView.getHitRect(topRect); 在4.3以前有bug,用以下方法代替
162
199
topRect = getHitRect (topRect , topView );
163
- //如果按下的位置不在顶部视图上,则不移动
164
- if (!topRect .contains ((int )downX , (int )downY )){
200
+ // 如果按下的位置不在顶部视图上,则不移动
201
+ if (!topRect .contains ((int ) downX , (int ) downY )) {
165
202
return false ;
166
203
}
167
- ViewPropertyAnimator anim = ViewPropertyAnimator .animate (topView )
168
- .translationY (ViewHelper .getTranslationY (topView ) + topView .getHeight ())
169
- .alpha (0 ).scaleX (1 )
170
- .setListener (null )
171
- .setDuration (200 );
204
+ ViewPropertyAnimator anim = ViewPropertyAnimator
205
+ .animate (topView )
206
+ .translationY (
207
+ ViewHelper .getTranslationY (topView )
208
+ + topView .getHeight ()).alpha (0 ).scaleX (1 )
209
+ .setListener (null ).setDuration (200 );
172
210
anim .setListener (new AnimatorListenerAdapter () {
173
211
@ Override
174
212
public void onAnimationEnd (Animator animation ) {
175
213
removeView (topView );
176
214
ensureFull ();
177
215
final int count = getChildCount ();
178
- for (int i = 0 ; i < count ; i ++){
216
+ for (int i = 0 ; i < count ; i ++) {
179
217
final View view = getChildAt (i );
180
- float scaleX = ViewHelper .getScaleX (view ) + ((float )1 /mMaxVisible )*0.2f ;
181
- float tranlateY = ViewHelper .getTranslationY (view ) + itemSpace ;
182
- if (i == count - 1 ){
218
+ float scaleX = ViewHelper .getScaleX (view )
219
+ + ((float ) 1 / mMaxVisible ) * 0.2f ;
220
+ float tranlateY = ViewHelper .getTranslationY (view )
221
+ + itemSpace ;
222
+ if (i == count - 1 ) {
183
223
bringToTop (view );
184
- }else {
185
- if ((count == mMaxVisible && i != 0 ) || count < mMaxVisible ){
186
- ViewPropertyAnimator .animate (view )
187
- .translationY (tranlateY )
188
- .setInterpolator (new AccelerateInterpolator ())
189
- .setListener (null )
190
- .scaleX (scaleX ).setDuration (200 );
224
+ } else {
225
+ if ((count == mMaxVisible && i != 0 )
226
+ || count < mMaxVisible ) {
227
+ ViewPropertyAnimator
228
+ .animate (view )
229
+ .translationY (tranlateY )
230
+ .setInterpolator (
231
+ new AccelerateInterpolator ())
232
+ .setListener (null ).scaleX (scaleX )
233
+ .setDuration (200 );
191
234
}
192
235
}
193
236
}
194
237
}
195
238
});
196
239
return true ;
197
240
}
198
-
241
+
199
242
/**
200
243
* 将下一个视图移到前边
244
+ *
201
245
* @param view
202
246
*/
203
247
private void bringToTop (final View view ) {
204
- float scaleX = ViewHelper .getScaleX (view ) + ((float )1 /mMaxVisible )*0.2f ;
248
+ float scaleX = ViewHelper .getScaleX (view ) + ((float ) 1 / mMaxVisible )
249
+ * 0.2f ;
205
250
float tranlateY = ViewHelper .getTranslationY (view ) + itemSpace ;
206
- ViewPropertyAnimator .animate (view )
207
- .translationY (tranlateY )
208
- .scaleX (scaleX )
209
- .setDuration (200 )
210
- .alpha (1 ).setInterpolator (new AccelerateInterpolator ())
211
- .setListener (null )
212
- .setListener (new AnimatorListenerAdapter () {
213
- public void onAnimationEnd (Animator animation ) {
214
- topPosition ++;
215
- remove = false ;
216
- }
217
- });
251
+ ViewPropertyAnimator .animate (view ).translationY (tranlateY )
252
+ .scaleX (scaleX ).setDuration (200 ).alpha (1 )
253
+ .setInterpolator (new AccelerateInterpolator ())
254
+ .setListener (null ).setListener (new AnimatorListenerAdapter () {
255
+ public void onAnimationEnd (Animator animation ) {
256
+ topPosition ++;
257
+ remove = false ;
258
+ }
259
+ });
218
260
}
219
-
220
-
261
+
221
262
@ Override
222
263
public boolean onInterceptTouchEvent (MotionEvent ev ) {
223
264
float currentY = ev .getY ();
224
- switch (ev .getAction ()){
265
+ switch (ev .getAction ()) {
225
266
case MotionEvent .ACTION_DOWN :
226
267
downX = ev .getX ();
227
268
downY = ev .getY ();
228
269
break ;
229
270
case MotionEvent .ACTION_MOVE :
230
271
float distance = currentY - downY ;
231
- if (distance > mTouchSlop ){
272
+ if (distance > mTouchSlop ) {
232
273
return true ;
233
274
}
234
275
break ;
235
276
}
236
- return super . onInterceptTouchEvent ( ev ) ;
277
+ return false ;
237
278
}
238
-
239
- public static Rect getHitRect (Rect rect ,View child ){
279
+
280
+ public static Rect getHitRect (Rect rect , View child ) {
240
281
rect .left = child .getLeft ();
241
282
rect .right = child .getRight ();
242
283
rect .top = (int ) (child .getTop () + ViewHelper .getTranslationY (child ));
243
- rect .bottom = (int ) (child .getBottom () + ViewHelper .getTranslationY (child ));
284
+ rect .bottom = (int ) (child .getBottom () + ViewHelper
285
+ .getTranslationY (child ));
244
286
return rect ;
245
287
}
246
-
288
+
247
289
private final DataSetObserver mDataSetObserver = new DataSetObserver () {
248
290
@ Override
249
291
public void onChanged () {
@@ -255,11 +297,11 @@ public void onInvalidated() {
255
297
super .onInvalidated ();
256
298
}
257
299
};
258
-
300
+
259
301
private OnClickListener listener = new OnClickListener () {
260
302
@ Override
261
303
public void onClick (View v ) {
262
- if (mListener != null ){
304
+ if (mListener != null ) {
263
305
mListener .onCardClick (v , topPosition );
264
306
}
265
307
}
0 commit comments