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