Android рдореЗрдВ SlideStackView рдпрд╛ ViewGroup рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░

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

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

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






рд╕реНрд▓рд╛рдЗрдбрд╕реНрдЯреИрдХ рд╡реНрдпреВ рдирд╛рдордХ рдирд┐рдпрдВрддреНрд░рдг рдХреЛ рдХреИрд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд┐рдХрд╛рд╕ рдкрдХреНрд╖ рдФрд░ рдЙрддреНрдкрд╛рдж рджреЛрдиреЛрдВ рд╕реЗ рдХреБрдЫ рдФрд░ рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рдереАрдВ:

1. рдкреНрд░рддреНрдпреЗрдХ рд╕реНрд▓рд╛рдЗрдб рдХреЛ рдПрдХ рдЯреБрдХрдбрд╝реЗ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
2. рдПрдХ "рд╕реНрдХреНрд░реЙрд▓ рдкреНрд░рднрд╛рд╡ рдкрд░ рдЙрдЫрд▓" рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП - рдЬрдм рд╕реНрд▓рд╛рдЗрдб рдХрд┐рдирд╛рд░реЗ рд╕реЗ рдмрд╣рд╛рд░ рд╣реЛ
3. рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЗ рдЕрдВрджрд░ рдХреА рд╡рд░реНрдЯрд┐рдХрд▓ рд▓рд┐рд╕реНрдЯ рдХреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рдЧреНрд▓рд┐рдЯреНрд╕ рдХреЗ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
4. рд╕реЗрд╡рд┐рдВрдЧ \ рд░реАрд╕реНрдЯреЛрд░рд┐рдВрдЧ рд╕реНрдЯреЗрдЯ (рдЦреБрд▓реА рд╕реНрд▓рд╛рдЗрдб рдХреА рд╕реНрдерд┐рддрд┐, рдЖрджрд┐)

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

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

public class SlideStackView extends ViewGroup{ public SlideStackView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); ... initAttributes(context, attrs); // we need to draw childs in reverse order setChildrenDrawingOrderEnabled(true); } public SlideStackView(Context context, AttributeSet attrs) { this(context, attrs, android.R.style.Theme_Black); } public SlideStackView(Context context) { this(context, null); } 

рдпрд╣рд╛рдВ рдХреА рд╡рд┐рд╢реЗрд╖ рдЪреАрдЬреЛрдВ рдореЗрдВ рд╕реЗ, рдЖрдк рдХреЗрд╡рд▓ рдпрд╣ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЖрдкрдХреЛ рдЕрдкрдиреА рд╕реНрд▓рд╛рдЗрдб рдмрдирд╛рддреЗ рд╕рдордп рдПрдХ рдЧреИрд░-рдорд╛рдирдХ рдЖрджреЗрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВред рд╢реБрд░реВ рдореЗрдВ рднреНрд░рдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реА рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рджрд╛рдПрдВ рд╕реЗ рдмрд╛рдПрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╕реЗ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдкрд╣рд▓реЗ рдЕрдХреНрд╖рд░реЛрдВ рдХреА рд╕реВрдЪреА (# 0) рдХреЗ рд╕рд╛рде рд╕реНрд▓рд╛рдЗрдб рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЬрдм рд╣рдо рдЗрд╕реЗ рдмрдВрдж рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╕реНрд▓рд╛рдЗрдб рдХреЛ рдлрд╝реЛрд▓реНрдбрд░реНрд╕ рдХреА рд╕реВрдЪреА (# 1) рдХреЗ рд╕рд╛рде рджреЗрдЦреЗрдВрдЧреЗ, рдФрд░ рдЕрдВрддрд┐рдо рд╣рдо рдЦрд╛рддреЛрдВ рдХреА рд╕реВрдЪреА (# 2) рдХреЗ рд╕рд╛рде рд╕реНрд▓рд╛рдЗрдб рджреЗрдЦреЗрдВрдЧреЗред рд╡реНрдпреВрдЧреНрд░реБрдк рдХреЗ рдирдВрдмрд░рд┐рдВрдЧ рдореЗрдВ, рд╕рд╛рдорд╛рдиреНрдп рдХреНрд░рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реЛрддрд╛ рд╣реИ - рдЕрд░реНрдерд╛рдд, рдмрд╛рдПрдВ рд╕реЗ рджрд╛рдПрдВ, рджреЛрдиреЛрдВ рд╕реНрд▓рд╛рдЗрдб рдЬреЛрдбрд╝рддреЗ рд╕рдордп, рдФрд░ рдЬрдм рд╡реЗ рдЖрдЧреЗ рдЦреАрдВрдЪреЗ рдЬрд╛рддреЗ рд╣реИрдВ, рддреИрдирд╛рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдЖрджрд┐ред рдпрд╣рд╛рдБ рдмрд╛рдд рдпрд╣ рднреА рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдкреНрд░рдерд╛рдЧрдд рд╣реИ, рдпрд╛ рдЗрд╕реЗ рдХреЛрдб рдХреА рдПрдХ рдкрдВрдХреНрддрд┐ рд╕реЗ рдХрдо рд▓рд┐рдЦрд╛ рдЬрд╛рдирд╛ рд╣реЛрдЧрд╛ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ MotionEvents рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред рдЬрдм рдЙрдиреНрд╣реЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЪрд┐рд▓реНрдб рдХрд╛ рд╕рд░рдгреА 0 рд╕реЗ рдЪрд╛рдЗрд▓реНрдбрдХрд╛рдЙрдВрдЯ рддрдХ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрджрд┐ рд╢реАрд░реНрд╖ рд╕реНрд▓рд╛рдЗрдб рдХреЛ рдиреАрдЪреЗ рдХреА рддрд░рдл рд╕реЗ рдКрдкрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдЕрдкрдиреЗ рдмрдЪреНрдЪреЛрдВ рдХреЛ рдЙрд╕ рд╕реНрд▓рд╛рдЗрдб рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдиреАрдЪреЗ рд╕реЗ рдКрдкрд░ рддрдХ рдХреНрд░реЙрд▓ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рд╕рдВрдЪрд╛рд░рд┐рдд рдореЛрд╢рди рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддрд╛ рд╣реИред рдЬрдм рд╣рдо MotionEvents рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдореИрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ рдЕрдХреНрд╕рд░ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ:

  /** * Same as {@link #getChildAt(int)} but uses adapter's * slide order in depending on the actual child order * in the view group * @param position position of the child to be retrieved * @return view in specified */ private View getChild(int position){ return getChildAt(getChildCount() - 1 - position); } 


рдлрд┐рд░, рдбреНрд░рд╛рдЗрдВрдЧ рдХреНрд░рдо рдореЗрдВ, рд╣рдореЗрдВ рдХреБрдЫ рднреА рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ:

  /** * Use this to manage child drawing order. We should draw * the slide #{lastSlide} (in adapter's data set indexes) first. Then draw * the slide with #{lastSlide - 1} and so on until the slide #0 inclusive * <p> * {@inheritDoc} */ @Override protected int getChildDrawingOrder(int childCount, int i) { //draw the last slide first. /** * __________ * __|0 | * |1 | | * | | | * | |__________| * |__________| */ return /*childCount - */i /*- 1*/; } 


рдЕрдм рдордЬрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдмреЗрд╢рдХ, рд╣рдо рд╕реНрд▓рд╛рдЗрдб рджрд┐рдЦрд╛рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рд╕рдВрдЦреНрдпрд╛ рд╡рд┐рд╡рд┐рдз рд╣реЛ рд╕рдХрддреА рд╣реИред рдПрдВрдбреНрд░реЙрдЗрдб рдлреНрд░реЗрдорд╡рд░реНрдХ рдЯреАрдо рдореЗрдВ, рд╣рдордиреЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рддрдерд╛рдХрдерд┐рдд рдПрдбрд╛рдкреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ - рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рджреГрд╖реНрдЯрд┐рдХреЛрдг, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рдХрд░реЗрдВрдЧреЗред рдФрд░ рд╣рдорд╛рд░реЗ рд╕рдмрд╕реЗ рдирдЬрд╝рджреАрдХ рдмрд╕ рдПрдбрд╛рдкреНрдЯрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ рдЬреЛ рдХрд┐ ViewPager рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рд╣рдореЗрдВ рдЗрд╕ рдПрдбрд╛рдкреНрдЯрд░ рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд░рд┐рд╡рд░реНрддрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рд▓реЗрдХрд┐рди рдмрд╛рдж рдореЗрдВ рдЗрд╕ рдкрд░ рдФрд░ рдЕрдзрд┐рдХред

  /** * Used in case we have no valid position or actual position * can not be found. */ static final int INVALID_POSITION = -1; /** * Index of the first element from adapter's data set * added to the layout of the slide stack */ private int mFirst; /** * Current selected slide position in adapter's data set */ private int mSelected; /** * A data set adapter that prepares view for the slide stack view * and is responsible for base information about the containing * data set. */ private SlideStateAdapter mAdapter; /** * {@link DataSetObserver} that indicates about changes in slides * data set */ private final DataSetObserver mObserver = new Observer(); /** * Sets the adapter for providing the SlideStackView with * slides. * @param adapter */ public void setAdapter(SlideStateAdapter adapter){ if (mAdapter != null){ mAdapter.unregDataSetObserver(mObserver); mFirst = INVALID_POSITION; mScroller.stopScrolling(); removeAllViews(); } if(adapter != null){ mAdapter = adapter; mAdapter.regDataSetObserver(mObserver); } } 

рдЬрд╣рд╛рдВ рдХреНрд▓рд╛рд╕ рдСрдмреНрдЬрд░реНрд╡рд░ рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
  private final class Observer extends DataSetObserver{ @Override public void onChanged() { //empty } @Override public void onInvalidated() { //empty } } 


рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдПрдбреЗрдкреНрдЯрд░ рд╣реИ рдЬреЛ рд╣рдо рджрд┐рдЦрд╛рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рд╣рдо рдЗрд╕реЗ рдХреИрд╕реЗ рдХрд░реЗрдВрдЧреЗ рдХреЗ рдмреАрдЪ рдПрдХ рдХрдбрд╝реА рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред

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

  public static class SlideScroller extends Scroller implements OnTouchListener{ private final ScrollingListener mListener; private final GestureDetector mGestureDetector; public SlideScroller(Context context, ScrollingListener listener, OnGestureListener gestureListener) { super(context); this.mListener = listener; this.mGestureDetector = new GestureDetector(context, gestureListener); mGestureDetector.setIsLongpressEnabled(false); } public void scroll(int distance, int time) { // ... } public void fling(int velocity){ ... } public void stopScrolling() { ... } @Override public boolean onTouch(View v, MotionEvent event) { ... } void finishScrolling() { ... } boolean isScrolling(){ ... } boolean isJustifying(){ ... } boolean isTouchScrolling(){ ... } } 


рдЕрдм рд╣рдо рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд╕рдВрдкреВрд░реНрдг рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рдХрд┐рдЪрди рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдХреЗрд╡рд▓ SlideStackView рдХреЛ рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧрд╕реНрдЯрд╛рд░рд┐рд╕реНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдШрдЯрдирд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

  public interface ScrollingListener { void onScroll(int distance); void onStarted(); void onFinished(); void onJustify(); } 


рдХрд┐рд╕реА рднреА ViewGroup рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╣рд╛рдБ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ? рд╡реНрдпреВрдЧреНрд░реБрдк рдПрдХ рд▓рд┐рдВрдХрд░ рд╣реИ рдЬреЛ рдХрд┐ рд╡реНрдпреВ рдХреНрдпрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕рдХреЗ рдЕрдВрджрд░ рдЕрдиреНрдп рд╡реНрдпреВрдЬ рднреА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ ViewGroup рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ, рдЬреЛ рдУрд╡рд░рд░рд╛рдЗрдб рд╡рд┐рдзрд┐рдпреЛрдВ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ:
  @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { } 

рдЬрд╣рд╛рдБ рд╣рдо рдЕрдкрдиреА рд╕реНрд▓рд╛рдЗрдбреНрд╕ рд▓рдЧрд╛рддреЗ рд╣реИрдВ:
  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } 

рдФрд░ рдЬрд╣рд╛рдВ рд╣рдо рдЕрдкрдиреА рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рдорд╛рдкрддреЗ рд╣реИрдВред
рдЪрд▓реЛ рдорд╛рдк рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:
  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); int childHeightSize = getMeasuredHeight(); int mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec( childHeightSize, MeasureSpec.EXACTLY); // Make sure we have created all fragments that we need to have shown. mInLayout = true; fillViewsIn(); mInLayout = false; // measure slides int size = getChildCount(); for (int i = 0; i < size; ++i) { final View child = getChild(i); if (child.getVisibility() != GONE) { int childWidthSize = getMeasuredWidth() - ( getRightEdgeDelta(mFirst + i - 1) + getLeftEdge(mFirst + i)); final int widthSpec = MeasureSpec.makeMeasureSpec( childWidthSize, MeasureSpec.EXACTLY); // LOG.v("Measuring #" + i + " " + child // + ": " + widthSpec); child.measure(widthSpec, mChildHeightMeasureSpec); } } } 


рдпрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ - рдкрд╣рд▓реЗ рд╣рдордиреЗ рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдХреЗ рд▓рд┐рдП рдЖрдХрд╛рд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬреЛ рдХрдВрдЯреЗрдирд░ рдиреЗ рд╣рдореЗрдВ рджрд┐рдпрд╛ рдерд╛ред рдореЛрдмрд╛рдЗрд▓ рдореЗрд▓ рдореЗрдВ, рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдорд╛рд░реНрдХрдЕрдк рдХрд╛ рдореВрд▓ рддрддреНрд╡ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рддрд░рд╣ рд╣рдо рдкреВрд░реЗ рдЙрдкрд▓рдмреНрдз рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рднрд░рддреЗ рд╣реИрдВред

рдХреНрдпреЛрдВрдХрд┐ рдЕрдЧрд░ рд╣рдо рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рдХрд┐ рд╣рдорд╛рд░реА рд╕реНрд▓рд╛рдЗрдб рдКрдБрдЪрд╛рдИ рдореЗрдВ рднрд┐рдиреНрди рд╣реЛ, рддреЛ рд╣рдо рдорд╛рдкрдиреЗ рдХреА рдКрдБрдЪрд╛рдИ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд╕рд╛рде рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдорд╛рдкрдХ рдзреНрд╡рдЬ рдФрд░ рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдХреА рдорд╛рдкрд┐рдд рдКрдБрдЪрд╛рдИ рдХреЗ рдмрд░рд╛рдмрд░ рдорд╛рди рд╣реЛрддрд╛ рд╣реИред

рдЕрдкрдиреА рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рдорд╛рдкрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдорд╛рд░реНрдХрдЕрдк рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдКрдкрд░ рд╕реЗ рдиреАрдЪреЗ рдХреА рдУрд░ рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рднрд░рдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдиреЗрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВ, рдЙрдирдХреА рд╡рд╛рдВрдЫрд┐рдд рдЪреМрдбрд╝рд╛рдИ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЪрд╛рдЗрд▓реНрдб.рдореЗрдпрд░ (рдЪреМрдбрд╝рд╛рдИрд╕реНрдкреЗрдХ, mChildHeightMeasureSpec) рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдорд╛рдкрддреЗ рд╣реИрдВред

рд╕реНрд▓рд╛рдЗрдб рдХреА рдЪреМрдбрд╝рд╛рдИ рдХреЛ рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдХреА рдЪреМрдбрд╝рд╛рдИ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рд╕реНрд▓рд╛рдЗрдб рдХреЗ рд▓рд┐рдП рдмрд╛рдИрдВ рдФрд░ рджрд╛рдИрдВ рдУрд░ рдЗрдВрдбреЗрдВрдЯреЗрд╢рди, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд╝реЛрд▓реНрдбрд░реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рд╕реНрд▓рд╛рдЗрдб рдХреЗ рд▓рд┐рдПред



рд╣рдордиреЗ рдЕрдкрдиреА рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рдорд╛рдкрдиреЗ рдХреЗ рдмрд╛рдж, рдЙрдиреНрд╣реЗрдВ рдХреЗрд╡рд▓ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╣реА рд░рд╣рддрд╛ рд╣реИ

  @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mInLayout = true; fillViewsIn(); mInLayout = false; for (int i = 0; i < getChildCount(); i++) { View child = getChild(i); int position = i + mFirst; onLayoutChild(child, position, changed); } mDirty.setEmpty(); } /** * Layouts child at the specified position (in adapter's data set). * Measures the child if needed. * @param child a child we are going to layout * @param position position of the child in adapter's data set */ protected void onLayoutChild(View child, int position, boolean changed) { if (child.getVisibility() != GONE) { LOG.d("onLayoutChild " + position); if (position < mSelected && changed){ closeView(position); LOG.v("close slide at " + position); } final LayoutParams lp = (LayoutParams) child.getLayoutParams(); SlideInfo info = getSlideInfo(child); int childLeft = getLeftEdge(position) + info.mOffset; int childRight = getRightEdge(position - 1) + info.mOffset; int childTop = getTop(); if (lp.needsMeasure) { lp.needsMeasure = false; final int widthSpec = MeasureSpec.makeMeasureSpec( childRight - childLeft, MeasureSpec.EXACTLY); final int heightSpec = MeasureSpec.makeMeasureSpec( getMeasuredHeight(), MeasureSpec.EXACTLY); child.measure(widthSpec, heightSpec); } // LOG.v("Positioning #" + position + " " + child + ":" + childLeft // + "," + childTop + " " + child.getMeasuredWidth() + "x" // + child.getMeasuredHeight()); child.layout(childLeft, getTop(), childRight, getBottom()); } } 


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

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдХреЛ рдорд╛рдкрдиреЗ рдХреЗ рдмрд╛рдж рдПрдХ рд╕реНрд▓рд╛рдЗрдб рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдЗрд╕ рд╕реНрд▓рд╛рдЗрдб рдХреЛ рднреА рдорд╛рдкрдирд╛ рд╣реЛрдЧрд╛ред

рдпрд╣рд╛рдВ SlideInfo рдПрдХ рдирд┐рдпрдорд┐рдд рдзрд╛рд░рдХ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕реНрд▓рд╛рдЗрдб рдХреА рд╕реНрдерд┐рддрд┐ рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╢рд╛рдорд┐рд▓ рд╣реИред

  /** * Simple info holder for the slide item * @author k.kharkov */ public static final class SlideInfo implements Parcelable{ /** * Describes slide offset relative to the slide stack. * Note that offset value do not describe actual slide * position inside the slide stack but only shows the * offset relative to the left position of the slide. * <p> * This means * <code>getLeftEdge(position) + info.mOffset</code> * equals to actual offset of the slide relative to * the slide stack view. */ private int mOffset = 0; /** * Indicates whether the slide is visible to the user * or hidden at near the slide stack side */ private boolean mOpened = true; /** * Position of the slide inside the slide stack */ private int mPosition = INVALID_POSITION; /** * The drawable to fill space between this slide and the * previous one. * @see SlideStackView#fillAreaToPrevSlide(Canvas, View) */ private Drawable mSpace; public SlideInfo() { super(); } } 


рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, SlideInfo рдХреЛ рдЕрд▓рдЧ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдЖрдк рд▓реЗрдЖрдЙрдЯрдкреНрд░реЗрдордореНрд╕ рд╡рд░реНрдЧ рдХреЗ рд╡рд╛рд░рд┐рд╕ рдХреЗ рд╕рд╛рде рдорд┐рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЕрдВрдд рдореЗрдВ рдореИрдВрдиреЗ рдЕрднреА рднреА рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред рд▓реЗрдЦрди рдХреЗ рд╕рдордп, рдореБрдЭреЗ рдпрд╣ рдирд╣реАрдВ рдкрддрд╛ рдерд╛ рдФрд░ рдЕрдм рдореИрдВрдиреЗ рдЗрд╕ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд▓реЗрдЖрдЙрдЯрдкрд╛рд░реНрдореНрд╕ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдмрд╣реБрдд рдЬрд▓реНрдж рдРрд╕рд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдХреБрдЫ рднреА рдирд╣реАрдВ рдЖрдкрд░рд╛рдзрд┐рдХ рдХреЛрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдзрд╛рд░рдХреЛрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рджреГрд╖реНрдЯрд┐рдХреЛрдг KISS рдХрд╛ рд╕рдорд░реНрдерди (рдпрд╣ рд╕рд░рд▓ рд░рдЦреЗрдВ рдмреЗрд╡рдХреВрдл), рдФрд░ рджреЛ рдХреЗ рдмрдЬрд╛рдп рдмрд╣реБрдд рдЖрд╕рд╛рди рдПрдХ рд╡рд╕реНрддреБ рдХрд╛ рдЙрдкрдпреЛрдЧ :)

рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдХрд┐ рд╕реНрд▓рд╛рдЗрдбреНрд╕ рд╕реЗ рдХреИрд╕реЗ рдирд┐рдкрдЯреЗрдВ рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рд╡реНрдпреВрдЧреНрд░реБрдк рдореЗрдВ рдЬреЛрдбрд╝ рджрд┐рдпрд╛ рд╣реИред рдЬрд┐рд╕ рдкреНрд░рд╢реНрди рдкрд░ рдЕрднреА рддрдХ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рд╡рд╣рд╛рдВ рдХреИрд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПред рдЗрд╕рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛:

  /** * Adds all required views in layout first. * Then adjusts visibility for each child. * @see #addViewsInside(int, int) * @see #adjustViewsVisibility() */ private void fillViewsIn() { int position = 0; int left = 0; if (getChildCount() > 0){ position = getLastVisiblePosition() + 1; View lastView = getChild(position - mFirst - 1); left = lastView.getLeft() - lastView.getScrollX(); } addViewsInside(position, left); adjustViewsVisibility(); } 


рдпрд╣ рд╡рд┐рдзрд┐ рдЕрдВрддрд┐рдо рд╕реНрд▓рд╛рдЗрдб рдвреВрдВрдврддреА рд╣реИ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рд╕реНрд▓рд╛рдЗрдбрд╕реНрдЯреИрдХ рд╡реНрдпреВ рдореЗрдВ, рдпрджрд┐ рдХреЛрдИ рд╣реЛ, рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рджрд┐рдЦрд╛рдИ рджреЗрдЧреАред рдпрд╣ рд╕рдм рдЗрд╕ рддрд░рд╣ рд╣реЛрддрд╛ рд╣реИ:

  /** * Uses the adapter to add views to the slide stack view. * @param position last visible position of the view * @param left left coordinate of the last visible slide */ private void addViewsInside(int position, int left) { if (mAdapter == null || mAdapter.getCount() == 0){ return; } mAdapter.startUpdate(this); while ((position <= mSelected + 1 || left > getLeft()) && position < mAdapter.getCount()){ if (mFirst == INVALID_POSITION){ mFirst = 0; } LOG.d("addView inside " + position + " mSelected " + mSelected); mAdapter.instantiateItem(this, position); left = mSelected > position ? getLeftEdge(position) : getRightEdge(position - 1); position ++; } mAdapter.finishUpdate(this); } 


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

рдлрд┐рд░ рд╣рдо рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рд╕рдорд╛рдпреЛрдЬрди рдХрд░рддреЗ рд╣реИрдВ, рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП, рдЬреЛ рдЕрднреА рдЬреЛрдбрд╝реЗ рдЧрдП рд╣реИрдВ, рдФрд░ рд╕реНрд▓рд╛рдЗрдб рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджреЛрд╣рд░рд╛рддреЗ рд╣реИрдВ рдЬрдм рддрдХ рдХрд┐ рд╕реНрд▓рд╛рдЗрдб рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛ рдЬрд╛рддреА рдпрд╛ рд╕реНрд▓рд╛рдЗрдб рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдХреА рджреГрд╢реНрдпрддрд╛ рд╕реЗ рдкрд░реЗ рдирд╣реАрдВ рдЬрд╛рддреАред рдпрджрд┐ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ <= getLeft () рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдордиреЗ рдЬреЛ рдЕрдВрддрд┐рдо рд╕реНрд▓рд╛рдЗрдб рдЬреЛрдбрд╝реА рд╣реИ рд╡рд╣ рд╕реНрдЯреИрдХ рд╕реНрд▓рд╛рдЗрдб рдХреА рд╕реАрдорд╛ рдХреЛ рдУрд╡рд░рд▓реИрдк рдХрд░рддреА рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЕрдЧрд▓реА рд╕реНрд▓рд╛рдЗрдб рдпрд╛ рддреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЗрд╕ рд╕реНрд▓рд╛рдЗрдб рдХреЗ рдиреАрдЪреЗ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдпрд╛ рдЗрд╕реЗ рдмрд╛рдИрдВ рдУрд░ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХреНрд╖реЗрддреНрд░ рд╕реНрдЯреИрдХ рд╕реНрд▓рд╛рдЗрдб рдХреА рд╕реАрдорд╛рдУрдВ рдореЗрдВ рдирд╣реАрдВ рдЖрдПрдЧрд╛ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрдЧрд╛ред рдФрд░ рддрдм рд╕реЗ рд╕реНрд▓рд╛рдЗрдб рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрдЧрд╛, рдлрд┐рд░ рднреА рдЗрд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред

"рд▓реЗрдХрд┐рди рд╕реНрд▓рд╛рдЗрдб рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд╣рд╛рдБ рд╣реИ?" рдЖрдк рдкреВрдЫрддреЗ рд╣реИрдВ рд╣рдо mAdapter.finishUpdate (рдЗрд╕) рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж; рдПрдбреЗрдкреНрдЯрд░ рд▓реЗрди-рджреЗрди рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ рдФрд░ FragmentManager рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрдВрдЯреЗрдирд░ рдореЗрдВ рдЯреБрдХрдбрд╝реЗ рдЬреЛрдбрд╝рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддрд╛ рд╣реИ (рдпрд╣ - рдпрд╣реА рд╣реИ, SlideStackView)ред рдПрдХ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЗрд╕ рд╡рд┐рд╖рдп рдХреЛ рд╕рдореАрдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП рдкрд╛рдардХ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝ рджреЗрдВ :) рдПрдХ рдЯреБрдХрдбрд╝реЗ рдХреЗ рдЬреАрд╡рдирдЪрдХреНрд░ рдХреЗ рджреМрд░рд╛рди, рдпрд╣ ViewGroup.addView (рджреЗрдЦреЗрдВ, int, LayoutParams) рд╡рд┐рдзрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдорд╛рд░реЗ рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛; рд╕реНрд▓рд╛рдЗрдб рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдХреБрдЫ рд╕рдорд╛рдпреЛрдЬрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
  /** * Specifies correct layout parameters for the child and * adds it according the the current {@link #mInLayout} * status. * <p> * {@inheritDoc} */ @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { LOG.d("Add view from outside " + child); if (!checkLayoutParams(params)) { params = generateLayoutParams(params); } final LayoutParams lp = (LayoutParams) params; SlideInfo info = getSlideInfo(child); info.mPosition = getChildCount(); if (mAdapter != null){ info.mSpace = mAdapter.getSpaceDrawable(info.mPosition); } if (mInLayout) { lp.needsMeasure = true; addViewInLayout(child, 0, params); } else { super.addView(child, 0, params); } if (info.mPosition < mSelected){ closeView(info.mPosition); } } 


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

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

рд╡рд┐рдзрд┐ fillViewsIn () рдореЗрдВ; рдЕрдВрддрд┐рдо рд▓рдВрдмрд┐рдд рд░реЗрдЦрд╛ рдмрдиреА рд╣реБрдИ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдПрдбрдЬрд╕реНрдЯреЗрдмрд▓ рд╡реНрдпреВрдЬрд┐рдмрд┐рд▓рд┐рдЯреА рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВ;

рдпрд╣ рд╡рд┐рдзрд┐, рдЬреИрд╕рд╛ рдХрд┐ рдирд╛рдо рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ, рд╕реНрд▓рд╛рдЗрдб рдХреА рджреГрд╢реНрдпрддрд╛ рдХреЛ рд╕рд╣реА рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЙрди рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рдЦреАрдВрдЪрдиреЗ рдореЗрдВ рд╕рдордп рдмрд░реНрдмрд╛рдж рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬрд┐рдиреНрд╣реЗрдВ рдорд╛рд░реНрдХрдЕрдк рд╕реЗ рд╣рдЯрд╛рдпрд╛ рдирд╣реАрдВ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬреЛ рдЕрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрддреЗ рд╣реИрдВред рджреГрд╢реНрдпрддрд╛ рдХреЛ рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░рдирд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ - рд╣рдо рдХреЗрд╡рд▓ View.setVisibility (int) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрд▓рд╛рдЗрдб рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдпрддрд╛ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рд╣рдо рдпрд╛ рддреЛ View.VISIBLE рдпрд╛ View.INVISIBLE рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рд╡рд┐рдзрд┐ рд╕реНрд╡рдпрдВ рдереЛрдбрд╝реА рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рджрд┐рдЦрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рдмрд╛рдж, рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

  /** * Sets visibility parameter for each child according * to the actual visibility on the screen. Takes into * account that child shouldn't be invisible if it's * shadow is visible on the screen because it would * prevent from triggering {@link #drawChild(Canvas, View, long)} * method over that child. */ private void adjustViewsVisibility() { /** * init the rect to align right edge if the slide stack view */ Rect drawingRect = new Rect(); drawingRect.left = getRight(); drawingRect.top = getTop(); drawingRect.right = getRight(); drawingRect.bottom = getTop() + getHeight(); Rect parent = getChildDrawingRectPositive(this); /** * Then union each child drawing rect * with drawingRect of the slide stack * in order to determine when the views * behind the last actually visible view * in the slideStack view and hide all * the following views in order to prevent * re-drawing non-visible views * ________________________________ * | slideStackView __________| * | ____________________| | * || _ _ _ _ | | * ||| | |visible | * || |slide #0 | * ||| hidden slide| | | * || #2 | | * |||_ _ _ _| | | * ||last actual visible | | * ||slide #1 |__________| * ||__________________________| | * |________________________________| */ for (int i = 0; i < getChildCount(); i ++){ boolean hideNext = false; // LOG.v("adjustVisibility " + i); View child = getChild(i); Rect childRect = getChildDrawingRectPositive(child); // LOG.v("child.left " + childRect.left + // " drawing.left" + drawingRect.left + // " parent " + parent.toShortString() + // " child" + childRect.toShortString()); if (childRect.left < drawingRect.left && Rect.intersects(parent, childRect)){ drawingRect.union(childRect); // LOG.d("drawingRect after union with child " + i + " = " + // drawingRect.toShortString()); hideNext = false; } else { // LOG.d("hide view " + i); // LOG.v("child " + childRect.toShortString() + // " drawing " + drawingRect.toShortString() + // " parent " + parent.toShortString()); Rect childShadow = getShadowRect(childRect); if (childShadow.isEmpty()){ hideNext = true; } // if shadow visible - do not hide the slide // and let the shadow to be drawn if (childShadow.left < drawingRect.left && Rect.intersects(parent, childShadow)){ hideNext = false; } else { hideNext = true; } } // LOG.d("set visibility for child " + i + " = " + // (hideNext ? "Invisible" : "Visible")); child.setVisibility(hideNext ? View.INVISIBLE : View.VISIBLE); } } 


рдореИрдВ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рдХрд╛рдо рдХреЛ рдЪрд┐рддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рдХрджрдо рд╕реЗ рдХрджрдо рдмрдврд╝рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред

рд╕рд╛рдорд╛рдиреНрдп рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

1. рд╕реНрдЯреИрдХ рд╕реНрд▓рд╛рдЗрдб рдХреЗ рджрд╛рд╣рд┐рдиреЗ рдХрд┐рдирд╛рд░реЗ рдХреЛ рд▓реЗрдВ (рдХреНрдпреЛрдВрдХрд┐ рд╕рдмрд╕реЗ рджрд╛рд╣рд┐рдиреА рд╕реНрд▓рд╛рдЗрдб рд╣рдореЗрд╢рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ рдФрд░ рдЬреЛ рдмрд╛рдИрдВ рдУрд░ рд╣реЛрддреА рд╣реИрдВ, рд╡реЗ рдЙрд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рдЯреИрдк рдХреА рдЬрд╛рддреА рд╣реИрдВред рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдпрд╣ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред)
2. рд╣рдо рд╕рднреА рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░, рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдерд╛, рдХрдмреНрдЬреЗ рд╡рд╛рд▓реЗ рдХреНрд╖реЗрддреНрд░ рдХреЛ рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдХреЗ рдЕрдВрджрд░ рдЬрдЧрд╣ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд╕реНрд▓рд╛рдЗрдб рдкрд░ рд░рд╣рддрд╛ рд╣реИред
3. рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЕрдЧрд▓реА рд╕реНрд▓рд╛рдЗрдб рдпрд╛ рддреЛ рд╕реНрдЯреИрдХ рд╕реНрд▓рд╛рдЗрдб рдХреА рд╕реАрдорд╛рдУрдВ рдХреЗ рдмрд╛рд╣рд░ рд╣реИ рдпрд╛ рдЗрд╕рдХреЗ рдКрдкрд░ рдкрдбрд╝реА рд╕реНрд▓рд╛рдЗрдбреЛрдВ рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмрдВрдж рд╣реИ, рддреЛ рдЗрд╕реЗ "рдЕрджреГрд╢реНрдп" рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░реЗрдВред рдЕрдиреНрдпрдерд╛, рд╕реНрд▓рд╛рдЗрдб рдХреЛ "рджреГрд╢реНрдпрдорд╛рди" рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред

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

рдпрд╣ рдЫрд╛рдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╛рдпреЛрдЬрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рд╣рдо рдЫрд╛рдпрд╛ рдХреЛ рд╕реНрд╡рдпрдВ рдЦреАрдВрдЪрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП, рдпрджрд┐ рд╣рдо рдЙрд╕ рд╕реНрдерд╛рди рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдЫрд╛рдпрд╛ рд╡реНрдпрд╛рдкреНрдд рд╣реИ, рддреЛ рд╕реНрд▓рд╛рдЗрдб рдХреА рджреГрд╢реНрдпрддрд╛ рдХреЛ рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдЙрд╕ рд╕рдордп рдПрдХ рдЕрдкреНрд░рд┐рдп рдкрд▓рдХ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬрдм рд╕реНрд▓рд╛рдЗрдб рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рдкреАрдЫреЗ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИрдВ / рдЫрд┐рдкрддреА рд╣реИрдВред рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдбреНрд░реЙрдЗрдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рджреМрд░рд╛рди рд╡реНрдпреВрдЧреНрд░реБрдк рдореЗрдВ рдпрд╣ рдЬрд╛рдВрдЪ рд╣реЛрддреА рд╣реИ рдХрд┐ рдмрдЪреНрдЪрд╛ рджрд┐рдЦрд╛рдИ рджреЗ рд░рд╣рд╛ рд╣реИ рдпрд╛ рдЕрджреГрд╢реНрдпред рдпрджрд┐ рдпрд╣ рдЕрджреГрд╢реНрдп рд╣реИ, рддреЛ рдбреНрд░реЙ рдЪрд╛рдЗрд▓реНрдб (рдХреИрдирд╡рд╕, рд╡реНрдпреВ, рд▓реЙрдиреНрдЧ) рд╡рд┐рдзрд┐ рдХреЛ рдмрд╕ рдЗрд╕ рдмрдЪреНрдЪреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдмрд╣реБрдд рддрд╛рд░реНрдХрд┐рдХ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рд╕реНрд▓рд╛рдЗрдб рдХреЛ рджреГрд╢реНрдпрдорд╛рди рдорд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдЙрд╕рдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдЫрд╛рдпрд╛ рджрд┐рдЦрд╛рдИ рджреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕ рд╕рдордп рдПрдХ рд╕рдВрд╢реЛрдзрди рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рд╣рдордиреЗ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рд╕реНрд▓рд╛рдЗрдб рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗ рд░рд╣реА рд╣реИред
  Rect childShadow = getShadowRect(childRect); if (childShadow.isEmpty()){ hideNext = true; } // if shadow visible - do not hide the slide // and let the shadow to be drawn if (childShadow.left < drawingRect.left && Rect.intersects(parent, childShadow)){ hideNext = false; } else { hideNext = true; } 

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

рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдЙрди рд╕реНрд▓рд╛рдЗрдбреНрд╕ рдХреЛ рдЦреАрдВрдЪрдиреЗ рд╕реЗ рд░реЛрдХрдирд╛ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрддреА рд╣реИрдВ, рд╕рдорд╕реНрдпрд╛ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддреА рд╣реИрдВред рд╣рдо рдЕрднреА рднреА рд╕реНрд▓рд╛рдЗрдб рдХреЗ "рдУрд╡рд░рд▓реЗ" рд╣реИрдВред рдпрд╣ рдЙрд╕ рд╕рдордп рд╣реЛрддрд╛ рд╣реИ рдЬрдм рд╣рдо рдПрдХ рд╕реНрд▓рд╛рдЗрдб рдХреЛ рдХрд┐рдирд╛рд░реЗ рдкрд░ рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдХреЗ рдиреАрдЪреЗ рд╕реЗ рдЕрдЧрд▓реА рд╕реНрд▓рд╛рдЗрдб рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рджреЗрдЦрддреЗ рд╣реИрдВред рдпрд╣реА рд╣реИ, рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрд▓рд╛рдЗрдб рдХрд╛ рдХреЗрд╡рд▓ рдПрдХ рд╣рд┐рд╕реНрд╕рд╛ (рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЫрд╛рдпрд╛ рдХрд╛ рдХреЗрд╡рд▓ рдПрдХ рд╣рд┐рд╕реНрд╕рд╛) рджреЗрдЦрддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдкреВрд░реА рд╕реНрд▓рд╛рдЗрдб рдХреЛ рдПрдХ рдкреВрд░реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдлрд┐рд░, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЗрд╕рдХреЗ рдКрдкрд░ рдПрдХ рдФрд░ рд╕реНрд▓рд╛рдЗрдб рдЦреАрдВрдЪреЗрдВред

рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ, рдореИрдВ Canvas.clipRect (Rect) рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рддрд░рд╣ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдЕрдиреНрдп рддрд░реАрдХрд╛ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдлреНрд░реЗрдо рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕ рд╕реНрд▓рд╛рдЗрдб рдХреЛ рджреЗрдЦреЗрдЧрд╛, рдХреИрдирд╡рд╛рд╕ рдкрд░ рдбреНрд░рд╛рдЗрдВрдЧ рдХреЗ рд▓рд┐рдП рдХреНрд╖реЗрддреНрд░ рдХреЛ рдЙрд╕ рд╕реНрдерд╛рди рддрдХ рд╕реАрдорд┐рдд рдХрд░реЗрдВ рдЬрд╣рд╛рдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрд╕ рд╕реНрд▓рд╛рдЗрдб рд╕реЗ рджреЗрдЦреЗрдВрдЧреЗ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА рд╕реНрд▓рд╛рдЗрдб рдЦреАрдВрдЪреЗрдВред

рдЙрдкрд░реЛрдХреНрдд рд╕реНрд▓рд╛рдЗрдб рдбреНрд░рд╛рдЗрдВрдЧ рд╡рд┐рдзрд┐ рдореЗрд░реЗ рд▓рд┐рдП рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИ:
  /** * Clips the canvas to the child current bounds plus shadow. * <p> * Draws the shadow as well for each child. * <p> * {@inheritDoc} * @see #applyShadowToChild(Canvas, View) */ @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { Rect childClip = getChildClipRect(child); // LOG.d("canvas " + canvas.getClipBounds().toShortString()); // LOG.d("draw Child " + child + " clip = " + childClip.toShortString()); // first // draw spaces between slides fillAreaToPrevSlide(canvas, child); // second // draw shadow for the slide applyShadowToChild(canvas, child); // third // actually draw child try{ canvas.save(); canvas.clipRect(childClip); boolean r = super.drawChild(canvas, child, drawingTime); return r; } finally { canvas.restore(); } } 

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

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╕рдм рдХреБрдЫ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рд╕рднреА рдЬрд╛рджреВ рдЙрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдЧрд┐рдирдиреЗ рдХреА рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ рд╣реИ рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рдЖрдкрдХреЛ рдХреИрдирд╡рд╛рд╕ рдХреЛ "рдХреНрд░реЙрдк" рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
  /** * Retrieves children's visible position on the screen * without it's shadow. * @param child we should retrieve visible bounds for * @return a child's visible bounds */ private Rect getChildClipRect(View child) { Rect childClip = getChildDrawingRectPositive(child); int position = getPositionForView(child); subtractRectWithChilds(childClip, position); // LOG.v("child clip " + position + " " + childClip.toShortString()); return childClip; } /** * Changes the specified clip rectangle, to subtract all the * following children from it. * @param childClip initial child rectangle in the screen * @param position child position within adapter's data set * @see #subtractToLeft(Rect, Rect) */ private void subtractRectWithChilds(Rect childClip, int position) { if (position >= 0){ position -= mFirst; for (int i = position - 1; i >= 0; i --){ View c = getChild(i); Rect r = getChildDrawingRectPositive(c); boolean changed = subtractToLeft(childClip, r); if (changed){ // LOG.v("child clipped " + childClip.toShortString()); } } } } 

рдкрд╣рд▓реА рд╡рд┐рдзрд┐ рдореЗрдВ, рд╣рдо рд╕реНрд▓рд╛рдЗрдб рд╕реНрдЯреИрдХ рдХреЗ рдЕрдВрджрд░ рд╕реНрд▓рд╛рдЗрдб рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВ, рдлрд┐рд░ рд╣рдо рд╕реНрд▓рд╛рдЗрдб рдПрдбрд╛рдкреНрдЯрд░ рдХреЗ рдЕрдиреБрдХреНрд░рдорд┐рдд рдореЗрдВ рдЗрд╕рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рд╕рднреА рдЕрдирд╛рд╡рд╢реНрдпрдХ "рдШрдЯрд╛рдирд╛" рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдо рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред

, ┬л┬╗ . , , ( ).

, .

, , , .
  /** * Same as {@link #subtract(Rect, Rect)} method, but processes * the case where source rectangle wasn't changed because it * contains <code>r</code>. In this case it adjusts <code>r</code> * from this: * <pre> * _______________________ * | source _________ | * | | r | | * | | | | * | | | | * | | | | * | |_________| | * |_______________________| * </pre> * * to this: in order to leave only left side of the source rectangle. * <pre> * ___________________________ * | source | r |1px| * | | |<->| * | | | | * | | | | * | | | | * | | | | * | | | | * |_________|_____________|___| * </pre> * @param source the rectangle we are going to subtract from * @param r the rectangle we are going to subtract from * source * @return <code>true</code> in case the source rectangle * has been changed. <code>false</code> otherwise */ private static boolean subtractToLeft(Rect source, Rect r){ boolean changed = subtract(source, r); if (!changed && source.contains(r)){ // adjust intersected rect manually r.right = source.right + 1; r.top = source.top; r.bottom = source.bottom; changed = subtract(source, r); } return changed; } /** * Subtracts <code>r</code> from the <code>source</code>. * Sets <code>r</code> rectangle to the intersection as well. * @param source * @param r * @return <code>true</code> if rectangle has been subtracted, * <code>false</code> otherwise. */ private static boolean subtract(Rect source, Rect r) { if (source.isEmpty() || r.isEmpty()){ return false; } if (r.contains(source)){ // LOG.w("return empty rect"); source.setEmpty(); return true; } if (source.contains(r)){ return false; } if (!r.intersect(source)){ return false; } boolean changed = false; if (source.left == r.left){ source.left = r.right; changed = true; } if (source.right == r.right){ source.right = r.left; changed = true; } if (source.top == r.top){ source.top = r.bottom; changed = true; } if (source.bottom == r.bottom){ source.bottom = r.top; changed = true; } source.sort(); return changed; } 

, , , ┬л┬╗ - :)

, , тАУ Rect. , . . , . ┬л┬╗ , - , . , . . , , , . , , .

, , , , .

, тАУ . , . , . , , MotionEvent' , , -, .

, , , ViewGroup.

тАУ - Mail.Ru. . , .

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


All Articles