Android Recyclerview视图不能与setNestedScrollingEnabled一起使用,它也不会回收任何视图

Android Recyclerview视图不能与setNestedScrollingEnabled一起使用,它也不会回收任何视图,android,android-recyclerview,android-nestedscrollview,onscrolllistener,Android,Android Recyclerview,Android Nestedscrollview,Onscrolllistener,我面临两个问题: 滚动侦听器无法工作 RecyclerView在附加到NestedScrollView时从不回收任何视图。它在ScrollView中的作用类似于线性布局。它会占用大量内存并产生延迟 我在recycler视图的顶部附加了一个youtube播放器片段,因为我不能在recycler视图中放置一个片段。在我的代码中,您可以看到有一个框架布局 我的布局如下所示: <android.support.v4.widget.NestedScrollView xmlns:android

我面临两个问题:

  • 滚动侦听器无法工作
  • RecyclerView
    在附加到
    NestedScrollView
    时从不回收任何视图。它在ScrollView中的作用类似于线性布局。它会占用大量内存并产生延迟 我在recycler视图的顶部附加了一个youtube播放器片段,因为我不能在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>
    

    但是在我开始滚动之前,recylerview会一次绑定所有视图,所以这种方法也不起作用。

    我就是这样做到的,我尝试将代码剥离到最低限度

    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;
        }
    
    }
    
    公共类DataAdapter扩展了RecyclerView.Adapter{
    私有静态最终整型视图\类型\加载=0;
    私有静态最终整数视图\类型\项=1;
    公共布尔孤岛加载;
    私有int visibleThreshold=5;
    private int lastVisibleItem,totalItemCount;
    公共阵列列表数据;
    私有OnLoadMoreListener mOnLoadMoreListener;
    公共数据适配器(RecyclerView mRecyclerView、ArrayList数据){
    this.datas=datas;
    最终LinearLayoutManager LinearLayoutManager=(LinearLayoutManager)mRecyclerView.getLayoutManager();
    mrecycleView.addOnScrollListener(新的RecycleView.OnScrollListener(){
    @凌驾
    已填空的公共空间(RecyclerView RecyclerView、int dx、int dy){
    super.onScrolled(recyclerView、dx、dy);
    totalItemCount=linearLayoutManager.getItemCount();
    lastVisibleItem=linearLayoutManager.findLastVisibleItemPosition();
    如果(!isLoading&&totalItemCount)
    当它连接到嵌套的滚动视图时,回收器视图从不回收任何视图,它在滚动视图内的线性布局上起到设置的作用。它创建了巨大的内存并滞后于屏幕

    没错。你不能在另一个滚动视图中放置RecyclerView

    这将不起作用,因为包装视图需要知道RecyclerView的总高度,而RecyclerView只能通过测量和布局其所有项目来知道其总高度

    如何解决这个问题? 不要将RecyclerView放在另一个滚动视图中。

    如果您需要页眉或页脚,则必须将其添加到RecyclerView中,并让RecyclerView负责显示该页眉或页脚。取消滚动视图,将页眉移动到RecyclerView中

    从技术上讲,也可以在RecyclerView中加载片段,但我必须承认,让它正常工作有点棘手


    还有很多库可以促进这一过程,我个人最喜欢的库是AirBnb制作的,但也有,还有很多其他库。

    我处理过这种情况。有一个recyclerview。recyclerview有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;
        }
    
    private boolean-touch=true;
    专用静态最终整数最小距离=200;
    私有浮动downX=0,downY=0,moveX=0,moveY=0,upX=0,upY;
    公共TouchInterceptRecyclerView(上下文){
    超级(上下文);
    }
    公共TouchInterceptRecyclerView(上下文上下文,@Nullable AttributeSet attrs){
    超级(上下文,attrs);
    }
    @凌驾
    公共布尔值onInterceptTouchEvent(MotionEvent ev){
    if(getRvTop()==0){
    火山口(ev);
    }
    回击;
    }
    @凌驾
    公共布尔onTouchEvent(运动事件){
    开关(event.getAction()){
    case MotionEvent.ACTION\u DOWN:
    downX=event.getX();
    downY=event.getY();
    打破
    case MotionEvent.ACTION\u移动:
    moveX=event.getX();
    moveY=event.getY();
    打破
    case MotionEvent.ACTION\u UP:
    upX=event.getX();
    upY=event.getY();
    打破
    }
    浮动deltaX=upX-downX;
    如果(getViewTop()==0&&moveY>downY&&Math.abs(moveY-downY)>minu距离){//向下移动
    触摸=真;
    }else if(数学绝对值(deltaX)>最小距离){
    如果(upX>downX){//从左向右滑动操作
    触摸=假;
    }else{//从右向左滑动操作
    触摸=假;
    }
    }else{//屏幕点击
    触摸=假;
    }
    返回super.onTouchEvent(事件);
    }
    @凌驾
    公共布尔dispatchTouchEvent(MotionEvent ev){
    返回超级dispatchTouchEvent(ev);
    }
    @凌驾
    CrollChanged上的受保护无效(int l、int t、int oldl、int oldt){
    super.onScrollChanged(l,t,oldl,oldt);
    }
    @凌驾
    已填空的公共空间(整数dx,整数dy){
    
    if(getViewTop()我正在使用recyclerview顶部的fragment。我不能这样写哦,对不起,我是在回答另一个问题。如果您确定您发布的答案有误,请随意删除您的答案。您知道吗,yh我没有发布错误问题的答案。我解决了在滚动到底部时将更多项目加载到recycler视图的问题。正如其他人所指出的,你不能在回收器视图中使用片段。总有更好的方法来实现你的目标。我已经加载了片段,但回收器视图不允许片段状态。它会随机崩溃。
    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 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>
    
    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;
        }