22
33import android .animation .ValueAnimator ;
44import android .content .res .Resources ;
5- import android .os .Handler ;
6- import android .os .Looper ;
75import android .util .Log ;
86import android .view .View ;
97import android .view .animation .DecelerateInterpolator ;
@@ -46,7 +44,6 @@ final class StackHelper implements ValueAnimator.AnimatorUpdateListener{
4644 private int mDuration = 500 ;
4745 private int mDelay = 3000 ;
4846 private StackLayout layout ;
49- private boolean debug = true ;
5047
5148 StackHelper (int touchSlop ) {
5249 mTouchSlop = touchSlop ;
@@ -70,10 +67,10 @@ int getItemCount(){
7067
7168 void unbindLayout () {
7269 setAutoPlay (false );
70+ mAnimator .cancelAnimator ();
7371 }
7472
7573 void measureChild (int width ,int height ){
76- //log("measue...");
7774 if (getItemCount () > 0 ){
7875 int size = layout .getRealStackSize ();
7976 if (originX .isEmpty ()) {
@@ -107,12 +104,11 @@ void measureChild(int width,int height){
107104 }
108105
109106 void layoutChild (){
110- //log("layout..."+layout.getChildCount());
111107 if (needRelayout && layout != null ) {
112108 needRelayout = false ;
113109 int childSize = layout .getChildCount ();
114110 int stackSize = layout .getRealStackSize ();
115- int realSize = layout . getRealStackSize ();
111+
116112 for (int i = 0 ; i < childSize ; i ++) {
117113 int top , bottom , left , right , pivot ;
118114 View view = layout .getChildAt (i );
@@ -130,16 +126,13 @@ void layoutChild(){
130126 pivot = layout .getWidth () - layout .stackEdge ;
131127 }
132128 view .setPivotX (pivot );
133- view .setPivotY (everyHeight / 2 );
134- view .layout (left , top , right , bottom );
135- view .setScaleY ((float ) Math .pow (layout .stackZoomY ,realSize -1 -i ));
136- if (view .getTranslationX () != 0f ){
137- if (i +1 < stackSize ){
138- view .setTranslationX (0 );
139- }else if (i +1 == stackSize && childSize == stackSize ){//恢复stackSize时,补偿距离
140- float distance = layout .stackEdgeModel == MODEL_RIGHT ? -everyWidth : everyWidth ;
141- view .setTranslationX (view .getTranslationX ()+distance );
142- }
129+ view .setPivotY (everyHeight /2f );
130+ if (mAnimator .isRunning () && i > 0 ){
131+
132+ }else {
133+ view .layout (left , top , right , bottom );
134+ view .setScaleY ((float ) Math .pow (layout .stackZoomY ,stackSize -1 -i ));
135+ view .setTranslationX (0 );
143136 }
144137 }else if (!isTopRemove ){//顶层加入
145138 if (layout .stackEdgeModel == MODEL_LEFT ) {
@@ -263,6 +256,24 @@ void executeScroll(int dx) {
263256 view = mAnimator .mAnimatorView ;
264257 }
265258 view .setTranslationX (view .getTranslationX () + 1.0f *everyWidth /layout .getWidth () * dx );
259+ scaleTransChild (dx );
260+ }
261+ }
262+
263+ void scaleTransChild (int dx ){
264+ int first = layout .getChildCount ()>layout .stackSize ? 1 : 0 ;
265+ int size = layout .getChildCount ()-1 ;
266+ int stackSize = layout .stackSize ;
267+ for (int i = first ; i <size ; i ++){
268+ View v = layout .getChildAt (i );
269+ int sign = MODEL_LEFT == layout .stackEdgeModel ? 1 : -1 ;
270+ float rate = 1f *dx /layout .getWidth ();
271+ int tx = originX .get (i -first +1 )-originX .get (i -first );
272+ v .setTranslationX (v .getTranslationX () + rate *tx );
273+
274+ double scaley = Math .pow (layout .stackZoomY ,stackSize -2 -i );
275+ double scale = Math .pow (layout .stackZoomY ,stackSize -1 -i );
276+ v .setScaleY (v .getScaleY ()+(float )(sign *rate *(scaley -scale )));
266277 }
267278 }
268279
@@ -307,7 +318,7 @@ void autoScroll(){
307318 void setAutoPlay (boolean looper ){
308319 if (looper ) {
309320 if (executor == null || executor .isShutdown ()){
310- executor = new ScheduledThreadPoolExecutor (2 );
321+ executor = new ScheduledThreadPoolExecutor (1 );
311322 }
312323 if (executor .getQueue ().size () <= 0 && getItemCount () > 1 ) {
313324 executor .scheduleWithFixedDelay (new AutoRunnable (this ), 2000 , mDelay , TimeUnit .MILLISECONDS );
@@ -316,6 +327,7 @@ void setAutoPlay(boolean looper){
316327 if (executor != null && !executor .isShutdown ()) {
317328 executor .shutdownNow ();
318329 }
330+
319331 }
320332 }
321333
@@ -354,7 +366,7 @@ private void removeBottomView(){
354366 if (displayPosition < 0 ){
355367 displayPosition += cnt ;
356368 }
357- needRelayout = true ;
369+ // needRelayout = true;
358370 View view = layout .getChildAt (0 );
359371 removeStackView (view );
360372 layout .getAdapter ().onItemDisplay (displayPosition );
@@ -363,10 +375,15 @@ private void removeBottomView(){
363375 @ Override
364376 public void onAnimationUpdate (ValueAnimator animation ) {
365377 float animateValue = (float ) animation .getAnimatedValue ();
378+ float lastValue = mAnimator .getTranslationX ();
366379 float fraction = animation .getAnimatedFraction ();
367380 mAnimator .setTranslationX (animateValue );
381+ scaleTransChild ((int )(mAnimator .getTranslationX ()-lastValue ));
368382 if (fraction >= 1.0f ) {
369383 mAnimator .endAnimator (this );
384+ needRelayout = true ;
385+ layout .requestLayout ();
386+
370387 } else if (fraction > 0.2 && mAnimator .needAddBottomView ()){
371388 addBottomView ();
372389 }
@@ -429,8 +446,16 @@ void startAnimator(boolean needRemoveTop,boolean needAddBottom,float transX, Val
429446 animator .start ();
430447 }
431448
449+ void cancelAnimator (){
450+ if (animator != null ){
451+ animator .removeAllUpdateListeners ();
452+ animator .cancel ();
453+ endAnimator (null );
454+ }
455+ }
456+
432457 void endAnimator (StackHelper helper ){
433- if (needRemoveTopView ) {
458+ if (needRemoveTopView && helper != null ) {
434459 helper .removeStackView (mAnimatorView );
435460 }
436461 animator .removeAllUpdateListeners ();
@@ -442,22 +467,26 @@ void endAnimator(StackHelper helper){
442467 }
443468
444469 static class AutoRunnable implements Runnable {
445- static Handler mHandler = new Handler (Looper .getMainLooper ());
446- StackHelper helper ;
470+ WeakReference <StackHelper > weakHelper ;
447471
448472 AutoRunnable (StackHelper stack ) {
449- this . helper = stack ;
473+ weakHelper = new WeakReference <>( stack ) ;
450474 }
451475
452476 @ Override
453477 public void run () {
454- if (helper .getItemCount () > 1 && helper .layout .getChildCount () > 0 ){
455- final StackLayout stack = helper .layout ;
456- int [] points = new int [2 ];
457- stack .getLocationInWindow (points );
458- if (points [1 ] < Resources .getSystem ().getDisplayMetrics ().heightPixels ){
459- mHandler .post (new AutoScrollRunnable (helper ));
478+ try {
479+ StackHelper helper = weakHelper .get ();
480+ if (helper != null && helper .getItemCount () > 1 && helper .layout .getChildCount () > 0 ) {
481+ StackLayout stack = helper .layout ;
482+ int [] points = new int [2 ];
483+ stack .getLocationInWindow (points );
484+ if (points [1 ] < Resources .getSystem ().getDisplayMetrics ().heightPixels ) {
485+ stack .getHandler ().post (new AutoScrollRunnable (helper ));
486+ }
460487 }
488+ }catch (Throwable ex ){
489+ ex .printStackTrace ();
461490 }
462491 }
463492 }
@@ -488,10 +517,8 @@ boolean filterClick(){
488517 }
489518
490519 void log (String msg ){
491- if (debug ) {
492- StackTraceElement element = Thread .currentThread ().getStackTrace ()[3 ];
493- Log .e ("StackLayout" , String .format ("%1$s:%2$s(%3$s):%4$s" , element .getClassName (),
494- element .getMethodName (), element .getLineNumber (), msg ));
495- }
520+ StackTraceElement element = Thread .currentThread ().getStackTrace ()[3 ];
521+ Log .e ("StackLayout" , String .format ("%1$s:%2$s(%3$s):%4$s" , element .getClassName (),
522+ element .getMethodName (), element .getLineNumber (), msg ));
496523 }
497524}
0 commit comments