نصائح للاستخدام المهني لبرنامج RecyclerView. الجزء 2

نصائح للاستخدام المهني لبرنامج RecyclerView. الجزء 2


استمرارًا للمقالة السابقة ، سأتحدث في هذا الموضوع عن ItemDecoration و ItemAnimator وأحاول شرح مبدأ عملهم في RecyclerView باستخدام مثال لتطبيق بسيط متاح على Github .


1. Item زخرفة


يستخدم ItemDecoration لتزيين عناصر القائمة في RecyclerView .


باستخدام ItemDecoration يمكنك إضافة فواصل بين مكونات view أو محاذاتها أو تقسيمها على فترات متساوية. لإضافة فاصل بسيط بين مكونات view ، استخدم فئة DividerItemDecoration ، والتي يمكن العثور عليها في إصدار مكتبة الدعم 25.1.0 والإصدارات الأحدث. يوضح جزء التعليمات البرمجية التالي تنفيذه:


 mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), mLayoutManager.getOrientation()); recyclerView.addItemDecoration(mDividerItemDecoration); 

أفضل طريقة لإنشاء الفاصل الخاص بك هو توسيع فئة RecyclerView.ItemDecoration . في تطبيق العينة ، استخدمت GridLayoutManager وقمت بتطبيق CharacterItemDecoration على RecyclerView :


 recyclerView.addItemDecoration(new CharacterItemDecoration(50)); 

هنا يقوم CharacterItemDecoration بتعيين الإزاحة ( eng. offset) إلى 50 بكسل في getItemOffsets(...) وإلغاء getItemOffsets(...) . داخل طريقة getItemOffsets() ، outRects كل حقل outRects عدد وحدات البكسل التي يجب تعيينها لكل مكون view ، على غرار الهوامش الداخلية والخارجية. نظرًا لأنني استخدمت GridLayoutManager وأردت تعيين مسافات متساوية بين عناصر الشبكة ، فقد قمت بتعيين المسافة البادئة على اليمين إلى 25 بكسل (أي الإزاحة / 2) لكل عنصر زوجي والمسافة البادئة على اليسار إلى 25 بكسل لكل عنصر فردي ، مع الحفاظ على نفس المسافة البادئة نفسها لجميع العناصر.


المسافة البادئة للشبكة


2. ItemAnimator


يستخدم ItemAnimator لتحريك العناصر أو view المكونات داخل RecyclerView .


تحريك العناصر في قائمة


دعونا نجعل تطبيقنا يشبه Instagram من خلال توسيع DefaultItemAnimator وتجاوز عدة طرق.


 public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { return true; } 

تحدد طريقة canReuseUpdatedViewHolder(...) ما إذا كان ViewHolder استخدام ViewHolder نفسه للرسوم المتحركة إذا تغيرت بيانات هذا العنصر. إذا ViewHolders false ، فسيتم ViewHolders كل من ViewHolders - القديمة والمحدثة - إلى أسلوب animateChange(...) .


 public ItemHolderInfo recordPreLayoutInformation(@NonNull RecyclerView.State state, @NonNull RecyclerView.ViewHolder viewHolder, int changeFlags, @NonNull List<Object> payloads) { if (changeFlags == FLAG_CHANGED) { for (Object payload : payloads) { if (payload instanceof String) { return new CharacterItemHolderInfo((String) payload); } } } return super.recordPreLayoutInformation(state, viewHolder, changeFlags, payloads); } public static class CharacterItemHolderInfo extends ItemHolderInfo { public String updateAction; public CharacterItemHolderInfo(String updateAction) { this.updateAction = updateAction; } } 

RecyclerView يستدعي طريقة recordPreLayoutInformation(...) لبدء تقديم layout . يجب أن يقوم ItemAnimator بتسجيل المعلومات الضرورية حول مكون view قبل استبداله أو نقله أو حذفه. سيتم نقل البيانات التي يتم إرجاعها بواسطة هذه الطريقة إلى طريقة الرسوم المتحركة المقابلة (في حالتنا ، هذا هو animateChange(...) ).


 @Override public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) { if (preInfo instanceof CharacterItemHolderInfo) { CharacterItemHolderInfo recipesItemHolderInfo = (CharacterItemHolderInfo) preInfo; CharacterRVAdapter.CharacterViewHolder holder = (CharacterRVAdapter.CharacterViewHolder) newHolder; if (CharacterRVAdapter.ACTION_LIKE_IMAGE_DOUBLE_CLICKED.equals(recipesItemHolderInfo.updateAction)) { animatePhotoLike(holder); } } return false; } private void animatePhotoLike(final CharacterRVAdapter.CharacterViewHolder holder) { holder.likeIV.setVisibility(View.VISIBLE); holder.likeIV.setScaleY(0.0f); holder.likeIV.setScaleX(0.0f); AnimatorSet animatorSet = new AnimatorSet(); ObjectAnimator scaleLikeIcon = ObjectAnimator.ofPropertyValuesHolder (holder.likeIV, PropertyValuesHolder.ofFloat("scaleX", 0.0f, 2.0f), PropertyValuesHolder.ofFloat("scaleY", 0.0f, 2.0f), PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f, 0.0f)); scaleLikeIcon.setInterpolator(DECELERATE_INTERPOLATOR); scaleLikeIcon.setDuration(1000); ObjectAnimator scaleLikeBackground = ObjectAnimator.ofPropertyValuesHolder (holder.characterCV, PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.95f, 1.0f), PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.95f, 1.0f)); scaleLikeBackground.setInterpolator(DECELERATE_INTERPOLATOR); scaleLikeBackground.setDuration(600); animatorSet.playTogether(scaleLikeIcon, scaleLikeBackground); animatorSet.start(); } 

يستدعي RecyclerView أسلوب animateChange(...) عند وجود عنصر المحول قبل وبعد التقديم بعد استدعاء الأسلوب notifyItemChanged(int) . يمكن استخدام هذه الطريقة أيضًا عند استدعاء notifyDataSetChanged() ، إذا كان المحول يستخدم معرفات ثابتة. يعد ذلك ضروريًا بحيث يمكن لـ RecyclerView إعادة استخدام مكونات view في ViewHolders نفسها. لاحظ أن هذه الطريقة تأخذ كوسيطة: (ViewHolder oldHolder ، ViewHolder newHolder ، ItemHolderInfo preInfo ، ItemHolderInfo postInfo) . نظرًا لأننا نعيد استخدام ViewHolder ، فإن كل من oldHolder و newHolder متماثلان.


عندما ينقر المستخدم نقرًا مزدوجًا فوق أي عنصر ، تُسمى الطريقة التالية:


 notifyItemChanged(position, ACTION_LIKE_IMAGE_DOUBLE_CLICKED); 

يؤدي هذا إلى بدء السلسلة الكاملة من المكالمات: canReuseUpdatedViewHolder(...) و recordPreLayoutInformation(...) ، وفي نهاية المطاف ، animateChange(...) في ItemAnimator ، والذي بدوره يحرك عنصر القائمة وأيقونة القلب في هذا العنصر ( مثال في ملف GIF أعلاه).


هذا هو الجزء الثاني من سلسلة مقالات حول RecyclerView . إذا فاتك الجزء الأول ، فاقرأه هنا .


بعض المقالات الجيدة على RecyclerView :



← نصائح للاستخدام المهني RecyclerView. الجزء الأول

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


All Articles