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());
注意在滚动停止时, 更新高亮比较好, 否则重绘速度较慢, 会影响滚动效果.
滑动效果
总结
好了,以上就是这篇文章的全部内容了,我们可以根据这些定制各式各样的滚动条了!希望这篇文章对大家能有所帮助。
推荐阅读
-
Android使用RecyclerView实现水平滚动控件
-
Android RecyclerView艺术般的控件使用完全解析
-
Android代码实现AdapterViews和RecyclerView无限滚动
-
Android实现Activity水平和垂直滚动条的方法
-
Android App使用RecyclerView实现上拉和下拉刷新的方法
-
Android RecyclerView艺术般的控件使用完全解析
-
Android代码实现AdapterViews和RecyclerView无限滚动
-
Android实现Activity水平和垂直滚动条的方法
-
Android App使用RecyclerView实现上拉和下拉刷新的方法
-
Android手机开发 使用线性布局和相对布局实现Button垂直水平居中