在RecyclerView上与ViewPager同步显示所选项目

时间:2016-02-22 09:38:09

标签: android android-fragments android-viewpager android-recyclerview

我正在尝试让ViewPager和RecyclerView在显示图像时同步工作。 ViewPager包含一个显示全尺寸图像的ImageView,回收者视图显示以前和即将出现的图像的缩略图。

如果用户在ViewPager上滑动,则RecyclerView会左/右同步移动。如果用户滚动然后单击照片,则ViewPager会设置该位置。

这一切都有效,只是给我的应用程序背景。

我坚持使用的部分显示当前在来自onPageSelected 的RecyclerView 中选择的缩略图周围的边框。被视为已选择的元素是当前在ViewPager

上显示的元素

许多其他问题使用onClickListener处理此问题。我的onClickListener只是调用

viewPager.setCurrentItem(index)

因此,无论何时选择一个项目,都会自然地从ViewPager或click事件中调用onPageSelected。所以我觉得我需要设置边框。

到目前为止,由于图像数量仅为20,我使用了一点点黑客。

for (int i = 0, ii = recyclerViewAdapter.getItemCount(); i < ii; i++) {
        //RecyclerView.ViewHolder holder = recyclerView.findViewHolderForItemId(recyclerViewAdapter.getItemId(i));
        RecyclerView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(position);

        if (holder instanceof RecyclerViewAdapter.RecyclerViewHolder) {
            if (i == position) {
                ...
                ((RecyclerViewAdapter.RecyclerViewHolder) holder).getViewHolderContainer().setBackground(border);
            } else {
                ((RecyclerViewAdapter.RecyclerViewHolder) holder).getViewHolderContainer().setBackground(null);
            }
        }
    }

这不起作用。如果得到正确的位置,因为我提供的是ViewPager,但是没有一种方法可以在&#39;位置检索ViewHolder。似乎工作。

所以,毕竟,我的问题是,是否有人可以推荐我一个干净的方式(或者甚至在这一点上甚至是黑客),这将让我根据来自ViewPager的onPageSelected的位置更新元素的当前位置

谢天谢地。

1 个答案:

答案 0 :(得分:2)

所以我最终使用两个接口来实现这一点。不需要丑陋的循环黑客。

ViewPager.OnPageChangeListener和OnChildAttachStateListener。

基本上我的问题是,如果我滚动离开RecyclerView中当前选定的项目,那么我之后无法取消选择该项目,因为ViewHolder已被回收或为null。基本上我无法访问上一个视图以取消选择它,因此当您滚动它时,最终会选择多个项目。

所以使用ViewPager很容易。

@Override
public void onPageSelected(int position)
    int previousItemPos = currentItemPos; //currentItemPos is a class attr
    currentItemPos = position;
    int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation()
    if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) { //portrait
        portraitScroll(position) //scrolls the recyclerView to currently selected item based on viewWidth
    } else if .. landscape do the same
    changeItem(position, previousItemPos);
}

@Override
public void onChildViewAttachedToWindow(View view) {
    int childPosition = recyclerView.getChildAdapterPosition(view);
    if (childPosition == currentItemPos) {
        highlightItem(view); //applies an effect
    }
}

@Override
public void onChildViewDetachedToWindow(View view) {
    unHighlightItem(view);
}

private void changeItem(int newItem, int oldItem) {
    ViewHolder holder = recyclerView.findViewHolderForItemId(recyclerView.getItemId(newItem));
    if (holder instance of RecyclerViewHolder) {
        highlightItem((RecyclerViewHolder) holder).getViewHolderContainer());
    }
    ViewHolder oldHolder = recyclerView.findViewHolderForItemId(recyclerView.getItemId(oldItem));
    if (oldHolder instance of RecyclerViewHolder) {
        unHighlightItem((RecyclerViewHolder) holder).getViewHolderContainer());
    }

所以基本上每次我们滚动以便ViewPager中当前选择的项目都不在视线范围内时,我们会在分离时取消选择它。如果我们回滚到它并且位置没有改变,我们重新选择它。

如果ViewPager更改项目,首先我们根据每个RecyclerViews视图的宽度滚动到该项目,然后我们在onPageSelected中选择它。