java - Android - Zoom animation using AnimatorSet -


the official zooming view tutorial uses animatorset zoom view. creates illusion of downward movement view expands. later, animatorset replayed backwards create illusion of zoom-out.

zoom-in downward movement need implement exact reverse of this. need start expanded view , shrink smaller view upward movement:

zoom-out upward movement doesn't seem can use reversal code in example. example assumes first zoom view , expand it, , shrink original thumbnail icon.

here's i've tried far. xml layout is

<framelayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent">  <linearlayout android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="vertical"     android:background="#1999da">                   <linearlayout         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_margintop="16dp"         android:orientation="horizontal"         android:layout_gravity="center"         android:gravity="center">          <!-- final shrunk image -->          <imageview             android:id="@+id/thumb_button_1"             android:layout_width="wrap_content"             android:layout_height="50dp"             android:layout_marginright="1dp"             android:visibility="invisible"/>      </linearlayout>  </linearlayout>  <!-- initial expanded image needs shrunk -->  <imageview     android:id="@+id/expanded_image"     android:layout_width="wrap_content"     android:layout_height="125dp"     android:layout_gravity="center"     android:src="@drawable/title_logo_expanded"     android:scaletype="centercrop"/>  </framelayout> 

and here method performs zoom-out operation. i've tried reverse procedure in tutorial:

private void zoomimagefromthumbreverse(final view expandedimageview, int imageresid, final int duration) {     // if there's animation in progress, cancel , proceed one.            if (mcurrentanimator != null) {         mcurrentanimator.cancel();     }      // load low-resolution "zoomed-out" image.     final imageview thumbview = (imageview) findviewbyid(r.id.thumb_button_1);     thumbview.setimageresource(imageresid);      // calculate starting , ending bounds zoomed-in image. step     // involves lots of math. yay, math.     final rect startbounds = new rect();     final rect finalbounds = new rect();     final point globaloffset = new point();      // start bounds global visible rectangle of container view (i.e. framelayout), ,     // final bounds global visible rectangle of thumbnail.     // set container view's offset origin bounds, since that's     // origin positioning animation properties (x, y).     findviewbyid(r.id.container).getglobalvisiblerect(startbounds, globaloffset);     thumbview.getglobalvisiblerect(finalbounds);     startbounds.offset(-globaloffset.x, -globaloffset.y);     finalbounds.offset(-globaloffset.x, -globaloffset.y);      // adjust start bounds same aspect ratio final bounds using     // "center crop" technique. prevents undesirable stretching during animation.     // calculate start scaling factor (the end scaling factor 1.0).     float startscale;     if ((float) finalbounds.width() / finalbounds.height()             > (float) startbounds.width() / startbounds.height()) {         // extend start bounds horizontally         startscale = (float) startbounds.height() / finalbounds.height();         float startwidth = startscale * finalbounds.width();         float deltawidth = (startwidth - startbounds.width()) / 2;         startbounds.left -= deltawidth;         startbounds.right += deltawidth;     } else {         // extend start bounds vertically         startscale = (float) startbounds.width() / finalbounds.width();         float startheight = startscale * finalbounds.height();         float deltaheight = (startheight - startbounds.height()) / 2;         startbounds.top -= deltaheight;         startbounds.bottom += deltaheight;     }      // hide expanded-image , show zoomed-out, thumbnail view. when animation begins,     // position zoomed-in view in place of thumbnail.     expandedimageview.setalpha(0f);     thumbview.setvisibility(view.visible);      // set pivot point scale_x , scale_y transformations top-left corner of     // zoomed-in view (the default center of view).     thumbview.setpivotx(0f);     thumbview.setpivoty(0f);      // construct , run parallel animation of 4 translation , scale properties     // (x, y, scale_x, , scale_y).     animatorset set = new animatorset();     set             .play(objectanimator.offloat(thumbview, view.x, startbounds.left,                     finalbounds.left))             .with(objectanimator.offloat(thumbview, view.y, startbounds.top,                     finalbounds.top))             .with(objectanimator.offloat(thumbview, view.scale_x, startscale, 1f))             .with(objectanimator.offloat(thumbview, view.scale_y, startscale, 1f));     //set.setduration(mshortanimationduration);     set.setduration(duration);     set.setinterpolator(new decelerateinterpolator());     set.addlistener(new animatorlisteneradapter() {         @override         public void onanimationend(animator animation) {             mcurrentanimator = null;         }          @override         public void onanimationcancel(animator animation) {             mcurrentanimator = null;         }     });     set.start();     mcurrentanimator = set;      // upon clicking zoomed-out image, should zoom down original bounds     // , show thumbnail instead of expanded image.     final float startscalefinal = startscale;     thumbview.setonclicklistener(new view.onclicklistener() {         @override         public void onclick(view view) {             if (mcurrentanimator != null) {                 mcurrentanimator.cancel();             }              // animate 4 positioning/sizing properties in parallel,             // original values.             animatorset set = new animatorset();             set                     .play(objectanimator.offloat(thumbview, view.x, startbounds.left))                     .with(objectanimator.offloat(thumbview, view.y, startbounds.top))                     .with(objectanimator                             .offloat(thumbview, view.scale_x, startscalefinal))                     .with(objectanimator                             .offloat(thumbview, view.scale_y, startscalefinal));             //set.setduration(mshortanimationduration);             set.setduration(duration);             set.setinterpolator(new decelerateinterpolator());             set.addlistener(new animatorlisteneradapter() {                 @override                 public void onanimationend(animator animation) {                     expandedimageview.setalpha(1f);                     thumbview.setvisibility(view.gone);                     mcurrentanimator = null;                 }                  @override                 public void onanimationcancel(animator animation) {                     expandedimageview.setalpha(1f);                     thumbview.setvisibility(view.gone);                     mcurrentanimator = null;                 }             });             set.start();             mcurrentanimator = set;         }     }); } 

i invoking method in oncreate() follows:

final view expandedimageview = findviewbyid(r.id.expanded_image); new handler().postdelayed(new runnable(){         public void run() {             zoomimagefromthumbreverse(expandedimageview, r.drawable.title_logo_min, 1000);         }}, 1000); 

well, that's it, folks. isn't working. @ loss why. demo example works perfectly, why doesn't work ? take gander , tell me if i'm crazy.

can identify error ? or point me in right direction ? appreciated.

this solution have used:

private void applyanimation(final view startview, final view finishview, long duration) {     float scalingfactor = ((float)finishview.getheight())/((float)startview.getheight());      scaleanimation scaleanimation =  new scaleanimation(1f, scalingfactor,                                                         1f, scalingfactor,                                                         animation.relative_to_self, 0.5f,                                                         animation.relative_to_self, 0.5f);      scaleanimation.setduration(duration);     scaleanimation.setinterpolator(new acceleratedecelerateinterpolator());      display display = getwindowmanager().getdefaultdisplay();      int h;      if(build.version.sdk_int >= 13){         point size = new point();         display.getsize(size);         h = size.y;     }     else{         h = display.getheight();     }      float h = ((float)finishview.getheight());      float verticaldisplacement = (-(h/2)+(3*h/4));      translateanimation translateanimation = new translateanimation(animation.absolute, 0,                                                                    animation.absolute, 0,                                                                    animation.absolute, 0,                                                                    animation.absolute, verticaldisplacement);      translateanimation.setduration(duration);     translateanimation.setinterpolator(new acceleratedecelerateinterpolator());      animationset animationset = new animationset(false);     animationset.addanimation(scaleanimation);     animationset.addanimation(translateanimation);     animationset.setfillafter(false);      startview.startanimation(animationset); } 

the key factor here value of toydelta in translateanimation parameter:

toydelta = (-(h/2)+(3*h/4)); 

understanding why works main thing. rest simple.