喜欢另辟蹊径的我,在这里废话不多说了,直接上代码和图片了。

效果图如下:

第一步:MainActivity的代码如下:

package net.loonggg.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet; import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams; public class MainActivity extends Activity {
private HashMap<String, Integer> selector;// 存放含有索引字母的位置
private LinearLayout layoutIndex;
private ListView listView;
private TextView tv_show;
private ListViewAdapter adapter;
private String[] indexStr = { "#", "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 List<Person> persons = null;
private List<Person> newPersons = new ArrayList<Person>();
private int height;// 字体高度
private boolean flag = false; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 去标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
layoutIndex = (LinearLayout) this.findViewById(R.id.layout);
layoutIndex.setBackgroundColor(Color.parseColor("#00ffffff"));
listView = (ListView) findViewById(R.id.listView);
tv_show = (TextView) findViewById(R.id.tv);
tv_show.setVisibility(View.GONE);
setData();
String[] allNames = sortIndex(persons);
sortList(allNames); selector = new HashMap<String, Integer>();
for (int j = 0; j < indexStr.length; j++) {// 循环字母表,找出newPersons中对应字母的位置
for (int i = 0; i < newPersons.size(); i++) {
if (newPersons.get(i).getName().equals(indexStr[j])) {
selector.put(indexStr[j], i);
}
} }
adapter = new ListViewAdapter(this, newPersons);
listView.setAdapter(adapter);
} /**
* 重新排序获得一个新的List集合
*
* @param allNames
*/
private void sortList(String[] allNames) {
for (int i = 0; i < allNames.length; i++) {
if (allNames[i].length() != 1) {
for (int j = 0; j < persons.size(); j++) {
if (allNames[i].equals(persons.get(j).getPinYinName())) {
Person p = new Person(persons.get(j).getName(), persons
.get(j).getPinYinName());
newPersons.add(p);
}
}
} else {
newPersons.add(new Person(allNames[i]));
}
}
} @Override
public void onWindowFocusChanged(boolean hasFocus) {
// 在oncreate里面执行下面的代码没反应,因为oncreate里面得到的getHeight=0
if (!flag) {// 这里为什么要设置个flag进行标记,我这里不先告诉你们,请读者研究,因为这对你们以后的开发有好处
height = layoutIndex.getMeasuredHeight() / indexStr.length;
getIndexView();
flag = true;
}
} /**
* 获取排序后的新数据
*
* @param persons
* @return
*/
public String[] sortIndex(List<Person> persons) {
TreeSet<String> set = new TreeSet<String>();
// 获取初始化数据源中的首字母,添加到set中
for (Person person : persons) {
set.add(StringHelper.getPinYinHeadChar(person.getName()).substring(
0, 1));
}
// 新数组的长度为原数据加上set的大小
String[] names = new String[persons.size() + set.size()];
int i = 0;
for (String string : set) {
names[i] = string;
i++;
}
String[] pinYinNames = new String[persons.size()];
for (int j = 0; j < persons.size(); j++) {
persons.get(j).setPinYinName(
StringHelper
.getPingYin(persons.get(j).getName().toString()));
pinYinNames[j] = StringHelper.getPingYin(persons.get(j).getName()
.toString());
}
// 将原数据拷贝到新数据中
System.arraycopy(pinYinNames, 0, names, set.size(), pinYinNames.length);
// 自动按照首字母排序
Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);
return names;
} /**
* 绘制索引列表
*/
public void getIndexView() {
LinearLayout.LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT, height);
for (int i = 0; i < indexStr.length; i++) {
final TextView tv = new TextView(this);
tv.setLayoutParams(params);
tv.setText(indexStr[i]);
tv.setPadding(10, 0, 10, 0);
layoutIndex.addView(tv);
layoutIndex.setOnTouchListener(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
float y = event.getY();
int index = (int) (y / height);
if (index > -1 && index < indexStr.length) {// 防止越界
String key = indexStr[index];
if (selector.containsKey(key)) {
int pos = selector.get(key);
if (listView.getHeaderViewsCount() > 0) {// 防止ListView有标题栏,本例中没有。
listView.setSelectionFromTop(
pos + listView.getHeaderViewsCount(), 0);
} else {
listView.setSelectionFromTop(pos, 0);// 滑动到第一项
}
tv_show.setVisibility(View.VISIBLE);
tv_show.setText(indexStr[index]);
}
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
layoutIndex.setBackgroundColor(Color
.parseColor("#606060"));
break; case MotionEvent.ACTION_MOVE: break;
case MotionEvent.ACTION_UP:
layoutIndex.setBackgroundColor(Color
.parseColor("#00ffffff"));
tv_show.setVisibility(View.GONE);
break;
}
return true;
}
});
}
} /**
* 设置模拟数据
*/
private void setData() {
persons = new ArrayList<Person>();
Person p1 = new Person("耿琦");
persons.add(p1);
Person p2 = new Person("王宝强");
persons.add(p2);
Person p3 = new Person("柳岩");
persons.add(p3);
Person p4 = new Person("文章");
persons.add(p4);
Person p5 = new Person("马伊琍");
persons.add(p5);
Person p6 = new Person("李晨");
persons.add(p6);
Person p7 = new Person("张馨予");
persons.add(p7);
Person p8 = new Person("韩红");
persons.add(p8);
Person p9 = new Person("韩寒");
persons.add(p9);
Person p10 = new Person("丹丹");
persons.add(p10);
Person p11 = new Person("丹凤眼");
persons.add(p11);
Person p12 = new Person("哈哈");
persons.add(p12);
Person p13 = new Person("萌萌");
persons.add(p13);
Person p14 = new Person("蒙混");
persons.add(p14);
Person p15 = new Person("烟花");
persons.add(p15);
Person p16 = new Person("眼黑");
persons.add(p16);
Person p17 = new Person("许三多");
persons.add(p17);
Person p18 = new Person("程咬金");
persons.add(p18);
Person p19 = new Person("程哈哈");
persons.add(p19);
Person p20 = new Person("爱死你");
persons.add(p20);
Person p21 = new Person("阿莱");
persons.add(p21); } }

此Activity的布局文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical" > <TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="列表显示"
android:textColor="#000000"
android:textSize="16sp" /> <FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff" > <ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:fadingEdge="none"
android:scrollbars="none" >
</ListView> <TextView
android:id="@+id/tv"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:background="#f0606060"
android:gravity="center"
android:text="A"
android:textColor="#ffffff"
android:textSize="30sp" /> <LinearLayout
android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="right"
android:background="#d7d7d7"
android:gravity="center"
android:orientation="vertical" >
</LinearLayout>
</FrameLayout> </LinearLayout>

第二步:自定义了一个Adapter,代码如下:

package net.loonggg.test;

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 ListViewAdapter extends BaseAdapter {
private Context context;
private List<Person> list;
private ViewHolder viewHolder; public ListViewAdapter(Context context, List<Person> list) {
this.context = context;
this.list = list;
} @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public boolean isEnabled(int position) {
// TODO Auto-generated method stub
if (list.get(position).getName().length() == 1)// 如果是字母索引
return false;// 表示不能点击
return super.isEnabled(position);
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
String item = list.get(position).getName();
viewHolder = new ViewHolder();
if (item.length() == 1) {
convertView = LayoutInflater.from(context).inflate(R.layout.index,
null);
viewHolder.indexTv = (TextView) convertView
.findViewById(R.id.indexTv);
} else {
convertView = LayoutInflater.from(context).inflate(R.layout.item,
null);
viewHolder.itemTv = (TextView) convertView
.findViewById(R.id.itemTv);
}
if (item.length() == 1) {
viewHolder.indexTv.setText(list.get(position).getName());
} else {
viewHolder.itemTv.setText(list.get(position).getName());
}
return convertView;
} private class ViewHolder {
private TextView indexTv;
private TextView itemTv;
} }

第三步:用到的ListView中的子布局文件如下:

1、index.xml布局文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#9c9c9c"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingTop="5dp" > <TextView
android:id="@+id/indexTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#0f0f0f" /> </LinearLayout>

2、item.xml布局文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingLeft="20dp"
android:paddingTop="5dp" > <TextView
android:id="@+id/itemTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="20sp" /> </LinearLayout>

第四步:用到的实体类及工具类如下:

1、Person.java代码如下:

package net.loonggg.test;

public class Person {
private String name;
private String pinYinName; public Person(String name) {
super();
this.name = name;
} public Person(String name, String pinYinName) {
super();
this.name = name;
this.pinYinName = pinYinName;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPinYinName() {
return pinYinName;
} public void setPinYinName(String pinYinName) {
this.pinYinName = pinYinName;
} }

2、工具类代码如下:

package net.loonggg.test;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; public class StringHelper {
/**
* 得到 全拼
*
* @param src
* @return
*/
public static String getPingYin(String src) {
char[] t1 = null;
t1 = src.toCharArray();
String[] t2 = new String[t1.length];
HanyuPinyinOutputFormat t3 = new HanyuPinyinOutputFormat();
t3.setCaseType(HanyuPinyinCaseType.LOWERCASE);
t3.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
t3.setVCharType(HanyuPinyinVCharType.WITH_V);
String t4 = "";
int t0 = t1.length;
try {
for (int i = 0; i < t0; i++) {
// 判断是否为汉字字符
if (java.lang.Character.toString(t1[i]).matches(
"[\\u4E00-\\u9FA5]+")) {
t2 = PinyinHelper.toHanyuPinyinStringArray(t1[i], t3);
t4 += t2[0];
} else {
t4 += java.lang.Character.toString(t1[i]);
}
}
return t4;
} catch (BadHanyuPinyinOutputFormatCombination e1) {
e1.printStackTrace();
}
return t4;
} /**
* 得到首字母
*
* @param str
* @return
*/
public static String getHeadChar(String str) { String convert = "";
char word = str.charAt(0);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if (pinyinArray != null) {
convert += pinyinArray[0].charAt(0);
} else {
convert += word;
}
return convert.toUpperCase();
} /**
* 得到中文首字母缩写
*
* @param str
* @return
*/
public static String getPinYinHeadChar(String str) { String convert = "";
for (int j = 0; j < str.length(); j++) {
char word = str.charAt(j);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if (pinyinArray != null) {
convert += pinyinArray[0].charAt(0);
} else {
convert += word;
}
}
return convert.toUpperCase();
}
}

到这里就完事,非常简单吧!喜欢我就关注我哦!

Android学习笔记(三)之带有侧边索引的快速查找(跟带字母索引查找的通讯录差不多)的更多相关文章

  1. android学习笔记三

    GUI==>Graphics User Interface,图形用户界面. android UI 建立在View.ViewGroup基础上,采用组合器设计模式设计View和ViewGoup. V ...

  2. Android学习笔记三:用Intent串联activity

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7513399.html 一:Intent Intent可以理解为 意图. 我们可以通过创建intent实例来定义 ...

  3. android学习笔记三--Activity 布局

    1.线性布局 标签 :<LinearLayout></LinearLayout> 方向:android:orientation, 垂直:vertical 水平:Horizont ...

  4. Android学习笔记(三)

    ContentProvider简单介绍 ContentProvider是不同应用程序之间进行数据交换的标准API,当一个应用程序须要把自己的数据暴露给其它程序使用时.该应用程序便可通过提供Conten ...

  5. 【转】Pro Android学习笔记(三):了解Android资源(上)

    在Android开发中,资源包括文件或者值,它们和执行应用捆绑,无需在源代码中写死,因此我们可以改变或替换他们,而无需对应用重新编译. 了解资源构成 参考阅读Android学习笔记(三八):资源res ...

  6. 【转】Pro Android学习笔记(三十):Menu(1):了解Menu

    目录(?)[-] 创建Menu MenuItem的属性itemId MenuItem的属性groupId MenuItem的属性orderId MenuItem的属性可选属性 Menu触发 onOpt ...

  7. 【转】 Pro Android学习笔记(五六):配置变化

    目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...

  8. 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...

  9. 【转】 Pro Android学习笔记(七八):服务(3):远程服务:AIDL文件

    目录(?)[-] 在AIDL中定义服务接口 根据AIDL文件自动生成接口代码 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.n ...

随机推荐

  1. 做php网站后台开发,在Linux系统上进行更好吗?【转载】

    1. PHP是开源软件,它在bsd/linux/win下都有很好的正式版及孪生版.并非开发php就必须要在linux下进行.主机服务商们习惯性的把asp与php分为两个主机系列几进行销售.由于asp只 ...

  2. jsonpath for js

    /** * @license * JSONPath 0.8.0 - XPath for JSON * * Copyright (c) 2007 Stefan Goessner (goessner.ne ...

  3. 如何去除decimal后面的零?

    如何去除decimal后面的零? 1.260000m.ToString("G29") 不显示科学记数法? decimal.Parse("0.0000001",S ...

  4. CircleIndicator

    dependencies { compile 'com.nineoldandroids:library:2.4.+' compile 'me.relex:circleindicator:1.0.0@a ...

  5. [VBA]批量替换PPT里的字体颜色

    不知道为什么计组老师的大量课件字体是伤害视力的亮蓝色……看久了眼睛疼,想把颜色替换成保护视力一点的灰色,但是找了N久也没找到在图形界面上直接操作的方法,于是在MSDN上晃了晃,Google了一下,写了 ...

  6. 面试题15:链表中倒数第K个节点

    类似问题:判断是否是环形节点,寻找中间节点,一个指针一次走一步,另一个指针一次走两步 注意检查三点鲁棒性: 1. 链表为空 2. k为0 3. 链表长度不够k ListNode* FindKthToT ...

  7. 三年.NET即将转Java,我该何去何从

    2014年5月,大三报了某培训班5个月学习.NET 2014年12月-2015年6月,在某软件公司实习,用ASP.NET开发企业级系统 2015年7月-2017年3月,从毕业生到成为该公司的主要开发人 ...

  8. bzoj 1853 容斥 + 搜索

    思路:先把所有幸运数字找出来, 把没有用的去掉,然后爆搜容斥,因为最多只会搜十几个就超过限制了, 所以是可行的. #include<bits/stdc++.h> #define LL lo ...

  9. Codeforces Round #496 (Div. 3) F - Berland and the Shortest Paths

    F - Berland and the Shortest Paths 思路:还是很好想的,处理出来最短路径图,然后搜k个就好啦. #include<bits/stdc++.h> #defi ...

  10. 创建数据模型(View Models )和监控属性(Observables)

    Knockout是建立在以下3个核心功能之上的: 1. 属性监控与依赖跟踪 2. 声明式绑定 3. 模版机制 在本节中,我们将学习3个核心里面的第一个.但在这之前,先让我们学习一下MVVM设计模式和V ...