2424
2525public class StackViewLayout extends ViewGroup {
2626
27- public final static int MODEL_LEFT = 1 ;
28- public final static int MODEL_RIGHT = 2 ;
29- public final static int MODEL_TOP = 3 ;
30- public final static int MODEL_BOTTOM = 4 ;
27+ public final static int MODEL_LEFT = 0x01 ;
28+ public final static int MODEL_RIGHT = 0x02 ;
29+ public final static int MODEL_TOP = 0x04 ;
30+ public final static int MODEL_BOTTOM = 0x08 ;
3131
3232 private int stackSize = 3 ;
3333 private float aspectRatio = 0 ;
@@ -39,16 +39,19 @@ public class StackViewLayout extends ViewGroup{
3939 private int paddingY = 10 ;
4040 private int offsetY = 2 ;
4141
42- private int startX , startY ,current ;
42+ private float initX ,lastX ,initY , lastY ;
43+ private int current ;
4344 private VelocityTracker mVelocity ;
4445 private int mMaximumVelocity ;
4546 private int mTouchSlop ;
4647 private Scroller mScroller ;
4748 private ScheduledThreadPoolExecutor executor ;
4849 private StackViewAdapter adapter ;
49- private int mDuration = 500 ;
50+ private int mDuration = 600 ;
5051 private int mDelay = 3000 ;
5152 private int childWidthMeasure ,childHeightMeasure ;
53+
54+ private int dragModel ;
5255 private boolean mIsDragged = false ;
5356 private List <Integer > xSpace = new ArrayList <>(stackSize );
5457 private List <Integer > ySpace = new ArrayList <>(stackSize );
@@ -122,7 +125,6 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
122125
123126 @ Override
124127 protected void onLayout (boolean changed , int l , int t , int r , int b ) {
125- log ("onLayout " +changed +",l=" +l );
126128 int size = getOffsetXSize ();
127129 for (int i = getChildCount (); i <size +2 && size >0 ; i ++) {
128130 int cnt = adapter .getItemCount ();
@@ -175,17 +177,23 @@ public void computeScroll() {
175177 int dx = mScroller .getCurrX ();
176178 scrollDx (dx );
177179 ViewCompat .postInvalidateOnAnimation (this );
178- }else {
179- endScroll ();
180180 }
181181 }
182182
183183 private void scrollDx (int dx ){
184+ int x = dx *childWidthMeasure /getMeasuredWidth ();
184185 int count = getChildCount ();
185- int i = count -2 ;
186- View child = getChildAt (i );
187-
188- int left = getPaddingLeft ()+edge +xSpace .get (i -1 )+dx ;
186+ View child ;
187+ int left ;
188+ if ( 0 == (dragModel &stackModel )){
189+ int i = count -2 ;
190+ child = getChildAt (i );
191+ left = getPaddingLeft ()+edge +xSpace .get (i -1 )+x ;
192+ }else {
193+ int i = count -1 ;
194+ child = getChildAt (i );
195+ left = getPaddingLeft ()+(MODEL_LEFT == stackModel ?getMeasuredWidth ():-childWidthMeasure )+x ;
196+ }
189197 int right = left + childWidthMeasure ;
190198 int top = getPaddingTop ();
191199 int bottom = childHeightMeasure -top ;
@@ -194,22 +202,26 @@ private void scrollDx(int dx){
194202
195203 private void scrollVelocity (int velocity ){
196204 int count = getChildCount ();
197- int i = count -2 ;
198-
199- View child = getChildAt (i );
200- int dx = getPaddingLeft ()+edge +xSpace .get (i -1 )-child .getLeft ();
205+ View child ;
206+ int dx ;
207+ if ( 0 == (dragModel &stackModel )) {
208+ int i = count - 2 ;
209+ child = getChildAt (i );
210+ dx = getPaddingLeft ()+edge +xSpace .get (i -1 )-child .getLeft ();
211+ }else {
212+ int i = count -1 ;
213+ child = getChildAt (i );
214+ dx = getPaddingLeft ()+(MODEL_LEFT == stackModel ?getMeasuredWidth ():-childWidthMeasure )-child .getLeft ();
215+ }
201216 startScroll (-dx ,dx );
202217 }
203218
204219 private void startScroll (int begin ,int dx ){
205- mScroller .startScroll (begin ,0 ,dx ,0 ,mDuration );
220+ int mills = Math .max (mDuration *Math .abs (dx )/getMeasuredWidth (),mDuration /2 );
221+ mScroller .startScroll (begin ,0 ,dx ,0 ,mills );
206222 ViewCompat .postInvalidateOnAnimation (this );
207223 }
208224
209- private void endScroll (){
210-
211- }
212-
213225 private void handleAutoPlay (boolean play ){
214226 if (play ) {
215227 if (executor == null || executor .isShutdown ()){
@@ -257,32 +269,40 @@ protected void onDetachedFromWindow() {
257269
258270 @ Override
259271 public boolean onInterceptTouchEvent (MotionEvent ev ) {
260- log (" action=" +ev .getAction ()+",x=" +ev .getX ()+",y=" +ev .getY ());
272+ log (" action=" +ev .getAction ()+",x=" +ev .getX ()+",y=" +ev .getY ()+ ",slop=" + mTouchSlop );
261273 final int action = ev .getAction () & MotionEvent .ACTION_MASK ;
262274 switch (action ) {
263275 case MotionEvent .ACTION_DOWN :
276+ mScroller .abortAnimation ();
277+ mIsDragged = false ;
264278 initVelocityTracker ();
265- startX = ( int ) ev .getX ();
266- startY = ( int ) ev .getY ();
279+ lastX = initX = ev .getX ();
280+ lastY = initY = ev .getY ();
267281 break ;
268282 //fixed inner view touch
269283 case MotionEvent .ACTION_MOVE :
270- float xDistance = Math .abs (startX - ev .getX ());
271- float yDistance = Math .abs (startY - ev .getY ());
272- if (xDistance > yDistance && xDistance > mTouchSlop ) {
284+ float dx = ev .getX () - lastX ;
285+ float xDistance = Math .abs (dx );
286+ float yDistance = Math .abs (lastY - ev .getY ());
287+ if (xDistance > mTouchSlop && xDistance /2 > yDistance ) {
273288 //水平滑动,需要拦截 在RecyclerView中需要禁止父类拦截
274289 requestDisallowInterceptTouchEvent (true );
290+ dragModel = dx > 0 ? MODEL_RIGHT : MODEL_LEFT ;
291+ lastX = dx > 0 ? initX +mTouchSlop : initX -mTouchSlop ;
275292 mIsDragged = true ;
276293 return true ;
277294 }
278- default :
295+ break ;
296+ case MotionEvent .ACTION_UP :
297+ case MotionEvent .ACTION_CANCEL :
298+ scrollVelocity (0 );
299+ break ;
279300 }
280301 return false ;
281302 }
282303
283304 @ Override
284305 public boolean onTouchEvent (MotionEvent ev ) {
285- log ("action=" +ev .getAction ()+",x=" +ev .getX ()+",y=" +ev .getY ());
286306 if (adapter == null || adapter .getItemCount () <= 1 ){
287307 return false ;
288308 }
@@ -293,18 +313,23 @@ public boolean onTouchEvent(MotionEvent ev) {
293313 int action = ev .getActionMasked ();
294314 switch (action ) {
295315 case MotionEvent .ACTION_DOWN :
316+ mScroller .abortAnimation ();
296317 mIsDragged = false ;
297318 break ;
298319 case MotionEvent .ACTION_MOVE :
299- float xDistance = Math .abs (startX - ev .getX ());
300- float yDistance = Math .abs (startY - ev .getY ());
301- if (xDistance > yDistance && xDistance > mTouchSlop ) {
302- requestDisallowInterceptTouchEvent (true );
303- mIsDragged = true ;
320+ if (!mIsDragged ) {
321+ float dx = ev .getX ()-lastX ;
322+ float xDistance = Math .abs (dx );
323+ float yDistance = Math .abs (ev .getY () - lastY );
324+ if (xDistance > yDistance && xDistance > mTouchSlop ) {
325+ requestDisallowInterceptTouchEvent (true );
326+ mIsDragged = true ;
327+ dragModel = dx > 0 ? MODEL_RIGHT : MODEL_LEFT ;
328+ lastX = dx > 0 ? initX +mTouchSlop : initX -mTouchSlop ;
329+ }
304330 }
305331 if (mIsDragged ){
306- int currentX = (int ) ev .getX ();
307- scrollDx (currentX -startX );
332+ scrollDx ((int )(ev .getX ()-lastX ));
308333 }
309334 break ;
310335 case MotionEvent .ACTION_UP :
@@ -313,7 +338,6 @@ public boolean onTouchEvent(MotionEvent ev) {
313338 int velocity = (int ) mVelocity .getXVelocity ();
314339 scrollVelocity (velocity );
315340 recycleVelocityTracker ();
316- default :
317341 }
318342 return true ;
319343 }
0 commit comments