当前位置: 移动技术网 > IT编程>移动开发>Android > Android使用RecyclerView实现水平滚动控件

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

鲁尔夫断骨,时风网上办公系统,陈鲁豫 心相约

前言

相信大家都知道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());

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

滑动效果

总结

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网