字母条索引定位

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

    <com.atguigu.quickindex.QuickIndexBar
        android:id="@+id/qucikIndexBar"
        android:layout_width="35dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:background="#CFCFCF" />

    <TextView
        android:id="@+id/currentIndex"
        android:layout_width="120dp"
        android:layout_height="105dp"
        android:layout_centerInParent="true"
        android:background="@drawable/bg_index"
        android:gravity="center"
        android:text="A"
        android:textColor="#ffffff"
        android:textSize="30sp"
        android:visibility="gone" />
</RelativeLayout>

item_friend.xml

<?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="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/index"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:paddingLeft="10dp"
        android:text="A"
        android:textColor="#ffffff"
        android:background="#666666"
        android:textSize="18sp"/>
    <TextView
        android:id="@+id/name"
        android:layout_height="wrap_content"
       	android:layout_width="match_parent"
       	android:padding="10dp"
        android:text="adasd"
        android:textColor="#666666"
        android:textSize="20sp"/>
</LinearLayout>

MainActivity

package com.atguigu.quickindex;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.atguigu.quickindex.QuickIndexBar.OnTouchIndexChange;

public class MainActivity extends Activity {

	private ListView listView;
	private QuickIndexBar qucikIndexBar;
	private TextView currentIndex;
	// 数据集合
	private List<Friend> friends = new ArrayList<Friend>();
	// 适配器
	private FriendAdapter adapter;
	private Handler handler = new Handler();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 加载主布局
		setContentView(R.layout.activity_main);
		// 初始化控件
		init();
	}

	private void init() {
		/** 初始化布局视图 */
		listView = (ListView) findViewById(R.id.listview);
		qucikIndexBar = (QuickIndexBar) findViewById(R.id.qucikIndexBar);
		currentIndex = (TextView) findViewById(R.id.currentIndex);
		/** 初始化数据 */
		initData();
		// 创建适配器
		adapter = new FriendAdapter();
		// 设置适配器
		listView.setAdapter(adapter);

		// 设置触摸的字母变化的监听
		qucikIndexBar.setOnTouchIndexChange(new OnTouchIndexChange() {
			@Override
			public void onChange(String word) {// word为当前触摸的字母
				// 显示当前触摸的字母
				showInexWord(word);
				// 使用列表定位到对应的列表项
				locationWord(word);
			}
		});
	}

	private void locationWord(String word) {
		for (int i = 0; i < friends.size(); i++) {
			//名字首字母
			String firstWord = friends.get(i).getPinyin().charAt(0) + "";
			if (firstWord.equals(word)) {
				//定位到item的位置
				listView.setSelection(i);
				return;
			}
		}
	}

	private void showInexWord(String word) {
		currentIndex.setVisibility(View.VISIBLE);
		currentIndex.setText(word);
		//停掉所用handler的消息,防止内存泄露
		handler.removeCallbacksAndMessages(null);
		//2秒的定时器
		handler.postDelayed(new Runnable() {
			@Override
			public void run() {
				currentIndex.setVisibility(View.GONE);
			}
		}, 2000);
	}

	private void initData() {
		// 虚拟数据
		friends.add(new Friend("张晓飞"));
		friends.add(new Friend("杨光福"));
		friends.add(new Friend("胡继群"));
		friends.add(new Friend("刘畅"));

		friends.add(new Friend("钟泽兴"));
		friends.add(new Friend("尹革新"));
		friends.add(new Friend("安传鑫"));
		friends.add(new Friend("张骞壬"));

		friends.add(new Friend("温松"));
		friends.add(new Friend("李凤秋"));
		friends.add(new Friend("刘甫"));
		friends.add(new Friend("娄全超"));
		friends.add(new Friend("张猛"));

		friends.add(new Friend("王英杰"));
		friends.add(new Friend("李振南"));
		friends.add(new Friend("孙仁政"));
		friends.add(new Friend("唐春雷"));
		friends.add(new Friend("牛鹏伟"));
		friends.add(new Friend("姜宇航"));

		friends.add(new Friend("刘挺"));
		friends.add(new Friend("张洪瑞"));
		friends.add(new Friend("张建忠"));
		friends.add(new Friend("侯亚帅"));
		friends.add(new Friend("刘帅"));

		friends.add(new Friend("乔竞飞"));
		friends.add(new Friend("徐雨健"));
		friends.add(new Friend("吴亮"));
		friends.add(new Friend("王兆霖"));

		friends.add(new Friend("阿三"));
		friends.add(new Friend("二毛"));

		/**
		 * Comparable。可以让自定义对象实现一个Comparable接口,这个接口只有一个方法comparableTo(Object o)
		 *
		 * 其规则是当前对象与o对象进行比较,返回一个int值,系统根据此值进行排序。
		 *
		 * 如当前对象>o对象,则返回值>0;
		 *
		 * 如当前对象=o对象,则返回值=0;
		 *
		 * 如当前对象<o对象,则返回值<0;
		 */
		Collections.sort(friends);
	}

	/**
	 * adapter
	 */
	class FriendAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			return friends.size();
		}

		@Override
		public Object getItem(int position) {
			return friends.get(position);
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder = null;
			if (convertView == null) {
				convertView = View.inflate(getApplicationContext(),
						R.layout.item_friend, null);
				holder = new ViewHolder();
				holder.index = (TextView) convertView.findViewById(R.id.index);
				holder.name = (TextView) convertView.findViewById(R.id.name);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			Friend friend = friends.get(position);
			String firstWord = friend.getPinyin().charAt(0) + "";// 得到拼音首字母

			if (position == 0) {// 如果是第一个, 显示首字母View
				holder.index.setVisibility(View.VISIBLE);
			} else {// 如果不是第一个
				// 上一项的拼音首字母
				String preFirstWord = friends.get(position - 1).getPinyin()
						.charAt(0)
						+ "";
				if (firstWord.equals(preFirstWord)) {// 如果当前的与上一个相同, 不显示首字母View
					holder.index.setVisibility(View.GONE);
				} else {// 否则, 显示
					holder.index.setVisibility(View.VISIBLE);
				}
			}

			holder.index.setText(firstWord);
			holder.name.setText(friend.getName());

			return convertView;
		}

		class ViewHolder {
			TextView index, name;
		}
	}
}

QuickIndexBar

package com.atguigu.quickindex;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * 自定义快速索引的View
 */
public class QuickIndexBar extends View {

	public QuickIndexBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 初始化paint
		paint = new Paint();
		paint.setAntiAlias(true);// 抗据齿
	}

	private Paint paint;

	// 字母的宽、高
	private int cellWidth;
	private int cellHeight;
	private int touchIndex = -1;
	// 字体选中、非选中大小
	private int textSize;
	private int textTouchSize;

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

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		cellWidth = this.getMeasuredWidth();
		cellHeight = this.getMeasuredHeight() / indexArr.length;

		textSize = cellHeight - 5;
		textTouchSize = cellHeight + 5;
	}

	@SuppressLint("DrawAllocation")
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		for (int i = 0; i < indexArr.length; i++) {
			// 字母的字体大小
			paint.setTextSize(i == touchIndex ? textTouchSize : textSize);
			// 字母的字体颜色
			paint.setColor(i == touchIndex ? Color.parseColor("#666666")
					: Color.WHITE);
			// 计算字母显示的宽高
			Rect bounds = new Rect();
			//paint.getTextBounds(str, 0, str.length(), rect);
			paint.getTextBounds(indexArr[i], 0, 1, bounds);
			int width = bounds.width();
			int height = bounds.height();
			// 计算字母绘制的坐标
			float x = cellWidth / 2 - width / 2;
			float y = i * cellHeight + cellHeight / 2 + height / 2;
			// 绘制字母文本
			canvas.drawText(indexArr[i], x, y, paint);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		// 相对于当前View的事件y坐标
		int y = (int) event.getY();

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
		case MotionEvent.ACTION_MOVE:
			// 如果没有在当前字母的区域内, 就需要更新touchIndex, 并重绘
			int index = y / cellHeight;
			if (index != touchIndex) {
				touchIndex = index;
				if (touchIndex >= indexArr.length)
					touchIndex = indexArr.length - 1;
				// 强制重绘
				invalidate();
				// 如果有监听器, 调用监听器的回调方法
				if (onTouchIndexChange != null) {
					onTouchIndexChange.onChange(indexArr[touchIndex]);
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			touchIndex = -1;
			// 强制重绘
			invalidate();
			break;
		default:
			break;
		}
		return true;
	}

	private OnTouchIndexChange onTouchIndexChange;

	public void setOnTouchIndexChange(OnTouchIndexChange onTouchIndexChange) {
		this.onTouchIndexChange = onTouchIndexChange;
	}

	public interface OnTouchIndexChange {
		public void onChange(String word);
	}
}

Friend

package com.atguigu.quickindex;

/**
 * 好友信息对象
 */
public class Friend implements Comparable<Friend> {

	private String name;//姓名
	private String pinyin;//姓名对应的拼音

	public Friend(String name) {
		super();
		this.name = name;
		//通过名字得到对应的拼音
		this.pinyin = PinYinUtils.getPinYin(name);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPinyin() {
		return pinyin;
	}

	public void setPinyin(String pinyin) {
		this.pinyin = pinyin;
	}

	@Override
	public String toString() {
		return "Friend [name=" + name + ", pinyin=" + pinyin + "]";
	}

	/**
	 * 此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 。
	 */
	@Override
	public int compareTo(Friend another) {
		return pinyin.compareTo(another.getPinyin());
	}
}

PinYinUtils

package com.atguigu.quickindex;

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.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * 将汉字转换为拼音
 */
public class PinYinUtils {
	/**
	 * 得到指定汉字的拼音
	 * 注意:不应该被频繁调用,它消耗一定内存
	 */
	public static String getPinYin(String hanzi){
		String pinyin = "";

		HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();//控制转换是否大小写,是否带音标
		format.setCaseType(HanyuPinyinCaseType.UPPERCASE);//大写
		format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

		//由于不能直接对多个汉字转换,只能对单个汉字转换
		char[] arr = hanzi.toCharArray();
		for (int i = 0; i < arr.length; i++) {
			if(Character.isWhitespace(arr[i]))continue;//如果是空格,则不处理,进行下次遍历

			//汉字是2个字节存储,肯定大于127,所以大于127就可以当为汉字转换
			if(arr[i]>127){
				try {
					//由于多音字的存在,单 dan shan
					String[] pinyinArr = PinyinHelper.toHanyuPinyinStringArray(arr[i], format);

					if(pinyinArr!=null){
						pinyin += pinyinArr[0];
					}else {
						pinyin += arr[i];
					}
				} catch (BadHanyuPinyinOutputFormatCombination e) {
					e.printStackTrace();
					//不是正确的汉字
					pinyin += arr[i];
				}
			}else {
				//不是汉字,
				pinyin += arr[i];
			}
		}
		return pinyin;
	}
}
时间: 2024-10-22 13:13:29

字母条索引定位的相关文章

一款很实用的 字母条索引+自定义进度条

代码下载地址 点击打开链接 自己之前写过几个联系人索引条的小demo,但没有在项目中自己体验过,最近项目中有用到,这个功能模块是同事写的,今天抽空摘出来下,以保存,将来可以用到 接下来就一步步简单的说下思路吧:action开始 首先先看下主界面的布局文件吧 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.andro

jquery模拟字母顺序排序定位城市列表方法(bug改进)

jquery模拟字母顺序排序定位城市列表方法 下载地址http://www.lanrenzhijia.com/jquery/3155.html bug 重庆--长沙不能正常排序. 原因是derail有可能会放回两个字符的数组.需要做判断 改进 //改动 特殊字符-->可能还有问题--返回的是数组有两个字符 var   derail =makePy(SortList.eq(i).find('.num_name').text().charAt(0)) if(derail.length==2&&a

JS仿淘宝详情页菜单条智能定位效果

类似于淘宝详情页菜单条智能定位 对于每个人来说并不陌生!如下截图所示:红色框的那部分! 基本原理: 是用JS侦听滚动事件,当页面的滚动距离(页面滚动的高度)大于或者等于 "对象"(要滚动的对象)距离页面顶部的高度,也就是说滚动的对象与窗口的上边缘接触时,立即将对象定位属性position值改成fixed(固定) (除IE6以外,因为IE6不支持fixed).对于IE6用绝对定位position:absolute,top:就是"游览器滚动的top".在 IE6下浏览看

联系人列表字母排序索引(三)

也是忙忙碌碌好几天,今天又有时间了,继续这个文章的编写.今天是这篇文章的最后一部分.主要内容包括以下几点: 1.将中文名字转化成拼音,并提取首字母,进行排序. 2.实现分组列表Adapter模板. 3.将列表与索引结合在一起. pinyin4j是一个将中文转化成拼音的高效工具,我的源码中带了这个依赖包.通过这个工具,可以先获取一个中文的拼音. public static String getLetter(String name) { StringBuilder sb = new StringBu

利用全局索引定位难缠的页面元素

前言 超级链接是网站中使用非常频繁的HTML元素,可以说超级链接是浏览者和服务器的交互的主要手段. 我们知道有点击链接时,大部分情况下都需要使用txt属性,因为链接没有其他属性可以用来匹配,但不是所有的超链接都支持txt属性特征串的,如果不支持,我们就只能通过索引+标签来定位唯一元素特征字符串了. 前言 咱们来举个栗子,比如我们想点击淘宝淘金币网址上的登陆查看金币明细这个页面元素,正常手动点击的话是会弹出账号登陆窗口的. 咱们启用网页分析工具按F9分析一下,发现这个肉眼看上去貌似是按钮的东西TA

一、ListView的侧边字母滑动索引

一.最终效果 二.功能分析与实现 1.LisetView布局 分析:同样的字母开头,第一个上方有该字母的标志 实现:在item布局中除了TextView再在其上方加一个TextView等布局(用于显示数据的首字母),然后在适配器的getView中判断该布局是否显示.默认设置该布局的Visibility为VISIBLE,当该布局的的文字内容首字母与上一个不同时说明该item是新的首字母开头,设置为VISIBLE,否则设置为GONE. 部分代码: // 默认显示 为了显示第一个布局以及布局复用出现的

android listView 根据字母排序和定位 (http://www.apkbus.com/android-69999-1-1.html)

第一步是实现字母的a-z的控件的显示: import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.dra

android源码大放送(实战开发必备),免费安卓demo源码,例子大全文件详细列表

免费安卓demo源码,例子大全文件详细列表 本列表源码永久免费下载地址:http://www.jiandaima.com/blog/android-demo 卷 yunpan 的文件夹 PATH 列表 卷序列号为 0000-73EC E:. │ jiandaima.com文件列表生成.bat │ 例子大全说明.txt │ 本例子永久更新地址~.url │ 目录列表2016.03.10更新.txt │ ├─前台界面 │ ├─3D标签云卡片热门 │ │ Android TagCloudView云标签

浅谈android中手机联系人字母索引表的实现

实际上字母索引表的效果,可以说在现在的众多APP中使用的非常流行,比如支付宝,微信中的联系人,还有购物,买票的APP中选择全国城市,切换城市的时候,这时候的城市也就是按照一个字母索引的顺序来显示,看起来是很方便的.其实这种字母索引表的效果最开始是出现在微信的联系人中.因为觉得这种效果功能在今后的项目中可以说是非常常见,可能会用的上,所以准备来波博客讲述一下实现的原理,一来方便以后自己复习,二来如果能够帮助一些android路上奋斗小伙伴也是蛮有意义的. 下面我们先来看下效果图, 看完效果图后我们