您的位置:首页 > 其它

模仿通讯录按字母分类显示,汉字,英文自动按英文字母分类显示,滑动时用气泡显示最上面的汉字首字母提示,右侧字母栏点击快速定位

2012-06-05 11:20 531 查看
废话不多说,先上图。




本Demo实现了如下功能:

1.根据汉字首字母,自动按英文字母分类显示。

2.滑动时,泡泡显示最上面的汉字首字母提示。

3.右侧字母栏点击快速定位,方便多数据的查找定位。

不足之处:

1.汉字转化得到拼音首字母的时候,我用到了一个pinyin4j-2.5.0.jar包,多音字和某些特殊汉字翻译不准确,如:我发现厦门,它会翻译成shamen,结果首字母变成了s。

结果我只好特殊处理了,朋友们有好的解决办法的话麻烦分享一下。

好了,废话不说了,上代码,总共3.java文件和3个配置文件。

(1)Main.java

package com.lmj.quickaction;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Map;

import com.lmj.quickaction.RightCharacterListView.OnTouchingLetterChangedListener;

import net.sourceforge.pinyin4j.PinyinHelper;

import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;

import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import android.app.Activity;

import android.content.Context;

import android.graphics.PixelFormat;

import android.os.Bundle;

import android.os.Handler;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup.LayoutParams;

import android.view.WindowManager;

import android.widget.AbsListView;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.Toast;

/**

* @author lmj

*/

public class Main extends Activity implements ListView.OnScrollListener,

OnItemClickListener, android.view.View.OnClickListener {

private RightCharacterListView letterListView;

private Handler handler;

private DisapearThread disapearThread;

private int scrollState;

private ListAdapter listAdapter;

private ListView listMain;

private TextView txtOverlay;

private WindowManager windowManager;

private String[] stringArr = { "阿拉伯", "阿镇", "阿布", "北京", "北城", "成", "城市",

"得", "额", "方", "搞", "广州", "黄石", "黄冈", "杭州", "上海", "上饶", "厦门", "深圳",

"武林", "武林", "武林", "武林", "武林", "武林", "武林", "武林", "武林", "武林", "武林",

"武林", "武林", "武林", "武林", "武汉", "下午", "责打", "浙江", "浙江", "浙江", "浙江",

"浙江", "浙江", "浙江", "浙江", "浙江", "浙江", "浙江", "浙江", "浙江", "浙江", "浙江",

"浙江", "浙江", "浙江", "浙江", "浙江", "浙江" };

private String[] stringArr3 = new String[0];

private ArrayList arrayList = new ArrayList();

private ArrayList arrayList2 = new ArrayList();

private ArrayList arrayList3 = new ArrayList();

private Map<String, String> map = new HashMap<String, String>();

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)取出首字母

pinyinString += PinyinHelper.toHanyuPinyinStringArray(

charArray[i], defaultFormat)[0].charAt(0);

} else {

pinyinString += charArray[i];

}

}

return pinyinString;

} catch (BadHanyuPinyinOutputFormatCombination e) {

e.printStackTrace();

return null;

}

}

public class LetterListViewListener implements

OnTouchingLetterChangedListener {

@Override

public void onTouchingLetterChanged(final String s) {

Toast.makeText(Main.this, s, Toast.LENGTH_LONG).show();

int num = 0;

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

if ("a".equals(s)) {

num = 0;

} else if (character2ASCII(stringArr[i].substring(0, 1)) < (character2ASCII(s) + 32)) {

num += 1;

}

}

listMain.setSelectionFromTop(num, 0);

// .setSelection(num);

}

}

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);

if (!arrayList2.contains(pinyin.substring(0, 1))) {

arrayList2.add(pinyin.substring(0, 1));

}

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());

}

stringArr3 = (String[]) arrayList3.toArray(stringArr3);// 得到右侧英文字母列表

letterListView = (RightCharacterListView) findViewById(R.id.rightCharacterListView);

String[] b = { "#", "A", "B", "C", "D", "E", "F", "G", "H", "S", "W",

"X", "Z" };

letterListView.setB(stringArr3);

letterListView

.setOnTouchingLetterChangedListener(new LetterListViewListener());

handler = new Handler();

// 初始化首字母悬浮提示框

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);

// 初始化ListAdapter

listAdapter = new ListAdapter(this, stringArr, this, map);

listMain = (ListView) findViewById(R.id.listInfo);

listMain.setOnItemClickListener(this);

listMain.setOnScrollListener(this);

listMain.setAdapter(listAdapter);

disapearThread = new DisapearThread();

}

public void onScroll(AbsListView view, int firstVisibleItem,

int visibleItemCount, int totalItemCount) {

// txtOverlay.setText(String.valueOf(stringArr[firstVisibleItem +

// (visibleItemCount >> 1)]

// .charAt(0)));//泡泡文字以中间的显示为准

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.5s再消失

boolean bool = handler.postDelayed(disapearThread, 1500);

} else {

txtOverlay.setVisibility(View.VISIBLE);

}

}

public void onItemClick(AdapterView<?> parent, View view, int position,

long id) {

// String personalName = stringArr[position];

String personalName = map.get(stringArr[position]);

}

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删除。

txtOverlay.setVisibility(View.INVISIBLE);

windowManager.removeView(txtOverlay);

}

/**

* 把单个英文字母或者字符串转换成数字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);

}

}



(2)ListAdapter,列表适配器

package com.lmj.quickaction;

import java.util.HashMap;

import java.util.Map;

import android.content.Context;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ImageView;

import android.widget.TextView;

/**

* @author lmj

* 列表适配器

*/

public class ListAdapter extends BaseAdapter {

private LayoutInflater layoutInflater;

private OnClickListener onClickListener;

private String[] stringArr;

private Map<String, String> map = new HashMap<String, String>();

public ListAdapter(Context context, String[] arr, OnClickListener listener,Map<String, String> 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) {



Log.d("position", position+"--->"+stringArr[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) {

holder.firstCharHintTextView.setVisibility(View.VISIBLE);

holder.firstCharHintTextView.setText(String.valueOf(currentChar));

} else {

//实例化一个CurrentView后,会被多次赋值并且只有最后一次赋值的position是正确

holder.firstCharHintTextView.setVisibility(View.GONE);

}

return convertView;

}

public final class ViewHolder {

public TextView firstCharHintTextView;

public TextView nameTextView;

}

}

(3)RightCharacterListView,右侧字母表,快速定位

package com.lmj.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 lmj

*

*/

public class RightCharacterListView extends View {

private String[] b = null;

public void setB(String[] b) {

this.b = b;

}

OnTouchingLetterChangedListener onTouchingLetterChangedListener;

// String[] b = {"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" };



// String[] b = {"A", "B", "C", "D", "E", "F", "G", "H", "S", "W", "X",

// "Z" };

int choose = -1;

Paint paint = new Paint();

boolean showBkg = false;

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

super(context, attrs, defStyle);

}

public RightCharacterListView(Context context, AttributeSet attrs) {

super(context, attrs);

}

public RightCharacterListView(Context context) {

super(context);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if (showBkg) {

canvas.drawColor(Color.parseColor("#40000000"));

}

int height = getHeight();

int width = getWidth();

int singleHeight = height / b.length;

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

paint.setColor(Color.WHITE);

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);

}

}

(4)main.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<ListView android:id="@+id/listInfo"

android:focusable="true"

android:layout_weight="1.0"

android:layout_height="wrap_content"

android:layout_width="fill_parent"

android:fastScrollEnabled="true"

android:cacheColorHint="#00000000"

android:background="@drawable/background"

>

</ListView>



<com.lmj.quickaction.RightCharacterListView

android:id="@+id/rightCharacterListView"

android:background="#40000000"

android:layout_width="30dip"

android:layout_height="fill_parent"

android:layout_alignParentRight="true" />



</RelativeLayout>

(5)list_item.xml<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:id="@+id/list_item_parent_layout"

>

<TextView android:id="@+id/text_first_char_hint"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textSize="@dimen/list_first_char_hint_text_size"

android:background="@color/char_color"

android:textColor="@*android:color/dim_foreground_light"

android:paddingLeft="@dimen/list_item_first_char_padding"

android:visibility="gone">

</TextView>



<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="horizontal"

android:layout_width="fill_parent"

android:layout_height="wrap_content">

<LinearLayout

android:orientation="vertical"

android:layout_width="wrap_content"

android:layout_height="fill_parent"

android:layout_weight="1">

<TextView android:id="@+id/text_website_name"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textColor="@android:color/white"

android:textSize="@dimen/list_item_name_size"

android:singleLine="true"

android:ellipsize="marquee"

></TextView>

</LinearLayout>

<View android:id="@+id/divider"

android:background="@*android:color/dim_foreground_dark"

android:focusable="false"

android:clickable="false"

android:longClickable="false"

android:layout_marginTop="@dimen/list_item_divider_margin"

android:layout_marginBottom="@dimen/list_item_divider_margin"

android:layout_width="1dp"

android:layout_height="fill_parent"

android:gravity="center_vertical"

></View>

</LinearLayout>

</LinearLayout>

(6)popup_char.xml

<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"

android:textSize="@dimen/popup_char_min_length"

android:textColor="@android:color/white"

android:background="@color/popup_char_color"

android:minWidth="@dimen/popup_char_min_length"

android:maxWidth="@dimen/popup_char_min_length"

android:gravity="center"

/>

(7)dimension.xml,资源文件

<?xml version="1.0" encoding="UTF-8"?>

<resources>

<dimen name="list_first_char_hint_text_size">15sp</dimen>

<dimen name="list_item_order_number_size">30sp</dimen>

<dimen name="list_item_first_view_right_margin">30sp</dimen>

<dimen name="list_item_first_char_padding">10dip</dimen>

<dimen name="list_item_name_size">25sp</dimen>

<dimen name="list_item_divider_margin">5dip</dimen>

<dimen name="list_item_icon_length">50sp</dimen>

<dimen name="popup_char_min_length">70dip</dimen>

</resources>

还有string.xml和color.xml就不贴了,也就几个,缺啥就补啥。

好了,今天就到这吧,朋友们有啥问题的给我留言,只要我能解决的,一定告诉大家。

以为写个博客就10分钟的事情,实际上我用了一个小时,oh,My God!!

不过要是有人能用的上,我的时间也算是有所值了,呵呵。

有问题欢迎讨论,还望各位口下留情。

忘了,还缺了个图片:


和第三方jar包pinyin4j-2.5.0,jar包自己下吧,呵呵。



源码下载:http://download.csdn.net/detail/nicholas6lee/4355391
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐