Issue
I have a fragment with a recyclerview which is not scrolling to the selected position. It works by preselecting the previous saved item. It does select it (the items in the list has radio buttons) but it does not scroll to that position as it should. I've tried every way i found but still not working.
Here is the code i've tried to the scrolling:
//1
mBinding.rvManufacturers.scrollToPosition(position);
//2
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mBinding.rvManufacturers.scrollToPosition(adapter.getSelectedItem());
}
}, 200);
//3
mBinding.rvManufacturers.post(() -> mBinding.rvManufacturers.smoothScrollToPosition(adapter.getSelectedItem()));
//4
linearLayoutManager.scrollToPositionWithOffset(adapter.getSelectedItem(), 20);
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvManufacturers"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/item_choose_node_manufacturer" />
</LinearLayout>
Fragment:
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
mActivity = getActivity();
((App) mActivity.getApplication()).getAppComponent().inject(this);
mScreenNavigator = new ScreenNavigator(mActivity, mActivity.getSupportFragmentManager());
mSettingsViewModel = new ViewModelProvider(mActivity, mViewModelFactory)
.get(SettingsViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mBinding = FragmentConfigurationBinding.inflate(inflater, container, false);
mSettingsViewModel.getSensorConfigurationsLiveData()
.observe(getViewLifecycleOwner()
,this::observeSensorConfiguration);
setupView();
return mBinding.getRoot();
}
private void setManufacturersList() {
manufacturersList = new ArrayList<>();
manufacturersList.add(new DigManufacturerModel("Ford", 1, TypeOfCar.Manual));
manufacturersList.add(new ManufacturerModel("Mazda", 2, TypeOfCar.Manual));
manufacturersList.add(new ManufacturerModel("Ferrari", 3, TypeOfCar.Manual));
manufacturersList.add(new ManufacturerModel("Renault", 4, TypeOfCar.Manual));
manufacturersList.add(new ManufacturerModel("Lamborghini", 5, TypeOfCar.Manual));
manufacturersList.add(new ManufacturerModel("Suzuki", 6, TypeOfCar.Manual));
manufacturersList.add(new DigManufacturerModel("Ford", 7, TypeOfCar.Automatic));
manufacturersList.add(new ManufacturerModel("Mazda", 8, TypeOfCar.Automatic));
manufacturersList.add(new ManufacturerModel("Ferrari", 9, TypeOfCar.Automatic));
manufacturersList.add(new ManufacturerModel("Renault", 10, TypeOfCar.Automatic));
manufacturersList.add(new ManufacturerModel("Lamborghini", 11,
TypeOfCar.Automatic));
manufacturersList.add(new ManufacturerModel("Suzuki", 12, TypeOfCar.Automatic));
adapter = new CarOptionAdapter(mActivity, manufacturersList,
R.layout.item_choose_car_manufacturer);
mBinding.rvManufacturers.setAdapter(adapter);
mBinding.rvManufacturers.setLayoutManager(new LinearLayoutManager(mContext));
}
//This method is called from the viewmodel. It's working properly because it
//is used to preselect in the recyclerview the previous saved car manufacturer
//radio button. But the scrolling isn't working.
private void observeCarManufacturer(String carManufacturerBrand) {
for (int i = 0; i < manufacturersList.size(); i++) {
if (carManufacturerBrand.equals(manufacturersList.get(i).getName())) {
adapter.updateSelectedItem(i);
mBinding.rvNodeManufacturers.scrollToPosition(i);
break;
}
}
}
Custom Adapter:
public class CarOptionAdapter extends RecyclerView.Adapter<CarOptionAdapter.ViewHolder> {
protected final Context mContext;
protected final List<ManufacturerModel> mData;
private int mSelectedItem = -1;
private final int mLayoutResId;
public CarOptionAdapter(final Context context, final List<ManufacturerModel> data,
int mLayoutResId) {
this.mContext = context;
this.mData = data;
this.mLayoutResId = mLayoutResId;
}
@NonNull
@Override
public CarOptionAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
final View view = inflater.inflate(mLayoutResId, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.ivManufacturer.setImageResource(R.drawable.ic_cloud);
holder.tvManufacturer.setText(mData.get(position).getName());
holder.radio.setChecked(position == mSelectedItem);
}
public int getSelectedItem() {
return mSelectedItem;
}
public void updateSelectedItem(int selectedItem) {
mSelectedItem = selectedItem;
}
@Override
public int getItemCount() {
return mData.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
RadioButton radio;
TextView tvManufacturer;
ImageView ivManufacturer;
public ViewHolder(final View inflate) {
super(inflate);
radio = inflate.findViewById(R.id.radioManufacturer);
tvManufacturer = inflate.findViewById(R.id.textManufacturer);
ivManufacturer = inflate.findViewById(R.id.ivManufacturer);
View.OnClickListener clickListener = v -> {
mSelectedItem = getAdapterPosition();
notifyItemRangeChanged(0, mData.size());
};
itemView.setOnClickListener(clickListener);
radio.setOnClickListener(clickListener);
}
}
}
Is there any other way to achieve the scrolling to position?
Solution
I realised that the recyclerView was embedded in a nestedScrollView so that's why the scroll was not working as expected.
Here is the fix for it:
mBinding.rvManufacturers.post(() -> {
float y = mBinding.rvManufacturers.getY() + mBinding.rvManufacturers.getChildAt(selectedItem).getY();
nestedScrollView.smoothScrollTo(0, (int) y);
});
The full discussion about it and the original answer is here: https://stackoverflow.com/a/50367883/13373575
Answered By - MadMax
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.