一、效果图:
二、主要功能:
[1 ] 点击英文字母,自动将该字母条目置顶;
[2 ] 点击字母,显示该字母(相当于一个Toast);
三、主要知识点:
[1 ] 自定义控件;
[2 ] ListView 的使用和适配器的加载;
好,接下来我们开始学习该效果怎么实现的;
一、自定义控件QuickIndexBar;
【1 】 首先需要将加载我们所需要的参数
private Paint mPaint;
private int mColor=0xFF7C7C7A;
//一个字母条目所占用的高度
private float cellHeight;
//字母的宽度
private float cellWidth;
//记录点击位置
private int lastLetter=-1;
//定义点击事件
private OnTouchLetterListener onTouchLetterListener;
private String [] indexArr=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"};
【2】 其次是设置Paint的属性,这里就不细讲了,我们讲高度的测量,下图详细讲解了测量的过程;
【3】 然后就是画图了,看完上面的图就能很直观的画出字母了,这里用了个点击变色,但是用真机时手指都挡住了,没什么用。
protected void onDraw(Canvas canvas) {
for (int i = 0; i < indexArr.length; i++) {
float x=cellWidth/2;
float y=cellHeight/2+getTextHeight(indexArr[i])/2+i*cellHeight;
//点击变色,这个判断可用可不用,因为变化速度太快了,了解就好
mPaint.setColor(lastLetter==i?Color.WHITE:mColor);
canvas.drawText(indexArr[i],x,y,mPaint);
}
}
第一个难点已经讲完了
【4】设置监听事件,流程就是定义接口实现,然后暴露实现方法;
public void setOnTouchLetterListener(OnTouchLetterListener onTouchLetterListener){
this.onTouchLetterListener=onTouchLetterListener;
}
public interface OnTouchLetterListener{
void TouchLetter(String letter);
}
【5】 设置触摸事件,原理就是,触摸的时候实现该触摸的是哪个文字所在的位置(高度),不多说直接上代码;这里运用到了刚开始定义的lastLetter判断并记录触摸的位置;
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float y=event.getY();
int index= (int) (y/cellHeight);
//安全性的检查,这样安全性能比较好一点,不然可能会发生ANR
if (index>=0&&index<indexArr.length){
if (lastLetter!=index){
// Log.d("index",indexArr[index]);
//点击事件方法回调
onTouchLetterListener.TouchLetter(indexArr[index]);
}
}
lastLetter=index;
break;
case MotionEvent.ACTION_UP:
lastLetter=-1;
break;
}
return true;
}
以上代码都能看得懂,好了,自定义控件已经完成,然后就是使用了;
二、使用QiuckIndexBar ;
【1】 在activity_main.xml中加入以下代码:
<com.xc.quickindexbar.view.QuickIndexBar
android:id="@+id/indexBar"
android:layout_width="40dp"
android:layout_height="match_parent"
android:background="@null"
android:padding="10dp"
android:layout_alignParentRight="true"/>
【2】初始化控件,这里就不用贴代码了;
【3】实现点击事件。首先在MainActivity里实现QuickIndexBar.OnTouchLetterListener 这个接口,实现TouchLetter()方法,这里用了一个Toast来显示点击的字母;
public void TouchLetter(String letter) {
Toast.makeText(getApplication(),letter,Toast.LENGTH_SHORT).show();
}
自定义QuickIndexBar的完整代码:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import static android.view.MotionEvent.*;
/**
* Created by xxdeng on 2017/10/20.
*/
public class QuickIndexBar extends View {
private Paint mPaint;
private int mColor=0xFF7C7C7A;
//一个字母条目所占用的高度
private float cellHeight;
//字母的宽度
private float cellWidth;
//记录点击位置
private int lastLetter=-1;
//定义点击事件
private OnTouchLetterListener onTouchLetterListener;
private String [] indexArr=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 QuickIndexBar(Context context) {
super(context);
init();
}
public QuickIndexBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public QuickIndexBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(mColor);
mPaint.setTextSize(18);
mPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
cellWidth=getMeasuredWidth();
cellHeight=getMeasuredHeight()*1f/26;
}
@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < indexArr.length; i++) {
float x=cellWidth/2;
float y=cellHeight/2+getTextHeight(indexArr[i])/2+i*cellHeight;
//这个判断可用可不用,因为变化速度太快了,了解就好
mPaint.setColor(lastLetter==i?Color.WHITE:mColor);
canvas.drawText(indexArr[i],x,y,mPaint);
}
}
/**
* 触摸事件
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float y=event.getY();
int index= (int) (y/cellHeight);
//安全性的检查,这样安全性能比较好一点,不然可能会发生ANR
if (index>=0&&index<indexArr.length){
if (lastLetter!=index){
// Log.d("index",indexArr[index]);
//点击事件回调
onTouchLetterListener.TouchLetter(indexArr[index]);
}
}
lastLetter=index;
break;
case MotionEvent.ACTION_UP:
lastLetter=-1;
break;
}
return true;
}
/**
*获取文字的高度
* @param text
* @return
*/
private int getTextHeight(String text) {
Rect bounds=new Rect();
mPaint.getTextBounds(text,0, text.length(),bounds);
return bounds.height();
}
//******************************下面是实现点击事件的接口,暴露方法**************************************************
public void setOnTouchLetterListener(OnTouchLetterListener onTouchLetterListener){
this.onTouchLetterListener=onTouchLetterListener;
}
public interface OnTouchLetterListener{
void TouchLetter(String letter);
}
}
自定义控件就完成了,先讲到这里,自定义控件中了解的主要的知识点就觉得很简单,后面的知识点就是ListView的使用了;
后续请参考: 快速检索(二)之ListView的使用进行数据填充及点击事件