gpt4 book ai didi

Android仿微信联系人按字母排序

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Android仿微信联系人按字母排序由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

app只要涉及到联系人的界面,几乎都是按照字母排序以及导航栏的方式。既然这个需求这么火,于是开始学习相关内容,此篇文章是我通过参考网上资料独立编写和总结的,希望多多少少对大家有所帮助,写的不好,还请各位朋友指教.

效果图如下:

Android仿微信联系人按字母排序

实现这个效果,需要三个知识点 : 1:将字符串 进行拼音分类 2:expandablelistview 二级扩展列表 3:右边字母分类view 。

我们先一个一个来了解解决方案,再上代码.

实现字母分类:

字母分类又分为三个小要点:一个是将中文转化为拼音,一个是实现按照字母的顺序排序,另一个是字母只显示在具有相同首字母中文的第一个前面.

1、将中文转化为拼音,这里使用了一个工具包,即pinyin4j-2.5.0.jar。官网地址:http://pinyin4j.sourceforge.net/ 点击下载,导入项目即可。(至于教程,网上很多) 。

Android仿微信联系人按字母排序

在这里我们只需要使用将中文转换成拼音的代码即可.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
pinyinutils.java
 
 
public static string getpingyin(string inputstring) {
   hanyupinyinoutputformat format = new hanyupinyinoutputformat();
   format.setcasetype(hanyupinyincasetype.lowercase);
   format.settonetype(hanyupinyintonetype.without_tone);
   format.setvchartype(hanyupinyinvchartype.with_v);
   char [] input = inputstring.trim().tochararray();
   string output = "" ;
   try {
    for ( char curchar : input) {
     if (java.lang.character.tostring(curchar).matches( "[\\u4e00-\\u9fa5]+" )) {
      string[] temp = pinyinhelper.tohanyupinyinstringarray(curchar, format);
      output += temp[ 0 ];
     } else
      output += java.lang.character.tostring(curchar);
    }
   } catch (badhanyupinyinoutputformatcombination e) {
    e.printstacktrace();
   }
   return output;
  }

2、实现按照字母的顺序排序,使用的是java自带的comparator接口,利用之前获取到的中文拼音,得到首字母并根据ascii值来实现排序.

?
1
2
3
4
5
6
7
8
9
10
11
12
private int sort(personbean lhs, personbean rhs) {
   // 获取ascii值
   int lhs_ascii = lhs.getfirstpinyin().touppercase().charat( 0 );
   int rhs_ascii = rhs.getfirstpinyin().touppercase().charat( 0 );
   // 判断若不是字母,则排在字母之后
   if (lhs_ascii < 65 || lhs_ascii > 90 )
    return 1 ;
   else if (rhs_ascii < 65 || rhs_ascii > 90 )
    return - 1 ;
   else
    return lhs.getpinyin().compareto(rhs.getpinyin());
  }

3、字母只显示在具有相同首字母中文的第一个前面。这里算是一个小技巧,这里字母显示的布局与中文名字的布局都是存放在listview的item的布局中的.

item的布局如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version= "1.0" encoding= "utf-8" ?>
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"
  android:layout_width= "match_parent"
  android:layout_height= "match_parent"
  android:orientation= "vertical" >
  <!-- 这个textview就是显示字母的 -->
  <textview
   android:id= "@+id/tv_lv_item_tag"
   android:layout_width= "match_parent"
   android:layout_height= "20dp"
   android:background= "#e6e6e6"
   android:gravity= "center_vertical"
   android:paddingleft= "10dip"
   android:text= "z"
   android:visibility= "visible" />
  <relativelayout
   android:layout_width= "match_parent"
   android:layout_height= "wrap_content" >
   <view
    android:id= "@+id/view_lv_item_line"
    android:layout_width= "match_parent"
    android:layout_height= "0.5dip"
    android:background= "#174465"
    android:layout_marginleft= "10dip"
    android:layout_marginright= "20dip"
    />
   <imageview
    android:id= "@+id/iv_lv_item_head"
    android:layout_width= "wrap_content"
    android:layout_height= "wrap_content"
    android:src= "@drawable/ic_launcher"
    android:layout_below= "@id/view_lv_item_line"
    android:layout_marginleft= "5dp" />
   <textview
    android:id= "@+id/tv_lv_item_name"
    android:layout_width= "wrap_content"
    android:layout_height= "wrap_content"
    android:layout_centervertical= "true"
    android:layout_torightof= "@id/iv_lv_item_head"
    android:layout_marginleft= "5dip"
    android:text= "周华健" />
  </relativelayout>
</linearlayout>

而判断是否需要显示字母,是通过判断当前item的position是否等于第一个出现item对应的中文首字母的索引.

如果相等,则说明是第一次出现,便需要显示字母,否则不显示字母。而这样的判断,有一个前提,那就是中文拼音的排序必须是按照字母顺序排序的,这就是我们在上一步排序的必要。  实现右侧的字母导航: 右侧的字母导航,其本质就是一个自定义view。除了绘制界面之外,需要注意的就是触摸事件的处理,还有回调机制(这个很多地方都会用到)的使用。这个比较重要,直接上代码吧.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.suse.contact;
import android.content.context;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.typeface;
import android.graphics.drawable.colordrawable;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
import android.widget.textview;
public class sidebar extends view {
  // 触摸事件
  private ontouchingletterchangedlistener ontouchingletterchangedlistener;
  // 26个字母
  public static string[] a_z = { "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 int choose = - 1 ; // 选中
  private paint paint = new paint();
  private textview mtextdialog;
  /**
   * 为sidebar设置显示字母的textview
   * @param mtextdialog
   */
  public void settextview(textview mtextdialog) {
   this .mtextdialog = mtextdialog;
  }
  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);
   // 获取焦点改变背景颜色.
   int height = getheight(); // 获取对应高度
   int width = getwidth(); // 获取对应宽度
   int singleheight = height / a_z.length- 2 ; // 获取每一个字母的高度 (这里-2仅仅是为了好看而已)
   for ( int i = 0 ; i < a_z.length; i++) {
    paint.setcolor(color.rgb( 33 , 65 , 98 )); //设置字体颜色
    paint.settypeface(typeface.default_bold); //设置字体
    paint.setantialias( true ); //设置抗锯齿
    paint.settextsize( 30 ); //设置字母字体大小
    // 选中的状态
    if (i == choose) {
     paint.setcolor(color.parsecolor( "#3399ff" )); //选中的字母改变颜色
     paint.setfakeboldtext( true ); //设置字体为粗体
    }
    // x坐标等于中间-字符串宽度的一半.
    float xpos = width / 2 - paint.measuretext(a_z[i]) / 2 ;
    float ypos = singleheight * i + singleheight;
    canvas.drawtext(a_z[i], xpos, ypos, paint); //绘制所有的字母
    paint.reset(); // 重置画笔
   }
  }
  @override
  public boolean dispatchtouchevent(motionevent event) {
   final int action = event.getaction();
   final float y = event.gety(); // 点击y坐标
   final int oldchoose = choose;
   final ontouchingletterchangedlistener listener = ontouchingletterchangedlistener;
   final int c = ( int ) (y / getheight() * a_z.length); // 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
   switch (action) {
   case motionevent.action_up:
    setbackgrounddrawable( new colordrawable( 0x00000000 ));
    choose = - 1 ; //
    invalidate();
    if (mtextdialog != null ) {
     mtextdialog.setvisibility(view.invisible);
    }
    break ;
   default :
    setbackgroundresource(r.drawable.sidebar_background);
    if (oldchoose != c) { //判断选中字母是否发生改变
     if (c >= 0 && c < a_z.length) {
      if (listener != null ) {
       listener.ontouchingletterchanged(a_z[c]);
      }
      if (mtextdialog != null ) {
       mtextdialog.settext(a_z[c]);
       mtextdialog.setvisibility(view.visible);
      }
      choose = c;
      invalidate();
     }
    }
    break ;
   }
   return true ;
  }
  /**
   * 向外公开的方法
   *
   * @param ontouchingletterchangedlistener
   */
  public void setontouchingletterchangedlistener(
    ontouchingletterchangedlistener ontouchingletterchangedlistener) {
   this .ontouchingletterchangedlistener = ontouchingletterchangedlistener;
  }
  /**
   * 接口
   *
   * @author coder
   *
   */
  public interface ontouchingletterchangedlistener {
   public void ontouchingletterchanged(string s);
  }
}

 接下来就是mainactivity和sortadapter的代码了.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
mainactivity.java:
package com.suse.contact;
import java.util.arraylist;
import java.util.collections;
import java.util.list;
import android.app.activity;
import android.os.bundle;
import android.widget.listview;
import android.widget.textview;
import com.suse.contact.sidebar.ontouchingletterchangedlistener;
/**
  *
* @classname: mainactivity
* @description: todo(这里用一句话描述这个类的作用)
* @author 银色的流星 欢迎批评、指导、交流 qq:962455668
  */
public class mainactivity extends activity {
  private listview listview;
  private sortadapter sortadapter;
  private list<personbean> data;
  private sidebar sidebar;
  private textview dialog;
  @override
  protected void oncreate(bundle savedinstancestate) {
   super .oncreate(savedinstancestate);
   setcontentview(r.layout.activity_main);
   init();
  }
  private list<personbean> getdata(string[] data) {
   list<personbean> listarray = new arraylist<personbean>();
   for ( int i = 0 ; i < data.length; i++) {
    string pinyin = pinyinutils.getpingyin(data[i]);
    string fpinyin = pinyin.substring( 0 , 1 ).touppercase();
    personbean person = new personbean();
    person.setname(data[i]);
    person.setpinyin(pinyin);
    // 正则表达式,判断首字母是否是英文字母
    if (fpinyin.matches( "[a-z]" )) {
     person.setfirstpinyin(fpinyin);
    } else {
     person.setfirstpinyin( "#" );
    }
    listarray.add(person);
   }
   return listarray;
  }
  private void init() {
   // todo auto-generated method stub
   sidebar = (sidebar) findviewbyid(r.id.sidebar);
   listview = (listview) findviewbyid(r.id.listview);
   dialog = (textview) findviewbyid(r.id.dialog);
   sidebar.settextview(dialog);
   // 设置字母导航触摸监听
   sidebar.setontouchingletterchangedlistener( new ontouchingletterchangedlistener() {
    @override
    public void ontouchingletterchanged(string s) {
     // todo auto-generated method stub
     // 该字母首次出现的位置
     int position = sortadapter.getpositionforselection(s.charat( 0 ));
     if (position != - 1 ) {
      listview.setselection(position);
     }
    }
   });
   data = getdata(getresources().getstringarray(r.array.listpersons));
   // 数据在放在adapter之前需要排序
   collections.sort(data, new pinyincomparator());
   sortadapter = new sortadapter( this , data);
   listview.setadapter(sortadapter);
  }
}

sortadapter.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package com.suse.contact;
import java.util.list;
import android.content.context;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
import android.widget.baseadapter;
import android.widget.textview;
public class sortadapter extends baseadapter {
  private context context;
  private list<personbean> persons;
  private layoutinflater inflater;
  public sortadapter(context context, list<personbean> persons) {
   this .context = context;
   this .persons = persons;
   this .inflater = layoutinflater.from(context);
  }
  @override
  public int getcount() {
   // todo auto-generated method stub
   return persons.size();
  }
  @override
  public object getitem( int position) {
   // todo auto-generated method stub
   return persons.get(position);
  }
  @override
  public long getitemid( int position) {
   // todo auto-generated method stub
   return position;
  }
  @override
  public view getview( int position, view convertview, viewgroup parent) {
   viewholder viewholder = null ;
   personbean person = persons.get(position);
   if (convertview == null ) {
    viewholder = new viewholder();
    convertview = inflater.inflate(r.layout.list_item, null );
    viewholder.tv_tag = (textview) convertview
      .findviewbyid(r.id.tv_lv_item_tag);
    viewholder.tv_name = (textview) convertview
      .findviewbyid(r.id.tv_lv_item_name);
    convertview.settag(viewholder);
   } else {
    viewholder = (viewholder) convertview.gettag();
   }
   // 获取首字母的assii值
   int selection = person.getfirstpinyin().charat( 0 );
   // 通过首字母的assii值来判断是否显示字母
   int positionforselection = getpositionforselection(selection);
   if (position == positionforselection) { // 相等说明需要显示字母
    viewholder.tv_tag.setvisibility(view.visible);
    viewholder.tv_tag.settext(person.getfirstpinyin());
   } else {
    viewholder.tv_tag.setvisibility(view.gone);
   }
   viewholder.tv_name.settext(person.getname());
   return convertview;
  }
  public int getpositionforselection( int selection) {
   for ( int i = 0 ; i < persons.size(); i++) {
    string fpinyin = persons.get(i).getfirstpinyin();
    char first = fpinyin.touppercase().charat( 0 );
    if (first == selection) {
     return i;
    }
   }
   return - 1 ;
  }
  class viewholder {
   textview tv_tag;
   textview tv_name;
  }
}

虽然不全,但比较重要的代码都已经贴上去了,希望对大家有所帮助  。

最后此篇关于Android仿微信联系人按字母排序的文章就讲到这里了,如果你想了解更多关于Android仿微信联系人按字母排序的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com