рдХреИрд╕реЗ рдореИрдВрдиреЗ рд╕рд╛рдЭрд╛ рддрддреНрд╡ рд╕рдВрдХреНрд░рдордг рд╕реЗ рд╕рдВрдШрд░реНрд╖ рдХрд┐рдпрд╛ рдФрд░ рдЕрдкрдиреА рдкрд╣рд▓реА рдУрдкрдирд╕реЛрд░реНрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд▓рд┐рдЦреА

рджреБрдирд┐рдпрд╛ рдореЗрдВ рдХреЛрдИ рджреБрдЦ рдХреА рдХрд╣рд╛рдиреА рдирд╣реАрдВ рд╣реИ
ViewPager'e рдФрд░ SET'e рдХреА рдХрд╣рд╛рдиреА рдХреА рддреБрд▓рдирд╛ рдореЗрдВ



рдореИрдВ рдЪреЗрддрд╛рд╡рдиреА рджреЗрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рд▓реЗрдЦрдХ рдПрдХ рдиреМрд╕рд┐рдЦрд┐рдпрд╛ рдПрдВрдбреНрд░реЙрдЗрдб рд╣реИ, рдЗрд╕рд▓рд┐рдП рд▓реЗрдЦ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рддрдХрдиреАрдХреА рдЕрд╢реБрджреНрдзрд┐рдпрд╛рдВ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рдмрд▓реНрдХрд┐ рдЪреЗрддрд╛рд╡рдиреА рджреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП рдХрд┐ рд▓реЗрдЦ рдореЗрдВ рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдХрдерди рджрд┐рдЦрд╛рдИ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред


рдЬрд╣рд╛рдВ рдмреИрдХрдПрдВрдб рд╣реЛрддрд╛ рд╣реИ


рдореЗрд░реЗ рд╕рд╛рд░реЗ рдЬреАрд╡рди рдореЗрдВ рдореИрдВрдиреЗ рдмреИрдХрдПрдВрдб рдХреЛ рджреЗрдЦрд╛ред 2019 рдХреА рд╢реБрд░реБрдЖрдд, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдорд╣рддреНрд╡рд╛рдХрд╛рдВрдХреНрд╖реА рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдзреВрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИред рдПрдХ рдЦреЛрдЬ рдХрдВрдкрдиреА рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рдХреНрд╖рд╛рддреНрдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдЬреНрдпреВрд░рд┐рдЦ рдореЗрдВ рдПрдХ рдмреЗрдХрд╛рд░ рдпрд╛рддреНрд░рд╛ред рд╕рд░реНрджреА, рдЧрдВрджрдЧреА, рдореВрдб рдирд╣реАрдВред рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдФрд░ рдЖрдЧреЗ рдЦреАрдВрдЪрдиреЗ рдХреА рдХреЛрдИ рддрд╛рдХрдд рдФрд░ рдЗрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реИред


рдореИрдВ рдЗрд╕ рднрдпрд╛рдирдХ рдмреИрдХрдПрдВрдб рдХреЛ рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рднреВрд▓ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рднрд╛рдЧреНрдп рдиреЗ рдореБрдЭреЗ рдПрдХ рд╡рд┐рдЪрд╛рд░ рджрд┐рдпрд╛ - рдпрд╣ рдПрдХ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдерд╛ред рдЗрд╕рдХреА рдореБрдЦреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреИрдорд░реЗ рдХрд╛ рдЧреИрд░-рдорд╛рдирдХ рдЙрдкрдпреЛрдЧ рд╣реЛрдирд╛ рдерд╛ред рдХрд╛рдо рдореЗрдВ рдЙрдмрд╛рд▓ рдЖрдиреЗ рд▓рдЧрд╛ред рдЗрд╕рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рдордп рд▓рдЧрд╛, рдФрд░ рдЕрдм рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рддреИрдпрд╛рд░ рд╣реИред рдЬрдм рддрдХ рдореИрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ " рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ " рдмрдирд╛рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рдирд╣реАрдВ рд▓реЗрддрд╛, рддрдм рддрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рд░рд┐рд▓реАрдЬ рдХрд░реАрдм рдЖ рд░рд╣реА рдереА рдФрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рдФрд░ рд╕реБрд╡реНрдпрд╡рд╕реНрдерд┐рдд рдерд╛ред


ViewPager рдФрд░ рд╕рд╛рдЭрд╛ рддрддреНрд╡ рд╕рдВрдХреНрд░рдордгред рд╣рдо рд╕реБрд▓рд╣ рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ


рдХреЛрдИ рднреА 2019 рдореЗрдВ рдЫреЛрдЯреЗ рдореЗрдиреВ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рд╕рднреА рджрд╛рдПрдВ рдФрд░ рдмрд╛рдПрдВ рд╡реЗ рд╕реНрдХреНрд░реАрди рдХреЛ рд╕реНрд╡рд╛рдЗрдк рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ - рдХрд┐рдпрд╛, рдХрд┐рдпрд╛ - рдХрд┐рдпрд╛ред рддреЛ рдкрд╣рд▓рд╛ ViewPager рдореЗрд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкрд░ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ (рдореИрдВрдиреЗ рдореЗрд░реЗ рдЬреИрд╕реЗ рд╣реА рдмреИрдХрдПрдВрдб рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╢рд░реНрддреЗрдВ рддрдп рдХреА рд╣реИрдВ - рдмрд╕ рдХрд░реНрд╕рд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ)ред рдФрд░ рд╕рд╛рдЭрд╛ рддрддреНрд╡ рд╕рдВрдХреНрд░рдордг (рдмрд╛рдж рдореЗрдВ рд╕реЗрдЯ рдпрд╛ рд╕рдВрдХреНрд░рдордг) - рд╕рд╛рдордЧреНрд░реА рдбрд┐рдЬрд╝рд╛рдЗрди рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рддрддреНрд╡, рдиреЗ рдореБрдЭреЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝рдХрд░ рдПрдХ ViewPager рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рдЗрдирдХрд╛рд░ рдХрд░ рджрд┐рдпрд╛: рд╕реНрдХреНрд░реАрди рдХреЗ рдмреАрдЪ рдпрд╛ рддреЛ рд╕реНрд╡рд╛рдЗрдк, рдпрд╛ рд╕реБрдВрджрд░ рд╕рдВрдХреНрд░рдордг рдПрдирд┐рдореЗрд╢рдиред рдореИрдВ рдПрдХ рдпрд╛ рджреВрд╕рд░реЗ рдХреЛ рдордирд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдЗрд╕рд▓рд┐рдП рдореЗрд░реА рдЦреЛрдЬ рд╢реБрд░реВ рд╣реБрдИред


рдЕрдзреНрдпрдпрди рдХреЗ рдШрдВрдЯреЗ: рдордВрдЪреЛрдВ рдкрд░ рджрд░реНрдЬрдиреЛрдВ рд╡рд┐рд╖рдп рдФрд░ StackOverflow рдкрд░ рдЕрдиреБрддреНрддрд░рд┐рдд рдкреНрд░рд╢реНрдиред рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдореИрдВ рдХреНрдпрд╛ рдЦреЛрд▓рддрд╛ рд╣реВрдВ, рдореБрдЭреЗ RecyclerView рд╕реЗ ViewPager рдореЗрдВ рдПрдХ рд╕рдВрдХреНрд░рдордг рдмрдирд╛рдиреЗ рдпрд╛ "рдПрдХ рдкреНрд▓рд╛рдВрдЯреИрди Fragment.postponeEnterTransition() " рд╕рдВрд▓рдЧреНрди рдХрд░рдиреЗ рдХреА рдкреЗрд╢рдХрд╢ рдХреА рдЧрдИ рдереАред



рд▓реЛрдХ рдЙрдкрдЪрд╛рд░ рдиреЗ рдорджрдж рдирд╣реАрдВ рдХреА, рдФрд░ рдореИрдВрдиреЗ ViewPager рдФрд░ Shared Element Transition рд╕реНрд╡рдпрдВ рдореЗрдВ рд╕рдореЗрдЯрдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред


ViewPager: рдкрд╣рд▓рд╛ рдЦреВрди


рдореИрдВрдиреЗ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛: "рд╕рдорд╕реНрдпрд╛ рдЙрд╕ рд╕рдордп рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХ рдкреГрд╖реНрда рд╕реЗ рджреВрд╕рд░реЗ рдкреГрд╖реНрда рдкрд░ рдЬрд╛рддрд╛ рд╣реИ ..."ред рдФрд░ рдлрд┐рд░ рдпрд╣ рдореБрдЭ рдкрд░ рд╣рд╛рд╡реА рд╣реЛ рдЧрдпрд╛: "рдпрджрд┐ рдЖрдк рдкреГрд╖реНрда рдирд╣реАрдВ рдмрджрд▓рддреЗ рд╣реИрдВ, рддреЛ рдкреГрд╖реНрда рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рджреМрд░рд╛рди рдЖрдкрдХреЛ SET рд╕реЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрдЧреА"ред



рд╣рдо рдПрдХ рд╣реА рдкреГрд╖реНрда рдкрд░ рд╕рдВрдХреНрд░рдордг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╡рд░реНрддрдорд╛рди рдкреГрд╖реНрда рдХреЛ ViewPager рдореЗрдВ рд▓рдХреНрд╖реНрдп рдкреГрд╖реНрда рд╕реЗ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЯреБрдХрдбрд╝реЗ рдмрдирд╛рдПрдВ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╣рдо рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред


 SmallPictureFragment small_picture_fragment = new SmallPictureFragment(); BigPictureFragment big_picture_fragment = new BigPictureFragment(); 

рдЖрдЗрдП рд╡рд░реНрддрдорд╛рди рдкреГрд╖реНрда рдореЗрдВ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдХреБрдЫ рдФрд░ рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред


 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); //  View      int fragmentContId = previousFragment.getView().getParent().getId(); //         fragmentTransaction.replace(fragmentContId, nextFragment); fragmentTransaction.commit(); 

рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ ... рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рд░рд┐рдХреНрдд рд╕реНрдХреНрд░реАрди рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдХрд╛рд░рдг рд╣реИ?


рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ Page1Container , Page2Container рдЬреИрд╕реЗ рдХрд┐рд╕реА рдордзреНрдпрд╕реНрде рдХреЗ рдмрд┐рдирд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХрд╛ рдХрдВрдЯреЗрдирд░ ViewPager рд╣реА рд╣реИред рдЗрд╕рд▓рд┐рдП, рдмрд╕ рдПрдХ рдкреГрд╖реНрда рдХреЛ рджреВрд╕рд░реЗ рдореЗрдВ рдмрджрд▓рдиреЗ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдкреВрд░реЗ pager рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдЦреИрд░, рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП рдХрдИ рдХрдВрдЯреЗрдирд░ рдЯреБрдХрдбрд╝реЗ рдмрдирд╛рддреЗ рд╣реИрдВред


 RootSmallPictureFragment root_small_pic_fragment = new RootSmallPictureFragment(); RootBigPictureFragment root_big_pic_fragment = new RootBigPictureFragment(); 

рдХреБрдЫ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред


java.lang.IllegalStateException: рдЯреБрдХрдбрд╝реЗ рдЯреБрдХрдбрд╝реЗ рдХреА рдХрдВрдЯреЗрдирд░ ID рдирд╣реАрдВ рдмрджрд▓ рд╕рдХрддреЗ BigPictureFragment {...}: 2131165289 рдерд╛ рдЕрдм 2131165290

рд╣рдо рджреВрд╕рд░реЗ рдкреГрд╖реНрда ( BigPictureFragment ) рдХреЗ рдПрдХ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╕рдВрд▓рдЧреНрди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рджреВрд╕рд░реЗ рдкреГрд╖реНрда рдХреЗ рдХрдВрдЯреЗрдирд░ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред


рд╣рдорд╛рд░реЗ рджрд╛рдВрддреЛрдВ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдзрд┐рдХ рдбрдмрд▓ рдЯреБрдХрдбрд╝реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред


 SmallPictureFragment small_picture_fragment_fake = new SmallPictureFragment(); BigPictureFragment big_picture_fragment_fake = new BigPictureFragment(); 

рдЬреАрдд рдЧрдП рд╣реИрдВ! GitHub рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдХреЙрдкреА рдХрд┐рдП рдЧрдП рд╕рдВрдХреНрд░рдордг рдХреЛрдб рдХреЛ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдлреАрдХрд╛ рдХрд░ рджрд┐рдпрд╛ рдФрд░ рдПрдирд┐рдореЗрд╢рди рдХреЛ рдлреАрдХрд╛ рдХрд░ рджрд┐рдпрд╛ ред рдЗрд╕рд▓рд┐рдП, рд╕рдВрдХреНрд░рдордг рд╕реЗ рдкрд╣рд▓реЗ, рдкрд╣рд▓реЗ рдЯреБрдХрдбрд╝реЗ рд╕реЗ рд╕рднреА рд╕реНрдерд┐рд░ рддрддреНрд╡ рдЧрд╛рдпрдм рд╣реЛ рдЧрдП, рдлрд┐рд░ рдЪрд┐рддреНрд░ рдЪрд▓реЗ рдЧрдП, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА рджреВрд╕рд░реЗ рдкреГрд╖реНрда рдХреЗ рддрддреНрд╡ рджрд┐рдЦрд╛рдИ рджрд┐рдПред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдкреГрд╖реНрдареЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЖрдВрджреЛрд▓рди рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред


рд╕рднреА рдПрдирд┐рдореЗрд╢рди рдкрд╛рд╕ рд╣реЛ рдЧрдП рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрднреА рднреА рдкрд╣рд▓реЗ рдкреГрд╖реНрда рдкрд░ рд╣реИ, рд▓реЗрдХрд┐рди рджреВрд╕рд░реЗ рдкрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред


рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рджреГрд╢реНрдпрдорд╛рди рдкреЗрдЬ рдкреЗрдЬ ViewPager рдзреНрдпрд╛рди рд╕реЗ рдПрдХ рджреВрд╕рд░реЗ рдХреЗ ViewPager рдмрджрд▓рддреЗ рд╣реИрдВред рдФрд░ рдлрд┐рд░ рд╣рдо рдкрд╣рд▓реЗ рдкреГрд╖реНрда рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдЙрдирдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред


  handler.postDelayed( () -> { //       activity.viewPager.setCurrentItem(nextPage, false); FragmentTransaction transaction = fragmentManager.beginTransaction(); //   . //       //    Shared Element Transition transaction.replace(fragmentContainer, previousFragment); transaction.commitAllowingStateLoss(); }, //      ,     FADE_DEFAULT_TIME + MOVE_DEFAULT_TIME + FADE_DEFAULT_TIME ); } 

рдкрд░рд┐рдгрд╛рдо рдХреНрдпрд╛ рд╣реИ? (рдПрдиреАрдореЗрд╢рди - реи. - mb)

рд╕рдВрдкреВрд░реНрдг рд╕реНрд░реЛрдд рдХреЛрдб
public class FragmentTransitionUtil {
private static final long FADE_DEFAULT_TIME = 500;
private static final long MOVE_DEFAULT_TIME = 1000;
public static void perform(
MainActivity activity,
Fragment previousFragment,
Fragment nextFragment,
Map<View, String> sharedElements,
int nextPage
) {
FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (previousFragment != null) {
// 1. Exit for Previous Fragment
Fade exitFade = new Fade();
exitFade.setDuration(FADE_DEFAULT_TIME);
previousFragment.setExitTransition(exitFade);
// 2. Shared Elements Transition
TransitionSet enterTransitionSet = new TransitionSet();
enterTransitionSet.addTransition(
new TransitionSet() {
{
setOrdering(ORDERING_TOGETHER);
addTransition(new ChangeBounds()).
addTransition(new ChangeTransform()).
addTransition(new ChangeImageTransform());
}
}
);
enterTransitionSet.setDuration(MOVE_DEFAULT_TIME);
enterTransitionSet.setStartDelay(FADE_DEFAULT_TIME);
nextFragment.setSharedElementEnterTransition(enterTransitionSet);
// 3. Enter Transition for New Fragment
Fade enterFade = new Fade();
enterFade.setStartDelay(MOVE_DEFAULT_TIME + FADE_DEFAULT_TIME);
enterFade.setDuration(FADE_DEFAULT_TIME);
nextFragment.setEnterTransition(enterFade);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (sharedElements != null) {
for (Map.Entry<View, String> viewStringEntry : sharedElements.entrySet()) {
View view = viewStringEntry.getKey();
String transName = viewStringEntry.getValue();
view.setTransitionName(transName);
fragmentTransaction.addSharedElement(
view,
transName
);
}
}
}
int fragmentContId = ((ViewGroup) previousFragment.getView().getParent()).getId();
fragmentTransaction.replace(fragmentContId, nextFragment);
fragmentTransaction.commit();
final Handler handler = new Handler();
handler.postDelayed(
() -> {
// Stealthy changing page visible to user. He wonтАЩt notice!
activity.viewPager.setCurrentItem(nextPage, false);
FragmentTransaction transaction = fragmentManager.beginTransaction();
// Restore previous fragment. It contains inappropriate view now
transaction.replace(fragmentContId, previousFragment);
transaction.commitAllowingStateLoss();
},
FADE_DEFAULT_TIME + MOVE_DEFAULT_TIME + FADE_DEFAULT_TIME
);
}
}
}

рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ GitHub рдкрд░ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред


рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рджреЗрдирд╛ред рдХреЛрдб рдмрд╣реБрдд рдЕрдзрд┐рдХ рдареЛрд╕ рд▓рдЧрдиреЗ рд▓рдЧрд╛: 2 рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЕрдВрд╢реЛрдВ рдХреЗ рдмрдЬрд╛рдп, рдореБрдЭреЗ 6 рдХреЗ рд░реВрдк рдореЗрдВ рдорд┐рд▓рд╛, рдЗрд╕рдореЗрдВ рдРрд╕реЗ рдирд┐рд░реНрджреЗрд╢ рджрд┐рдЦрд╛рдИ рджрд┐рдП рдЬреЛ рд╕рд╣реА рд╕рдордп рдкрд░ рдЯреБрдХрдбрд╝реЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реБрдП рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдФрд░ рдпрд╣ рдХреЗрд╡рд▓ рдбреЗрдореЛ рдореЗрдВ рд╣реИред


рдПрдХ рд╣реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, рдХреЛрдб рдореЗрдВ рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ, рд╕рдмрд╕реЗ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рдмреИрдХрдЕрдк рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд▓рдЧреЗред рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ "рдЧрд▓рдд" рдкреГрд╖реНрдареЛрдВ рд╕реЗ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдирд┐рдпреБрдХреНрддрд┐рдпреЛрдВ рдХреА рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рдХрд╛рдо рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЙрдиреНрд╣реЛрдВрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реЛрдиреЗ рджрд┐рдпрд╛ред


рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рд╕рдВрдХреНрд░рдордг рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдВрдбреНрд░реЙрдЗрдб рдореЗрдВ рдХреЙрд▓рдмреИрдХ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рдмрд╣реБрдд рд╣реА рдордирдорд╛рдирд╛ рд╣реИ рдФрд░ рдпрд╣ рдХрдИ рдХрд╛рд░рдХреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрд░рд┐рдгрд╛рдореА рдЯреБрдХрдбрд╝реЗ рдореЗрдВ RecyclerView рдЬрд▓реНрджреА рд╕реЗ рдХреИрд╕реЗ рд▓реЛрдб рд╣реЛрддрд╛ рд╣реИ)ред рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдерд╛ рдХрд┐ handler.postDelayed() рдореЗрдВ рдЯреБрдХрдбрд╝рд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЕрдХреНрд╕рд░ рдмрд╣реБрдд рдЬрд▓реНрдж рдпрд╛ рдмрд╣реБрдд рджреЗрд░ рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрддрд╛ handler.postDelayed() , рдЬреЛ рдХреЗрд╡рд▓ рдкрд┐рдЫрд▓реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдмрдврд╝рд╛ рджреЗрддрд╛ рдерд╛ред


рдЕрдВрддрд┐рдо рдореБрдЦреНрдп рдЖрдХрд░реНрд╖рдг рдпрд╣ рдерд╛ рдХрд┐ рдПрдиреАрдореЗрд╢рди рдХреЗ рджреМрд░рд╛рди, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрд╕ рджреВрд╕рд░реЗ рдкреГрд╖реНрда рдкрд░ рд╕реНрд╡рд╛рдЗрдк рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рджреЛ рдЯреНрд╡рд┐рди рд╕реНрдХреНрд░реАрди рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдиреЗ рдЗрд╕реЗ рд╡рд╛рдВрдЫрд┐рдд рд╕реНрдХреНрд░реАрди рдкрд░ рднреА рдЦреАрдВрдЪ рд▓рд┐рдпрд╛ред


рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рджрд┐рд▓рдЪрд╕реНрдк рдХрд▓рд╛рдХреГрддрд┐рдпрд╛рдБ (рдПрдиреАрдореЗрд╢рди - 2.7 mb)

рдпрд╣ рд░рд╛рдЬреНрдп рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрд░реЗ рдЕрдиреБрдХреВрд▓ рдирд╣реАрдВ рдереА, рдФрд░ рдореИрдВ, рдзрд░реНрдореА рдЧреБрд╕реНрд╕реЗ рд╕реЗ рднрд░рд╛, рдПрдХ рдФрд░ рд╕рдорд╛рдзрд╛рди рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рд▓рдЧрд╛ред


Viewpager рдореЗрдВ Shared Element Transition рдХреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреИрд╕реЗ рдХрд░реЗрдВ


рдкреЗрдЬрдЯреНрд░рд╛рдВрд╕рдлреЙрд░реНрдорд░ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ


рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рдЕрднреА рднреА рдХреЛрдИ рдЬрд╡рд╛рдм рдирд╣реАрдВ рдереЗ, рдФрд░ рдореИрдВрдиреЗ рд╕реЛрдЪрд╛: рдЗрд╕ рд╕рдВрдХреНрд░рдордг рдХреЛ рдФрд░ рдХреИрд╕реЗ рдХреНрд░реИрдВрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЪреЗрддрдирд╛ рдХреЗ рдЙрдкрд╕рдВрд╕реНрдерд╛рди рдореЗрдВ рдХреБрдЫ рдореЗрд░реЗ рд▓рд┐рдП рдлреБрд╕рдлреБрд╕рд╛рдП: " PageTransformer , рд▓реНрдпреВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред" рд╡рд┐рдЪрд╛рд░ рдореБрдЭреЗ рдЖрд╢рд╛рдЬрдирдХ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдФрд░ рдореИрдВрдиреЗ рд╕реБрдирдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред


PageTransformer рдмрдирд╛рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ, рдЬреЛ Android SET рдХреЗ рд╡рд┐рдкрд░реАрдд, setTransitionName(transitionName) рдФрд░ FragmentTransaction.addSharedElement(sharedElement,name) рдХрдИ рджреЛрд╣рд░рд╛рд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреАред рдпрд╣ рд╕реНрд╡рд╛рдЗрдк рдХреЗ рдмрд╛рдж рддрддреНрд╡реЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдЧрд╛ рдФрд░ рдлреЙрд░реНрдо рдХрд╛ рдПрдХ рд╕рд░рд▓ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реЛрдЧрд╛:


  public void addSharedTransition(int fromViewId, int toViewId) 

рд╣рдо рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдореИрдВ рдбреЗрдЯрд╛ рдХреЛ addSharedTransition(fromId, toId) рд╡рд┐рдзрд┐ рд╕реЗ Set рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Pair рд╕реЗ Set addSharedTransition(fromId, toId) рдФрд░ рдЗрд╕реЗ PageTransfomer рд╡рд┐рдзрд┐ рд╕реЗ рдкреНрд░рд╛рдкреНрдд PageTransfomer


 /**     ,   ,     */ public void transformPage(@NonNull View page, float position) 

рдЕрдВрджрд░, рдореИрдВ рд╕рднреА рд╕рд╣реЗрдЬреЗ рдЧрдП View рдЬреЛрдбрд╝реЗ рд╕реЗ рдЧреБрдЬрд░реВрдВрдЧрд╛, рдЬрд┐рдирдХреЗ рдмреАрдЪ рдореБрдЭреЗ рдПрдХ рдПрдиреАрдореЗрд╢рди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдФрд░ рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реВрдВрдЧрд╛ рддрд╛рдХрд┐ рдХреЗрд╡рд▓ рджреГрд╢реНрдп рддрддреНрд╡ рдПрдирд┐рдореЗрдЯреЗрдб рд╣реЛрдВред


рдкрд╣рд▓реЗ, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдПрдирд┐рдореЗрдЯреЗрдб рд╣реЛрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╡рд╛рд▓реЗ рддрддреНрд╡ рдмрдирд╛рдП рдЧрдП рд╣реИрдВ рдпрд╛ рдирд╣реАрдВред рд╣рдо рдЪреЙрд╕реА рдирд╣реАрдВ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдПрдиреАрдореЗрд╢рди рдХреА рд╢реБрд░реБрдЖрдд рд╕реЗ рдкрд╣рд▓реЗ View рдирд╣реАрдВ рдмрдирд╛рдпрд╛ View , рддреЛ рд╣рдо рдкреВрд░реЗ рдПрдиреАрдореЗрд╢рди ( рд╕рд╛рдЭрд╛ рддрддреНрд╡ рдЯреНрд░рд╛рдВрдЬрд╝рд┐рд╢рди рдХреА рддрд░рд╣ ) рдХреЛ рдирд╣реАрдВ рддреЛрдбрд╝реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЬрдм рддрддреНрд╡ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рдЙрдард╛рддреЗ рд╣реИрдВред


 for (Pair<Integer,Integer> idPair : sharedElementIds) { Integer fromViewId = idPair.first; Integer toViewId = idPair.second; View fromView = activity.findViewById(fromViewId); View toView = activity.findViewById(toViewId); if (fromView != null && toView != null) { 

рдореБрдЭреЗ рд╡реЗ рдкреГрд╖реНрда рдорд┐рд▓рддреЗ рд╣реИрдВ рдЬрд┐рдирдХреЗ рдмреАрдЪ рдореЗрдВ рдЖрдВрджреЛрд▓рди рд╣реЛрддрд╛ рд╣реИ (рдореИрдВ рдкреГрд╖реНрда рд╕рдВрдЦреНрдпрд╛ рдХреИрд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ рдиреАрдЪреЗ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛)ред


 View fromPage = pages.get(fromPageNumber); View toPage = pages.get(toPageNumber); 

рдпрджрд┐ рджреЛрдиреЛрдВ рдкреГрд╖реНрда рдкрд╣рд▓реЗ рд╕реЗ рдмрдиреЗ рд╣реИрдВ, рддреЛ рдореИрдВ рдЙрди рдкрд░ рдПрдХ рдЬреЛрдбрд╝реА рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рдореБрдЭреЗ рдЪреЗрддрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


 If (fromPage != null && toPage != null) { fromView = fromPage.findViewById(fromViewId); toView = toPage.findViewById(toViewId); 

рдЗрд╕ рд╕реНрддрд░ рдкрд░, рд╣рдордиреЗ рджреГрд╢реНрдп рдЪреБрдирд╛, рдЬреЛ рдЙрди рдкреГрд╖реНрдареЛрдВ рдкрд░ рд╕реНрдерд┐рдд рд╣реИ рдЬрд┐рдирдХреЗ рдмреАрдЪ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рддрд╛ рд╣реИред


рдпрд╣ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЪрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рдореИрдВ рд╕рдВрджрд░реНрдн рдмрд┐рдВрджреБрдУрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реВрдВ:


 //         //     float fromX = fromView.getX() - fromView.getTranslationX(); float fromY = fromView.getY() - fromView.getTranslationY(); float toX = toView.getX() - toView.getTranslationX(); float toY = toView.getY() - toView.getTranslationY(); float deltaX = toX - fromX; float deltaY = toY - fromY; //      float fromWidth = fromView.getWidth(); float fromHeight = fromView.getHeight(); float toWidth = toView.getWidth(); float toHeight = toView.getHeight(); float deltaWidth = toWidth - fromWidth; float deltaHeight = toHeight - fromHeight; //       boolean slideToTheRight = toPageNumber > fromPageNumber; 

рдЕрдВрддрд┐рдо рд╕реНрдирд┐рдкреЗрдЯ рдореЗрдВ, рдореИрдВрдиреЗ slideToTheRight рд╕реЗрдЯ slideToTheRight , рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред translation рдореЗрдВ рд╕рдВрдХреЗрдд рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ View рдЕрдкрдиреА рдЬрдЧрд╣ рдкрд░ рдЙрдбрд╝ рдЬрд╛рдПрдЧрд╛ рдпрд╛ рд╕реНрдХреНрд░реАрди рд╕реЗ рдХрд╣реАрдВ рджреВрд░ред


 float pageWidth = getScreenWidth(); float sign = slideToTheRight ? 1 : -1; float translationY = (deltaY + deltaHeight / 2) * sign * (-position); float translationX = (deltaX + sign * pageWidth + deltaWidth / 2) * sign * (-position); 

рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЖрд░рдВрднрд┐рдХ рдкреГрд╖реНрда рдФрд░ рдкрд░рд┐рдгрд╛рдореА рдкреГрд╖реНрда рдкрд░ рджреЛрдиреЛрдВ View рд▓рд┐рдП X рдФрд░ Y рд▓рд┐рдП рдСрдлрд╝рд╕реЗрдЯ рдлрд╝рд╛рд░реНрдореБрд▓реЛрдВ, рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдСрдлрд╝рд╕реЗрдЯреНрд╕ рдХреЗ рдмрд╛рд╡рдЬреВрдж рд╕рдорд╛рди рд╣реЛ рдЧрдПред


рд▓реЗрдХрд┐рди рдкреИрдорд╛рдиреЗ рдХреЗ рд╕рд╛рде, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдпрд╣ рдЪрд╛рд▓ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧреА - рдЖрдкрдХреЛ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ View рдПрдиреАрдореЗрд╢рди рдХрд╛ рд╢реБрд░реБрдЖрддреА рдпрд╛ рдЕрдВрдд рдмрд┐рдВрджреБ рд╣реИред


рдпрд╣ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╢реНрдЪрд░реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЖ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди transformPage(@NonNull View page, float position) рдХреЛ рдХрдИ рдмрд╛рд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: рдкреНрд░рддреНрдпреЗрдХ рдХреИрд╢реНрдб рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП (рдХреИрд╢ рдЖрдХрд╛рд░ рдЕрдиреБрдХреВрд▓рди рдпреЛрдЧреНрдп рд╣реИ)ред рдФрд░, transformPage() рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдХреЙрд▓ рдХреЗ рд▓рд┐рдП, рдХрдИ рдмрд╛рд░ рдПрдирд┐рдореЗрдЯреЗрдб View рдХреЛ рдлрд┐рд░ рд╕реЗ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдХреЗрд╡рд▓ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЛ рдмрджрд▓рддреЗ рд╣реИрдВ рдЬреЛ рд╡рд░реНрддрдорд╛рди page ред


рд╣рдо рдПрдирд┐рдореЗрдЯреЗрдб рддрддреНрд╡реЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдФрд░ рдкреИрдорд╛рдиреЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ
 //   View     if (page.findViewById(fromId) != null) { //      fromView.setTranslationX(translationX); fromView.setTranslationY(translationY); / /   float scaleX = (fromWidth == 0) ? 1 : //  View   , //        (fromWidth + deltaWidth * sign * (-position)) / fromWidth; float scaleY = (fromHeight == 0) ? 1 : //  View   , //        (fromHeight + deltaHeight * sign * (-position)) / fromHeight; fromView.setScaleX(scaleX); fromView.setScaleY(scaleY); } //   View     if (page.findViewById(toId) != null) { toView.setTranslationX(translationX); toView.setTranslationY(translationY); float scaleX = (toWidth == 0) ? 1 : (toWidth + deltaWidth * sign * (-position)) / toWidth; float scaleY = (toHeight == 0) ? 1 : (toHeight + deltaHeight * sign * (-position)) / toHeight; toView.setScaleX(scaleX); toView.setScaleY(scaleY); } 

рдПрдирд┐рдореЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкреГрд╖реНрдареЛрдВ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ


ViewPager рднреА рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреА рдЬрд▓реНрджреА ViewPager рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреМрди рд╕реЗ рдкреГрд╖реНрда рд╕реНрдХреНрд░реЙрд▓ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдерд╛, рдЕрдм рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдХреИрд╕реЗ рдорд┐рд▓рддреА рд╣реИред рд╣рдорд╛рд░реЗ PageTransformer рд╣рдо рдЕрднреА рддрдХ рдПрдХ рдФрд░ ViewPager.OnPageChangeListener рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред System.out.println() рдорд╛рдзреНрдпрдо рд╕реЗ onPageScrolled() рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж System.out.println() рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд onPageScrolled() рдЖрдпрд╛:


 public void onPageScrolled( int position, float positionOffset, int positionOffsetPixels ) { Set<Integer> visiblePages = new HashSet<>(); visiblePages.add(position); visiblePages.add(positionOffset >= 0 ? position + 1 : position - 1); visiblePages.remove(fromPageNumber); toPageNumber = visiblePages.iterator().next(); if (pages == null || toPageNumber >= pages.size()) toPageNumber = null; } public void onPageSelected(int position) { this.position = position; } public void onPageScrollStateChanged(int state) { if (state == SCROLL_STATE_IDLE) { //      ,    fromPageNumber = position; resetViewPositions(); } } 

рд╡рд╣ рд╕рдм рд╣реИред рд╣рдордиреЗ рдХрд░ рджрд┐рдЦрд╛рдпрд╛! рдПрдиреАрдореЗрд╢рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЗрд╢рд╛рд░реЛрдВ рдкрд░ рдирдЬрд╝рд░ рд░рдЦрддрд╛ рд╣реИред рдЬрдм рдЖрдк рд╕рдм рдХреБрдЫ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рд╕реНрд╡рд╛рдЗрдк рдФрд░ рд╢реЗрдпрд░реНрдб рдПрд▓реАрдореЗрдВрдЯ рдЯреНрд░рд╛рдВрдЬрд╝рд┐рд╢рди рдХреЗ рдмреАрдЪ рдЪрдпрди рдХреНрдпреЛрдВ рдХрд░реЗрдВред


рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрддреЗ рд╕рдордп, рдореИрдВрдиреЗ рд╕реНрдереИрддрд┐рдХ рддрддреНрд╡реЛрдВ рдХреЗ рдЧрд╛рдпрдм рд╣реЛрдиреЗ рдХреЗ рдкреНрд░рднрд╛рд╡ рдХреЛ рдЬреЛрдбрд╝рд╛ - рдпрд╣ рдЕрднреА рднреА рдмрд╣реБрдд рдХрдЪреНрдЪрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдирд╣реАрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред


рджреЗрдЦреЗрдВ рдХрд┐ рдЕрдВрдд рдореЗрдВ рдХреНрдпрд╛ рд╣реБрдЖ (рдПрдиреАрдореЗрд╢рди - 2.4 рдПрдордмреА)

рд╕рдВрдкреВрд░реНрдг рд╕реНрд░реЛрдд рдХреЛрдб
/**
* PageTransformer that allows you to do shared element transitions between pages in ViewPager.
* It requires view pager sides match screen sides to function properly. I.e. ViewPager page width
* must be equal to screen width. <br/>
* Usage:<br/>
* <code>
* sharedElementPageTransformer.addSharedTransition(R.id.FirstPageTextView, R.id.SecondPageTextView)</code>
* </code>
*
*
*/
public class SharedElementPageTransformer implements ViewPager.PageTransformer, ViewPager.OnPageChangeListener {
/** Android need the correction while view scaling for some reason*/
private static float MAGICAL_ANDROID_RENDERING_SCALE = 1;
// private static float MAGICAL_ANDROID_RENDERING_SCALE = 0.995f;
// External variables
private final Activity activity;
List<Fragment> fragments;
private Set<Pair<Integer,Integer>> sharedElementIds = new HashSet<>();
//Internal variables
private List<View> pages;
private Map<View, Integer> pageToNumber = new HashMap<>();
private Integer fromPageNumber = 0;
private Integer toPageNumber;
/** current view pager position */
private int position;
/**
* @param activity activity that hosts view pager
* @param fragments fragment that are in view pager in the SAME ORDER
*/
public SharedElementPageTransformer(Activity activity, List<Fragment> fragments) {
this.activity = activity;
this.fragments = fragments;
}
@Override
public void transformPage(@NonNull View page, float position) {
updatePageCache();
if (fromPageNumber == null || toPageNumber == null) return;
for (Pair<Integer,Integer> idPair : sharedElementIds) {
Integer fromViewId = idPair.first;
Integer toViewId = idPair.second;
View fromView = activity.findViewById(fromViewId);
View toView = activity.findViewById(toViewId);
if (fromView != null && toView != null) {
//Looking if current Shared element transition matches visible pages
View fromPage = pages.get(fromPageNumber);
View toPage = pages.get(toPageNumber);
if (fromPage != null && toPage != null) {
fromView = fromPage.findViewById(fromViewId);
toView = toPage.findViewById(toViewId);
// if both views are on pages user drag between apply transformation
if (
fromView != null
&& toView != null
) {
// saving shared element position on the screen
float fromX = fromView.getX() - fromView.getTranslationX();
float fromY = fromView.getY() - fromView.getTranslationY();
float toX = toView.getX() - toView.getTranslationX();
float toY = toView.getY() - toView.getTranslationY();
float deltaX = toX - fromX;
float deltaY = toY - fromY;
// scaling
float fromWidth = fromView.getWidth();
float fromHeight = fromView.getHeight();
float toWidth = toView.getWidth();
float toHeight = toView.getHeight();
float deltaWidth = toWidth - fromWidth;
float deltaHeight = toHeight - fromHeight;
int fromId = fromView.getId();
int toId = toView.getId();
boolean slideToTheRight = toPageNumber > fromPageNumber;
if (position <= -1) {
} else if (position < 1) {
float pageWidth = getSceenWidth();
float sign = slideToTheRight ? 1 : -1;
float translationY = (deltaY + deltaHeight / 2) * sign * (-position);
float translationX = (deltaX + sign * pageWidth + deltaWidth / 2) * sign * (-position);
if (page.findViewById(fromId) != null) {
fromView.setTranslationX(translationX);
fromView.setTranslationY(translationY);
float scaleX = (fromWidth == 0) ? 1 : (fromWidth + deltaWidth * sign * (-position)) / fromWidth;
float scaleY = (fromHeight == 0) ? 1 : (fromHeight + deltaHeight * sign * (-position)) / fromHeight;
fromView.setScaleX(scaleX);
fromView.setScaleY(scaleY * MAGICAL_ANDROID_RENDERING_SCALE);
}
if (page.findViewById(toId) != null) {
toView.setTranslationX(translationX);
toView.setTranslationY(translationY);
float scaleX = (toWidth == 0) ? 1 : (toWidth + deltaWidth * sign * (-position)) / toWidth;
float scaleY = (toHeight == 0) ? 1 :(toHeight + deltaHeight * sign * (-position)) / toHeight;
toView.setScaleX(scaleX);
toView.setScaleY(scaleY);
}
} else {
}
}
}
}
}
}
private float getSceenWidth() {
Point outSize = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(outSize);
return outSize.x;
}
/**
* Creating page cache array to determine if shared element on
* currently visible page
*/
private void updatePageCache() {
pages = new ArrayList<>();
for (int i = 0; i < fragments.size(); i++) {
View pageView = fragments.get(i).getView();
pages.add(pageView);
pageToNumber.put(pageView, i);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Set<Integer> visiblePages = new HashSet<>();
visiblePages.add(position);
visiblePages.add(positionOffset >= 0 ? position + 1 : position - 1);
visiblePages.remove(fromPageNumber);
toPageNumber = visiblePages.iterator().next();
if (pages == null || toPageNumber >= pages.size()) toPageNumber = null;
}
@Override
public void onPageSelected(int position) {
this.position = position;
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == SCROLL_STATE_IDLE) {
fromPageNumber = position;
resetViewPositions();
}
}
private void resetViewPositions() {
for (Pair<Integer, Integer> idPair : sharedElementIds) {
View sharedElement = activity.findViewById(idPair.first);
if(sharedElement != null) {
sharedElement.setTranslationX(0);
sharedElement.setTranslationY(0);
sharedElement.setScaleX(1);
sharedElement.setScaleY(1);
}
sharedElement = activity.findViewById(idPair.second);
if(sharedElement != null) {
sharedElement.setTranslationX(0);
sharedElement.setTranslationY(0);
sharedElement.setScaleX(1);
sharedElement.setScaleY(1);
}
}
}
/**
* Set up shared element transition from element with <code>fromViewId</code> to
* element with <code>toViewId</code>. Note that you can setup each transition
* direction separately. e.g. <br/>
* <code>addSharedTransition(R.id.FirstPageTextView, R.id.SecondPageTextView)</code><br/>
* and<br/>
* <code>addSharedTransition(R.id.SecondPageTextView, R.id.FirstPageTextView)</code><br/>
* are different.
* @param fromViewId
* @param toViewId
*/
public void addSharedTransition(int fromViewId, int toViewId) {
addSharedTransition(fromViewId, toViewId, false);
}
/**
* Set up shared element transition from element with <code>fromViewId</code> to
* element with <code>toViewId</code>. Note that you can setup each transition
* direction separately. e.g. <br/>
* <code>addSharedTransition(R.id.FirstPageTextView, R.id.SecondPageTextView)</code><br/>
* and<br/>
* <code>addSharedTransition(R.id.SecondPageTextView, R.id.FirstPageTextView)</code><br/>
* are different.
* @param fromViewId
* @param toViewId
* @param bothDirections to include backward transition from toViewId to fromViewId aswell
*/
public void addSharedTransition(int fromViewId, int toViewId, boolean bothDirections) {
sharedElementIds.add(new Pair<>(fromViewId, toViewId));
if(bothDirections) {
sharedElementIds.add(new Pair<>(toViewId, fromViewId));
}
}
/**
* In case there is "ladder" appears between while transition.
* You may try to tune that magical scale to get rid of it.
* @param magicalAndroidRenderingScale float between 0 and infinity. Typically very close to 1.0
*/
public static void setMagicalAndroidRenderingScale(float magicalAndroidRenderingScale) {
MAGICAL_ANDROID_RENDERING_SCALE = magicalAndroidRenderingScale;
}
}

рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ


рд╡рд┐рдиреНрдпрд╛рд╕ рдмрд╣реБрдд рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдирд┐рдХрд▓рд╛ред


рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рд╕реЗрдЯрдЕрдк рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ
 ArrayList<Fragment> fragments = new ArrayList<>(); fragments.add(hello_fragment); fragments.add(small_picture_fragment); fragments.add(big_picture_fragment); SharedElementPageTransformer transformer = new SharedElementPageTransformer(this, fragments); transformer.addSharedTransition(R.id.smallPic_image_cat2, R.id.bigPic_image_cat, true); transformer.addSharedTransition(R.id.smallPic_text_label3, R.id.bigPic_text_label, true); transformer.addSharedTransition(R.id.hello_text, R.id.smallPic_text_label3, true); viewPager.setPageTransformer(false, transformer); viewPager.addOnPageChangeListener(transformer); 

рд╕рднреА рд╕рдВрдХреНрд░рдордг рд╕рд╣рд┐рдд onClick , рдЗрд╕ рддрд░рд╣ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:


 smallCatImageView.setOnClickListener( v -> activity.viewPager.setCurrentItem(2) ); 

рддрд╛рдХрд┐ рдХреЛрдб рдЧрд╛рдпрдм рди рд╣реЛ рдЬрд╛рдП, рдореИрдВрдиреЗ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдЬреЗрд╕реАрдЯрд░ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдФрд░ рдЧрд┐рдЯрд╣рдм рдореЗрдВ рдбрд╛рд▓ рджрд┐рдпрд╛ред рдЗрд╕рд▓рд┐рдП рдореИрдВ рдУрдкрдирд╕реЛрд░реНрд╕ рдХреА рджреБрдирд┐рдпрд╛ рдХреЗ рд╕рдВрдкрд░реНрдХ рдореЗрдВ рдЖ рдЧрдпрд╛ред рдЖрдк рдЗрд╕реЗ рдХреЗрд╡рд▓ рдЬреЛрдбрд╝рдХрд░ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рдЖрдЬрдорд╛ рд╕рдХрддреЗ рд╣реИрдВ


 dependencies { //... implementation 'com.github.kirillgerasimov:shared-element-view-pager:0.0.2-alpha' } 

GitHub рдкрд░ рд╕рднреА рд╕реНрд░реЛрдд рдЙрдкрд▓рдмреНрдз рд╣реИрдВ


рдирд┐рд╖реНрдХрд░реНрд╖


рднрд▓реЗ рд╣реА рдЗрдВрдЯрд░рдиреЗрдЯ рдХреЛ рдЬрд╡рд╛рдм рдирд╣реАрдВ рдкрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдирд╣реАрдВ рд╣реИред Workarounds рдХреЗ рд▓рд┐рдП рджреЗрдЦреЛ, рдЬрдм рддрдХ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЛред рд╢рд╛рдпрдж рдЖрдк рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЗрд╕ рддрд╣ рддрдХ рдкрд╣реБрдВрдЪреЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рд╕рдореБрджрд╛рдп рдХреЗ рд╕рд╛рде рд╕рд╛рдЭрд╛ рдХрд░реЗрдВрдЧреЗред

Source: https://habr.com/ru/post/hi451116/


All Articles