RecyclerView-comment mettre en évidence l'élément central visible pendant le défilement

j'ai besoin d'un RecyclerView comme ceci:

enter image description here

Il ne doit:

  • afficher les 7 éléments en fonction du temps ( FAIT )

  • centrer la RecyclerView sur l'élément central visible ( fait )

  • quand je fais défiler vers droite/gauche, l'élément central sera "surligné" (le bouton est sélectionné > couleur bleue) ( besoin D'aide )

  • quand je clique sur un bouton, il sera centré avec un scrool lisse ( besoin D'aide )

j'ai utilisé la classe SnapHelper pour centrer le RecyclerView sur les articles centraux (je récupère l'article central visible obtenir l'enfant le plus proche à l'écran centre)

MON ADAPTATEUR:

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

EN PAGE DE L'ÉLÉMENT:

<?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>
7
demandé sur eldivino87 2017-05-12 19:32:23

1 réponses

Espérons que cette aide -

notez qu'il s'agit d'une solution hacky, en particulier la mise en évidence sur le rouleau. En outre, je n'ai pas profilé de performance. Vous devriez probablement vérifier. J'ai aussi changé timeLapseButton en TextView car changer le fond sur Button va faire s'effondrer d'autres propriétés de layout.

si vous n'aimez pas la solution hacky, vous pouvez consulter quelques bibliothèques de cartes.

ex:) https://github.com/PhilJay/MPAndroidChart

Classe Adaptateur

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

activité ou Fragment où vous avez recyclerView & adaptateur

...

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;
        }
    }
});
8
répondu Emma 2017-05-13 01:21:46