Je suis confronté à deux problèmes:
RecyclerView
ne recycle jamais les vues lorsqu'elle est attachée à une NestedScrollView
. Il agit comme une mise en page linéaire dans ScrollView. Il utilise beaucoup de mémoire et crée des décalages. J'attache un fragment de lecteur youtube au-dessus de la vue du recycleur, car je ne peux pas en insérer un dans la vue du recycleur. Dans mon code, vous pouvez voir qu'il y a une disposition du cadre.
Ma mise en page ressemble à ceci:
<Android.support.v4.widget.NestedScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/nestedScroll"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="#ffffff"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="#ffffff"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="240dp"
Android:layout_alignParentTop="true"/>
</LinearLayout>
<Android.support.v7.widget.RecyclerView
Android:id="@+id/recycler_view"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_below="@+id/youtube_layout"
Android:visibility="visible"/>
</LinearLayout>
</Android.support.v4.widget.NestedScrollView>
Je veux utiliser le listener de défilement pour charger plus d’éléments . J’ai donc essayé ce qui suit:
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
Log.i(TAG, "onScrolled: ");
// bail out if scrolling upward or already loading data
if (dy < 0 || dataLoading.isDataLoading()) return;
final int visibleItemCount = recyclerView.getChildCount();
final int totalItemCount = layoutManager.getItemCount();
final int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
if ((totalItemCount - visibleItemCount) <= (firstVisibleItem )) {
onLoadMore();
}
}
Mais layoutManager.findFirstVisibleItemPosition()==0
ne fonctionne donc pas, et plus encore sur onScrolled never called twice
puisque j'ai défini Recyclerview.setNestedScrollingEnabled (false)
donc j'ai essayé dans onBindView
comme ça
public void onBindViewHolder(RecyclerView.ViewHolder customViewHolder, int i) {
Log.w("d","inside bind view");
if(i>=getItemCount()-1 && !datamanager.isDataLoading()){
datamanager.loadmoreData();
}
mais le recylerview lie la vue tout à la fois avant même que je commence à faire défiler, donc cette méthode ne fonctionne pas non plus.
La vue recycleur ne recycle jamais aucune vue lorsqu'elle est attachée à la vue de défilement imbriquée, elle agit comme une mise en page linéaire dans la vue de défilement. Elle crée une mémoire énorme et retarde l'écran.
Exactement. Vous ne pouvez pas placer un RecyclerView dans une autre vue défilante.
Cela ne fonctionnera pas, car la vue d'habillage doit connaître la hauteur totale de RecyclerView et RecyclerView ne peut connaître sa hauteur totale qu'en mesurant et en mettant en forme tous de ses éléments.
Ne placez pas un RecyclerView dans une autre vue défilante.
Si vous avez besoin d'un en-tête ou d'un pied de page, vous devrez l'ajouter à RecyclerView et laisser le RecyclerView se charger de l'afficher. Débarrassez-vous de votre ScrollView et déplacez votre en-tête à l'intérieur de RecyclerView.
Techniquement, il est également possible de charger des fragments à l'intérieur d'un RecyclerView, mais je dois admettre que le fonctionnement correct de ce dernier est un peu délicat.
Il y a aussi beaucoup de bibliothèques qui facilitent le processus, mon préféré étant Epoxy fabriqué par AirBnb, mais il y a aussi Groupie , et bien d'autres.
J'ai géré ce genre de situation. Il y a un recyclage. La vue Recycler a viewpager. Le visualiseur a des fragments, puis il y a une vue de recyclage à l'intérieur du fragment.
Vous devez pirater les touches pour le faire défiler parfaitement.
private boolean interceptTouch = true;
private static final int MIN_DISTANCE = 200;
private float downX = 0, downY = 0, moveX = 0, moveY = 0, upX = 0, upY;
public TouchInterceptRecyclerView(Context context) {
super(context);
}
public TouchInterceptRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (getRvTop() == 0) {
onTouchEvent(ev);
}
return interceptTouch;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
moveX = event.getX();
moveY = event.getY();
break;
case MotionEvent.ACTION_UP:
upX = event.getX();
upY = event.getY();
break;
}
float deltaX = upX - downX;
if (getViewTop() == 0 && moveY > downY && Math.abs(moveY - downY) > MIN_DISTANCE) { // moving down
interceptTouch = true;
}else if (Math.abs(deltaX) > MIN_DISTANCE) {
if (upX > downX) { // Left to Right swipe action
interceptTouch = false;
}else { // Right to left swipe action
interceptTouch = false;
}
} else { // screen tap
interceptTouch = false;
}
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
}
@Override
public void onScrolled(int dx, int dy) {
if (getViewTop() <= 0) {
interceptTouch = false; // dispatch the touch to child when reached top
} else {
interceptTouch = true; // do not dispatch the touch event
}
super.onScrolled(dx, dy);
}
public int getViewTop() {
int top = 0;
View v = this.getChildAt(1);
if (v == null) {
v = this.getChildAt(0);
}
if (v != null && v instanceof LinearLayout) {
top = v.getTop();
}
return top;
}
public int getRvTop() {
int top = -1;
View v = this.getChildAt(1);
if (v == null) {
v = this.getChildAt(0);
}
if (v != null && v instanceof LinearLayout) {
ViewPager vp = (ViewPager) v.findViewById(R.id.single_tribe_pager);
if (vp != null) {
int currentPos = vp.getCurrentItem();
RecyclerView rv = (RecyclerView) vp.findViewWithTag("recyclerview" + currentPos);
if (rv != null) {
View v1 = rv.getChildAt(0);
if (v1 != null && v1 instanceof CardView) {
top = v1.getTop() - ResourceUtils.getDimensionPixelOffset(R.dimen.padding_20); // deducting 20 as we have give top margin as 20 to the top layout
}
}
}
}
return top;
}