Recyclerview view не работает с setNestedScrollingEnabled и никогда не перерабатывает любые виды

Я столкнулся с двумя проблемами:

  1. Слушатель прокрутки не работает
  2. RecyclerView никогда не перерабатывает какие-либо представления, когда он подключен к NestedScrollView . Он действует как линейный макет внутри ScrollView. Он использует много памяти и создает лага.

Я прикрепляю фрагмент проигрывателя youtube поверх представления recycler, так как я не могу поместить фрагмент в представление recycler. В моем коде вы видите, что есть макет кадра.

Мой макет выглядит так:

  <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> 

Я хочу использовать прослушиватель прокрутки для загрузки большего количества элементов, поэтому я попробовал следующее:

 @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(); } } 

Но layoutManager.findFirstVisibleItemPosition()==0 поэтому он не работает, и больше onScrolled never called twice так как я устанавливаю recyclerview.setNestedScrollingEnabled (false)

Поэтому я попытался в onBindView как это

  public void onBindViewHolder(RecyclerView.ViewHolder customViewHolder, int i) { Log.w("d","inside bind view"); if(i>=getItemCount()-1 && !datamanager.isDataLoading()){ datamanager.loadmoreData(); } 

Но recylerview связывает все представления сразу, прежде чем я даже начну прокрутку, поэтому этот метод также не работает.

Представление recycler никогда не перерабатывает какие-либо представления, когда он привязан к вложенному представлению прокрутки, его действия, установленные на линейной компоновке внутри прокрутки, создают огромную память и отстают от экрана.

В точку. Вы не можете поместить RecyclerView в другой прокручиваемый вид.

Это не сработает, потому что представление об упаковке должно знать общую высоту RecyclerView, и RecyclerView может знать только свою общую высоту, измеряя и компонуя все ее элементы.

Как это исправить?

Не размещайте RecyclerView внутри другого прокрутки.

Если вам нужен верхний или нижний колонтитул, вам придется добавить его в RecyclerView и позволить RecyclerView позаботиться о его отображении. Избавьтесь от своего ScrollView и переместите заголовок внутри RecyclerView.

Технически можно также загружать фрагменты внутри RecyclerView, но я должен признать, что это нормально работает, немного сложно.

Есть также множество библиотек, которые облегчают этот процесс, моим личным фаворитом является Epoxy от AirBnb, но есть также Groupie и многие другие.

Я справился с такой ситуацией. Существует рециклинг. В представлении Recycler есть viewpager. У viewpager есть фрагменты, а затем внутри фрагмента есть recyclerview.

Вам нужно взломать штрихи, чтобы они прокручивались отлично.

 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; } 

Вот как я это добился, Ive попытался скрыть код до минимального минимума

 public class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int VIEW_TYPE_LOADING = 0; private static final int VIEW_TYPE_ITEM = 1; public boolean isLoading; private int visibleThreshold = 5; private int lastVisibleItem, totalItemCount; public ArrayList<Data> datas; private OnLoadMoreListener mOnLoadMoreListener; public DataAdapter(RecyclerView mRecyclerView, ArrayList<Data> datas) { this.datas = datas; final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager(); mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); totalItemCount = linearLayoutManager.getItemCount(); lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) { if (mOnLoadMoreListener != null) { DataAdapter.this.datas.remove(null); mOnLoadMoreListener.onLoadMore(); } } } }); } public static class DataObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener { //your views public DataObjectHolder(View itemView) { super(itemView); //initialize your views } @Override public void onClick(View v) { if (onItemClickListener != null) onItemClickListener.onItemClick(getAdapterPosition(), v); } } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } @Override public int getItemViewType(int position) { return datas.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == VIEW_TYPE_ITEM) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_data, parent, false); DataObjectHolder dataObjectHolder = new DataObjectHolder(view); return dataObjectHolder; } else if (viewType == VIEW_TYPE_LOADING) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_loading_item, parent, false); return new LoadingViewHolder(view); } return null; } @Override public void onBindViewHolder(final RecyclerView.ViewHolder hldr, final int position) { if (hldr instanceof DataObjectHolder) { final Data data = datas.get(position); final DataObjectHolder holder = (DataObjectHolder) hldr; //bind your views } else if (hldr instanceof LoadingViewHolder) { LoadingViewHolder loadingViewHolder = (LoadingViewHolder) hldr; if (isLoading) { loadingViewHolder.progressBar.setVisibility(View.VISIBLE); loadingViewHolder.progressBar.setIndeterminate(true); loadingViewHolder.tv_load_more.setVisibility(View.GONE); loadingViewHolder.tv_load_more.setOnClickListener(null); } else { loadingViewHolder.progressBar.setVisibility(View.GONE); loadingViewHolder.tv_load_more.setVisibility(View.VISIBLE); loadingViewHolder.tv_load_more.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mOnLoadMoreListener != null) { datas.remove(null); mOnLoadMoreListener.onLoadMore(); } } }); } } } @Override public int getItemCount() { return datas.size(); } public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) { this.mOnLoadMoreListener = mOnLoadMoreListener; } } 

XML для loadViewHolder показан ниже, вы в основном просто раздуваете, чтобы получить держатель

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp"> <ProgressBar android:id="@+id/progressBar1" android:layout_width="20dp" android:layout_height="20dp" android:layout_centerInParent="true" android:layout_gravity="center" android:indeterminate="true"/> <TextView android:id="@+id/tv_load_more" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:gravity="center" android:text="Tap to load more" android:textSize="14sp"/> </RelativeLayout> 

Надеюсь, вы найдете это полезным