Infinite/Circular Recyclerview, smothScrollToPosition goes to wrong index

烈酒焚心 提交于 2020-03-03 11:38:52

问题


I am trying to achieve an infinite/circular recyclerview, Here's the implementation of the Adapter class.

    public class MyAdapter extends
        RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final String TAG = MyAdapter.class.getSimpleName();

    private static final int VIEW_TYPE_NORMAL = 1;

    private static final int VIEW_TYPE_GAP = 2;

    private Context mContext;

    private final List<ChannelInfo> mChannelInfoList;

    private LinearTunerClickListener mClickListener;

    public MyAdapter(
            Context context, List<ChannelInfo> channelInfoList, LinearTunerClickListener mClickListener) {
        mChannelInfoList = channelInfoList;
        mContext = context;
        this.mClickListener = mClickListener;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        //Variable to store inflated view based on VIEW TYPE.
        View inflatedView;

        BaseHolder baseHolder;

        if (viewType == VIEW_TYPE_NORMAL) {
            inflatedView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_some_holder1, parent, false);
            baseHolder = new SomeHolder1(inflatedView);
        } else {
            inflatedView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_some_holder2, parent, false);
            baseHolder = new SomeHolder2(inflatedView);
        }

        return baseHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder myViewHolder, int position) {

        if (mContext != null) {

            if (mChannelInfoList != null) {

                mPos = position % mChannelInfoList.size();

               // do stuff
            }

        }

    }

    @Override
    public int getItemViewType(int position) {
        bPos = position % mChannelInfoList.size();
        int viewType;
        if (bPos != mChannelInfoList.size() - 1) {
            viewType = VIEW_TYPE_NORMAL;
        } else {
            // If current position is last item, then return view type as GAP
            viewType = VIEW_TYPE_GAP;
        }
        return viewType;
    }

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

}

and this is the class which holds the adapter and takes an index(required position to scroll from bundle)

 public class MainActivity extends AppCompatActivity implements SomeListener {
        private static final String TAG = "MainActivity" + " : ";
        @BindView(R.id.activity_main2_rv)
        RecyclerView mRecyclerView;

    private MyAdapter mAdapter;
    private List<ChannelInfo> mChannelInfoList = new ArrayList<>();

    private SnapHelper mSnapHelper;
    private CenterLayoutManager mLayoutManager;
    private Integer mIndex;
    private String mChannelNo;

    private int mFocusPos = -1;
    private View mFocusedView;
    private int pos = -1;
    private int BIG = Integer.MAX_VALUE;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.linear);
        ButterKnife.bind(this);
        Log.e(TAG, "onCreate(): ");

        bundleOperation();
        setUpRecycler();
        setUpSnapHelper();
        setAdapter();


        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (mLayoutManager != null) {


                    mLayoutManager.scrollToPosition(Integer.MAX_VALUE/2);
                    mRecyclerView.smoothScrollToPosition(Integer.MAX_VALUE/2 + (mIndex-3));


                }
            }
        }, 300);

    }


    private void bundleOperation() {
        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
            Log.d(TAG, "get Bundle: ");
            mIndex = bundle.getInt("index");
            mChannelNo = bundle.getString("ch_no");
            Log.v(TAG, " we have,  " + " index : " + mIndex + " and " + " ch_no : " + mChannelNo);
            mChannelInfoList = bundle.getParcelableArrayList("list");

        }

    }

    private void setUpRecycler() {
        mLayoutManager = new CenterLayoutManager(
                this,
                CenterLayoutManager.HORIZONTAL,
                false
        );
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

    }

    private void setUpSnapHelper() {
        mSnapHelper = new LinearSnapHelper();
        mSnapHelper.attachToRecyclerView(mRecyclerView);
    }

    private void setAdapter() {
        mAdapter = new MyAdapter(this, mChannelInfoList, this);
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.notifyDataSetChanged();
    }

}

FYI, I have used one custom Layout Manager for carousel effect, so now let's say my list size has total 12 items, now

  mLayoutManager.scrollToPosition(Integer.MAX_VALUE/2);
                mRecyclerView.smoothScrollToPosition(Integer.MAX_VALUE/2 + (mIndex-3));

Logic works fine as it should.------------------------

Now if I modify the list, say adding more items or deleting them, then logic fails miserably on that.

It misses the index completely.

Could you hint me out where to debug or like that, stumbled for many hours. In case you need Center Layout Manager class,

    public class CenterLayoutManager extends LinearLayoutManager {

    private static final float BALANCING_FACTOR = 0.78f;

    private static final float fastScrollSpeedFactor = 50f;

    public CenterLayoutManager(Context context) {
        super(context);
    }

    public CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public CenterLayoutManager(Context context,
                               AttributeSet attrs,
                               int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                       int position) {


        RecyclerView.SmoothScroller smoothScroller =
                new CenterSmoothScroller(recyclerView.getContext()) {


                    @Override
                    protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                        return fastScrollSpeedFactor / displayMetrics.densityDpi;
                    }

                };

        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);

    }

    @Override
    public PointF computeScrollVectorForPosition(int targetPosition) {
        return super.computeScrollVectorForPosition(targetPosition);
    }

    @Override
    public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
                                    RecyclerView.State state) {
        int scrolled = super.scrollHorizontallyBy(dx, recycler, state);

       // some logic to show center item, ZOOMED in
        return scrolled;
    }


    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);
      //  scrollHorizontallyBy(0, recycler, state);
    }

    private static class CenterSmoothScroller extends LinearSmoothScroller {

        CenterSmoothScroller(Context context) {
            super(context);
        }


        @Override
        public int calculateDtToFit(int viewStart, int viewEnd, int boxStart,
                                    int boxEnd, int snapPreference) {
            return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
        }
    }

}

Please ask me if you need a broader scenario to grasp the situation and try to avoid putting link ref directly if it doesn't cover the above scenario. Thanks

来源:https://stackoverflow.com/questions/52074312/infinite-circular-recyclerview-smothscrolltoposition-goes-to-wrong-index

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!