рдПрдиреАрдореЗрд╢рди рдХреЛ ListView рдореЗрдВ рдЬреЛрдбрд╝рдирд╛

рдЕрднрд┐рд╡рд╛рджрди, рд╕рд╛рдерд┐рдпреЛрдВ,

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

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

рдЪрд▓реЛ, рдЕрдм, рдореИрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рд╣реБрдЖ, рдпрд╣ рдХреИрд╕реЗ рдмрджрд▓ рдЧрдпрд╛, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

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





рд╕рд░рд▓ рдЖрдВрджреЛрд▓рди



рдЪреВрдВрдХрд┐ рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рддрддреНрд╡ "рдкреЙрдк рдЕрдк" рдХрд░реЗрдВ рдЬрдм рд╡реЗ рд╕реВрдЪреА рдХреЗ рдиреАрдЪреЗ рдпрд╛ рдКрдкрд░ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ, рддреЛ рд╕рдмрд╕реЗ рддрд╛рд░реНрдХрд┐рдХ рд╕реНрдерд╛рди рд╣рдорд╛рд░реЗ рдПрдбреЗрдкреНрдЯрд░ рдХреЗ getView рдореЗрдВ рдХреЛрдб рдЬреЛрдбрд╝рдирд╛ рд╣реИред

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { animatePostHc(position, v); } else { animatePreHc(position, v); } 


рдореИрдВ рддреБрд░рдВрдд рдзреНрдпрд╛рди рджреВрдВрдЧрд╛ рдХрд┐ рдореЗрд░рд╛ рдореБрдЦреНрдп рдзреНрдпрд╛рди ICS + рдкрд░ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреВрдВрдЧрд╛ред

рдЖрдЗрдП рдЪреЗрддрдирдкреЛрд╕реНрдЯрд╣реЙрдХ рд╡рд┐рдзрд┐ рджреЗрдЦреЗрдВ;

 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) private void animatePostHc(int position, View v) { if (prevPosition < position) { v.setTranslationX(animX); v.setTranslationY(animY); } else { v.setTranslationX(-animX); v.setTranslationY(-animY); } v.animate().translationY(0).translationX(0).setDuration(300) .setListener(new InnerAnimatorListener(v)).start(); } 


рдХрджрдоред рд╣рдо рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реА рд╕реВрдЪреА рдХрд┐рд╕ рджрд┐рд╢рд╛ рдореЗрдВ рдЖрдЧреЗ рдмрдврд╝ рд░рд╣реА рд╣реИ рдФрд░ рдЙрдЪрд┐рдд рдСрдлрд╕реЗрдЯ рдмрдирд╛рддреА рд╣реИред рдЕрдЧрд▓рд╛, рдирдП рдПрдиреАрдореЗрд╢рди рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо 300 рдПрдордПрд╕ рдореЗрдВ (0, 0) рдкрд░ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рд╣рдо рдПрдХ рд╣реИрдВрдбрд▓рд░ рднреА рд▓рдЯрдХрд╛рддреЗ рд╣реИрдВ рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ:

 static class InnerAnimatorListener implements AnimatorListener { private View v; private int layerType; public InnerAnimatorListener(View v) { this.v = v; } @Override public void onAnimationStart(Animator animation) { layerType = v.getLayerType(); v.setLayerType(View.LAYER_TYPE_HARDWARE, null); } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { v.setLayerType(layerType, null); } @Override public void onAnimationCancel(Animator animation) { } } 


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

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЬреЗрд▓реА рдмреАрди рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдирд╛, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╣реА рдЪреАрдЬ рдХреЛ рдмрд╣реБрдд рдЖрд╕рд╛рди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддреН, рдПрдирд┐рдореЗрдЯрд░ рдХреА рд╡рд┐рдзрд┐ () рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ:

 v.animate().withLayer().translationY(0).translationX(0).setDuration(300).setListener(new InnerAnimatorListener(v)).start(); 


рд▓реЗрдХрд┐рди рд╣рдо рдПрдХ рдЖрджрд░реНрд╢ рджреБрдирд┐рдпрд╛ рдореЗрдВ рдирд╣реАрдВ рд░рд╣рддреЗ рд╣реИрдВред

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

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдПрдбреЗрдкреНрдЯрд░ рдореЗрдВ рдмреВрд▓рд┐рдпрди рдлрд╝реАрд▓реНрдб рдХреЛ рдЬреЛрдбрд╝рд╛ред рдЕрдм рд╣рдореЗрдВ рдмрд╕ ListView рдкрд░ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд▓рдЯрдХрд╛ рджреЗрдирд╛ рд╣реИ рдФрд░ рдПрдирд┐рдореЗрд╢рди рдХреЛ рдЪрд╛рд▓реВ / рдмрдВрдж рдХрд░рдирд╛ рд╣реИ:

 listView.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { adapter.setAnimate(scrollState == SCROLL_STATE_FLING || SCROLL_STATE_TOUCH_SCROLL == scrollState); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } }); 


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

рд╡рд┐рдХреГрддрд┐


рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛, Google I / O 2013 рдХреЗ рдЗрд╕ рд╡реНрдпрд╛рдЦреНрдпрд╛рди рдиреЗ рдореБрдЭреЗ рдЗрд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд┐рдпрд╛ред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рд░реЛрдорди рдЧрд╛рдЗ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рд╛рдордЧреНрд░реА (рд╡реАрдбрд┐рдпреЛ, рдмреНрд▓реЙрдЧ рдкреЛрд╕реНрдЯ рдЖрджрд┐) рдмрд┐рд▓реНрдХреБрд▓ рдЕрдореВрд▓реНрдп рд╣реИред

рд╕реВрдЪреА рдЖрдЗрдЯрдо рдореЗрдВ рдереЛрдбрд╝реА рд╡рд┐рдХреГрддрд┐ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдХрд╕реНрдЯрдо рд▓реЗрдЖрдЙрдЯ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЪрд┐рдВрддрд╛ рдордд рдХрд░реЛ, рдореИрдВ рдпрд╣ рдирд╣реАрдВ рдХрд╣ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рд╣рдореЗрдВ рдЗрд╕реЗ рдЦрд░реЛрдВрдЪ рд╕реЗ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд╣рдореЗрдВ рдмрд╕ рдореМрдЬреВрджрд╛ рдПрдХ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореЗрд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╕реВрдЪреА рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдПрдХ RelativeLayout рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ SkewingRelativeLayout рд╡рд░реНрдЧ рдмрдирд╛рдХрд░ рдЗрд╕рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд┐рдпрд╛:

 public class SkewingRelativeLayout extends RelativeLayout { private float skewX = 0; public SkewingRelativeLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public SkewingRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SkewingRelativeLayout(Context context) { super(context); } @Override public void draw(Canvas canvas) { if (skewX != 0) { canvas.skew(skewX, 0); } super.draw(canvas); } public void setSkewX(float skewX) { this.skewX = skewX; ViewCompat.postInvalidateOnLayout(this); } } 


рд╣рдордиреЗ рддрд┐рд░рдЫрд╛ рдХреНрд╖реЗрддреНрд░ рдЬреЛрдбрд╝рд╛ - рд╡рд┐рдХреГрддрд┐ред рдЕрдм, рд╣рдордиреЗ рдЕрдкрдиреА рдбреНрд░рд╛ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдореЗрдВ, рд╣рдорд╛рд░реЗ рдШрдЯрдХ рдХреЛ рдЦреАрдВрдЪрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдХреИрдирд╡рд╛рд╕ рдХреЛ рд╡рд┐рдХреГрдд рдХрд░рддреЗ рд╣реИрдВред

рд╕реВрдЪреА рдЖрдЗрдЯрдо рдХреЛ SkewingRelativeLayout рд╕реЗ рдмрджрд▓реЗрдВред

рдЕрдм рдПрдиреАрдореЗрд╢рди рдХреЗ рд▓рд┐рдП ... рд╣рдорд╛рд░реЗ рддрддреНрд╡ рдХреЗ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╡рд┐рд░реВрдкрдг рдФрд░ рдЖрдВрджреЛрд▓рди рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдЗрд╕рдХреЗ рдПрдиреАрдореЗрд╢рди рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдереЛрдбрд╝рд╛ рдмрджрд▓рдирд╛ рдкрдбрд╝рд╛:

 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) private void animatePostHc(int position, View v) { float startSkewX = 0.15f; float translationX; float translationY; if (prevPosition < position) { translationX = animX; translationY = animY; } else { translationX = -animX; translationY = -animY; } ObjectAnimator skewAnimator = ObjectAnimator.ofFloat(v, "skewX", startSkewX, 0f); ObjectAnimator translationXAnimator = ObjectAnimator.ofFloat(v, View.TRANSLATION_X, translationX, 0.0f); ObjectAnimator translationYAnimator = ObjectAnimator.ofFloat(v, View.TRANSLATION_Y, translationY, 0.0f); AnimatorSet set = new AnimatorSet(); set.playTogether(skewAnimator, translationXAnimator, translationYAnimator); set.setDuration(300); set.setInterpolator(decelerator); set.addListener(new AnimatorWithLayerListener(v)); set.start(); } 


ViewPropertyAnimator рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рддреАрди рдЕрд▓рдЧ-рдЕрд▓рдЧ ObjectAimimators рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдЗрд╕рдХреЗ рдореВрд▓реНрдп (рд╡рд┐рд░реВрдкрдг, рдПрдХреНрд╕ рдСрдлрд╕реЗрдЯ, рд╡рд╛рдИ рдСрдлрд╕реЗрдЯ) рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рддрд╛рдХрд┐ рд╡реЗ рддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░реЗрдВ рдФрд░ рдПрдХ рд╣реА рдЗрдВрдЯрд░рдкреЛрд▓рд░ рдкрд░, рд╣рдо рдХреНрд▓рд╛рд╕ рдПрдирд┐рдореЗрдЯрд░рд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

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

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

рддреЗрдЬреА рд╕реЗ рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдПрдХ рджреЛрд╖ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдПрдВ


рдкреНрд░рдпреЛрдЧреЛрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рдмрд╛рдж, рдореИрдВ рдЗрд╕ рдирд┐рд╖реНрдХрд░реНрд╖ рдкрд░ рдкрд╣реБрдВрдЪрд╛ рдХрд┐ рдЕрд╡рд╛рдВрдЫрд┐рдд рджреЛрд╖реЛрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рджреЛ рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


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

рдЧрддрд┐ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдХреЛрдб рдХреЛ рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛:

 listView.setOnScrollListener(new OnScrollListener() { private int previousFirstVisibleItem = 0; private long previousEventTime = 0; private double speed = 0; private int scrollState; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { this.scrollState = scrollState; adapter.setAnimate(scrollState == SCROLL_STATE_FLING || SCROLL_STATE_TOUCH_SCROLL == scrollState); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (previousFirstVisibleItem != firstVisibleItem) { long currTime = System.currentTimeMillis(); long timeToScrollOneElement = currTime - previousEventTime; speed = ((double) 1 / timeToScrollOneElement) * 1000; previousFirstVisibleItem = firstVisibleItem; previousEventTime = currTime; if (scrollState == SCROLL_STATE_FLING && speed > 16) { adapter.setAnimate(false); adapter.cancelAnimations(); } else { adapter.setAnimate(true); } } } }); 


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

рдПрдбреЙрдкреНрдЯрд░ рдореЗрдВ, рдореИрдВ рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рддрд╛ рд╣реВрдВ:

  public void cancelAnimations() { for (int i = anims.size() - 1; i >= 0; i--) { anims.get(i).cancel(); } } 


рдФрд░ рдореИрдВ рд╢реНрд░реЛрддрд╛ рдПрдиреАрдореЗрд╢рди рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддрд╛ рд╣реВрдВред рдЕрдВрддрд┐рдо рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

 private class AnimatorWithLayerListener implements AnimatorListener { View view; public AnimatorWithLayerListener(View view) { this.view = view; } @Override public void onAnimationStart(Animator animation) { ViewCompat.setHasTransientState(view, true); } @Override public void onAnimationEnd(Animator animation) { ViewCompat.setHasTransientState(view, false); anims.remove(animation); } @Override public void onAnimationCancel(Animator animation) { view.setTranslationX(0); view.setTranslationY(0); ((SkewingRelativeLayout) view).setSkewX(0); } @Override public void onAnimationRepeat(Animator animation) { } } 


рдЕрдм, рдЬрдм рдЖрдк рдПрдиреАрдореЗрд╢рди рдХреЛ рд░рджреНрдж рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рддреБрд░рдВрдд рд╕рднреА рдСрдлрд╕реЗрдЯ рдФрд░ рд╡рд┐рдХреГрддрд┐рдпреЛрдВ рдХреЛ рд╣рдЯрд╛ рджреЗрддреЗ рд╣реИрдВред рдпрд╣ рддреБрд░рдВрдд рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ onAnimationEnd рд╡рд┐рдзрд┐ рдХреЛ рд╣рдореЗрд╢рд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: рд░рджреНрдж рдХрд░рдиреЗ рдХреЗ рджреМрд░рд╛рди рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рд╕рдорд╛рдкреНрддрд┐ рдХреЗ рджреМрд░рд╛рди рджреЛрдиреЛрдВред рдЗрд╕рд▓рд┐рдП, рдпрд╣ рд░рджреНрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ рдЗрд╕рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред

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

рдкреАрдЫреЗ рд╕рдВрдЧрддрддрд╛


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

 private void animatePreHc(int position, View v) { if (prevPosition < position) { v.clearAnimation(); v.startAnimation(AnimationUtils.loadAnimation(context, R.anim.pop_from_bottom)); } else { v.clearAnimation(); v.startAnimation(AnimationUtils.loadAnimation(context, R.anim.pop_from_top)); } } 


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

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


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

рдЬреЗрдбред рдПрд╕ред рдЕрдЧрд░ рдХреЛрдИ рдФрд░ рдЕрдзрд┐рдХ рдкреВрд░реНрдг рд╕реНрд░реЛрдд рдЪрд╛рд╣рддрд╛ рд╣реИ - рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдкреВрдЫреЗрдВ рдХрд┐ рд╕рдордп рдХреИрд╕рд╛ рд╣реЛрдЧрд╛, рддреЛ рдореИрдВ рдЗрд╕ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдкреАрдКрдВрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдЧреАрдереВрдм рдкрд░ рдбрд╛рд▓реВрдВрдЧрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЬреЛ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЙрд╕рдХрд╛ 95% рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдкрд░рд┐рд▓рдХреНрд╖рд┐рдд рд╣реЛрддрд╛ рд╣реИред

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


All Articles