国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android仿微信通訊錄列表側邊欄效果

2019-12-12 03:34:33
字體:
來源:轉載
供稿:網友

先看Android仿微信通訊錄列表側邊欄效果圖

這是比較常見的效果了吧

列表根據首字符的拼音字母來排序,且可以通過側邊欄的字母索引來進行定位。

實現這樣一個效果并不難,只要自定義一個索引View,然后引入一個可以對漢字進行拼音解析的jar包――pinyin4j-2.5.0即可

首先,先來定義側邊欄控件View,只要直接畫出來即可。

字母選中項會變為紅色,且滑動時背景會變色,此時SideBar并不包含居中的提示文本

public class SideBar extends View {  private Paint paint = new Paint();  private int choose = -1;  private boolean showBackground;  public static String[] letters = {"#", "A", "B", "C", "D", "E", "F", "G", "H",      "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",      "V", "W", "X", "Y", "Z"};  private OnChooseLetterChangedListener onChooseLetterChangedListener;  public SideBar(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);  }  public SideBar(Context context, AttributeSet attrs) {    super(context, attrs);  }  public SideBar(Context context) {    super(context);  }  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    if (showBackground) {      canvas.drawColor(Color.parseColor("#D9D9D9"));    }    int height = getHeight();    int width = getWidth();    //平均每個字母占的高度    int singleHeight = height / letters.length;    for (int i = 0; i < letters.length; i++) {      paint.setColor(Color.BLACK);      paint.setAntiAlias(true);      paint.setTextSize(25);      if (i == choose) {        paint.setColor(Color.parseColor("#FF2828"));        paint.setFakeBoldText(true);      }      float x = width / 2 - paint.measureText(letters[i]) / 2;      float y = singleHeight * i + singleHeight;      canvas.drawText(letters[i], x, y, paint);      paint.reset();    }  }  @Override  public boolean dispatchTouchEvent(MotionEvent event) {    int action = event.getAction();    float y = event.getY();    int oldChoose = choose;    int c = (int) (y / getHeight() * letters.length);    switch (action) {      case MotionEvent.ACTION_DOWN:        showBackground = true;        if (oldChoose != c && onChooseLetterChangedListener != null) {          if (c > -1 && c < letters.length) {            onChooseLetterChangedListener.onChooseLetter(letters[c]);            choose = c;            invalidate();          }        }        break;      case MotionEvent.ACTION_MOVE:        if (oldChoose != c && onChooseLetterChangedListener != null) {          if (c > -1 && c < letters.length) {            onChooseLetterChangedListener.onChooseLetter(letters[c]);            choose = c;            invalidate();          }        }        break;      case MotionEvent.ACTION_UP:        showBackground = false;        choose = -1;        if (onChooseLetterChangedListener != null) {          onChooseLetterChangedListener.onNoChooseLetter();        }        invalidate();        break;    }    return true;  }  @Override  public boolean onTouchEvent(MotionEvent event) {    return super.onTouchEvent(event);  }  public void setOnTouchingLetterChangedListener(OnChooseLetterChangedListener onChooseLetterChangedListener) {    this.onChooseLetterChangedListener = onChooseLetterChangedListener;  }  public interface OnChooseLetterChangedListener {    void onChooseLetter(String s);    void onNoChooseLetter();  }}

SideBar只是畫出了側邊欄索引條而已,不包含居中的提示文本,這個在另一個布局添加即可

public class HintSideBar extends RelativeLayout implements SideBar.OnChooseLetterChangedListener {  private TextView tv_hint;  private SideBar.OnChooseLetterChangedListener onChooseLetterChangedListener;  public HintSideBar(Context context, AttributeSet attrs) {    super(context, attrs);    LayoutInflater.from(context).inflate(R.layout.view_hint_side_bar, this);    initView();  }  private void initView() {    SideBar sideBar = (SideBar) findViewById(R.id.sideBar);    tv_hint = (TextView) findViewById(R.id.tv_hint);    sideBar.setOnTouchingLetterChangedListener(this);  }  @Override  public void onChooseLetter(String s) {    tv_hint.setText(s);    tv_hint.setVisibility(VISIBLE);    if (onChooseLetterChangedListener != null) {      onChooseLetterChangedListener.onChooseLetter(s);    }  }  @Override  public void onNoChooseLetter() {    tv_hint.setVisibility(INVISIBLE);    if (onChooseLetterChangedListener != null) {      onChooseLetterChangedListener.onNoChooseLetter();    }  }  public void setOnChooseLetterChangedListener(SideBar.OnChooseLetterChangedListener onChooseLetterChangedListener) {    this.onChooseLetterChangedListener = onChooseLetterChangedListener;  }}

HintSideBar通過回調接口來更新居中TextView的文本內容和可見性

使用到的布局

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent">  <com.czy.demo.SideBar    android:id="@+id/sideBar"    android:layout_width="30dp"    android:layout_height="match_parent"    android:layout_alignParentRight="true" />  <TextView    android:id="@+id/tv_hint"    android:layout_width="70dp"    android:layout_height="70dp"    android:layout_centerInParent="true"    android:background="#4b0e0e0e"    android:gravity="center"    android:textColor="#ffffff"    android:textSize="30sp"    android:visibility="invisible" /></RelativeLayout>

此時就完成了索引View的繪制,不過定位功能還需要再通過回調接口來完成。

引入jar包后,先來設定一個工具類,包含一個可以解析字符串的方法,返回值為首字符對應的拼音首字母或者為包含一個空格的char類型數據。

public class Utils {  /**   * 如果字符串的首字符為漢字,則返回該漢字的拼音大寫首字母   * 如果字符串的首字符為字母,也轉化為大寫字母返回   * 其他情況均返回' '   *   * @param str 字符串   * @return 首字母   */  public static char getHeadChar(String str) {    if (str != null && str.trim().length() != 0) {      char[] strChar = str.toCharArray();      char headChar = strChar[0];      //如果是大寫字母則直接返回      if (Character.isUpperCase(headChar)) {        return headChar;      } else if (Character.isLowerCase(headChar)) {        return Character.toUpperCase(headChar);      }      // 漢語拼音格式輸出類      HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat();      hanYuPinOutputFormat.setCaseType(UPPERCASE);      hanYuPinOutputFormat.setToneType(WITHOUT_TONE);      if (String.valueOf(headChar).matches("[//u4E00-//u9FA5]+")) {        try {          String[] stringArray = PinyinHelper.toHanyuPinyinStringArray(headChar, hanYuPinOutputFormat);          if (stringArray != null && stringArray[0] != null) {            return stringArray[0].charAt(0);          }        } catch (BadHanyuPinyinOutputFormatCombination e) {          return ' ';        }      }    }    return ' ';  }}

然后再定義一個實體類,包含用戶名,電話,用戶名首字符的拼音首字母等三個屬性
需要實現Comparable 接口,用于排序

public class User implements Comparable {  private String userName;  private String phone;  private char headLetter;  public User(String userName, String phone) {    this.userName = userName;    this.phone = phone;    headLetter = Utils.getHeadChar(userName);  }  public String getUserName() {    return userName;  }  public String getPhone() {    return phone;  }  public char getHeadLetter() {    return headLetter;  }  @Override  public boolean equals(Object object) {    if (this == object) {      return true;    }    if (object == null || getClass() != object.getClass()) {      return false;    }    User that = (User) object;    return getUserName().equals(that.getUserName()) && getPhone().equals(that.getPhone());  }  @Override  public int compareTo(Object object) {    if (object instanceof User) {      User that = (User) object;      if (getHeadLetter() == ' ') {        if (that.getHeadLetter() == ' ') {          return 0;        }        return -1;      }      if (that.getHeadLetter() == ' ') {        return 1;      } else if (that.getHeadLetter() > getHeadLetter()) {        return -1;      } else if (that.getHeadLetter() == getHeadLetter()) {        return 0;      }      return 1;    } else {      throw new ClassCastException();    }  }}

主布局文件如下

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent">  <android.support.v7.widget.RecyclerView    android:id="@+id/rv_userList"    android:layout_width="match_parent"    android:layout_height="match_parent" />  <com.czy.demo.HintSideBar    android:id="@+id/hintSideBar"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_gravity="right" /></FrameLayout>

聯系人列表使用的是RecyclerView,還需要定義一個Adapter

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserHolder> {  private List<User> userList;  private LayoutInflater inflater;  public UserAdapter(Context context) {    inflater = LayoutInflater.from(context);    userList = new ArrayList<>();  }  @Override  public UserHolder onCreateViewHolder(ViewGroup parent, int viewType) {    View view = inflater.inflate(R.layout.item_user, parent, false);    return new UserHolder(view);  }  @Override  public void onBindViewHolder(UserHolder holder, int position) {    holder.tv_userName.setText(userList.get(position).getUserName());    holder.tv_phone.setText(userList.get(position).getPhone());  }  public void setData(List<User> userList) {    this.userList.clear();    this.userList = userList;  }  public int getFirstPositionByChar(char sign) {    if (sign == '#') {      return 0;    }    for (int i = 0; i < userList.size(); i++) {      if (userList.get(i).getHeadLetter() == sign) {        return i;      }    }    return -1;  }  @Override  public int getItemCount() {    return userList.size();  }  class UserHolder extends RecyclerView.ViewHolder {    public TextView tv_userName;    public TextView tv_phone;    public UserHolder(View itemView) {      super(itemView);      tv_userName = (TextView) itemView.findViewById(R.id.tv_userName);      tv_phone = (TextView) itemView.findViewById(R.id.tv_phone);    }  }}

以下方法用于獲取聯系人列表中第一個首字符為sign的item的位置

public int getFirstPositionByChar(char sign)

主Activity代碼如下

public class MainActivity extends AppCompatActivity implements SideBar.OnChooseLetterChangedListener {  private List<User> userList;  private UserAdapter adapter;  private RecyclerView rv_userList;  private LinearLayoutManager manager;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    supportRequestWindowFeature(Window.FEATURE_NO_TITLE);    setContentView(R.layout.activity_main);    HintSideBar hintSideBar = (HintSideBar) findViewById(R.id.hintSideBar);    rv_userList = (RecyclerView) findViewById(R.id.rv_userList);    hintSideBar.setOnChooseLetterChangedListener(this);    manager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);    rv_userList.setLayoutManager(manager);    userList = new ArrayList<>();    adapter = new UserAdapter(this);    initData();    adapter.setData(userList);    rv_userList.setAdapter(adapter);  }  @Override  public void onChooseLetter(String s) {    int i = adapter.getFirstPositionByChar(s.charAt(0));    if (i == -1) {      return;    }    manager.scrollToPositionWithOffset(i, 0);  }  @Override  public void onNoChooseLetter() {  }}

initData()用于向Adapter填充數據

public void initData() {    User user1 = new User("陳", "12345678");    User user2 = new User("趙", "12345678");    ...    userList.add(user1);    userList.add(user2);    ...    Collections.sort(userList);    adapter.notifyDataSetChanged();  }

這樣,整個效果就都完成了。

這里提供代碼下載:Android 仿微信通訊錄列表側邊欄

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 磴口县| 金堂县| 中方县| 桦甸市| 孟津县| 黔西| 金堂县| 紫阳县| 岐山县| 乃东县| 石屏县| 囊谦县| 北海市| 上饶县| 绥棱县| 扬州市| 平顺县| 白玉县| 宁化县| 大姚县| 汉阴县| 如东县| 平南县| 都兰县| 怀化市| 福贡县| 元阳县| 大悟县| 衡阳市| 东安县| 承德市| 福海县| 临海市| 马公市| 吉首市| 凌源市| 芦溪县| 凤山市| 迁西县| 武功县| 蒙城县|