Как получить центральный элемент после того, как RecyclerView привязал его к центру?

Я реализую горизонтальный RecyclerView которые привязывают элементы к центру после прокрутки, как горизонтальные списки Google Play App. Это обзор.

Мой код ниже:

MainMenuAdapter mainMenuAdapter = new MainMenuAdapter(this, mDataset);

final LinearLayoutManager layoutManagaer = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);

RecyclerView mainMenu = (RecyclerView) findViewById(R.id.main_menu);
mainMenu.setLayoutManager(layoutManagaer);
mainMenu.setAdapter(mainMenuAdapter);

final SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mainMenu);     

Как я могу получить центральный пункт (позицию) после RecyclerView щелкнул по центру? Нет ли реализации для этого слушателя? Также при касании вида элемента я хочу привязать его к центру. Как я могу это сделать?

2 ответа

Решение

Если вам нужен вид, вы можете позвонить

 View view =  snapHelper.findSnapView(layoutManagaer);

как только у вас появится представление, вы сможете получить позицию в наборе данных для этого представления. Например, используя

   mainMenu.getChildAdapterPosition(view)

Даже если вы не собираетесь использовать SnapHelper Вы можете получить положение центрального элемента, RecyclerView.OnScrollListener,

  1. копия MiddleItemFinder класс для вашего проекта.
  2. Создать объект обратного вызова MiddleItemCallback,

    MiddleItemFinder.MiddleItemCallback callback = 
            new MiddleItemFinder.MiddleItemCallback() {
                    @Override
                    public void scrollFinished(int middleElement) {
                        // interaction with middle item
                    }
    };
    
  3. Добавить новый слушатель прокрутки к вашему RecyclerView

    recyclerView.addOnScrollListener(
            new MiddleItemFinder(getContext(), layoutManager, 
                    callback, RecyclerView.SCROLL_STATE_IDLE));
    
  4. Последний параметр или MiddleItemFinder конструктор scrollState,

    • RecyclerView.SCROLL_STATE_IDLE - RecyclerView в настоящее время не прокручивается. Прокрутка закончена.
    • RecyclerView.SCROLL_STATE_DRAGGING - RecyclerView в настоящее время перетаскивается с помощью внешнего ввода, такого как сенсорный ввод пользователя.
    • RecyclerView.SCROLL_STATE_SETTLING - RecyclerView в настоящее время анимируется до конечной позиции, не находясь под внешним контролем.
    • MiddleItemFinder.ALL_STATES - Все штаты вместе.
  5. Например, если вы выберете RecyclerView.SCROLL_STATE_IDLE в качестве последнего параметра конструктора, чем в конце всей прокрутки, объект обратного вызова вернет вам среднюю позицию элемента.

Класс MiddleItemFinder:

public class MiddleItemFinder extends RecyclerView.OnScrollListener {

    private
    Context context;

    private
    LinearLayoutManager layoutManager;

    private
    MiddleItemCallback callback;

    private
    int controlState;

    public
    static final int ALL_STATES = 10;

    public MiddleItemFinder(Context context, LinearLayoutManager layoutManager, MiddleItemCallback callback, int controlState) {
    this.context = context;
    this.layoutManager = layoutManager;
    this.callback = callback;
    this.controlState = controlState;
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

        if (controlState == ALL_STATES || newState == controlState) {

            int firstVisible = layoutManager.findFirstVisibleItemPosition();
            int lastVisible = layoutManager.findLastVisibleItemPosition();
            int itemsCount = lastVisible - firstVisible + 1;

            int screenCenter = context.getResources().getDisplayMetrics().widthPixels / 2;

            int minCenterOffset = Integer.MAX_VALUE;

            int middleItemIndex = 0;

            for (int index = 0; index < itemsCount; index++) {

                View listItem = layoutManager.getChildAt(index);

                if (listItem == null)
                    return;

                int leftOffset = listItem.getLeft();
                int rightOffset = listItem.getRight();
                int centerOffset = Math.abs(leftOffset - screenCenter) + Math.abs(rightOffset - screenCenter);

                if (minCenterOffset > centerOffset) {
                    minCenterOffset = centerOffset;
                    middleItemIndex = index + firstVisible;
                }
            }

            callback.scrollFinished(middleItemIndex);
        }
    }

    public interface MiddleItemCallback {

        void scrollFinished(int middleElement);
    }
}
Другие вопросы по тегам