快速检索(一)之自定义快速检索QiuckIndexBar控件

一、效果图

      


二、主要功能:

    [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的使用进行数据填充及点击事件


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值