源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2022-07-02 11:22 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Android使用RecyclerView实现水平滚动控件
[b]前言[/b] 相信大家都知道Android滚动控件的实现方式有很多, 使用RecyclerView也比较简单. 做了一个简单的年龄滚动控件, 让我们来看看RecyclerView的使用方式, 主要有以下几点:      (1) 对齐控件中心位置.      (2) 计算滚动距离.      (3) 高亮中心视图.      (4) 实时显示中心数据.      (5) 停止时自动对齐.      (6) 滚动时, 设置按钮状态开关. [b]效果[/b] [img]http://files.jb51.net/file_images/article/201609/20169884440046.png?20168884533[/img] [b]1. 框架[/b] [b]主要关注RecyclerView部分逻辑.[/b]
 /**
  * 初始化年龄滑动条
  */
 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());
 }
[b]设置一个水平布局[/b]
LinearLayoutManager mLayoutManager =
    new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
  mRvAgeList.setLayoutManager(mLayoutManager);
[b]添加Adapter, 设置起始和结束位置.[/b]
  mAgeAdapter = new PersonAgeAdapter(START_NUM, END_NUM);
  mRvAgeList.setAdapter(mAgeAdapter);
[b]2. Adapter[/b] Adapter定制一些功能, 如标示指向中心位置, 数据联动显示, 高亮[code]Item[/code]等.
/**
 * 年龄的适配器
 * <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);
 }
单数[code]Item[/code]数量, 则中心的指示器必指向中心[code]Item[/code]的中心. 根据选中状态, 更新[code]Item[/code]样式.
 @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()会重绘所选择的页面.
获取宽度, 把一行显示[code]Item[/code]数量设置为单数, 则中心指向一个[code]Item[/code].
 // 获取标准宽度
 public static int getItemStdWidth() {
  DisplayMetrics displayMetrics = ChunyuApp.getAppContext().getResources().getDisplayMetrics();
  return displayMetrics.widthPixels / ITEM_NUM;
 }
[b]注意RecyclerView不能移动半个单元, 每行数量是单数时, 则必会指向中心.[/b] [b]3. 滚动逻辑[/b] 在滚动时, 实时更新页面显示; 在停止时, 更新高亮和存储数据; 滚动结束时, 激活按钮.
  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());
 }
判断滚动的距离单位, 偏移总距离/单个[code]Item[/code]宽度.
 private int getScrollPosition() {
  return (int) ((double) mRvAgeList.computeHorizontalScrollOffset()
    / (double) PersonAgeAdapter.getItemStdWidth());
 }
[code]computeHorizontalScrollOffset()[/code]获取RecyclerView的偏移总位移. 中间位置, 还要加上半行[code]Item[/code]数量
 private int getMiddlePosition() {
  return getScrollPosition() + (PersonAgeAdapter.ITEM_NUM / 2);
 }
判断滚动是否停止.
if (newState == RecyclerView.SCROLL_STATE_IDLE)
在滚动停止时, 自动对齐.
mRvAgeList.scrollToPosition(getScrollPosition());
调用需要高亮显示的[code]Item[/code].
mAgeAdapter.highlightItem(getMiddlePosition());
注意在滚动停止时, 更新高亮比较好, 否则重绘速度较慢, 会影响滚动效果. [b]滑动效果 [/b] [img]http://files.jb51.net/file_images/article/201609/20169885419265.gif?20168885430[/img] [b]总结[/b] 好了,以上就是这篇文章的全部内容了,我们可以根据这些定制各式各样的滚动条了!希望这篇文章对大家能有所帮助。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部