自定义View-字母排序

做地址选择的时候的经常会用到字母筛选,如下图所示
在这里插入图片描述
我们只实现右边的字母,字母的实现可以使用列表的形式实现,也可以自定义View来实现,本次我们采用第二种自定义View,代码如下:

public class LetterSortView extends View {
    //一个是选中的画笔,一个是默认的画笔
    private Paint defaultPaint;
    private Paint selectPaint;

    private String mCurrentTouchLetter;
    private OnTouchLetterListener listener;

    public void setListener(OnTouchLetterListener listener) {
        this.listener = listener;
    }

    // 26个字母
    public  static final String[] LETTERS = {"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 LetterSortView(Context context) {
        super(context,null);
        initPaint();
    }

    public LetterSortView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    public LetterSortView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initPaint();

    }

    private void initPaint() {
        defaultPaint = new Paint();
        defaultPaint.setAntiAlias(true);
        //颜色大小这里可以随需求自定义
        defaultPaint.setTextSize(sp2px(12));
        defaultPaint.setColor(Color.GRAY);


        selectPaint = new Paint();
        selectPaint.setAntiAlias(true);
        //颜色大小这里可以随需求自定义
        selectPaint.setTextSize(sp2px(12));
        selectPaint.setColor(Color.RED);

    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        //相邻字母间的高度差
        int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom())/LETTERS.length;
        for (int i = 0; i < LETTERS.length; i++) {
            //x 坐标 取文本最左边位置,默认的文本对齐方式是靠左
            int textWidth = (int) defaultPaint.measureText(LETTERS[i]);
            int dx = getWidth()/2 - textWidth/2;

            //y基线坐标
            Paint.FontMetrics fontMetrics = defaultPaint.getFontMetrics();
            //这里不能用控件高度的1/2 来作为基线,可以从网上详细查看基线的计算公式
            int dy = (int) ((fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom);
            int baseY = dy + itemHeight * i + itemHeight /2 - getPaddingTop();


            if (LETTERS[i].equals(mCurrentTouchLetter)){
                //触摸的是当前的字母
                canvas.drawText(LETTERS[i],dx,baseY,selectPaint);
            }else {
                canvas.drawText(LETTERS[i],dx,baseY,defaultPaint);
            }
        }


    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            //只关注按下的时候
            case MotionEvent.ACTION_DOWN:
                int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom())/LETTERS.length;
                int  currentY = (int) event.getY();
                int currentPos = currentY/itemHeight;
                if (currentPos < 0){
                    currentPos = 0;
                }

                if (currentPos > LETTERS.length -1){
                    currentPos = LETTERS.length -1;
                }

                mCurrentTouchLetter = LETTERS[currentPos];

                invalidate();



                break;
            case MotionEvent.ACTION_UP:
                if (listener != null){
                    listener.onTouchLetter(mCurrentTouchLetter);
                }
                break;
        }
        return true;

    }

    // sp 转 px
    private float sp2px(int sp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                sp, getResources().getDisplayMetrics());
    }

    //将选中的字母回调出去
    public interface OnTouchLetterListener{
        void onTouchLetter(String letter);
    }


}

在使用的时候可以拿到回调的字母,来进行操作,比如要在界面中间展示选中的字母,以及进行查询列表操作

LetterSortView letterSortView = findViewById(R.id.letter);
        letterSortView.setListener(new LetterSortView.OnTouchLetterListener() {
            @Override
            public void onTouchLetter(String letter) {

            }
        });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值