Android 如何在水平循环视图中捕捉到LinearSnapHelper的特定位置?

Android 如何在水平循环视图中捕捉到LinearSnapHelper的特定位置?,android,android-recyclerview,kotlin,pagersnaphelper,Android,Android Recyclerview,Kotlin,Pagersnaphelper,如何在水平循环视图中捕捉LinearSnapHelper()的特定位置?有一个用于RecyclerView的函数scrolltoposition,该函数滚动到该位置,但没有为此snaphelper将其保持在中心位置 我正在寻找类似下图的东西。所以当我设置到特定的位置时,它会保持在中心。我找不到任何与选择职位有关的信息 我找到了,但这帮不了我。 任何帮助都将不胜感激 对于水平循环视图,您应该使用PagerSnapHelper()而不是LinearSnapHelper()如果我理解您的问题,您正在寻

如何在水平循环视图中捕捉LinearSnapHelper()的特定位置?有一个用于RecyclerView的函数scrolltoposition,该函数滚动到该位置,但没有为此snaphelper将其保持在中心位置

我正在寻找类似下图的东西。所以当我设置到特定的位置时,它会保持在中心。我找不到任何与选择职位有关的信息

我找到了,但这帮不了我。 任何帮助都将不胜感激


对于水平循环视图,您应该使用
PagerSnapHelper()
而不是
LinearSnapHelper()

如果我理解您的问题,您正在寻找跳转到某个位置并使该位置在
循环视图中居中的方法

可能您已经尝试了
RecyclerView.scrollToPosition()
,但这并没有捕捉到视图。您可能还尝试了
RecyclerView.smoothScrollToPosition()
,效果更好,但如果您有很多项目并且滚动时间较长,您可能希望避免所有移动

scrollToPosition()
不起作用的原因是它不会触发使用滚动侦听器检测何时捕捉的
LinearSnapHelper
。由于
smoothScrollToPosition()
确实触发了
LinearSnapHelper
,我们将使用
scrollToPosition()
进入目标视图的区域,然后使用
smoothScrollToPosition()
将视图居中,如下所示:

private RecyclerView mRecycler;

private void newScrollTo(final int pos) {
    RecyclerView.ViewHolder vh = mRecycler.findViewHolderForLayoutPosition(pos);
    if (vh != null) {
        // Target view is available, so just scroll to it.
        mRecycler.smoothScrollToPosition(pos);
    } else {
        // Target view is not available. Scroll to it.
        mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
            // From the documentation:
            // This callback will also be called if visible item range changes after a layout
            // calculation. In that case, dx and dy will be 0.This callback will also be called
            // if visible item range changes after a layout calculation. In that case,
            // dx and dy will be 0.
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                mRecycler.removeOnScrollListener(this);
                if (dx == 0) {
                    newScrollTo(pos);
                }
            }
        });
        mRecycler.scrollToPosition(pos);
    }
}
示例应用程序

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private final LinearLayoutManager mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
    private final List<String> mItems = new ArrayList<>();
    private RecyclerView mRecycler;
    private final int mItemCount = 2000;
    private final Handler mHandler = new Handler();
    private final LinearSnapHelper mLinearSnapHelper = new LinearSnapHelper();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (int i = 0; i < mItemCount; i++) {
            mItems.add(i + "");
        }

        mRecycler = findViewById(R.id.recyclerView);
        final RecyclerViewAdapter adapter = new RecyclerViewAdapter(null);
        adapter.setItems(mItems);
        mRecycler.setLayoutManager(mLayoutManager);
        mRecycler.setAdapter(adapter);
        mLinearSnapHelper.attachToRecyclerView(mRecycler);
        newScrollTo(1);
//        fireScrollTo();
    }

    private int maxScrolls = mItemCount;

    private void fireScrollTo() {
        if (--maxScrolls > 0) {
            int pos = (int) (Math.random() * mItemCount);
            newScrollTo(pos);
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    fireScrollTo();
                }
            }, 2000);
        }
    }

    private void newScrollTo(final int pos) {
        mRecycler.smoothScrollToPosition(pos);
        RecyclerView.ViewHolder vh = mRecycler.findViewHolderForLayoutPosition(pos);
        if (vh != null) {
            // Target view is available, so just scroll to it.
            mRecycler.smoothScrollToPosition(pos);
        } else {
            // Target view is not available. Scroll to it.
            mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
                // From the documentation:
                // This callback will also be called if visible item range changes after a layout
                // calculation. In that case, dx and dy will be 0.This callback will also be called
                // if visible item range changes after a layout calculation. In that case,
                // dx and dy will be 0.
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    mRecycler.removeOnScrollListener(this);
                    if (dx == 0) {
                        newScrollTo(pos);
                    }
                }
            });
            mRecycler.scrollToPosition(pos);
        }
    }
}
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<String> mItems;

    RecyclerViewAdapter(List<String> items) {
        mItems = items;
    }

    @Override
    public @NonNull
    RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
        view.getLayoutParams().width = 220;
        view.getLayoutParams().height = 220;
//        view.setPadding(220 * 3, 0, 220 * 3, 0);
        ((TextView) view).setGravity(Gravity.CENTER);
        return new ItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        ItemViewHolder vh = (ItemViewHolder) holder;
        String itemText = mItems.get(position);

        vh.mItemTextView.setText(itemText);
        int bgColor = (position % 2 == 0)
            ? android.R.color.holo_blue_light
            : android.R.color.holo_green_light;
        holder.itemView.setBackgroundColor(
            holder.itemView.getContext().getResources().getColor(bgColor));
    }

    @Override
    public int getItemCount() {
        return (mItems == null) ? 0 : mItems.size();
    }

    @Override
    public int getItemViewType(int position) {
        return TYPE_ITEM;
    }

    static class ItemViewHolder extends RecyclerView.ViewHolder {
        private TextView mItemTextView;

        ItemViewHolder(View item) {
            super(item);
            mItemTextView = item.findViewById(android.R.id.text1);
        }
    }

    public void setItems(List<String> items) {
        mItems = items;
    }

    @SuppressWarnings("unused")
    private final static String TAG = "RecyclerViewAdapter";

    private final static int TYPE_ITEM = 1;
}
public类MainActivity扩展了AppCompatActivity{
专用最终LinearLayoutManager mllayoutmanager=新的LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
private final List mItems=new ArrayList();
私人垃圾回收站;
私人最终整数mItemCount=2000;
私有最终处理程序mHandler=新处理程序();
私有最终LinearSnapHelper mLinearSnapHelper=新的LinearSnapHelper();
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
对于(int i=0;i0){
int pos=(int)(Math.random()*mItemCount);
新闻集团(pos);
mHandler.postDelayed(新的Runnable(){
@凌驾
公开募捐{
fireScrollTo();
}
}, 2000);
}
}
私有无效新闻克隆(最终int pos){
mRecycler.smoothScrollToPosition(位置);
RecyclerView.ViewHolder vh=mRecycler.FindViewHolder用于布局位置(pos);
如果(vh!=null){
//目标视图可用,所以只需滚动到它。
mRecycler.smoothScrollToPosition(位置);
}否则{
//目标视图不可用。请滚动到该视图。
mRecycler.addOnScrollListener(新的RecyclerView.OnScrollListener(){
//从文件中:
//如果布局后可见项范围发生更改,也将调用此回调
//计算。在这种情况下,dx和dy将为0。此回调也将被调用
//如果布局计算后可见项目范围发生变化。在这种情况下,
//dx和dy将为0。
@凌驾
已填空的公共空间(RecyclerView RecyclerView、int dx、int dy){
super.onScrolled(recyclerView、dx、dy);
mRecycler.removeOnScrollListener(此);
如果(dx==0){
新闻集团(pos);
}
}
});
mRecycler.scrollToPosition(位置);
}
}
}
活动\u main.xml

<android.support.constraint.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:layout_width="3px"
        android:layout_height="match_parent"
        android:background="@android:color/holo_red_light"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingStart="660px"
        android:paddingEnd="660px"/>

</android.support.constraint.ConstraintLayout>

RecycleServiceAdapter.java

public class MainActivity extends AppCompatActivity {
    private final LinearLayoutManager mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
    private final List<String> mItems = new ArrayList<>();
    private RecyclerView mRecycler;
    private final int mItemCount = 2000;
    private final Handler mHandler = new Handler();
    private final LinearSnapHelper mLinearSnapHelper = new LinearSnapHelper();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (int i = 0; i < mItemCount; i++) {
            mItems.add(i + "");
        }

        mRecycler = findViewById(R.id.recyclerView);
        final RecyclerViewAdapter adapter = new RecyclerViewAdapter(null);
        adapter.setItems(mItems);
        mRecycler.setLayoutManager(mLayoutManager);
        mRecycler.setAdapter(adapter);
        mLinearSnapHelper.attachToRecyclerView(mRecycler);
        newScrollTo(1);
//        fireScrollTo();
    }

    private int maxScrolls = mItemCount;

    private void fireScrollTo() {
        if (--maxScrolls > 0) {
            int pos = (int) (Math.random() * mItemCount);
            newScrollTo(pos);
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    fireScrollTo();
                }
            }, 2000);
        }
    }

    private void newScrollTo(final int pos) {
        mRecycler.smoothScrollToPosition(pos);
        RecyclerView.ViewHolder vh = mRecycler.findViewHolderForLayoutPosition(pos);
        if (vh != null) {
            // Target view is available, so just scroll to it.
            mRecycler.smoothScrollToPosition(pos);
        } else {
            // Target view is not available. Scroll to it.
            mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
                // From the documentation:
                // This callback will also be called if visible item range changes after a layout
                // calculation. In that case, dx and dy will be 0.This callback will also be called
                // if visible item range changes after a layout calculation. In that case,
                // dx and dy will be 0.
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    mRecycler.removeOnScrollListener(this);
                    if (dx == 0) {
                        newScrollTo(pos);
                    }
                }
            });
            mRecycler.scrollToPosition(pos);
        }
    }
}
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<String> mItems;

    RecyclerViewAdapter(List<String> items) {
        mItems = items;
    }

    @Override
    public @NonNull
    RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
        view.getLayoutParams().width = 220;
        view.getLayoutParams().height = 220;
//        view.setPadding(220 * 3, 0, 220 * 3, 0);
        ((TextView) view).setGravity(Gravity.CENTER);
        return new ItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        ItemViewHolder vh = (ItemViewHolder) holder;
        String itemText = mItems.get(position);

        vh.mItemTextView.setText(itemText);
        int bgColor = (position % 2 == 0)
            ? android.R.color.holo_blue_light
            : android.R.color.holo_green_light;
        holder.itemView.setBackgroundColor(
            holder.itemView.getContext().getResources().getColor(bgColor));
    }

    @Override
    public int getItemCount() {
        return (mItems == null) ? 0 : mItems.size();
    }

    @Override
    public int getItemViewType(int position) {
        return TYPE_ITEM;
    }

    static class ItemViewHolder extends RecyclerView.ViewHolder {
        private TextView mItemTextView;

        ItemViewHolder(View item) {
            super(item);
            mItemTextView = item.findViewById(android.R.id.text1);
        }
    }

    public void setItems(List<String> items) {
        mItems = items;
    }

    @SuppressWarnings("unused")
    private final static String TAG = "RecyclerViewAdapter";

    private final static int TYPE_ITEM = 1;
}
类RecycleServiceAdapter扩展了RecycleView.Adapter{ 私人名单; RecycleServiceAdapter(列表项){ mItems=项目; } @凌驾 public@NonNull RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup父级,int-viewType){ View View=LayoutInflater.from(parent.getContext()).flate(android.R.layout.simple\u list\u item\u 1,parent,false); view.getLayoutParams().width=220; view.getLayoutParams().height=220; //视图。设置填充(220*3,0,220*3,0); ((文本视图)视图)。设置重力(重心); 返回新的ItemViewHolder(视图); } @凌驾 public void onBindViewHolder(@NonNull RecyclerView.ViewHolder,int位置){ ItemViewHolder vh=(ItemViewHolder)持有人; String itemText=mItems.get(位置); vh.mItemTextView.setText(itemText); int bgColor=(位置%2==0) ?android.R.color.holo_蓝光 :android.R.color.holo_绿色_灯; holder.itemView.setBackgroundColor( holder.itemView.getContext().getResources().getColor(bgColor)); } @凌驾 public int getItemCount(){ 返回值(mItems==null)?0:mItems.size(); } @凌驾 public int getItemViewType(int位置){ 返回类型\ U项目; } 静态类ItemViewHolder扩展了RecyclerView.ViewHolder{ 私有文本视图miteTextView; ItemViewHolder(查看项目