Android使用RecyclerView实现水平滚动控件

前言

相信大家都知道Android滚动控件的实现方式有很多, 使用RecyclerView也比较简单. 做了一个简单的年龄滚动控件, 让我们来看看RecyclerView的使用方式, 主要有以下几点:

(1) 对齐控件中心位置.

(2) 计算滚动距离.

(3) 高亮中心视图.

(4) 实时显示中心数据.

(5) 停止时自动对齐.

(6) 滚动时, 设置按钮状态开关.

效果

1. 框架

主要关注RecyclerView部分逻辑.

/** * 初始化年龄滑动条 */ private void initAgeList() { LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false); mRvAgeList.setLayoutManager(mLayoutManager); mAgeAdapter = new PersonAgeAdapter(START_NUM, END_NUM); mRvAgeList.setAdapter(mAgeAdapter); mRvAgeList.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); mBDownStep.setEnabled(false); // 效果在暂停时显示, 否则会导致重绘异常 if (newState == RecyclerView.SCROLL_STATE_IDLE) { mAgeAdapter.highlightItem(getMiddlePosition()); mRvAgeList.scrollToPosition(getScrollPosition()); mLastValue = getMiddlePosition(); UserInfoManager.setAge(getMiddlePosition() + START_NUM); mBDownStep.setEnabled(true); // 滑动时不可用, 停止时才可以 } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { // 值是实时增加 mTvAgeValue.setText(String.valueOf(getMiddlePosition() + START_NUM)); } }); mAgeAdapter.highlightItem(getMiddlePosition()); }

设置一个水平布局

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

添加Adapter, 设置起始和结束位置.

mAgeAdapter = new PersonAgeAdapter(START_NUM, END_NUM); mRvAgeList.setAdapter(mAgeAdapter);

2. Adapter

Adapter定制一些功能, 如标示指向中心位置, 数据联动显示, 高亮Item等.

/** * 年龄的适配器 * <p> * Created by wangchenlong on 15/11/12. */ public class PersonAgeAdapter extends RecyclerView.Adapter<PersonAgeAdapter.AgeItemViewHolder> { public static final int ITEM_NUM = 7; // 每行拥有的Item数, 必须是奇数 private int mFrom; // 起始 private int mTo; // 终止 private int mHighlight = -1; // 高亮 public PersonAgeAdapter(int from, int to) { mFrom = from; mTo = to; } @Override public AgeItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View item = LayoutInflater.from(parent.getContext()). inflate(R.layout.view_age_item, parent, false); // 设置Item的宽度 ViewGroup.LayoutParams lp = item.getLayoutParams(); lp.width = getItemStdWidth(); return new AgeItemViewHolder(item); } @Override public void onBindViewHolder(AgeItemViewHolder holder, int position) { holder.getTextView().setText(String.valueOf(mFrom + position)); // 高亮显示 if (isSelected(position)) { holder.getTextView().setTextSize(30); holder.getTextView().setTextColor(ChunyuApp.getAppContext().getResources().getColor(R.color.black)); } else { holder.getTextView().setTextSize(20); holder.getTextView().setTextColor(ChunyuApp.getAppContext().getResources().getColor(R.color.gray_line)); } } // 高亮中心, 更新前后位置 public void highlightItem(int position) { mHighlight = position; int offset = ITEM_NUM / 2; for (int i = position - offset; i <= position + offset; ++i) notifyItemChanged(i); } // 判断是否是高亮 public boolean isSelected(int position) { return mHighlight == position; } @Override public int getItemCount() { return mTo - mFrom + 1; } // 获取标准宽度 public static int getItemStdWidth() { DisplayMetrics displayMetrics = ChunyuApp.getAppContext().getResources().getDisplayMetrics(); return displayMetrics.widthPixels / ITEM_NUM; } // ViewHolder public class AgeItemViewHolder extends RecyclerView.ViewHolder { private TextView mTextView; public AgeItemViewHolder(View itemView) { super(itemView); mTextView = (TextView) itemView.findViewById(R.id.item_age_value); mTextView.setTag(this); } public TextView getTextView() { return mTextView; } } }

每个单元格宽度是屏幕宽度的奇数分之一, 填充屏幕, 则起始指向中心.

@Override public AgeItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View item = LayoutInflater.from(parent.getContext()). inflate(R.layout.view_age_item, parent, false); // 设置Item的宽度 ViewGroup.LayoutParams lp = item.getLayoutParams(); lp.width = getItemStdWidth(); return new AgeItemViewHolder(item); }

单数Item数量, 则中心的指示器必指向中心Item的中心.

根据选中状态, 更新Item样式.

@Override public void onBindViewHolder(AgeItemViewHolder holder, int position) { holder.getTextView().setText(String.valueOf(mFrom + position)); // 高亮显示 if (isSelected(position)) { holder.getTextView().setTextSize(30); holder.getTextView().setTextColor(ChunyuApp.getAppContext().getResources().getColor(R.color.black)); } else { holder.getTextView().setTextSize(20); holder.getTextView().setTextColor(ChunyuApp.getAppContext().getResources().getColor(R.color.gray_line)); } }

设置高亮, 把中心位置高亮, 两边恢复, 通知Adapter重绘ViewHolder.

// 高亮中心, 更新前后位置 public void highlightItem(int position) { mHighlight = position; int offset = ITEM_NUM / 2; for (int i = position - offset; i <= position + offset; ++i) notifyItemChanged(i); } // 判断是否是高亮 public boolean isSelected(int position) { return mHighlight == position; } notifyItemChanged()会重绘所选择的页面.

获取宽度, 把一行显示Item数量设置为单数, 则中心指向一个Item.

// 获取标准宽度 public static int getItemStdWidth() { DisplayMetrics displayMetrics = ChunyuApp.getAppContext().getResources().getDisplayMetrics(); return displayMetrics.widthPixels / ITEM_NUM; }

注意RecyclerView不能移动半个单元, 每行数量是单数时, 则必会指向中心.

3. 滚动逻辑

在滚动时, 实时更新页面显示; 在停止时, 更新高亮和存储数据; 滚动结束时, 激活按钮.

mRvAgeList.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); mBDownStep.setEnabled(false); // 效果在暂停时显示, 否则会导致重绘异常 if (newState == RecyclerView.SCROLL_STATE_IDLE) { mAgeAdapter.highlightItem(getMiddlePosition()); mRvAgeList.scrollToPosition(getScrollPosition()); mLastValue = getMiddlePosition(); UserInfoManager.setAge(getMiddlePosition() + START_NUM); mBDownStep.setEnabled(true); // 滑动时不可用, 停止时才可以 } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { // 值是实时增加 mTvAgeValue.setText(String.valueOf(getMiddlePosition() + START_NUM)); } }); mAgeAdapter.highlightItem(getMiddlePosition()); } /** * 获取中间位置 * * @return 当前值 */ private int getMiddlePosition() { return getScrollPosition() + (PersonAgeAdapter.ITEM_NUM / 2); } /** * 获取滑动值, 滑动偏移 / 每个格子宽度 * * @return 当前值 */ private int getScrollPosition() { return (int) ((double) mRvAgeList.computeHorizontalScrollOffset() / (double) PersonAgeAdapter.getItemStdWidth()); }

判断滚动的距离单位, 偏移总距离/单个Item宽度.

private int getScrollPosition() { return (int) ((double) mRvAgeList.computeHorizontalScrollOffset() / (double) PersonAgeAdapter.getItemStdWidth()); }

computeHorizontalScrollOffset()获取RecyclerView的偏移总位移.

中间位置, 还要加上半行Item数量

private int getMiddlePosition() { return getScrollPosition() + (PersonAgeAdapter.ITEM_NUM / 2); }

判断滚动是否停止.

if (newState == RecyclerView.SCROLL_STATE_IDLE)

在滚动停止时, 自动对齐.

mRvAgeList.scrollToPosition(getScrollPosition());

调用需要高亮显示的Item.

mAgeAdapter.highlightItem(getMiddlePosition());

注意在滚动停止时, 更新高亮比较好, 否则重绘速度较慢, 会影响滚动效果.

滑动效果

总结

好了,以上就是这篇文章的全部内容了,我们可以根据这些定制各式各样的滚动条了!希望这篇文章对大家能有所帮助。

时间: 2024-08-02 21:23:53

Android使用RecyclerView实现水平滚动控件的相关文章

Android使用RecyclerView实现水平滚动控件_Android

前言 相信大家都知道Android滚动控件的实现方式有很多, 使用RecyclerView也比较简单. 做了一个简单的年龄滚动控件, 让我们来看看RecyclerView的使用方式, 主要有以下几点:      (1) 对齐控件中心位置.      (2) 计算滚动距离.      (3) 高亮中心视图.      (4) 实时显示中心数据.      (5) 停止时自动对齐.      (6) 滚动时, 设置按钮状态开关. 效果 1. 框架 主要关注RecyclerView部分逻辑. /**

HorizontalScrollView水平滚动控件使用方法详解

一.简介 用法ScrollView大致相同 二.方法 1)HorizontalScrollView水平滚动控件使用方法 1.在layout布局文件的最外层建立一个HorizontalScrollView控件 2.在HorizontalScrollView控件中加入一个LinearLayout控件,并且把它的orientation设置为horizontal 3.在LinearLayout控件中放入多个装有图片的ImageView控件 2)HorizontalScrollView和ScrollVie

Android垂直滚动控件ScrollView使用方法详解

一.简介 二.方法 1)ScrollView垂直滚动控件使用方法 1.在layout布局文件的最外层建立一个ScrollView控件 2.在ScrollView控件中加入一个LinearLayout控件,并且把它的orientation设置为vertical 3.在LinearLayout控件中放入多个装有图片的ImageView控件 三.代码实例 1.效果图 2.代码 /Ex27ScrollView/src/fry/Activity01.java <?xml version="1.0&q

Android实现果冻滑动效果的控件_Android

前言 在微信是的处理方法是让用户滑动,但最终还是回滚到最初的地方,这样的效果很生动(毕竟成功还是取决于细节).那么在安卓我们要怎么弄呢.下面为大家介绍一下JellyScrollView,是我继承ScrollView的一个有阻尼的效果的果冻滑动控件. 下面话不多说了,先来看看效果图 (在虚拟机或者真机跑起来是很流畅,可能是录制视频做成gif的时候有点卡顿.) 实现原理 其实只需要重写下它的拦截方法的逻辑就好了,ScrollView的拦截方法onInterceptTouchEvent一般情况下都默认

Android开发实现自定义水平滚动的容器示例

本文实例讲述了Android开发实现自定义水平滚动的容器.分享给大家供大家参考,具体如下: public class HorizontalScrollView extends ViewGroup { //手势 private GestureDetector mGestureDetector; private HorizontalScroller mScroller; private int curID; //快速滑动 private boolean isFlying; //--回调函数-----

Android动态添加设置布局与控件的方法_Android

本文实例讲述了Android动态添加设置布局与控件的方法.分享给大家供大家参考,具体如下: 有时候我们会在代码端,动态的设置,添加布局和控件.下面我们就看来看一下如何处理,直接上代码,代码里面的注解很清楚了. 布局文件:fragment_hot.xml 说明:这个部局,我用的是scrollView做为基础布局,主要是为了实现一个滚动.这里不多说,这个你可以使用任何布局都可以,这里的id我是提前定义的. 这里面的现在有的布局是我为了看到我在代码端,动态添加的代码,是否可以追加到现有布局的后面而加上

Android动态添加设置布局与控件的方法

本文实例讲述了Android动态添加设置布局与控件的方法.分享给大家供大家参考,具体如下: 有时候我们会在代码端,动态的设置,添加布局和控件.下面我们就看来看一下如何处理,直接上代码,代码里面的注解很清楚了. 布局文件:fragment_hot.xml 说明:这个部局,我用的是scrollView做为基础布局,主要是为了实现一个滚动.这里不多说,这个你可以使用任何布局都可以,这里的id我是提前定义的. 这里面的现在有的布局是我为了看到我在代码端,动态添加的代码,是否可以追加到现有布局的后面而加上

Android绑定添加了注解的控件,及其事件方法

  Android绑定添加了注解的控件,及其事件方法.根据成员方法的注解进行绑定,根据成员变量的注解进行绑定,设置事件的监听器,对控件赋值,注意:它必须在activity调用了setContentView之后调用.

界面-android多个activity使用同一个控件

问题描述 android多个activity使用同一个控件 最近在做一个跟播放有关的项目 里面有一个需求是在每个界面(activity)都有一个播放窗口,在播放同一个视频 我想请教一下,有什么方法可以实现让一个播放窗口一直存在,不管切换到哪个acitivty都会存在 或者有没有其他什么折中的方法? 望请教. 解决方案 我有点不明白你的需求,我的理解是,你希望有一个窗口不管用户在操作什么都在播放某个用户指定的视频,是这个意思的话.activity时没有办法实现的. 因为activity的栈模式.你