RecyclerView вложенный RecyclerView smoothScrolltoPostion автоматическая прокрутка не является нормальной

Теперь есть такой спрос, RecyclerView внутри каждого элемента вложен пейджер с вертикальной прокруткой, а просмотрпейджер автоматически запускает бесконечный цикл. Я использую вложенный RecyclerView RecyclerView для достижения эффекта скользящего просмотра пейджера. Я использовал RecyclerView smoothScrollToPosition для достижения. Но в этом процессе я столкнулся с проблемой: несколько раз скользит вперед и назад за пределы скольжения RecyclerView, внутренний SmoothScrollToPosition RecyclerViwe будет скользить хаосом. Если сделано то же требование. Неполадки

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>

Внешний адаптер:

    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>

это изображение — то, что я хочу

это неправильное изображение, когда я прокручиваю внешний recycerview, smoothScrollToPosition() не работает должным образом


person zqandroiddev    schedule 19.05.2016    source источник
comment
Можете ли вы опубликовать макет вашего макета. Просто я не могу это представить.   -  person Шах    schedule 19.05.2016
comment
я выложил две картинки   -  person zqandroiddev    schedule 19.05.2016
comment
Извините, но я все равно ничего не понимаю. Что ты хочешь? Как это связано с ViewPager? Можешь переписать попонятнее? Вы получите помощь быстрее.   -  person Шах    schedule 19.05.2016


Ответы (2)


Я вижу ваш код здесь. Только представьте, когда скролл остановится?, вам скажут "если while ложно или вообще счетчик закончится". будет ли он?

Давайте зарегистрируем 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();
person raditya gumay    schedule 19.05.2016
comment
спасибо за ответ, но я не знаю как это исправить - person zqandroiddev; 19.05.2016
comment
@zqandroiddev, пожалуйста, поместите куда-нибудь свой полный код, тогда я смогу помочь вам решить эту проблему. или создайте новый проект и просто скопируйте этот фрагмент кода, адаптер и активность. - person raditya gumay; 29.05.2016

Во-первых, добавлять слушателя в 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++);
      }
     }
     });
}
person Шах    schedule 19.05.2016
comment
Это наше требование к продукту. как я могу добавить условие. Можете ли вы дать мне простой план, я хочу проверить его - person zqandroiddev; 19.05.2016
comment
Чтобы я мог помочь вам, мне нужно понять, что вы хотите) я не очень хорошо знаю английский, поэтому я не могу понять - person Шах; 19.05.2016
comment
Вам нужно, чтобы каждый внутренний RecyclerView прокручивал следующий элемент за 2 секунды? - person Шах; 19.05.2016
comment
Затем вам нужно сохранить указатель на экземпляры объекта потока. Теперь вы можете создавать несколько потоков на один RecyclerView - person Шах; 19.05.2016
comment
да, мне нужно, чтобы каждый внутренний RecyclerView прокручивал следующий элемент за 2 секунды. Мой английский тоже плохой. Какой вы национальности? - person zqandroiddev; 19.05.2016
comment
Цыган и башкир, что вам больше нравится :) - person Шах; 19.05.2016
comment
Смотрите мой ответ, он вам поможет. - person Шах; 19.05.2016
comment
но я не знаю как это реализовать - person zqandroiddev; 19.05.2016
comment
Например, в конструкторе вашего адаптера вы создаете новый поток с телом, как в ответе. Затем, когда ваш Activity или Fragment создан, вы вызываете начальный поток, и когда они останавливаются, вы пытаетесь остановить поток. - person Шах; 19.05.2016
comment
Но ваша схема даст вам исключение StackOverflow, потому что вы только добавляете новый элемент, но не удаляете его. Вы должны удалить первый элемент после добавления нового. - person Шах; 19.05.2016
comment
И еще... Если вам просто нужно показать бесконечное скольжение чего-либо без возможности ручной прокрутки, то лучшим решением будет использовать ViewSwitcher с анимацией или пользовательским представлением. - person Шах; 19.05.2016
comment
спасибо за вашу помощь, даже я до сих пор не могу ее решить. наш босс попросил меня выполнить другие функции, а затем успеть проконсультироваться с вами - person zqandroiddev; 19.05.2016
comment
Нет никаких трудностей. Если вам это понадобится в следующий раз, напишите мне, я опубликую полный код. Просто пишу с телефона, невнимательно :) - person Шах; 19.05.2016
comment
Если у вас есть время, я надеюсь, вы можете дать мне полный код :) - person zqandroiddev; 19.05.2016