Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android仿微信聯系人列表字母側滑控件

Android仿微信聯系人列表字母側滑控件

編輯:關於Android編程

仿微信聯系人列表字母側滑控件, 側滑控件參考了以下博客:

Android實現ListView的A-Z字母排序和過濾搜索功能

首先分析一下字母側滑控件應該如何實現,根據側滑控件的高度和字母的數量來平均計算每個字母應該占據的高度。

在View的onDraw()方法下繪制每一個字母

protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  int height = getHeight();// 獲取對應高度
  int width = getWidth(); // 獲取對應寬度
  int singleHeight = height / getData().size();// 獲取每一個字母的高度

  for (int i = 0; i < getData().size(); i++) {
   mPaint.setColor(getLetterColor());//繪制字母的顏色
   mPaint.setTypeface(Typeface.DEFAULT);
   mPaint.setAntiAlias(true);
   mPaint.setTextSize(singleHeight);
   // 如果是選中的狀態
   if (i == mPosition) {
    mPaint.setColor(getLetterPressedColor());
    mPaint.setFakeBoldText(true);
   }
   // x坐標等於總體寬度中間的位置減去字符串寬度的一半.
   float xPos = width / 2 - mPaint.measureText(getData().get(i)) / 2;
   float yPos = singleHeight * i + singleHeight;
   canvas.drawText(getData().get(i), xPos, yPos, mPaint);
   mPaint.reset();// 重置畫筆
  }

 }

然後再看一下觸控事件的攔截處理

 @Override
 public boolean dispatchTouchEvent(MotionEvent event) {
  final int action = event.getAction();
  final float y = event.getY();// 點擊y坐標
  final int lastPosition = mPosition;//記錄上一次選中字母的位置
  final int position = (int) (y / getHeight() * getData().size());// 點擊y坐標所占總高度的比例*b數組的長度就等於點擊b中的個數.

  switch (action) {
   //當手指離開
   case MotionEvent.ACTION_UP:
   //設置側滑控件的背景色
    setBackgroundColor(getBackgroundNormalColor());
    mPosition = -1;
    invalidate();

    if (getOnTouchLetterListener() != null) {
    //回調事件,告知當前手指已經離開當前區域
     getOnTouchLetterListener().onTouchOutside();
    }

    break;

   default:
   //更改當字母為選中狀態時控件的背景色
    setBackgroundColor(getBackgroundPressedColor());
    //如果選中字母的位置不等於上一次選中的位置
    if (lastPosition != position) {
     if (position >= 0 && position < getData().size()) {
      if (getOnTouchLetterListener() != null) {
      //回調事件,返回當前選中的字母
       getOnTouchLetterListener().onTouchLetter(getData().get(position));
      }
      mPosition = position;
      invalidate();
     }
    }

    break;
  }
  return true;
 }

 public interface OnTouchLetterListener {

  /**
   * 當接觸到某個key的時候會調用;
   * @param s
   */
  void onTouchLetter(String s);

  /**
   * 當離開控件可觸摸區域時會調用;
   */
  void onTouchOutside();
 }

側滑控件完成後, 再分析一下分組界面是怎麼實現的,不同分組由不同的字母作為標題,用ListView就可以實現,ListView裡使用的Adapter裡面有一個方法getItemViewType()方法用於區分返回多種類型的View,這裡我們就兩種, 一個是標題,一個是聯系人信息;頂部裡那些新的朋友、群聊等可以用ListView的addHeaderView()實現。但是用最SDK自帶的BaseAdapter實現分組的話也不方便,實際上我們可以進一步包裝;

首先看一下最基本的Adapter封裝:

public abstract class SimpleAdapter<T> extends BaseAdapter {

 protected Context mContext;
 protected List<T> mData;

 public SimpleAdapter(){}

 public SimpleAdapter(Context context, List<T> data){
  init(context, data);
 }

 public void init(Context context, List<T> data){
  this.mContext = context;
  this.mData = data;
 }

 @Override
 public int getCount() {
  return mData.size();
 }

 @Override
 public T getItem(int position) {
  if(checkPositionIsOutOfRange(position)){
   return null;
  }
  return mData.get(position);
 }

 @Override
 public long getItemId(int position) {
  return position;
 }

 @Override
 public abstract View getView(int position, View convertView, ViewGroup parent);

 public void refresh(List<T> data){
  if(data == null){
   this.mData.clear();
  }else{
   this.mData = data;
  }
  notifyDataSetChanged();
 }

 public boolean checkPositionIsOutOfRange(int position){
  if(0 <= position && position < mData.size()){
   return false;
  }
  return true;
 }

 public Context getContext(){
  return mContext;
 }

 public List<T> getData(){
  return mData;
 }
}

這個SimpleAdapter實現了數據基於List的最基本方法的實現,使得每次繼承BaseAdapter不用再實現一些基本的方法,接下來再看一下用於更好實現分組的Adapter的進一步封裝:

public abstract class SortAdapter<K extends SortKey, V, VH_G extends ViewHolder, VH_C extends ViewHolder> extends SimpleAdapter<Object> {

 public final static int VIEW_TYPE_GROUP = 0;
 public final static int VIEW_TYPE_CHILD = 1;

 private HashMap<SortKey, Integer> mKeyIndex = new HashMap<>();

 public SortAdapter(Context context, Map<K, List<V>> map) {
  init(context, convertMapToList(map));
 }

 public SortAdapter(Context context, List<Object> list) {
  init(context, list);
 }

 /**
  * 轉換分組數據為List,並且更新鍵值的索引
  * @param map
  * @return
  */
 public List<Object> convertMapToList(Map<K, List<V>> map) {
  List<Object> mData = new ArrayList<>();
  mKeyIndex.clear();
  for (Map.Entry<K, List<V>> entry : map.entrySet()) {
   mData.add(entry.getKey());
   mKeyIndex.put(entry.getKey(), mData.size() - 1);
   for (V v : entry.getValue()) {
    mData.add(v);
   }
  }
  return mData;
 }

 public void refresh(Map<K, List<V>> map) {
  super.refresh(convertMapToList(map));
 }

 @Override
 public void refresh(List<Object> data) {
  super.refresh(data);
  mKeyIndex.clear();
 }

 /**
  * 得到鍵值的索引值
  * @param k
  * @return
  */
 public int getKeyIndex(K k){
  Integer integer = mKeyIndex.get(k);
  if(integer == null){
   return getKeyIndexFromList(k);
  }
  return integer;
 }

 public int getKeyIndexFromList(K k){
  for(int i = 0; i < getCount(); i++){
   Object obj = getItem(i);
   if(obj != null && obj instanceof SortKey){
    if(obj.equals(k)){
     mKeyIndex.put(k, i);
     return i;
    }
   }
  }
  return -1;
 }

 @Override
 public int getItemViewType(int position) {
  Object obj = getItem(position);

  if (obj instanceof SortKey) {
   return VIEW_TYPE_GROUP;
  }
  return VIEW_TYPE_CHILD;
 }

 @Override
 public int getViewTypeCount() {
  return 2;
 }

 @Override
 public int getCount() {
  return mData.size();
 }

 @Override
 public Object getItem(int position) {
  if (0 <= position && position < mData.size()) {
   return mData.get(position);
  }
  return null;
 }

 @Override
 public long getItemId(int position) {
  return position;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {

  int viewType = getItemViewType(position);

  View view = null;
  Object obj = getItem(position);
  switch (viewType) {
   case VIEW_TYPE_GROUP:
    view = getGroupView((K)obj, position, convertView, parent);
    break;
   case VIEW_TYPE_CHILD:
    view = getChildView((V)obj, position, convertView, parent);
    break;
  }
  return view;
 }

 public View getGroupView(K key, int position, View convertView, ViewGroup parent){
  VH_G vh;
  if(convertView == null){
   convertView = LayoutInflater.from(mContext).inflate(getGroupLayoutId(), null);
   vh = onCreateGroupViewHolder(convertView, parent);
   convertView.setTag(vh);
  }else{
   vh = (VH_G)convertView.getTag();
  }

  onBindGroupViewHolder(vh, key, position);
  return convertView;
 }

 public View getChildView(V value, int position, View convertView, ViewGroup parent){
  VH_C vh;
  if(convertView == null){
   convertView = LayoutInflater.from(mContext).inflate(getChildLayoutId(), null);
   vh = onCreateChildViewHolder(convertView, parent);
   convertView.setTag(vh);
  }else{
   vh = (VH_C)convertView.getTag();
  }

  onBindChildViewHolder(vh, value, position);
  return convertView;
 }

 public abstract @LayoutRes int getGroupLayoutId();

 public abstract VH_G onCreateGroupViewHolder(View convertView, ViewGroup parent);

 public abstract void onBindGroupViewHolder(VH_G vh, K key, int position);

 public abstract @LayoutRes int getChildLayoutId();

 public abstract VH_C onCreateChildViewHolder(View convertView, ViewGroup parent);

 public abstract void onBindChildViewHolder(VH_C vh, V value, int position);

 public interface SortKey {
 }

 public static class ViewHolder{

  public View mParent;
  public ViewHolder(View parent){
   mParent = parent;
  }

  public View findViewById(@IdRes int id){
   return mParent.findViewById(id);
  }
 }

本項目Github地址(基於AndroidStudio構建):
https://github.com/yuhengye/LetterSort

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved