RecyclerView - 如何在滚动期间突出显示中心可见项目

2023-12-29

我需要一个像这样的 RecyclerView:

它应该做:

  • 每次显示 7 项(DONE)

  • 将 RecyclerView 置于中央可见项目的中心(DONE)

  • 当我向右/向左滚动时,中心项目将“突出显示”(选择按钮>蓝色)(需要帮忙)

  • 当我单击按钮时,它将以平滑滚动居中(需要帮忙)

I used SnapHelper类将 RecyclerView 置于中心项目的中心(我检索中心可见项目,使距离屏幕中心最近的子项)

我的适配器:

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

}

设置回收器视图:

mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
mRecyclerView.setLayoutManager(mLayoutManager);

SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);

填充回收商视图:

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

滚动管理:

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

项目布局:

<?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>

希望这可以帮助 -

请注意,这是一个 hacky 解决方案,尤其是滚动时的突出显示。 另外,我还没有介绍任何性能。你也许应该检查一下。 我也改变了timeLapseButton to TextView自从改变背景Button将折叠其他布局属性。

如果您不喜欢黑客解决方案,您可以查看一些图表库。

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

适配器类

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

您拥有 recyclerView 和适配器的 Activity 或 Fragment

...

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;
        }
    }
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RecyclerView - 如何在滚动期间突出显示中心可见项目 的相关文章

  • 在 flutter 应用程序中添加启动屏幕的正确方法是什么?

    我正在开发一个基于 flutter 的应用程序 并研究了几种添加闪屏的方法 但我不确定哪一个是最好实现的 import dart async import package flutter material dart import packa
  • 更改 Android 应用程序的所有字体[重复]

    这个问题在这里已经有答案了 如何更改 Android 应用程序的整个字体 以前我看到这个帖子 https gist github com artem zinnatullin 7749076在 github 上 该解决方案仅适用于低于 api
  • 将 MapView 限制为屏幕的一半

    我试图让地图仅填充屏幕的上半部分 并在下半部分填充一些其他布局 现在我知道使用权重与表格布局相结合应该可以实现这一点 但是同一段 XML 代码可以完美地与 say 按钮配合使用 但不能与地图配合使用 截图在这里 https i stack
  • 使用 OpenWeatherMap API 密钥

    我得到异常 http api openweathermap org data 2 5 weather q 悉尼 http api openweathermap org data 2 5 weather q Sydney 有人可以帮助如何使用
  • 如果使用键盘,如何捕获 TimePicker 中的时间变化?

    我有一个小部件 它是一个 TimePicker 用于检索数据库字段中保存的时间 问题是 当用户更改小部件中的时间值时 这不会保存在数据库中 所以我遇到了setOnTimeChangedListener如果您只在小部件中使用加号和减号 那么该
  • 底部导航视图 - 渐变图标色调

    I have changed icon tint in BottomNavigationView using selector and gradient color as tint when icon is pressed but inst
  • GoogleMap 本质上是可打包的吗?

    我对java和android很陌生 我遇到了一个基本问题 在这个给定的fragment 我可以添加GoogleMap对象为parcelable没有任何额外的pracelable类为 public class SecondFragment e
  • Android 的@hide 注解到底有什么作用?

    Android中很多内部API都被标记出来了 hide What exactly这是吗 另一个答案 https stackoverflow com questions 17035271 what does hide mean in the
  • 从 java 活动 *.java 启动 kotlin 活动 *.kt?

    使缓存无效 重新启动 帮助我 我在java类中的代码是 Intent intent new Intent view getActivity AddPaymentActivity class view getActivity startAct
  • 使用协程对任务进行排队

    我最近开始阅读有关协程的内容 我想询问某个场景 考虑一个带有一个按钮的简单屏幕 单击后 它会执行一堆打印语句和一些延迟 其间 到目前为止 我正在使用协程来实现这一目标 现在 我的问题是 如果用户反复向该按钮发送垃圾邮件 是否有一种方法可以将
  • Android - 带图像的按钮 - 禁用按钮时图像变暗

    在 Android 中 我有一个包含图像和文本的按钮 禁用该按钮时 文本会自动变灰 但图像保持不变 当按钮被禁用时是否可以使图像变暗而不需要两个单独的图像 在您的代码中 您还可以使用彩色滤光片 http developer android
  • 覆盖乔达一周的第一天?

    是否有可能覆盖乔达弱的第一天sunday 因为 Joda 使用Monday作为一周的第一天 如果有办法的话 谁能解释一下 我在 SOF 中提到了以下主题 乔达时间 一周的第一天 https stackoverflow com questio
  • 使用 ACTION_VIEW Intent Action 启动文件

    我有以下代码来启动文件 try path fileJsonObject getString filePath if path indexOf 0 path path substring 1 path length path root pat
  • Keytool 不要求别名密码

    我正在尝试生成一个密钥库文件来签署我的 React Native Android 应用程序并将其发布到 Play 商店 我正在尝试按照本文档中的描述进行操作 https facebook github io react native doc
  • 如何在flutter app android中添加Startapp广告?

    我想用其他广告更改 AdMob 广告 一些个人问题 如何在flutter app android中添加Startapp广告 有什么方法可以将启动广告添加到我的 flutter 应用程序 android 中 StartApp 现已更名为 St
  • 如何使用Android Studio录制Android屏幕?

    我已经在 Mac 上的 Applications 文件夹中安装了 Android Studio 我认为 sdk 位于包内容中 但现在我想使用 AShot jar 录制屏幕以获取应用程序的演示视频 我必须放弃SDK的路径 当我给出我认为正确的
  • Android动态功能模块,找不到资源

    当下载的功能模块发布到 Play 商店时 我在启动活动时遇到问题 它总是在下载模块活动中的 setContentView 上崩溃 java lang RuntimeException Unable to start activity Com
  • 如何从 Google Fit API 获取步数?

    请原谅我的笨蛋 我对 Android 和 Google API 完全陌生 我有以下连接到 GoogleFit 的代码 我还有一个 API 密钥和 Oauth 我在哪里 如何使用 API 密钥和 Oauth 关于如何获取它们的指南有很多 但关
  • 如何从 Android 应用程序调用 REST API? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我是 android 新手 也是编程新手 如何从 Android 应用程序调用 REST api GET POST 请求 请给我推荐一
  • 更改 ActionMode 溢出图标

    有没有办法更改 ActionMode Overflow 图标而不更改 正常 ActionBar 的图标 我仍然需要弄清楚如何仅更改 ActionMode Actionbar 内部的溢出图标 因为我更改了默认操作栏中的溢出图标 该图标在 Ac

随机推荐