您的位置:首页 > 其它

快速索引的简单实现

2015-11-07 09:45 274 查看
防微信联系人快速索引的简单实现,

首先,要画出26个英文字母,所以,我们就要自定义控件的技术了,这里直接继承View,进行重绘比较简单的实现

1.定义一个自己的类,去继承View, 具体的代码如下:

public class QuickIndexView extends View {
// 画笔的 类
private Paint mPaint;

// 单元格的宽和高
private int singleWindth;
private float singleHeight;
private OnLetterUpdeteListener mListener;
// 需要用到的26个字母
private static final String[] LETTERS = new String[] { "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 QuickIndexView(Context context) {
this(context, null);
}

public QuickIndexView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public QuickIndexView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
// 设置抗锯齿
mPaint.setAntiAlias(true);
// 设置画笔的颜色为 白色
mPaint.setColor(Color.WHITE);
// 设置文本的 格式为 加粗的格式
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
// 设置显示字体的大小 参数为 float
mPaint.setTextSize(20);
}


自定义一个类继承View,把用到的26个字母声明出来 .把前两个构造方法,串起来,还有就是画笔的初始化,在代码里面也都有对应的注释. 还有声明出来的两个int的变量 主要的作用就是去确定每一个字母在屏幕显示的位置,用来绘制的

接下来,就是去重写onDraw()方法去绘制,

@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < LETTERS.length; i++) {
String text = LETTERS[i];
// mPaint.measureText 画笔的方法 可以得到画的文本的 宽度
// 通过这个方法 得到x轴的 坐标点
int x = (int) (singleWindth / 2.0f - mPaint.measureText(text) / 2.0f);
// 获得 文本的所在的 矩形
Rect bounds = new Rect();
// 获取文本的高度
// 参数1 文本的内容,string类型 ,参数2和参数3 是文本内容的长度
mPaint.getTextBounds(text, 0, text.length(), bounds);
// 通过矩形的四个参数得到文本的高度
int textHeight = bounds.height();
// 得到每个 字母画的y轴的坐标
int y = (int) (singleHeight / 2.0f + textHeight / 2.0f + i
* singleHeight);
canvas.drawText(text, x, y, mPaint);

}
}


这里在刚刚前面声明的两个int类型的变量就用到了,但是我们并没有看到,在哪里赋值,看下 变量在哪里赋值的把,

// 当view的大小 改变的时候回调的方法
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);

singleWindth = getMeasuredWidth();
int height = getMeasuredHeight();
singleHeight = height * 1.0f / LETTERS.length;

}


下面就可以简单的运行下,看下效果了.当然我们要在xml布局中 引用我们的控件的

代码如下

<LinearLayout 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"
android:orientation="horizontal"
tools:context=".MainActivity" >
<ListView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:id="@+id/lv_main"
></ListView>

<com.qianfeng.quickindex.ui.QuickIndexView
android:layout_width="40dp"
android:background="#ff0000"
android:id="@+id/my_indexView"
android:layout_height="match_parent"
/>

</LinearLayout>


布局也很简单,下面就可以简单的运行下,看下效果了.效果图



图是我截的,嘻嘻,

下面就是处理我们的点击事件了,其实点击的事件,也很好的处理 ,下面看具体的代码:

private int lastIndex= -1;
@SuppressLint("NewApi") @Override
public boolean onTouchEvent(MotionEvent event) {
int index=  -1;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
surePostion(index, event);

break;
case MotionEvent.ACTION_MOVE:

surePostion(index, event);

break;
case MotionEvent.ACTION_UP:
index=-1;
break;
}
// 这里返回true 表示持续接收事件的处理
return true;
}
// 确定当前的位置 跟上一次的位置不相等的时候,才去显示吐司
private void surePostion( int index,MotionEvent event){
index =(int) event.getY()/LETTERS.length;
if(index>0&&index<LETTERS.length){
if (index!=lastIndex) {

if (mListener!=null) {
mListener.onLetterUpdete(LETTERS[index]);
}

//              Utils.showToast(getContext(), LETTERS[index]);
}

}
lastIndex=index;
}


还有就是自定义的一个监听器的实现 看实现

// 监听 字母被点击的时候回调接口
public interface OnLetterUpdeteListener{

// 当字母被点击的时候回调的方法
void onLetterUpdete(String msg);
}

public void setonLetterUpdeteListener(OnLetterUpdeteListener letterListener){
this.mListener=letterListener;
}```

下面就是ListView填充数据还有拼音字母的转化了,话不多说,直接上代码


public class MainActivity extends Activity {

private QuickIndexView mIndexView;

private ListView mlistView;

private List mPersons;

// private MyListViewAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mlistView = (ListView) findViewById(R.id.lv_main);
mIndexView = (QuickIndexView) findViewById(R.id.my_indexView);
// 监听 利用接口回调的

mIndexView.setonLetterUpdeteListener(new OnLetterUpdeteListener() {

@Override
public void onLetterUpdete(String msg) {
Utils.showToast(MainActivity.this, msg);

for (int i = 0; i < mPersons.size(); i++) {
Person person = mPersons.get(i);
String l = person.getPinyin().charAt(0) + "";
if (TextUtils.equals(l, msg)) {
mlistView.setSelection(i);
break;

}

}
}
});

getDataAndSort();

mlistView.setAdapter(new MyListViewAdapter(mPersons, this));

}

private void getDataAndSort() {
mPersons = new ArrayList<Person>();
for (int i = 0; i < Cheeses.NAMES.length; i++) {
mPersons.add(new Person(Cheeses.NAMES[i]));
}

Collections.sort(mPersons);
}


}

汉子转化的拼音的类


public class PinyinUtils {

/**
* 根据传入的字符串(包含汉子),得到 字母
*
* @param str
* @return
*/
public static String getPinyin(String str) {
// 汉字拼音输出的类型 都封装到这个类上面去了
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

StringBuilder sb = new StringBuilder();

char[] charArray = str.toCharArray();
try {
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
// Character.isWhitespace 判断得到的字符串是不是空格 如果是空格跳过
if (Character.isWhitespace(c)) {
continue;
}
// 如果是特殊的字符, 直接添加到 sb上面去
if (c >= -127 && c < 128) {
sb.append(c);
} else {
String s = "";

s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
sb.append(s);

}
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();

}

return sb.toString();
}


}

当然这里要用到一个jar包,下面有连接 自己去下载吧,还有就是ListViewAdapter的实现了


public class MyListViewAdapter extends BaseAdapter {

private List mPersons;

private Context context;

public MyListViewAdapter(List<Person> mPersons, Context context) {
this.mPersons = mPersons;
this.context = context;
}

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

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

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) {
convertView = View.inflate(context, R.layout.list_item, null);

}
Viewholder holder = Viewholder.getHolder(convertView);

Person p=mPersons.get(position);
String flag=null;
String currentPinyin=p.getPinyin().charAt(0)+"";

if (position==0) {
flag= currentPinyin;
}else {
String lastString=mPersons.get(position-1).getPinyin().charAt(0)+"";
if (!lastString.equals(currentPinyin)) {
flag=currentPinyin;
}

}
holder.tv_name.setText(p.getName());
// 如果flag ==null 的时候 不让它 显示 .不等于null 的时候显示
holder.tv_title.setVisibility(flag==null? View.GONE:View.VISIBLE);
holder.tv_title.setText(currentPinyin);
return convertView;
}

static class Viewholder {
TextView tv_name;
TextView tv_title;

public static Viewholder getHolder(View view) {
Object tag = view.getTag();

if (tag != null) {
return (Viewholder) (tag);
} else {
Viewholder viewholder = new Viewholder();
viewholder.tv_name = (TextView) view.findViewById(R.id.tv_name);
viewholder.tv_title = (TextView) view
.findViewById(R.id.tv_title);
view.setTag(viewholder);
return viewholder;

}

}
}


}

listView的布局文件

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

<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:textColor="#ffffff"
android:layout_height="40dp"
android:background="#888888" />
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="40dp"/>

</LinearLayout>


下面是代码的下载连接

http://download.csdn.net/detail/ma229358084/9249367
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: