Android使用RecyclerView實現水平滾動控制項_Android

來源:互聯網
上載者:User

前言

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

注意在滾動停止時, 更新高亮比較好, 否則重繪速度較慢, 會影響滾動效果.

滑動效果

總結

好了,以上就是這篇文章的全部內容了,我們可以根據這些定製各式各樣的捲軸了!希望這篇文章對大家能有所協助。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.