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.
need implement exact reverse of this. need start expanded view , shrink smaller view 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.