在上一篇文章当中,主要学习了ListView的A-Z字母排序功能以及根据输入框的输入值改变来过滤搜索结果,如果输入框里面的值为空,更新为原来的列表,否则为过滤数据列表,包括汉字转成拼音的功能,如果你还没看过的话上一篇文章的话,可以点击:Android 仿美团网,探索ListView的A-Z字母排序功能实现选择城市。其实对联系人和城市列表等实现A-Z的排序的实现原理都差不多。我只是在上一篇文章的基础上做了一些修改。

按照惯例先来看一下最终效果图:

这里写图片描述

现在我们来看下项目结构图

这里写图片描述

其实很多都是和上一篇文章一样的,我在这里就不多说啦,不是很明白的地方,可以看一下上一篇文章

我还是按照项目中类的顺序把代码贴出来吧

1.ContactSortModel

package com.adan.contactsdome.view;

public class ContactSortModel {

private String name;//显示的数据

private String sortLetters;//显示数据拼音的首字母

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSortLetters() {

return sortLetters;

}

public void setSortLetters(String sortLetters) {

this.sortLetters = sortLetters;

}

}

2.还是一样EditTextWithDel类就不贴上代码了Android 带清除功能的输入框控件EditTextWithDel

3.PinyinComparator

package com.adan.contactsdome.view;

import java.util.Comparator;

/**

* 用来对ListView中的数据根据A-Z进行排序,前面两个if判断主要是将不是以汉字开头的数据放在后面

*/

public class PinyinComparator implements Comparator {

public int compare(ContactSortModel o1, ContactSortModel o2) {

//这里主要是用来对ListView里面的数据根据ABCDEFG...来排序

if (o1.getSortLetters().equals("@")

|| o2.getSortLetters().equals("#")) {

return -1;

} else if (o1.getSortLetters().equals("#")

|| o2.getSortLetters().equals("@")) {

return 1;

} else {

return o1.getSortLetters().compareTo(o2.getSortLetters());

}

}

}

4.PinyinUtils类,就是第一点所讲的PinYin4j.jar用于将汉字转换为拼音啦,这里就不粘贴代码啦,探索PinYin4j.jar将汉字转换为拼音的基本用法

5.SideBar类就是ListView右侧的字母索引View

package com.adan.contactsdome.view;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Typeface;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.widget.TextView;

import com.adan.contactsdome.R;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

/**

* ListView右侧的字母索引View

*/

public class SideBar extends View {

public static String[] INDEX_STRING = {"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 OnTouchingLetterChangedListener onTouchingLetterChangedListener;

private List letterList;

private int choose = -1;

private Paint paint = new Paint();

private TextView mTextDialog;

public SideBar(Context context) {

this(context, null);

}

public SideBar(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public SideBar(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init();

}

private void init() {

setBackgroundColor(Color.parseColor("#FFFFFF"));

letterList = Arrays.asList(INDEX_STRING);

}

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

int height = getHeight();// 获取对应高度

int width = getWidth();// 获取对应宽度

int singleHeight = height / letterList.size();// 获取每一个字母的高度

for (int i = 0; i < letterList.size(); i++) {

paint.setColor(Color.parseColor("#606060"));

paint.setTypeface(Typeface.DEFAULT_BOLD);

paint.setAntiAlias(true);

paint.setTextSize(20);

// 选中的状态

if (i == choose) {

paint.setColor(Color.parseColor("#4F41FD"));

paint.setFakeBoldText(true);

}

// x坐标等于中间-字符串宽度的一半.

float xPos = width / 2 - paint.measureText(letterList.get(i)) / 2;

float yPos = singleHeight * i + singleHeight / 2;

canvas.drawText(letterList.get(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() * letterList.size());// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.

switch (action) {

case MotionEvent.ACTION_UP:

setBackgroundColor(Color.parseColor("#FFFFFF"));

choose = -1;

invalidate();

if (mTextDialog != null) {

mTextDialog.setVisibility(View.GONE);

}

break;

default:

setBackgroundResource(R.drawable.bg_sidebar);

if (oldChoose != c) {

if (c >= 0 && c < letterList.size()) {

if (listener != null) {

listener.onTouchingLetterChanged(letterList.get(c));

}

if (mTextDialog != null) {

mTextDialog.setText(letterList.get(c));

mTextDialog.setVisibility(View.VISIBLE);

}

choose = c;

invalidate();

}

}

break;

}

return true;

}

public void setIndexText(ArrayList indexStrings) {

this.letterList = indexStrings;

invalidate();

}

/**

* 为SideBar设置显示当前按下的字母的TextView

*

* @param mTextDialog

*/

public void setTextView(TextView mTextDialog) {

this.mTextDialog = mTextDialog;

}

/**

* 向外公开的方法

*

* @param onTouchingLetterChangedListener

*/

public void setOnTouchingLetterChangedListener(

OnTouchingLetterChangedListener onTouchingLetterChangedListener) {

this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;

}

/**

* 接口

*/

public interface OnTouchingLetterChangedListener {

void onTouchingLetterChanged(String s);

}

}

6.SortAdapter数据的适配器类,这里我们需要用到的就是SectionIndexer接口,它能够有效地帮助我们对分组进行控制。使用SectionIndexer接口需要实现三个方法:getSectionForPosition(int position),getPositionForSection(int section),getSections(),我们只需要自行实现前面两个方法:

(一)getSectionForPosition(int position)是根据ListView的position来找出当前位置所在的分组

(二)getPositionForSection(int section)就是根据首字母的Char值来获取在该ListView中第一次出现该首字母的位置,也就是当前分组所在的位置

package com.adan.contactsdome;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.SectionIndexer;

import android.widget.TextView;

import com.adan.contactsdome.view.ContactSortModel;

import java.util.List;

public class SortAdapter extends BaseAdapter implements SectionIndexer {

private List list = null;

private Context mContext;

public SortAdapter(Context mContext, List list) {

this.mContext = mContext;

this.list = list;

}

/**

* 当ListView数据发生变化时,调用此方法来更新ListView

*

* @param list

*/

public void updateListView(List list) {

this.list = list;

notifyDataSetChanged();

}

public int getCount() {

return this.list.size();

}

public Object getItem(int position) {

return list.get(position);

}

public long getItemId(int position) {

return position;

}

public View getView(final int position, View view, ViewGroup arg2) {

ViewHolder viewHolder = null;

final ContactSortModel mContent = list.get(position);

if (view == null) {

viewHolder = new ViewHolder();

view = LayoutInflater.from(mContext).inflate(R.layout.item_contact, null);

viewHolder.tvTitle = (TextView) view.findViewById(R.id.tv_city_name);

view.setTag(viewHolder);

viewHolder.tvLetter = (TextView) view.findViewById(R.id.tv_catagory);

} else {

viewHolder = (ViewHolder) view.getTag();

}

int section = getSectionForPosition(position);

if (position == getPositionForSection(section)) {

viewHolder.tvLetter.setVisibility(View.VISIBLE);

viewHolder.tvLetter.setText(mContent.getSortLetters());

} else {

viewHolder.tvLetter.setVisibility(View.GONE);

}

viewHolder.tvTitle.setText(this.list.get(position).getName());

return view;

}

final static class ViewHolder {

TextView tvLetter;

TextView tvTitle;

}

public int getSectionForPosition(int position) {

return list.get(position).getSortLetters().charAt(0);

}

public int getPositionForSection(int section) {

for (int i = 0; i < getCount(); i++) {

String sortStr = list.get(i).getSortLetters();

char firstChar = sortStr.toUpperCase().charAt(0);

if (firstChar == section) {

return i;

}

}

return -1;

}

@Override

public Object[] getSections() {

return null;

}

}

7.MainActivity 对EditTextWithDel设置addTextChangedListener监听,当输入框内容发生变化根据里面的值过滤ListView,里面的值为空显示原来的列表和给ListView添加表头等

package com.adan.contactsdome;

import android.app.Activity;

import android.os.Bundle;

import android.text.Editable;

import android.text.TextUtils;

import android.text.TextWatcher;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.Toast;

import com.adan.contactsdome.view.ContactSortModel;

import com.adan.contactsdome.view.EditTextWithDel;

import com.adan.contactsdome.view.PinyinComparator;

import com.adan.contactsdome.view.PinyinUtils;

import com.adan.contactsdome.view.SideBar;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

public class MainActivity extends Activity {

private ListView sortListView;

private SideBar sideBar;

private TextView dialog, mTvTitle;

private SortAdapter adapter;

private EditTextWithDel mEtSearchName;

private List SourceDateList;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initViews();

}

private void initViews() {

mEtSearchName = (EditTextWithDel) findViewById(R.id.et_search);

sideBar = (SideBar) findViewById(R.id.sidrbar);

dialog = (TextView) findViewById(R.id.dialog);

mTvTitle = (TextView) findViewById(R.id.tv_title);

sortListView = (ListView) findViewById(R.id.lv_contact);

initDatas();

initEvents();

setAdapter();

}

private void setAdapter() {

SourceDateList = filledData(getResources().getStringArray(R.array.contacts));

Collections.sort(SourceDateList, new PinyinComparator());

adapter = new SortAdapter(this, SourceDateList);

sortListView.setAdapter(adapter);

}

private void initEvents() {

//设置右侧触摸监听

sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {

@Override

public void onTouchingLetterChanged(String s) {

//该字母首次出现的位置

int position = adapter.getPositionForSection(s.charAt(0));

if (position != -1) {

sortListView.setSelection(position + 1);

}

}

});

//ListView的点击事件

sortListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView> parent, View view,

int position, long id) {

mTvTitle.setText(((ContactSortModel) adapter.getItem(position - 1)).getName());

Toast.makeText(getApplication(), ((ContactSortModel) adapter.getItem(position)).getName(), Toast.LENGTH_SHORT).show();

}

});

//根据输入框输入值的改变来过滤搜索

mEtSearchName.addTextChangedListener(new TextWatcher() {

@Override

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

//当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表

filterData(s.toString());

}

@Override

public void afterTextChanged(Editable s) {

}

});

}

private void initDatas() {

sideBar.setTextView(dialog);

}

/**

* 根据输入框中的值来过滤数据并更新ListView

*

* @param filterStr

*/

private void filterData(String filterStr) {

List mSortList = new ArrayList<>();

if (TextUtils.isEmpty(filterStr)) {

mSortList = SourceDateList;

} else {

mSortList.clear();

for (ContactSortModel sortModel : SourceDateList) {

String name = sortModel.getName();

if (name.toUpperCase().indexOf(filterStr.toString().toUpperCase()) != -1 || PinyinUtils.getPingYin(name).toUpperCase().startsWith(filterStr.toString().toUpperCase())) {

mSortList.add(sortModel);

}

}

}

// 根据a-z进行排序

Collections.sort(mSortList, new PinyinComparator());

adapter.updateListView(mSortList);

}

private List filledData(String[] date) {

List mSortList = new ArrayList<>();

ArrayList indexString = new ArrayList<>();

for (int i = 0; i < date.length; i++) {

ContactSortModel sortModel = new ContactSortModel();

sortModel.setName(date[i]);

String pinyin = PinyinUtils.getPingYin(date[i]);

String sortString = pinyin.substring(0, 1).toUpperCase();

if (sortString.matches("[A-Z]")) {

sortModel.setSortLetters(sortString.toUpperCase());

if (!indexString.contains(sortString)) {

indexString.add(sortString);

}

}

mSortList.add(sortModel);

}

Collections.sort(indexString);

sideBar.setIndexText(indexString);

return mSortList;

}

}

android 字母排序i,Android 使用ListView的A-Z字母排序功能实现联系人模块相关推荐

  1. [Android精品源码] Android 仿美团网,探索ListView的A-Z字母排序功能实现选择城市

    Material Design中文版Code4APPPHP100UI4APP 开启辅助访问设为首页收藏本站快捷导航切换到宽版切换风格 石刚 | |我的 |签到打卡 |设置 |消息 |提醒(2) |退出 ...

  2. android程序设计排序方法,Android编程之可以实现拖动排序的listview控件

    DragSortListView是一个可以实现拖动排序的listview控件,是我看到的交互较为复杂的开源代码中不管是代码质量还是流畅性都最好的. DragSortListView 简称DSLV,继承 ...

  3. android 字母索引三方,Android ListView字母索引(仿微信通讯录列表)

    布局代码 xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_paren ...

  4. android listview排序分组,Android:如何对ListView的数据进行排序?

    我有一些要从服务器中提取的JSON数据. 此数据中的字段之一是距离值. 我需要按照ListView中从最低到最高的距离对数据进行排序. 我不确定该怎么做? 任何帮助表示赞赏. 这是我获取数据的代码,不 ...

  5. android listview排序分组,Android:如何为ListView排序数据?

    我从服务器上下载了一些 JSON数据.该数据中的一个字段是距离值.我需要按ListView中从最低到最高的距离对数据进行排序.我不知道该怎么做呢? 任何帮助赞赏. 这是我的代码,以获取数据不确定如何正 ...

  6. 【Android 应用开发】Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片

    一. Application用途 1. Application用途 创建Application时机 : Application在启动的时候会调用Application无参的构造方法创建实例; Appl ...

  7. Android 开发之漫漫长途 XIV——ListView

    关注 code小生 ,每日一篇技术推送! 作者:忘了12138 地址:http://www.cnblogs.com/wangle12138/p/8441136.html 声明:本文是 忘了12138 ...

  8. android 项目学习随笔十三(ListView实现ITEM点击事件,将已读状态持久化到本地)...

    1.因为给LISTVIEW增加了两个头布局,所以在点击事件ITEM索引会增加2,比如原来第一条数据的索引应该为0,增加两个头布局后,它的索引变为        2,为了使LISTVIEW的ITEM在点 ...

  9. android开发小技巧:实现listview异步加载图片

    2019独角兽企业重金招聘Python工程师标准>>> 针对listview异步加载图片这个问题,麦子学院android开发老师讲了一种非常实用的方法,麦子学院android开发老师 ...

最新文章

  1. Android 自定义View —— Path
  2. c mysql显示多条数据_用一条mysql语句插入多条数据
  3. Mac版 Android Studio Android Sdk 更新方式
  4. 初始化QChart极坐标图(含曲线、散点)
  5. maven项目配置定时任务
  6. 盘点物联网常用的八种通信协议
  7. javascript小游戏_个人网站集成js小游戏《圈小猫》教程及源码
  8. Vrep 中的运动规划1(主要是基于RRT算法)
  9. yum安装ruby_rediscluster安装
  10. Spark Streaming保存到HDFS目录中案例
  11. 数据可视化制作工具推荐
  12. 五个有用的过滤器 (转)
  13. mysql(一主从从)
  14. 斐讯K3刷官方root版
  15. 解剖一些外挂制作原理(DNF)
  16. php实现12306验证码,PHP仿12306点图验证码
  17. 拳皇重生服务器维护,《拳皇97 OL》3月10日更新维护公告
  18. Java之ip地址存储的数据类型
  19. 蘑菇街暑期实习生一面面经 大三
  20. openwrt 格式化_OPENWRT路由固件入门食用教程S2:磁盘挂载及分区,网络共享,脱机下载。...

热门文章

  1. Python 超简单爬取新浪微博数据
  2. 阿尔法狗怎么用机器学习做决策:马尔科夫链减少搜索空间说起(附PDF公号发“马链搜索”下载)...
  3. 痛惜!34岁研究生猝死!事发当天熬夜到凌晨两点半,生前称被延毕半年…
  4. 英语读书笔记-Book Lovers Day 08
  5. 互联网大厂开启智慧养猪,网友:以后可能没机会养猪了
  6. 7-19 支票面额 (15 分) 一个采购员去银行兑换一张y元f分的支票,结果出纳员错给了f元y分。采购员用去了n分之后才发觉有错,于是清点了余额尚有2y元2f分,问该支票面额是多少?
  7. 极速office2021(ppt)怎么修改页面布局
  8. 检测有人在用该台计算机怎么处理,我尝试在新计算机上注册IDM,但它显示有关在另一台计算机上使用它的警告消息。我该怎么办?...
  9. 科学界震惊,类人智人祖先的古老埋葬地点揭示人类进化之谜
  10. linux系统挂载u盘步骤和命令,如何在linux中挂载U盘/硬盘