RecyclerView嵌套的RecyclerView smoothScrolltoPostion自动滚动是不正常的

时间:2016-05-19 02:09:35

标签: android android-recyclerview recycler-adapter nestedrecyclerview

现在有了这样的需求,RecyclerView里面的每个项目都嵌套了一个垂直滚动的viewpager,而viewpager会自动无限循环滚动。我使用嵌套的RecyclerView RecyclerView来实现,以及滚动viewpager的效果。我用RecyclerView smoothScrollToPosition来实现。但是在这个过程中,我遇到了一个问题,就是在RecyclerView的滑动之外来回滑动几次,内部的RecyclerViwe smoothScrollToPosition会混乱滑动。如果完成相同的需求。

下的麻烦分享
public class MainActivity extends AppCompatActivity {

    private RecyclerView mRvOuter;
    private LinearLayoutManager linearLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRvOuter = (RecyclerView) findViewById(R.id.rv_outer);
        linearLayoutManager = new LinearLayoutManager(this);
        mRvOuter.setLayoutManager(linearLayoutManager);
        mRvOuter.setAdapter(new OuterAdapter(this));
    }
}

MainActivity的布局

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#eeeeee">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_outer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
    </RelativeLayout>

OuterAdapter:

    public class OuterAdapter extends RecyclerView.Adapter<OuterAdapter.OuterViewHolder> {
        LayoutInflater layoutInflater;
        List<String> mDatas;
        Context mContext;

        public OuterAdapter(Context context) {
            mContext = context;
            layoutInflater = LayoutInflater.from(context);
        }

        @Override
        public OuterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            OuterViewHolder viewHolder = new OuterViewHolder(layoutInflater.inflate(R.layout.item_outer, parent, false));
            return viewHolder;
        }

        @Override
        public void onBindViewHolder(final OuterViewHolder holder, int position) {
            LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext);
            holder.mRvInner.setLayoutManager(linearLayoutManager);
            holder.mRvInner.setAdapter(new InnerAdapter(mContext, initDada(position)));

            holder.mRvInner.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
                @Override
                public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                    return e.getAction() == MotionEvent.ACTION_MOVE;
                }

                @Override
                public void onTouchEvent(RecyclerView rv, MotionEvent e) {

                }

                @Override
                public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

                }
            });
            final Handler handler = new Handler();
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        SystemClock.sleep(2000);
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                holder.mRvInner.smoothScrollToPosition(holder.i++);
                            }
                        });
                    }
                }
            });
            thread.start();
        }

        @Override
        public int getItemCount() {
            return 30;
        }

        public class OuterViewHolder extends RecyclerView.ViewHolder {
            RecyclerView mRvInner;

            int i;

            public OuterViewHolder(View itemView) {
                super(itemView);
                mRvInner = (RecyclerView) itemView.findViewById(R.id.rv_inner);
            }
        }


        private List<String> initDada(int i) {
            mDatas = new ArrayList<String>();
            for (int j = 0; j <= i; j++) {
                mDatas.add("" + j);
            }
            return mDatas;
        }
    }


    InnerAdapter:

    public class InnerAdapter extends RecyclerView.Adapter<InnerAdapter.InnerViewHolder> {


        private List<String> mInnerDatas;
        private LayoutInflater mInflater;

        public InnerAdapter(Context context, List<String> innerDatas) {
            mInflater = LayoutInflater.from(context);
            mInnerDatas = innerDatas;
        }

        @Override
        public InnerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            InnerViewHolder viewHolder = new InnerViewHolder(mInflater.inflate(R.layout.item_inner, parent, false));
            return viewHolder;
        }

        @Override
        public void onBindViewHolder(InnerViewHolder holder, int position) {
            holder.mTvInner.setText(mInnerDatas.get(position % mInnerDatas.size()));
        }

        @Override
        public int getItemCount() {
            return Integer.MAX_VALUE;
        }

        public class InnerViewHolder extends RecyclerView.ViewHolder {
            TextView mTvInner;

            public InnerViewHolder(View itemView) {
                super(itemView);
                mTvInner = (TextView) itemView.findViewById(R.id.tv_inner);
            }
        }
    }

项目外部布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:background="#ffffff"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:gravity="center"
            android:text="i am belong outerRecyclerView"
            android:textSize="20sp" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_inner"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:layout_marginTop="15dp"
            android:background="#ffaadd"></android.support.v7.widget.RecyclerView>
    </LinearLayout>

    item inner:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_inner"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:textColor="#000"
            android:textSize="30sp" />
    </LinearLayout>

this image is what i want

this is the wrong image, when i sroll outer recycerview, smoothScrollToPosition() does not work well

2 个答案:

答案 0 :(得分:0)

我在这里看到你的代码。想象一下,当滚动停止?时,你会说&#34;如果while是假的,甚至计数器都会结束&#34;。会吗?

让上面的第1行

holder.mRvInner.smoothScrollToPosition(holder.i++);

我们会得到什么。

final Handler handler = new Handler();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    SystemClock.sleep(2000);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            holder.mRvInner.smoothScrollToPosition(holder.i++);
                        }
                    });
                }
            }
        });
        thread.start();

答案 1 :(得分:0)

首先,在onBindViewHolder中添加监听器是一个坏主意。

final Handler handler = new Handler();
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            SystemClock.sleep(2000);
            handler.post(new Runnable() {
                @Override
                public void run() {
                    holder.mRvInner.smoothScrollToPosition(holder.i++);
                }
            });
       }
    }
});
thread.start();

现在,您在每个项目绑定上创建一个新线程。因此,每个RecyclerView可以有几个线程。你不能制作+100500线程。您应该创建一个将遍历所有项目(可见)并滚动其位置的线程。

要获取您应该使用的可见项目的位置:

int findFirstVisibleItemPosition();
int findLastVisibleItemPosition();

要使用ViewHolder

ViewHolder findViewHolderForLayoutPosition(int position);

E.g。

    while (isRunned) {
     SystemClock.sleep(2000);
     handler.post(new Runnable() {
     @Override
     public void run() {
      int last = findLastVisibleItemPosition();
      for(int i = findFirstVisibleItemPosition(); i <= last; ++i) {
       ViewHolder holder = findViewHolderForLayoutPosition(i);
       holder.mRvInner.smoothScrollToPosition(holder.i++);
      }
     }
     });
}