I need a RecyclerView like this:
It should does:
show 7 items per time (DONE)
center the RecyclerView on the central visible item (DONE)
when I scroll to right/left, the central item will be "highlighted" (the button is selected > blue color) (need HELP)
when I click on a button, it will be centered with a smooth scrool (need HELP)
I used SnapHelper
class to center the RecyclerView on the central items (I retrieve the central visible item getting the nearest child to the screen center)
MY ADAPTER:
public class RvTrendsGraphAdapter extends RecyclerView.Adapter<RvTrendsGraphAdapter.ViewHolder> { private float deviceWidth; private float itemWidth; private List<RvTrendsGraphModel> models; private Context context; public RvTrendsGraphAdapter(Context context, List<RvTrendsGraphModel> models) { this.models = models; this.context = context; } private Context getContext() { return context; } public class ViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.rv_trends_graph_layout) PercentRelativeLayout rootLayout; @BindView(R.id.rv_trends_graph_layout_superiore) PercentRelativeLayout layoutSuperiore; @BindView(R.id.rv_trends_graph_layout_inferiore) RelativeLayout layoutInferiore; @BindView(R.id.rv_trends_graph_vertical_progressbar) ProgressBar verticalProgressBar; @BindView(R.id.rv_trends_graph_button) Button timeLapseButton; public ViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } @Override public RvTrendsGraphAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Context context = parent.getContext(); LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.recycler_trends_graph, parent, false); // Set the width to show 7 elements DisplayMetrics displayMetrics = new DisplayMetrics(); WindowManager windowmanager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); windowmanager.getDefaultDisplay().getMetrics(displayMetrics); deviceWidth = displayMetrics.widthPixels; float progressBarWidth = getContext().getResources().getDimension(R.dimen.picker_time_lapse_progressbar_width); itemWidth = ((deviceWidth + progressBarWidth) / 8f + 1f); view.getLayoutParams().width = (int) itemWidth; return new ViewHolder(view); } @Override public void onBindViewHolder(RvTrendsGraphAdapter.ViewHolder viewHolder, int position) { RvTrendsGraphModel model = models.get(position); PercentRelativeLayout rootLayout = viewHolder.rootLayout; ProgressBar verticalProgressBar = viewHolder.verticalProgressBar; Button timeLapseButton = viewHolder.timeLapseButton; verticalProgressBar.setProgress(model.getProgress()); setTimeLapseButton(timeLapseButton, model.getTimeLapseValue()); } @Override public int getItemCount() { return models.size(); } public RvTrendsGraphModel getItem(int position) { return models.get(position); } /* UTILS */ private void setTimeLapseButton(Button button, String text) { //button.setSelected(false); button.setText(text); } }
SETUP RECYCLER VIEW:
mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false); mRecyclerView.setLayoutManager(mLayoutManager); SnapHelper snapHelper = new LinearSnapHelper(); snapHelper.attachToRecyclerView(mRecyclerView);
POPULATE RECYCLER VIEW:
list = new ArrayList<>(); /* Create foo list... */ list.add(new RvTrendsGraphModel(75, String.valueOf(list.size()))); list.add(new RvTrendsGraphModel(33, String.valueOf(list.size()))); // ... adapter = new RvTrendsGraphAdapter(getActivity(), list); mRecyclerView.setAdapter(adapter); adapter.notifyDataSetChanged(); mRecyclerView.smoothScrollToPosition(list.size() - 1);
SCROLL MANAGEMENT:
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { // Get adapter position of the central item PercentRelativeLayout root = (PercentRelativeLayout) mRecyclerView.findChildViewUnder(centralX, 0); pos = mRecyclerView.getChildAdapterPosition(root); // first try (very bad) if (lastPos != pos) { pos = lastPos; adapter.notifyDataSetChanged(); } // second try (I cannot call notifyitemchanged during the scroll if () { final int pos = mRecyclerView.getChildAdapterPosition(root); adapter.getItem(pos).setCentered(true); adapter.notifyItemChanged(pos); } } });
ITEM LAYOUT:
<?xml version="1.0" encoding="utf-8"?> <android.support.percent.PercentRelativeLayout 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:id="@+id/rv_trends_graph_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="MissingPrefix"> <android.support.percent.PercentRelativeLayout android:id="@+id/rv_trends_graph_layout_superiore" android:layout_width="match_parent" android:layout_height="0dp" app:layout_heightPercent="75%"> <ProgressBar android:id="@+id/rv_trends_graph_vertical_progressbar" style="@style/Widget.ProgressBar.Vertical" android:layout_width="@dimen/picker_time_lapse_progressbar_width" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:progress="50" /> </android.support.percent.PercentRelativeLayout> <RelativeLayout android:id="@+id/rv_trends_graph_layout_inferiore" android:layout_width="match_parent" android:layout_height="0dp" android:layout_below="@+id/rv_trends_graph_layout_superiore" app:layout_heightPercent="25%"> <Button android:id="@+id/rv_trends_graph_button" fontPath="fonts/Roboto-Light.ttf" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/picker_time_lapse_selector" android:minHeight="0dp" android:minWidth="0dp" android:textAllCaps="true" android:textColor="@color/picker_time_lapse_text_color_selector" android:textSize="@dimen/text_size_medium" tools:ignore="ContentDescription" tools:text="16"/> </RelativeLayout> </android.support.percent.PercentRelativeLayout>