android - Fragment shared element transitions don't work with ViewPager -
my app contains view consists of viewpager consisting of handful of fragments. when click on item in 1 of these fragments, expected behavior shared element (in case image) transition fragment displays more information clicked content.
here simple video of should like:
https://dl.dropboxusercontent.com/u/97787025/device-2015-06-03-114842.mp4
this using fragment->fragment transition.
the problem arises when place starting fragment inside viewpager. suspect because viewpager uses parent fragment's child fragment manager, different fragment manager of activity, handling fragment transaction. here video of happens:
https://dl.dropboxusercontent.com/u/97787025/device-2015-06-03-120029.mp4
i'm pretty issue here explained above child fragment manager vs activity's fragment manager. here how making transition:
simplefragment fragment = new simplefragment(); fragmenttransaction transaction = getsupportfragmentmanager().begintransaction(); transaction.replace(r.id.am_list_pane, fragment, fragment.getclass().getsimplename()); if(build.version.sdk_int >= build.version_codes.lollipop) { transitionset entertransition = new transitionset(); entertransition.addtransition(new changebounds()); entertransition.addtransition(new changeclipbounds()); entertransition.addtransition(new changeimagetransform()); entertransition.addtransition(new changetransform()); transitionset returntransition = new transitionset(); returntransition.addtransition(new changebounds()); returntransition.addtransition(new changeclipbounds()); returntransition.addtransition(new changeimagetransform()); returntransition.addtransition(new changetransform()); fragment.setsharedelemententertransition(entertransition); fragment.setsharedelementreturntransition(returntransition); transaction.addsharedelement(iv, iv.gettransitionname()); } transaction.addtobackstack(fragment.getclass().getname()); transaction.commit(); this works fine when both fragments managed activity's fragment manager, when load viewpager this:
viewpager pager = (viewpager) view.findviewbyid(r.id.pager); pager.setadapter(new adapter(getchildfragmentmanager())); the children of viewpager not being managed activity, , doesn't work anymore.
is oversight android team? there way pull off? thanks.
probably you've found answer in case haven't, here's did fix after few hours of scratching head.
the problem think combination of 2 factors:
the
fragmnetsinviewpagerload delay, meaning activity returns lot faster fragments contained insideviewpagerif me,
viewpager's child fragments same type. means, share same transition name (if you've set them in xml layout), unless set them in code , set once, on visible fragment.
to fix both of these problems, did:
1. fixing delayed loading problem:
inside activity (the 1 contains viewpager), add line after super.oncreate() , before setcontentview():
@override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); activitycompat.postponeentertransition(this); // line need add setcontentview(r.layout.feeds_content_list_activity); ... } 2. fixing problem multiple fragments same transition name:
now there quite few ways of going doing ended inside "detail" activity, i.e. activity contains viewpager (in oncreate() can anywhere really):
_viewpager.setadapter(_sectionspageradapter); _viewpager.setcurrentitem(position); ... ... _pageradapter.getitem(position).settransitionname(getresources().getstring(r.string.transition_contenet_topic)); you need careful since activity may not yet attached viewpager fragment it's easier pass in transition name activity fragment if you're loading resource
the actual implementation simple expect:
public void settransitionname(string transitionname) { _transitionname = transitionname; } then inside fragment's onviewcreated(), add line:
public void onviewcreated(view view, bundle savedinstancestate) { super.onviewcreated(view, savedinstancestate); ... if (_transitionname != null && android.os.build.version.sdk_int >= android.os.build.version_codes.lollipop) { settransitionnamelollipop(); } ... } @targetapi(build.version_codes.lollipop) private void settransitionnameslollipop() { _imgtopic.settransitionname(_transitionname); } the last piece of puzzle find out when fragment loaded , call activitycompat.startpostponedentertransition(getactivity());.
in case, fragments not loaded until later since i'm loading things off ui thread means had figure out way call when loaded if that's not case, can call right after call settransitionnamelollipop().
the problem approach exit transition may not work unless you're careful , reset transition name on "visible" fragment right before exit activity navigate back. can done so:
- listen page change on
viewpager - remove transition name(s) fragment out of view
- set transition name(s) on visible fragment.
- instead of calling
finish(), callactivitycompat.finishaftertransition(activity);
this can complex if transition needs transition recyclerview case. that, there's better answer provided @alex lockwood here: viewpager fragments – shared element transitions has written example code (albeit lot more complicated wrote) here: https://github.com/alexjlockwood/activity-transitions/tree/master/app/src/main/java/com/alexjlockwood/activity/transitions
in case, didn't have go far implement solution , above solution posted worked case.
in case have multiple shared elements, i'm sure can figure out how extend methods in order cater them.
Comments
Post a Comment