您的位置:首页 > 移动开发 > Android开发

Android开发-自定义View-AndroidStudio(十五)快速索引(2)

2016-12-28 11:11 633 查看
转载请注明出处:http://blog.csdn.net/iwanghang/article/details/53906660
觉得博文有用,请点赞,请评论,请关注,谢谢!~

项目源码下载:http://download.csdn.net/detail/iwanghang/9723388

老规矩,先上GIF动态图,看个效果,如果符合你的项目或者确定你要了解的内容,再往下看吧:
文字转化拼音,但是会遇到多音字的问题,这个不是jar包的错误。联系人一般没问题,或者说这次没有遇到。尝试了2个非人名的多音字,确实遇到了问题。
类似于地名这样的拼音排序,一般是从服务器接收Json串的时候,一起接收过来,因为可能有Web、Android、IOS,都需要用同一个接口,排序方式一样,会比较规范。



MainActivity.java:
package com.iwanghang.indexeddemo;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class MainActivity extends AppCompatActivity {

private ListView lv_main;
private TextView tv_word;
private IndexView iv_words;

private Handler handler = new Handler();
/**
* 联系人的集合
*/
private ArrayList<Person> persons;
private IndexAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv_main = (ListView) findViewById(R.id.lv_main);
tv_word = (TextView) findViewById(R.id.tv_word);
iv_words = (IndexView) findViewById(R.id.iv_words);
tv_word.setVisibility(View.GONE);
//设置监听字母下标索引的变化
iv_words.setOnIndexChangeListener(new MyOnIndexChangeListener());
//准备数据
initData();
//设置适配器
adapter = new IndexAdapter();
lv_main.setAdapter(adapter);
}

class IndexAdapter extends BaseAdapter{
@Override
public int getCount() {
return persons.size();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
convertView = View.inflate(MainActivity.this,R.layout.item_main,null);
viewHolder = new ViewHolder();
viewHolder.tv_word = (TextView) convertView.findViewById(R.id.tv_word);
viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}

String name = persons.get(position).getName();// 刘德华
String word = persons.get(position).getPinyin().substring(0,1);// LIUDEHUA->L
viewHolder.tv_word.setText(word);
viewHolder.tv_name.setText(name);
if(position == 0){
viewHolder.tv_word.setVisibility(View.VISIBLE);
}else{
// 得到前一个位置对应的字母,如果当前的字母和上一个相同,隐藏;否则就显示
String preWord = persons.get(position-1).getPinyin().substring(0,1);//A~Z
if(word.equals(preWord)){
viewHolder.tv_word.setVisibility(View.GONE);
}else{
viewHolder.tv_word.setVisibility(View.VISIBLE);
}

}

return convertView;
}

@Override
public Object getItem(int position) {
return null;
}

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

}

static class ViewHolder{
TextView tv_word;
TextView tv_name;
}

// 当触摸的字母发生改变,这里接到回传,重新设置TextView
class MyOnIndexChangeListener implements IndexView.OnIndexChangeListener {
@Override
public void onIndexChange(String word) {
updateWord(word);
updateListView(word); // A~Z
}
}

private void updateListView(String word) {
for(int i=0;i<persons.size();i++){
String listWord = persons.get(i).getPinyin().substring(0,1); // LIUDEHUA->L
if (word.equals(listWord)) {
//i是listView中的位置
lv_main.setSelection(i); // 定位到ListView中的某个位置
return;
}
}
}

private void updateWord(String word) {
//显示
tv_word.setVisibility(View.VISIBLE);
tv_word.setText(word);
handler.removeCallbacksAndMessages(null);
handler.postDelayed(new Runnable() {
@Override
public void run() {
//也是运行在主线程
System.out.println(Thread.currentThread().getName()+"------------");
tv_word.setVisibility(View.GONE);
}
}, 500);
}

/**
* 初始化数据
*/
private void initData() {
persons = new ArrayList<>();
persons.add(new Person("张晓飞"));
persons.add(new Person("杨光福"));
persons.add(new Person("胡继群"));
persons.add(new Person("刘畅"));

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

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

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

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

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

persons.add(new Person("阿三"));
persons.add(new Person("李博俊"));

persons.add(new Person("会计 多音字问题")); // 多音字问题 首字母判断为H
persons.add(new Person("长春 多音字问题")); // 多音字问题 首字母判断为Z

// 排序
Collections.sort(persons, new Comparator<Person>() {
@Override
public int compare(Person lhs, Person rhs) {
return lhs.getPinyin().compareTo(rhs.getPinyin());
}
});

}
}
IndexView.java:
package com.iwanghang.indexeddemo;

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;

/**
* 绘制快速索引的字母
*/
public class IndexView extends View {

/**
* 每条的宽和高
*/
private int itemWidth;
private int itemHeight;

private Paint paint;

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

public IndexView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
paint.setTextSize(25);
paint.setColor(Color.WHITE);
paint.setAntiAlias(true); // 抗锯齿,字体圆滑
paint.setTypeface(Typeface.DEFAULT_BOLD);//设置粗体字
}

/**
* 测量方法
* 测量包裹字母的条目的宽高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
itemWidth = getMeasuredWidth();
itemHeight = getMeasuredHeight() / words.length;
}

/**
* 在画布上 绘制字母
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < words.length; i++) {

// 根据onTouchEvent 监听手势滑动位置,设置当前滑动的字母的下标 来设置字母颜色 A2
if(touchIndex == i){
// 设置灰色
paint.setColor(Color.GRAY);
}else{
// 设置白色
paint.setColor(Color.WHITE);
}

String word = words[i];// A

Rect rect = new Rect();
// 画笔
// 0,1的取一个字母
paint.getTextBounds(word, 0, 1, rect);

// 字母的高和宽
int wordWidth = rect.width();
int wordHeight = rect.height();

// 计算每个字母在视图上的坐标位置
float wordX = itemWidth / 2 - wordWidth / 2;
float wordY = itemHeight / 2 + wordHeight / 2 + i * itemHeight;

canvas.drawText(word, wordX, wordY, paint);
}
}

/**
* 字母的下标位置
*/
private int touchIndex = -1;

/**
* 监听手势滑动位置,设置当前滑动的字母的下标 A1
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float Y = event.getY();
int index = (int) (Y/itemHeight); // 字母索引
if(index != touchIndex){

touchIndex = index;
invalidate();//强制绘制onDraw();
if(onIndexChangeListener != null && touchIndex > -1 && touchIndex < words.length){
onIndexChangeListener.onIndexChange(words[touchIndex]); // 回传触摸的字母,告诉MainActivity
}
}
break;
case MotionEvent.ACTION_UP:
touchIndex = -1;
invalidate();
break;
}
return true;
}

/**
* 字母下标索引变化的监听器
* 字母改变 回调接口 B1
*/
public interface OnIndexChangeListener{
/**
* 当字母下标位置发生变化的时候回调
* @param word 字母(A~Z)
*/
void onIndexChange(String word); // 回传一个字母
}

private OnIndexChangeListener onIndexChangeListener;

/**
* 设置字母下标索引变化的监听
* @param onIndexChangeListener
*/
public void setOnIndexChangeListener(OnIndexChangeListener onIndexChangeListener) {
this.onIndexChangeListener = onIndexChangeListener;
}
}
Person.java:
package com.iwanghang.indexeddemo;

public class Person {

private String name;

private String pinyin;

public Person(String name){
this.name = name;
this.pinyin = PinYinUtils.getPinYin(name);
}

public String getPinyin() {
return pinyin;
}

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

public String getName() {
return name;
}

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

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", pinyin='" + pinyin + '\'' +
'}';
}
}
PinYinUtils.java:
package com.iwanghang.indexeddemo;

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];
}
}
System.out.println("pinyin = "+ pinyin);
return pinyin;
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.iwanghang.indexeddemo.MainActivity">

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

<TextView
android:id="@+id/tv_word"
android:layout_centerInParent="true"
android:textSize="30sp"
android:gravity="center"
android:textColor="#FFFFFF"
android:background="#44000000"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="A" />

<com.iwanghang.indexeddemo.IndexView
android:id="@+id/iv_words"
android:layout_alignParentRight="true"
android:background="#44000000"
android:layout_width="30dp"
android:layout_height="match_parent" />

</RelativeLayout>
item_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/tv_word"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#44000000"
android:text="A"
android:textColor="#000000"
android:textSize="25sp" />

<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="刘德华"
android:textColor="#000000"
android:textSize="25sp" />

</LinearLayout>


转载请注明出处:http://blog.csdn.net/iwanghang/article/details/53906660

欢迎移动开发爱好者交流
沈阳或周边城市公司有意开发Android,请与我联系
联系方式



微信:iwanghang
QQ:413711276
邮箱:iwanghang@qq.com



项目源码下载:http://download.csdn.net/detail/iwanghang/9723388

觉得博文有用,请点赞,请评论,请关注,谢谢!~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息