RecyclerView – Cómo resaltar el elemento visible central durante el desplazamiento

Necesito un RecyclerView como este:

Introduzca aquí la descripción de la imagen

Debe hacer:

  • Mostrar 7 artículos por tiempo ( HECHO )

  • Centre el RecyclerView en el elemento visible central ( DONE )

  • Cuando me desplazo hacia la derecha / izquierda, el elemento central será "resaltado" (el botón está seleccionado> color azul) ( necesita ayuda )

  • Cuando hago clic en un botón, se centrará con un scrool suave ( necesidad de AYUDA )

SnapHelper clase de SnapHelper para centrar el RecyclerView en los artículos centrales (recupero el artículo visible central que consigue el niño más cercano al centro de la pantalla)

MI ADAPTADOR:

 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); } } 

CONFIGURACIÓN RECICLADOR VIEW:

 mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false); mRecyclerView.setLayoutManager(mLayoutManager); SnapHelper snapHelper = new LinearSnapHelper(); snapHelper.attachToRecyclerView(mRecyclerView); 

POPULATE RECICLADOR 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); 

GESTIÓN DE SCROLL:

 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); } } }); 

DISPOSICIÓN DEL ARTÍCULO:

 <?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> 

Espero que esto ayude –

Tenga en cuenta que se trata de una solución hacky, especialmente el resaltado en desplazamiento. Además, no he perfilado ninguna actuación. Probablemente debería comprobarlo. También cambié timeLapseButton a TextView puesto que cambiar el fondo en el Button colapsará otras características de la disposición.

Si no te gusta la solución hacky, puedes consultar algunas bibliotecas de gráficos.

Ex 🙂 https://github.com/PhilJay/MPAndroidChart

Clase del adaptador

 public interface TimeLapseButtonClickListener { void onClick(int position); } private TimeLapseButtonClickListener timeLapseButtonListener; public void setTimeLapseButtonClickListener(TimeLapseButtonClickListener listener) { this.timeLapseButtonListener = listener; } private void setTimeLapseButton(Button button, String text, final int position) { button.setText(text); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { this.timeLapseButtonListener.onClick(position); } }); } 

Actividad o Fragmento donde tiene recicladorVer y adaptador

 ... private int prevCenterPos; // Keep track the previous pos to dehighlight ... // Click and smooth scroll to get clicked item in the middle adapter.setListener(new RvTrendsGraphAdapter.TimeLapseButtonClickListener() { @Override public void onClick(int position) { View view = mRecyclerView.getLayoutManager().findViewByPosition(position); int middle = mRecyclerView.getWidth() / 2; mRecyclerView.smoothScrollBy(view.getLeft() - middle, 0, new AccelerateDecelerateInterpolator()); } }); // Highlight view in the middle on scroll mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); int center = mRecyclerView.getWidth() / 2; View centerView = mRecyclerView.findChildViewUnder(center, mRecyclerView.getTop()); int centerPos = mRecyclerView.getChildAdapterPosition(centerView); if (prevCenterPos != centerPos) { // dehighlight the previously highlighted view View prevView = mRecyclerView.getLayoutManager().findViewByPosition(prevCenterPos); if (prevView != null) { View button = prevView.findViewById(R.id.rv_trends_graph_button); int white = ContextCompat.getColor(context, R.color.white); button.setBackgroundColor(white); } // highlight view in the middle if (centerView != null) { View button = centerView.findViewById(R.id.rv_trends_graph_button); int highlightColor = ContextCompat.getColor(context, R.color.colorAccent); button.setBackgroundColor(highlightColor); } prevCenterPos = centerPos; } } }); 
  • ¿Necesito múltiples viewHolders para ExpandableListView?
  • ¿Por qué notifyItemChanged sólo funciona en post Runnable después de setAdapter?
  • Firebase RecyclerVisualización infinita
  • Hace notificydatasetchanged llamada onCreateViewHolder al usar RecyclerView
  • NotifyDataSetChanged después del cambio de configuración
  • Cómo actualizar ListView en fragmento que se rellena con BaseAdapter?
  • Adaptador AutoCompleteTextView, adaptador "oculto"?
  • Uso de la API Palatte en el adaptador ListView
  • El adaptador personalizado getview no se llama
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.