当前位置: 首页 > 知识库问答 >
问题:

滚动时获取RecycleView的中心可见项

尹弘壮
2023-03-14

这就是我想要的:

如上图所示,我想在RecycleView上画一条中心线,然后在滚动时获得中心项(以及向左或向右移动)
以下是我尝试画一个水平的RecycleView

    HorizontalAdapter adapter = new HorizontalAdapter(data);
    LinearLayoutManager layoutManager
            = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
    recycleView.setLayoutManager(layoutManager);
    recycleView.setAdapter(adapter);

有没有办法知道哪个项目移动到了回收视图的中心?如何将RecycleView向左或向右滚动一个位置?

更新:我尝试使用滚动侦听器来获得中间位置,但它不能作为一个方面。

  @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            int firstPos = layoutManager.findFirstVisibleItemPosition();
            int lastPos = layoutManager.findLastVisibleItemPosition();
            int middle = Math.abs(lastPos - firstPos) / 2 + firstPos;

            int selectedPos = -1;
            for (int i = 0; i < adapter.getItemCount(); i++) {
                if (i == middle) {
                    adapter.getItem(i).setSelected(true);
                    selectedPos = i;
                } else {
                    adapter.getItem(i).setSelected(false);
                }
            }

            adapter.notifyDataSetChanged();
        }

并得到结果:

我只想在蓝色Rect上更改选中的项目(使文本变为白色)

共有3个答案

韩瀚
2023-03-14

哦,孩子。我寻找这个答案已经快一个星期了,然后找到了解决办法。自定义布局管理器?否。ItemDecorator?不。

以下是最简单的方法

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:paddingStart="150dp"
    android:paddingEnd="150dp"
    android:clipToPadding="false" />

关键部分是:

    android:paddingStart="150dp"
    android:paddingEnd="150dp"
    android:clipToPadding="false"

然后只需将SnapHelper分配给您的RecylcerView

val snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(recyclerView)

就是这样。这个问题最简单、最完美的解决方案

符学
2023-03-14

有时需要将整个示例代码块放在一起,因为可能会遗漏一些内容。这是我所拥有的,请随意纠正任何事情,因为我可能在某个地方犯了一些小错误。是的,这个答案是@tranhieu答案的扩展。谢谢@tranhieu。

主要活动。JAVA

package com.test;

import android.app.Activity;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import java.util.ArrayList;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    public float firstItemWidthDate;
    public float paddingDate;
    public float itemWidthDate;
    public int allPixelsDate;
    public int finalWidthDate;
    private DateAdapter dateAdapter;
    private ArrayList<LabelerDate> labelerDates = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getRecyclerviewDate();

    }


    public void getRecyclerviewDate() {
        final RecyclerView recyclerViewDate = (RecyclerView) findViewById(R.id.rv_tasks_date);
        if (recyclerViewDate != null) {
            recyclerViewDate.postDelayed(new Runnable() {
                @Override
                public void run() {
                    setDateValue();
                }
            }, 300);
            recyclerViewDate.postDelayed(new Runnable() {
                @Override
                public void run() {
                    recyclerViewDate.smoothScrollToPosition(dateAdapter.getItemCount()-1);
                    setDateValue();
                }
            }, 5000);
        }
        ViewTreeObserver vtoDate = recyclerViewDate.getViewTreeObserver();
        vtoDate.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {


            @Override
            public boolean onPreDraw() {
                recyclerViewDate.getViewTreeObserver().removeOnPreDrawListener(this);
                finalWidthDate = recyclerViewDate.getMeasuredWidth();
                itemWidthDate = getResources().getDimension(R.dimen.item_dob_width);
                paddingDate = (finalWidthDate - itemWidthDate) / 2;
                firstItemWidthDate = paddingDate;
                allPixelsDate = 0;

                final LinearLayoutManager dateLayoutManager = new LinearLayoutManager(getApplicationContext());
                dateLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
                recyclerViewDate.setLayoutManager(dateLayoutManager);
                recyclerViewDate.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                        super.onScrollStateChanged(recyclerView, newState);
                        synchronized (this) {
                            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                                calculatePositionAndScrollDate(recyclerView);
                            }
                        }

                    }

                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                        super.onScrolled(recyclerView, dx, dy);
                        allPixelsDate += dx;
                    }
                });
                if (labelerDates == null) {
                    labelerDates = new ArrayList<>();
                }
                genLabelerDate();
                dateAdapter = new DateAdapter(labelerDates, (int) firstItemWidthDate);
                recyclerViewDate.setAdapter(dateAdapter);
                dateAdapter.setSelecteditem(dateAdapter.getItemCount() - 1);
                return true;
            }
        });
    }

    private void genLabelerDate() {
        for (int i = 0; i < 32; i++) {
            LabelerDate labelerDate = new LabelerDate();
            labelerDate.setNumber(Integer.toString(i));
            labelerDates.add(labelerDate);

            if (i == 0 || i == 31) {
                labelerDate.setType(DateAdapter.VIEW_TYPE_PADDING);
            } else {
                labelerDate.setType(DateAdapter.VIEW_TYPE_ITEM);
            }
        }
    }
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/

    private void calculatePositionAndScrollDate(RecyclerView recyclerView) {
        int expectedPositionDate = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);

        if (expectedPositionDate == -1) {
            expectedPositionDate = 0;
        } else if (expectedPositionDate >= recyclerView.getAdapter().getItemCount() - 2) {
            expectedPositionDate--;
        }
        scrollListToPositionDate(recyclerView, expectedPositionDate);

    }

    /* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/
    private void scrollListToPositionDate(RecyclerView recyclerView, int expectedPositionDate) {
        float targetScrollPosDate = expectedPositionDate * itemWidthDate + firstItemWidthDate - paddingDate;
        float missingPxDate = targetScrollPosDate - allPixelsDate;
        if (missingPxDate != 0) {
            recyclerView.smoothScrollBy((int) missingPxDate, 0);
        }
        setDateValue();
    }

    //
    private void setDateValue() {
        int expectedPositionDateColor = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);
        int setColorDate = expectedPositionDateColor + 1;
//        set color here
        dateAdapter.setSelecteditem(setColorDate);
    }


    public class DateAdapter extends RecyclerView.Adapter<DateAdapter.DateViewHolder> {
        private ArrayList<LabelerDate> dateDataList;


        private static final int VIEW_TYPE_PADDING = 1;
        private static final int VIEW_TYPE_ITEM = 2;
        private int paddingWidthDate = 0;

        private int selectedItem = -1;

        public DateAdapter(ArrayList<LabelerDate> dateData, int paddingWidthDate) {
            this.dateDataList = dateData;
            this.paddingWidthDate = paddingWidthDate;

        }


        @Override
        public DateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == VIEW_TYPE_ITEM) {
                final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,
                    parent, false);
                return new DateViewHolder(view);
            } else {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,
                    parent, false);

                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
                layoutParams.width = paddingWidthDate;
                view.setLayoutParams(layoutParams);
                return new DateViewHolder(view);
            }
        }

        @Override
        public void onBindViewHolder(DateViewHolder holder, int position) {
            LabelerDate labelerDate = dateDataList.get(position);
            if (getItemViewType(position) == VIEW_TYPE_ITEM) {
                holder.tvDate.setText(labelerDate.getNumber());
                holder.tvDate.setVisibility(View.VISIBLE);

                Log.d(TAG, "default " + position + ", selected " + selectedItem);
                if (position == selectedItem) {
                    Log.d(TAG, "center" + position);
                    holder.tvDate.setTextColor(Color.parseColor("#76FF03"));
                    holder.tvDate.setTextSize(35);

                } else {
                    holder.tvDate.setTextColor(Color.WHITE);
                    holder.tvDate.setTextSize(18);
                }
            } else {
                holder.tvDate.setVisibility(View.INVISIBLE);
            }
        }

        public void setSelecteditem(int selecteditem) {
            this.selectedItem = selecteditem;
            notifyDataSetChanged();
        }

        @Override
        public int getItemCount() {
            return dateDataList.size();
        }

        @Override
        public int getItemViewType(int position) {
            LabelerDate labelerDate = dateDataList.get(position);
            if (labelerDate.getType() == VIEW_TYPE_PADDING) {
                return VIEW_TYPE_PADDING;
            } else {
                return VIEW_TYPE_ITEM;
            }

        }


        public class DateViewHolder extends RecyclerView.ViewHolder {
            public TextView tvDate;

            public DateViewHolder(View itemView) {
                super(itemView);
                tvDate = (TextView) itemView.findViewById(R.id.txt_date);
            }
        }
    }

    private class LabelerDate {
        private int type;
        private String number;

        public String getNumber() {
            return number;
        }

        public void setNumber(String number) {
            this.number = number;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }
    }
}

主要活动。xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_tasks_date"
            android:layout_width="match_parent"
            android:layout_height="48dp" />

        <ImageView
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_gravity="center"
            android:layout_marginTop="48dp"
            android:src="@android:drawable/ic_dialog_info" />
    </FrameLayout>

</LinearLayout>

项目xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical" android:layout_width="wrap_content"
              android:layout_height="match_parent">

    <TextView
        android:id="@+id/txt_date"
        android:layout_width="@dimen/item_dob_width"
        android:layout_height="48dp"
        android:text="32"
        android:textColor="@android:color/white"
        android:background="@android:color/darker_gray"
        android:textSize="28sp"
        android:gravity="center"/>

</LinearLayout>

dimens.xml

<resources>
    <dimen name="item_dob_width">100dp</dimen>
</resources>
郎恺
2023-03-14

这是我的回收查看适配器

public class DateAdapter extends RecyclerView.Adapter<DateAdapter.DateViewHolder> {
private ArrayList<LabelerDate> dateDataList;


private static final int VIEW_TYPE_PADDING = 1;
private static final int VIEW_TYPE_ITEM = 2;
private int paddingWidthDate = 0;

private int selectedItem = -1;

public DateAdapter(ArrayList<LabelerDate> dateData, int paddingWidthDate) {
    this.dateDataList = dateData;
    this.paddingWidthDate = paddingWidthDate;

}


@Override
public DateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == VIEW_TYPE_ITEM) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_date,
                parent, false);
        return new DateViewHolder(view);
    } else {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_padding,
                parent, false);

        RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
        layoutParams.width = paddingWidthDate;
        view.setLayoutParams(layoutParams);
        return new DateViewHolder(view);
    }
}

@Override
public void onBindViewHolder(DateViewHolder holder, int position) {
    LabelerDate labelerDate = dateDataList.get(position);
    if (getItemViewType(position) == VIEW_TYPE_ITEM) {
        if(labelerDate.dateType.equals(BirthDayActivity.DateType.C31))
                holder.tvDate.setText(String.valueOf(labelerDate.valueDate));
                holder.tvDate.setVisibility(View.VISIBLE);
                holder.imgSmall.setVisibility(View.VISIBLE);

        if (position == selectedItem) {
            holder.tvDate.setTextColor(Color.parseColor("#094673"));
            holder.tvDate.setTextSize(35);
            holder.imgSmall.setBackgroundResource(R.color.textviewbold);

        } else {
            holder.tvDate.setTextColor(Color.GRAY);
            holder.tvDate.setTextSize(35);
            holder.imgSmall.setBackgroundResource(R.color.gray);
        }
    }
}

public void setSelecteditem(int selecteditem) {
    this.selectedItem = selecteditem;
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return dateDataList.size();
}

@Override
public int getItemViewType(int position) {
    LabelerDate labelerDate = dateDataList.get(position);
    if (labelerDate.dateType.equals(BirthDayActivity.DateType.NONE)) {
        return VIEW_TYPE_PADDING;
    }
    return VIEW_TYPE_ITEM;
}


public class DateViewHolder extends RecyclerView.ViewHolder {
    public TextView tvDate;
    public ImageView imgSmall;

    public DateViewHolder(View itemView) {
        super(itemView);
        tvDate = (TextView) itemView.findViewById(R.id.tvNumberDate);
        imgSmall = (ImageView) itemView.findViewById(R.id.small_marked_dob);
    }
}}

这是最重要的alogrithm:

public void getRecyclerviewDate() {
    recyclerViewDate = (RecyclerView) findViewById(R.id.recyclerViewDay);
    ViewTreeObserver vtoDate = recyclerViewDate.getViewTreeObserver();
    vtoDate.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            recyclerViewDate.getViewTreeObserver().removeOnPreDrawListener(this);
            finalWidthDate = recyclerViewDate.getMeasuredWidth();
            itemWidthDate = getResources().getDimension(R.dimen.item_dob_width);
            paddingDate = (finalWidthDate - itemWidthDate) / 2;
            firstItemWidthDate = paddingDate ;
            allPixelsDate = 0;

            final LinearLayoutManager dateLayoutManager = new LinearLayoutManager(getApplicationContext());
            dateLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
            recyclerViewDate.setLayoutManager(dateLayoutManager);
            recyclerViewDate.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    synchronized (this) {
                         if(newState == RecyclerView.SCROLL_STATE_IDLE){           
                            calculatePositionAndScrollDate(recyclerView);
                        }
                    }

                }

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    allPixelsDate += dx;
                }
            });
            if (labelerDates == null)
                labelerDates = new ArrayList<>();
            labelerDates.addAll(genLabelerDate(currentMonth, currentYear));
            dateAdapter = new DateAdapter(labelerDates, (int) firstItemWidthDate);
            recyclerViewDate.setAdapter(dateAdapter);
            return true;
        }
    });
}
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/

private void calculatePositionAndScrollDate(RecyclerView recyclerView) {
    int expectedPositionDate = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);

    if (expectedPositionDate == -1) {
        expectedPositionDate = 0;
    } else if (expectedPositionDate >= recyclerView.getAdapter().getItemCount() - 2) {
        expectedPositionDate--;
    }
    scrollListToPositionDate(recyclerView, expectedPositionDate);

}
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/
private void scrollListToPositionDate(RecyclerView recyclerView, int expectedPositionDate) {
    float targetScrollPosDate = expectedPositionDate * itemWidthDate + firstItemWidthDate - paddingDate;
    float missingPxDate = targetScrollPosDate - allPixelsDate;
    if (missingPxDate != 0) {
        recyclerView.smoothScrollBy((int) missingPxDate, 0);
    }
}
private void setDateValue() {
    int expectedPositionDateColor = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);
    setColorDate = expectedPositionDateColor + 1;
    //set color here
    dateAdapter.setSelecteditem(setColorDate);
}
 @Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);   
    allPixelsDate = savedInstanceState.getFloat(BUNDLE_LIST_PIXELS_DATE);
    allPixelsDateChanged = savedInstanceState.getFloat(BUNDLE_LIST_PIXELS_DATE_CHANGED);
}

@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putFloat(BUNDLE_LIST_PIXELS_DATE, allPixelsDate);
    outState.putFloat(BUNDLE_LIST_PIXELS_DATE_CHANGED, allPixelsDateChanged);
}

看这个视频链接,这是我的应用程序演示

 类似资料:
  • 我是一个android编程新手,在我的应用程序中,我使用recycleview来显示SQLite数据库的内容,我将数据库读入一个Arraylist,我在recycleview中显示它。我已经成功实现了向左滑动(删除项目)和向右滑动(编辑项目)功能。我在向左滑动时遇到了一个问题,这意味着在删除功能中,我实现了一个撤销功能: (SequenceItem 是我的自定义项类,sequenceItemLis

  • 如何在中获取当前项?在我的用例中,RV项占用了所有屏幕空间,因此一次只有一个项。我以前试过谷歌,但没有找到任何有用的东西。

  • 我需要像这样的回收视图: 它应该做到: > 每次显示7项(完成) 将回收视图居中放置在中心可见项上(完成) 当我向右/向左滚动时,中心项目将被“突出显示”(按钮被选中) 当我点击一个按钮时,它将以一个平滑的圆点居中(需要帮助) 我使用类将RecyclerView集中在中心项上(我检索中心可见项,将最近的子项放在屏幕中心) 我的适配器: 设置回收器视图: 填充回收器视图: 滚动管理: 项目布局:

  • ListView或者RecycleView滚动时隐藏Toolbar( Part 2 ) 原文链接 : How to hide/show Toolbar when list is scrolling (part 2)/) 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: 这里校对者的github用户名 状态 : 校对中 Hello,各位小伙伴,俺胡汉三又来了

  • ListView或者RecycleView滚动时隐藏Toolbar (1) 原文链接 : How to hide/show Toolbar when list is scroling (part 1) 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: 这里校对者的github用户名 状态 : 校对中 今天我打算写一篇博文给大家介绍Google+ App的一

  • 问题内容: 我有一个弹出列表,其中包含子s 的垂直列表。我添加了向上/向下键盘导航来更改当前突出显示的哪个孩子。 现在,如果我按下向下键的次数足够多,则突出显示的项目将不再可见。如果滚动视图,则向上键也会发生相同的情况。 在React中自动将孩子滚动到视图中的正确方法是什么? 问题答案: 我假设您具有某种组件和某种组件。我在一个项目中执行此操作的方式是让该项目知道它是否处于活动状态。该项目将要求列