рджреБрдирд┐рдпрд╛ рдореЗрдВ рдХреЛрдИ рджреБрдЦ рдХреА рдХрд╣рд╛рдиреА рдирд╣реАрдВ рд╣реИ 
ViewPager'e рдФрд░ SET'e рдХреА рдХрд╣рд╛рдиреА рдХреА рддреБрд▓рдирд╛ рдореЗрдВ
рдореИрдВ рдЪреЗрддрд╛рд╡рдиреА рджреЗрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рд▓реЗрдЦрдХ рдПрдХ рдиреМрд╕рд┐рдЦрд┐рдпрд╛ рдПрдВрдбреНрд░реЙрдЗрдб рд╣реИ, рдЗрд╕рд▓рд┐рдП рд▓реЗрдЦ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рддрдХрдиреАрдХреА рдЕрд╢реБрджреНрдзрд┐рдпрд╛рдВ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рдмрд▓реНрдХрд┐ рдЪреЗрддрд╛рд╡рдиреА рджреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП рдХрд┐ рд▓реЗрдЦ рдореЗрдВ рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдХрдерди рджрд┐рдЦрд╛рдИ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред
рдЬрд╣рд╛рдВ рдмреИрдХрдПрдВрдб рд╣реЛрддрд╛ рд╣реИ
рдореЗрд░реЗ рд╕рд╛рд░реЗ рдЬреАрд╡рди рдореЗрдВ рдореИрдВрдиреЗ рдмреИрдХрдПрдВрдб рдХреЛ рджреЗрдЦрд╛ред 2019 рдХреА рд╢реБрд░реБрдЖрдд, рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдорд╣рддреНрд╡рд╛рдХрд╛рдВрдХреНрд╖реА рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдзреВрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИред рдПрдХ рдЦреЛрдЬ рдХрдВрдкрдиреА рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рдХреНрд╖рд╛рддреНрдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдЬреНрдпреВрд░рд┐рдЦ рдореЗрдВ рдПрдХ рдмреЗрдХрд╛рд░ рдпрд╛рддреНрд░рд╛ред рд╕рд░реНрджреА, рдЧрдВрджрдЧреА, рдореВрдб рдирд╣реАрдВред рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдФрд░ рдЖрдЧреЗ рдЦреАрдВрдЪрдиреЗ рдХреА рдХреЛрдИ рддрд╛рдХрдд рдФрд░ рдЗрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реИред
рдореИрдВ рдЗрд╕ рднрдпрд╛рдирдХ рдмреИрдХрдПрдВрдб рдХреЛ рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рднреВрд▓ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рднрд╛рдЧреНрдп рдиреЗ рдореБрдЭреЗ рдПрдХ рд╡рд┐рдЪрд╛рд░ рджрд┐рдпрд╛ - рдпрд╣ рдПрдХ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдерд╛ред рдЗрд╕рдХреА рдореБрдЦреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреИрдорд░реЗ рдХрд╛ рдЧреИрд░-рдорд╛рдирдХ рдЙрдкрдпреЛрдЧ рд╣реЛрдирд╛ рдерд╛ред рдХрд╛рдо рдореЗрдВ рдЙрдмрд╛рд▓ рдЖрдиреЗ рд▓рдЧрд╛ред рдЗрд╕рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рдордп рд▓рдЧрд╛, рдФрд░ рдЕрдм рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рддреИрдпрд╛рд░ рд╣реИред рдЬрдм рддрдХ рдореИрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ " рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ " рдмрдирд╛рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рдирд╣реАрдВ рд▓реЗрддрд╛, рддрдм рддрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рд░рд┐рд▓реАрдЬ рдХрд░реАрдм рдЖ рд░рд╣реА рдереА рдФрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рдФрд░ рд╕реБрд╡реНрдпрд╡рд╕реНрдерд┐рдд рдерд╛ред
рдХреЛрдИ рднреА 2019 рдореЗрдВ рдЫреЛрдЯреЗ рдореЗрдиреВ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рд╕рднреА рджрд╛рдПрдВ рдФрд░ рдмрд╛рдПрдВ рд╡реЗ рд╕реНрдХреНрд░реАрди рдХреЛ рд╕реНрд╡рд╛рдЗрдк рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ - рдХрд┐рдпрд╛, рдХрд┐рдпрд╛ - рдХрд┐рдпрд╛ред рддреЛ рдкрд╣рд▓рд╛ ViewPager рдореЗрд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкрд░ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ (рдореИрдВрдиреЗ рдореЗрд░реЗ рдЬреИрд╕реЗ рд╣реА рдмреИрдХрдПрдВрдб рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╢рд░реНрддреЗрдВ рддрдп рдХреА рд╣реИрдВ - рдмрд╕ рдХрд░реНрд╕рд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ)ред рдФрд░ рд╕рд╛рдЭрд╛ рддрддреНрд╡ рд╕рдВрдХреНрд░рдордг (рдмрд╛рдж рдореЗрдВ рд╕реЗрдЯ рдпрд╛ рд╕рдВрдХреНрд░рдордг) - рд╕рд╛рдордЧреНрд░реА рдбрд┐рдЬрд╝рд╛рдЗрди рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рддрддреНрд╡, рдиреЗ рдореБрдЭреЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝рдХрд░ рдПрдХ ViewPager рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рдЗрдирдХрд╛рд░ рдХрд░ рджрд┐рдпрд╛: рд╕реНрдХреНрд░реАрди рдХреЗ рдмреАрдЪ рдпрд╛ рддреЛ рд╕реНрд╡рд╛рдЗрдк, рдпрд╛ рд╕реБрдВрджрд░ рд╕рдВрдХреНрд░рдордг рдПрдирд┐рдореЗрд╢рдиред рдореИрдВ рдПрдХ рдпрд╛ рджреВрд╕рд░реЗ рдХреЛ рдордирд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдЗрд╕рд▓рд┐рдП рдореЗрд░реА рдЦреЛрдЬ рд╢реБрд░реВ рд╣реБрдИред
рдЕрдзреНрдпрдпрди рдХреЗ рдШрдВрдЯреЗ: рдордВрдЪреЛрдВ рдкрд░ рджрд░реНрдЬрдиреЛрдВ рд╡рд┐рд╖рдп рдФрд░ StackOverflow рдкрд░ рдЕрдиреБрддреНрддрд░рд┐рдд рдкреНрд░рд╢реНрдиред рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдореИрдВ рдХреНрдпрд╛ рдЦреЛрд▓рддрд╛ рд╣реВрдВ, рдореБрдЭреЗ RecyclerView рд╕реЗ ViewPager рдореЗрдВ рдПрдХ рд╕рдВрдХреНрд░рдордг рдмрдирд╛рдиреЗ рдпрд╛ "рдПрдХ рдкреНрд▓рд╛рдВрдЯреИрди Fragment.postponeEnterTransition() " рд╕рдВрд▓рдЧреНрди рдХрд░рдиреЗ рдХреА рдкреЗрд╢рдХрд╢ рдХреА рдЧрдИ рдереАред
рд▓реЛрдХ рдЙрдкрдЪрд╛рд░ рдиреЗ рдорджрдж рдирд╣реАрдВ рдХреА, рдФрд░ рдореИрдВрдиреЗ ViewPager рдФрд░ Shared Element Transition рд╕реНрд╡рдпрдВ рдореЗрдВ рд╕рдореЗрдЯрдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред
рдореИрдВрдиреЗ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛: "рд╕рдорд╕реНрдпрд╛ рдЙрд╕ рд╕рдордп рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХ рдкреГрд╖реНрда рд╕реЗ рджреВрд╕рд░реЗ рдкреГрд╖реНрда рдкрд░ рдЬрд╛рддрд╛ рд╣реИ ..."ред рдФрд░ рдлрд┐рд░ рдпрд╣ рдореБрдЭ рдкрд░ рд╣рд╛рд╡реА рд╣реЛ рдЧрдпрд╛: "рдпрджрд┐ рдЖрдк рдкреГрд╖реНрда рдирд╣реАрдВ рдмрджрд▓рддреЗ рд╣реИрдВ, рддреЛ рдкреГрд╖реНрда рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рджреМрд░рд╛рди рдЖрдкрдХреЛ SET рд╕реЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрдЧреА"ред
рд╣рдо рдПрдХ рд╣реА рдкреГрд╖реНрда рдкрд░ рд╕рдВрдХреНрд░рдордг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╡рд░реНрддрдорд╛рди рдкреГрд╖реНрда рдХреЛ ViewPager рдореЗрдВ рд▓рдХреНрд╖реНрдп рдкреГрд╖реНрда рд╕реЗ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЯреБрдХрдбрд╝реЗ рдмрдирд╛рдПрдВ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╣рдо рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред
 SmallPictureFragment small_picture_fragment = new SmallPictureFragment(); BigPictureFragment big_picture_fragment = new BigPictureFragment(); 
рдЖрдЗрдП рд╡рд░реНрддрдорд╛рди рдкреГрд╖реНрда рдореЗрдВ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдХреБрдЫ рдФрд░ рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ ... рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рд░рд┐рдХреНрдд рд╕реНрдХреНрд░реАрди рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдХрд╛рд░рдг рд╣реИ?
рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ 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( () -> {  
рдкрд░рд┐рдгрд╛рдо рдХреНрдпрд╛ рд╣реИ? (рдПрдиреАрдореЗрд╢рди - реи. - 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) рдпрд╣ рд░рд╛рдЬреНрдп рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрд░реЗ рдЕрдиреБрдХреВрд▓ рдирд╣реАрдВ рдереА, рдФрд░ рдореИрдВ, рдзрд░реНрдореА рдЧреБрд╕реНрд╕реЗ рд╕реЗ рднрд░рд╛, рдПрдХ рдФрд░ рд╕рдорд╛рдзрд╛рди рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рд▓рдЧрд╛ред
рдкреЗрдЬрдЯреНрд░рд╛рдВрд╕рдлреЙрд░реНрдорд░ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ
рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рдЕрднреА рднреА рдХреЛрдИ рдЬрд╡рд╛рдм рдирд╣реАрдВ рдереЗ, рдФрд░ рдореИрдВрдиреЗ рд╕реЛрдЪрд╛: рдЗрд╕ рд╕рдВрдХреНрд░рдордг рдХреЛ рдФрд░ рдХреИрд╕реЗ рдХреНрд░реИрдВрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЪреЗрддрдирд╛ рдХреЗ рдЙрдкрд╕рдВрд╕реНрдерд╛рди рдореЗрдВ рдХреБрдЫ рдореЗрд░реЗ рд▓рд┐рдП рдлреБрд╕рдлреБрд╕рд╛рдП: " 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); 
рдЗрд╕ рд╕реНрддрд░ рдкрд░, рд╣рдордиреЗ рджреГрд╢реНрдп рдЪреБрдирд╛, рдЬреЛ рдЙрди рдкреГрд╖реНрдареЛрдВ рдкрд░ рд╕реНрдерд┐рдд рд╣реИ рдЬрд┐рдирдХреЗ рдмреАрдЪ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЪрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рдореИрдВ рд╕рдВрджрд░реНрдн рдмрд┐рдВрджреБрдУрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реВрдВ:
 
рдЕрдВрддрд┐рдо рд╕реНрдирд┐рдкреЗрдЯ рдореЗрдВ, рдореИрдВрдиреЗ 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 ред
рд╣рдо рдПрдирд┐рдореЗрдЯреЗрдб рддрддреНрд╡реЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдФрд░ рдкреИрдорд╛рдиреЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдПрдирд┐рдореЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкреГрд╖реНрдареЛрдВ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ
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) {  
рд╡рд╣ рд╕рдм рд╣реИред рд╣рдордиреЗ рдХрд░ рджрд┐рдЦрд╛рдпрд╛! рдПрдиреАрдореЗрд╢рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЗрд╢рд╛рд░реЛрдВ рдкрд░ рдирдЬрд╝рд░ рд░рдЦрддрд╛ рд╣реИред рдЬрдм рдЖрдк рд╕рдм рдХреБрдЫ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рд╕реНрд╡рд╛рдЗрдк рдФрд░ рд╢реЗрдпрд░реНрдб рдПрд▓реАрдореЗрдВрдЯ рдЯреНрд░рд╛рдВрдЬрд╝рд┐рд╢рди рдХреЗ рдмреАрдЪ рдЪрдпрди рдХреНрдпреЛрдВ рдХрд░реЗрдВред
рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрддреЗ рд╕рдордп, рдореИрдВрдиреЗ рд╕реНрдереИрддрд┐рдХ рддрддреНрд╡реЛрдВ рдХреЗ рдЧрд╛рдпрдм рд╣реЛрдиреЗ рдХреЗ рдкреНрд░рднрд╛рд╡ рдХреЛ рдЬреЛрдбрд╝рд╛ - рдпрд╣ рдЕрднреА рднреА рдмрд╣реБрдд рдХрдЪреНрдЪрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдирд╣реАрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред
рджреЗрдЦреЗрдВ рдХрд┐ рдЕрдВрдд рдореЗрдВ рдХреНрдпрд╛ рд╣реБрдЖ (рдПрдиреАрдореЗрд╢рди - 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 {  
GitHub рдкрд░ рд╕рднреА рд╕реНрд░реЛрдд рдЙрдкрд▓рдмреНрдз рд╣реИрдВ
рдирд┐рд╖реНрдХрд░реНрд╖
рднрд▓реЗ рд╣реА рдЗрдВрдЯрд░рдиреЗрдЯ рдХреЛ рдЬрд╡рд╛рдм рдирд╣реАрдВ рдкрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдирд╣реАрдВ рд╣реИред Workarounds рдХреЗ рд▓рд┐рдП рджреЗрдЦреЛ, рдЬрдм рддрдХ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЛред рд╢рд╛рдпрдж рдЖрдк рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЗрд╕ рддрд╣ рддрдХ рдкрд╣реБрдВрдЪреЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рд╕рдореБрджрд╛рдп рдХреЗ рд╕рд╛рде рд╕рд╛рдЭрд╛ рдХрд░реЗрдВрдЧреЗред