先看看图片效果,我的是来源于网上资料的改进,希望帮助对这方面有需要的的朋友
直接上图上代码,就不解释了,最底部有代码下载链接,想要的童鞋就去下吧
下载地址:http://download.csdn.net/detail/touchsnow/5349469
实现的功能:混合字符串处理 中英文排序 右侧悬浮栏 顶部名称提示栏 滚动悬浮提示
一 右侧字母表工具
package com.zuo.quickaction;
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;
/**
* 右侧字母表,快速定位
*
* @author zuo
* @email [email protected]
*/
public class QuickLocationRightTool extends View
{
private String[] b = null;
public void setB(String[] b)
{
this.b = b;
}
OnTouchingLetterChangedListener onTouchingLetterChangedListener;
int choose = -1;
Paint paint = new Paint();
boolean showBkg = false;
public QuickLocationRightTool(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public QuickLocationRightTool(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public QuickLocationRightTool(Context context)
{
super(context);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (showBkg) {
canvas.drawColor(Color.parseColor("#10000000"));
}
int height = getHeight();
int width = getWidth();
int singleHeight = height / b.length;
for (int i = 0; i < b.length; i++) {
paint.setColor(Color.BLACK);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
if (i == choose) {
paint.setColor(Color.parseColor("#3399ff"));
paint.setFakeBoldText(true);
}
float xPos = width / 2 - paint.measureText(b[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(b[i], xPos, yPos, paint);
paint.reset();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
final int action = event.getAction();
final float y = event.getY();
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * b.length); //字母位置
switch (action) {
case MotionEvent.ACTION_DOWN:
showBkg = true;
if (oldChoose != c && listener != null) {
if (c > 0 && c <= b.length) { //如果第一个字母是#,无效点击的话,条件变为c>0
listener.onTouchingLetterChanged(b[c]);
choose = c; //处理重复
invalidate();
}
}
break;
case MotionEvent.ACTION_MOVE:
if (oldChoose != c && listener != null) {
if (c > 0 && c <= b.length) { //如果第一个字母是#,无效点击的话,条件变为c>0
listener.onTouchingLetterChanged(b[c]);
choose = c;
invalidate();
}
}
break;
case MotionEvent.ACTION_UP:
showBkg = false;
choose = -1;
invalidate();
break;
}
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
return super.onTouchEvent(event);
}
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener)
{
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
public interface OnTouchingLetterChangedListener
{
public void onTouchingLetterChanged(String s);
}
}
二 分组排序的列表适配器
package com.zuo.quickaction;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author zuo
* 列表适配器
*/
public class QuickLocationListAdapter extends BaseAdapter
{
private LayoutInflater layoutInflater;
private OnClickListener onClickListener;
private String[] stringArr;
private Map map = new HashMap();
public QuickLocationListAdapter(Context context, String[] arr, OnClickListener listener, Map map)
{
layoutInflater = LayoutInflater.from(context);
this.onClickListener = listener;
stringArr = arr;
this.map = map;
}
public int getCount()
{
return stringArr == null ? 0 : stringArr.length;
}
public Object getItem(int position)
{
if (stringArr != null) {
String string = map.get(stringArr[position]);
return string;
}
return null;
}
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.firstCharHintTextView = (TextView) convertView
.findViewById(R.id.text_first_char_hint);
holder.nameTextView = (TextView) convertView.findViewById(R.id.text_website_name);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.nameTextView.setText(map.get(stringArr[position]));
int idx = position - 1;
char previewChar = idx >= 0 ? stringArr[idx].charAt(0) : ' '; //前一个字符
char currentChar = stringArr[position].charAt(0); //当前字符
if (currentChar != previewChar) { //如果不相等时显示
if (isWord(currentChar)) {
if (position != 0) {
holder.firstCharHintTextView.setVisibility(View.VISIBLE);
}
else {
holder.firstCharHintTextView.setVisibility(View.GONE);
}
holder.firstCharHintTextView.setText(String.valueOf(currentChar));
}
else {
if (isWord(previewChar)) {
holder.firstCharHintTextView.setVisibility(View.VISIBLE);
holder.firstCharHintTextView.setText("*");
}
else {
holder.firstCharHintTextView.setVisibility(View.GONE);
}
}
}
else {
holder.firstCharHintTextView.setVisibility(View.GONE);
}
return convertView;
}
public final class ViewHolder
{
public TextView firstCharHintTextView;
public TextView nameTextView;
}
public boolean isWord(char c)
{
Pattern pattern = Pattern.compile("^[A-Za-z]+$");
Matcher isNum = pattern.matcher(String.valueOf(c));
if (!isNum.matches()) {
return false;
}
else {
return true;
}
}
}
三 主函数
package com.zuo.quickaction;
import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.*;
import android.widget.AdapterView.OnItemClickListener;
import com.zuo.quickaction.QuickLocationRightTool.OnTouchingLetterChangedListener;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author zuowen
* @time 2013.05.08
* @email [email protected]
*
* 混合字符串处理 中英文排序 右侧悬浮栏 顶部名称提示栏 滚动悬浮提示
*/
public class QuickLocationMainActivity extends Activity implements ListView.OnScrollListener,
OnItemClickListener, android.view.View.OnClickListener
{
private QuickLocationRightTool letterListView;
private Handler handler;
private DisapearThread disapearThread;
private int scrollState;
private QuickLocationListAdapter quickLocationListAdapter;
private ListView listMain;
private TextView txtOverlay, title;
private WindowManager windowManager;
private String[] stringArr = {"ai", "zuo", "wn", "g黄真伊", "he河智苑", "@", "&&*(*", "한국 친구를 찾아요", "?", "擬好",
"上饶", "厦门", "深圳", "武林", "text1", "+*())*&%$^", "11112", "6666", "898和",
"阿拉伯", "阿镇", "下午", "责打", "浙江", "浙江", "阿布", "北京", "北城", "成", "城市", "123a", "234b", "678c", "得", "额",
"方", "搞", "广州", "黄石", "黄冈", "杭州", "上海", "武林"};
private String[] stringArr3 = new String[0];
private ArrayList arrayList = new ArrayList();
private ArrayList arrayList2 = new ArrayList();
private ArrayList arrayList3 = new ArrayList();
private Map map = new HashMap();
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
for (int i = 0; i < stringArr.length; i++) {
String pinyin = converterToPinYin(stringArr[i]);
arrayList.add(pinyin); //此列表增加拼音
Collections.sort(arrayList, new MixComparator());
if (!arrayList2.contains(pinyin.substring(0, 1)) && isWord(pinyin.substring(0, 1))) {
arrayList2.add(pinyin.substring(0, 1)); //此列表添加拼音首字母
Collections.sort(arrayList2, new MixComparator());
}
map.put(pinyin, stringArr[i]);
}
stringArr = (String[]) arrayList.toArray(stringArr);
arrayList3.add("#"); //此列表添加不规则字符
for (int i = 0; i < arrayList2.size(); i++) {
String string = (String) arrayList2.get(i);
arrayList3.add(string.toUpperCase()); //toUpperCase大写字母
}
arrayList3.add("*");
stringArr3 = (String[]) arrayList3.toArray(stringArr3); // 得到右侧英文字母列表
letterListView = (QuickLocationRightTool) findViewById(R.id.rightCharacterListView);
letterListView.setB(stringArr3);
letterListView.setOnTouchingLetterChangedListener(new LetterListViewListener());
textOverlayout();
// 初始化ListAdapter
quickLocationListAdapter = new QuickLocationListAdapter(this, stringArr, this, null);
listMain = (ListView) findViewById(R.id.listInfo);
listMain.setOnItemClickListener(this);
listMain.setOnScrollListener(this);
listMain.setAdapter(quickLocationListAdapter);
disapearThread = new DisapearThread();
}
/**
* 滚到悬浮字母
*/
public void textOverlayout()
{
handler = new Handler();
//顶部悬浮
title = (TextView) findViewById(R.id.list_title);
// 初始化首字母悬浮提示框
txtOverlay = (TextView) LayoutInflater.from(this).inflate(
R.layout.popup_char, null);
txtOverlay.setVisibility(View.INVISIBLE);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
windowManager.addView(txtOverlay, lp);
}
/**
* 右侧导航条点击列表滚动指定位置
*/
public class LetterListViewListener implements
OnTouchingLetterChangedListener
{
public void onTouchingLetterChanged(final String s)
{
int num = 0;
for (int i = 0; i < stringArr.length; i++) {
if ("a".equals(s) || "#".equals(s)) { //顶部
num = 0;
}
else if ("*".equals(s)) { //底部
num = stringArr.length;
}
else if (isWord(stringArr[i].substring(0, 1)) && (character2ASCII(stringArr[i].substring(0, 1)) < (character2ASCII(s) + 32))) {
num += 1; //首先判断是字母,字母的ascll值小于s是,滚动位置+1;如果有10个数据小于s,就滚到10处
}
}
if (num < 2) {
listMain.setSelectionFromTop(num, 0);
}
else {
listMain.setSelectionFromTop(num, 5); //留点间隔
}
}
}
/**
* 滚动处理
* @param view
* @param firstVisibleItem
* @param visibleItemCount
* @param totalItemCount
*/
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount)
{
title.setVisibility(View.VISIBLE);
if (firstVisibleItem != 0) {
title.setText(map.get(stringArr[firstVisibleItem]));
}
else {
title.setText("a");
}
title.setText(map.get(stringArr[firstVisibleItem]));
txtOverlay.setText(String.valueOf(stringArr[firstVisibleItem].charAt(0)));// 泡泡文字以第一个可见列表为准
}
public void onScrollStateChanged(AbsListView view, int scrollState)
{
this.scrollState = scrollState;
if (scrollState == ListView.OnScrollListener.SCROLL_STATE_IDLE) {
handler.removeCallbacks(disapearThread);
// 提示延迟1.0s再消失
boolean bool = handler.postDelayed(disapearThread, 1000);
}
else {
txtOverlay.setVisibility(View.VISIBLE);
}
}
/**
* 列表点击
* @param parent
* @param view
* @param position
* @param id
*/
public void onItemClick(AdapterView> parent, View view, int position,
long id)
{
String personalName = map.get(stringArr[position]);
Toast.makeText(QuickLocationMainActivity.this, personalName, 1).show();
}
public void onClick(View view)
{
}
private class DisapearThread implements Runnable
{
public void run()
{
// 避免在1.5s内,用户再次拖动时提示框又执行隐藏命令。
if (scrollState == ListView.OnScrollListener.SCROLL_STATE_IDLE) {
txtOverlay.setVisibility(View.INVISIBLE);
}
}
}
public void onDestroy()
{
super.onDestroy();
txtOverlay.setVisibility(View.INVISIBLE);
title.setVisibility(View.INVISIBLE);
windowManager.removeView(txtOverlay);
}
/**
* 汉语拼音转换工具
*
* @param chinese
* @return
*/
public String converterToPinYin(String chinese)
{
String pinyinString = "";
char[] charArray = chinese.toCharArray();
// 根据需要定制输出格式,我用默认的即可
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
try {
// 遍历数组,ASC码大于128进行转换
for (int i = 0; i < charArray.length; i++) {
if (charArray[i] > 128) {
// charAt(0)取出首字母
if (charArray[i] >= 0x4e00 && charArray[i] <= 0x9fa5) { //判断是否中文
pinyinString += PinyinHelper.toHanyuPinyinStringArray(
charArray[i], defaultFormat)[0].charAt(0);
}
else { //不是中文的打上未知,所以无法处理韩文日本等等其他文字
pinyinString += "?";
}
}
else {
pinyinString += charArray[i];
}
}
return pinyinString;
}
catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
return null;
}
}
/**
* 把单个英文字母或者字符串转换成数字ASCII码
*
* @param input
* @return
*/
public static int character2ASCII(String input)
{
char[] temp = input.toCharArray();
StringBuilder builder = new StringBuilder();
for (char each : temp) {
builder.append((int) each);
}
String result = builder.toString();
return Integer.parseInt(result);
}
/**
* 混合排序工具
*/
public class MixComparator implements Comparator
{
public int compare(String o1, String o2)
{
// 判断是否为空""
if (isEmpty(o1) && isEmpty(o2))
return 0;
if (isEmpty(o1))
return -1;
if (isEmpty(o2))
return 1;
String str1 = "";
String str2 = "";
try {
str1 = (o1.toUpperCase()).substring(0, 1);
str2 = (o2.toUpperCase()).substring(0, 1);
}
catch (Exception e) {
System.out.println("某个str为\" \" 空");
}
if (isWord(str1) && isWord(str2)) { //字母
return str1.compareTo(str2);
}
else if (isNumeric(str1) && isWord(str2)) { //数字字母
return 1;
}
else if (isNumeric(str2) && isWord(str1)) {
return -1;
}
else if (isNumeric(str1) && isNumeric(str2)) { //数字数字
if (Integer.parseInt(str1) > Integer.parseInt(str2)) {
return 1;
}
else {
return -1;
}
}
else if (isAllWord(str1) && (!isAllWord(str2))) { //数字字母 其他字符
return -1;
}
else if ((!isAllWord(str1)) && isWord(str2)) {
return 1;
}
else {
return 1;
}
}
}
/**
* 判断空
*
* @param str
* @return
*/
private boolean isEmpty(String str)
{
return "".equals(str.trim());
}
/**
* 判断数字
*
* @param str
* @return
*/
public boolean isNumeric(String str)
{
Pattern pattern = Pattern.compile("^[0-9]*$");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
else {
return true;
}
}
/**
* 判读字母
*
* @param str
* @return
*/
public boolean isWord(String str)
{
Pattern pattern = Pattern.compile("^[A-Za-z]+$");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
else {
return true;
}
}
/**
* 判断字母数字混合
*
* @param str
* @return
*/
public boolean isAllWord(String str)
{
Pattern pattern = Pattern.compile("^[A-Za-z0-9]+$");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
else {
return true;
}
}
}
四 xml文件
list_item.xml
main.xml