动手撸一个简单的首字母侧边栏

废话不多说先上效果图
这里写图片描述

先分析实现方法:
1,将26个字母和两个符号绘制在画布上。
2,复写onTouchEvent方法监听手指触摸控件位置。

代码很简单首先创建MySideBar类继承View类

public class MySideBar extends View {

    private 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","-"};
    private Paint paint;
    private TextView textViewDialog;//显示选中的字母
    private float letterHeight;//单个字母的区域高度
    private OnSideBarTouchListener onSideBarTouchListener;
    public MySideBar(Context context) {
        this(context,null);
    }

    public MySideBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.slideswitch);
        a.recycle();
        initPaint();
    }

    private void initPaint(){
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setFakeBoldText(true);
        paint.setColor(Color.parseColor("#0066FF"));
        paint.setTextSize(16);
    }
  }

上面代码是申明一个类继承View,并初始化画笔和存放字母的字符串数组。

/**
     * 在画布上绘制26个字母
     * */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        letterHeight = (height*1f)/letters.length;

        for(int i=0;i<letters.length;i++){
            float textHeight = paint.measureText(letters[i]);
            float y = (letterHeight*i)+letterHeight/2-textHeight/2;//字母y方向的起始绘制位置
            float x = (width*1f)/2-textHeight/2;
            canvas.drawText(letters[i],x,y,paint);
        }

    }

上面代码是计算每个字母的位置并用canvas的drawText将字母绘制在画布上。要注意paint.measureText方法是算出字母在画布上的所占的宽高。

最后一步是监听触摸事件。

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_UP:
                if(textViewDialog!=null){
                    textViewDialog.setVisibility(GONE);
                }
                break;
            default:
                if(textViewDialog!=null){
                    float touchY = event.getY();
                    int touchP = (int) (touchY/letterHeight);

                    if(touchP<=27&&touchP>=0) {
                        textViewDialog.setVisibility(VISIBLE);
                        textViewDialog.setText(letters[touchP]);
                        if(onSideBarTouchListener!=null){
                            onSideBarTouchListener.onLetterChange(letters[touchP]);
                        }
                    }else {
                        textViewDialog.setVisibility(GONE);
                    }
                }
                break;
        }
        return true;
    }

根据event.getY()获得手指在y方向的位置除以每个字母所占区域的高度就得到当前手指所处区域,然后从字符串数组中取出该字符大功告成。
下面贴上完整代码

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

/**
 * Created by yxd on 2017/12/7.
 * 字母列表侧边栏
 */

public class MySideBar extends View {

    private 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","#"};
    private Paint paint;
    private TextView textViewDialog;//显示选中的字母
    private float letterHeight;//单个字母的区域高度
    private OnSideBarTouchListener onSideBarTouchListener;
    public MySideBar(Context context) {
        this(context,null);
    }

    public MySideBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.slideswitch);
        a.recycle();
        initPaint();
    }

    private void initPaint(){
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setFakeBoldText(true);
        paint.setColor(Color.parseColor("#0066FF"));
        paint.setTextSize(16);
    }

    /**
     * 在画布上绘制26个字母
     * */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        letterHeight = (height*1f)/letters.length;

        for(int i=0;i<letters.length;i++){
            float textHeight = paint.measureText(letters[i]);
            float y = (letterHeight*i)+letterHeight/2-textHeight/2;//字母y方向的起始绘制位置
            float x = (width*1f)/2-textHeight/2;
            canvas.drawText(letters[i],x,y,paint);
        }

    }

    public void setTextViewDialog(TextView textViewDialog) {
        this.textViewDialog = textViewDialog;
    }

    public void setOnSideBarTouchListener(OnSideBarTouchListener onSideBarTouchListener) {
        this.onSideBarTouchListener = onSideBarTouchListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_UP:
                if(textViewDialog!=null){
                    textViewDialog.setVisibility(GONE);
                }
                break;
            default:
                if(textViewDialog!=null){
                    float touchY = event.getY();
                    int touchP = (int) (touchY/letterHeight);

                    if(touchP<=27&&touchP>=0) {
                        textViewDialog.setVisibility(VISIBLE);
                        textViewDialog.setText(letters[touchP]);
                        if(onSideBarTouchListener!=null){
                            onSideBarTouchListener.onLetterChange(letters[touchP]);
                        }
                    }else {
                        textViewDialog.setVisibility(GONE);
                    }
                }
                break;
        }
        return true;
    }

    public interface OnSideBarTouchListener{
        void onLetterChange(String s);
    }

}

下面我们创建一个activity测试该控件。

public class TestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        TextView tvDialog = (TextView) findViewById(R.id.tv_dialog);
        MySideBar mySideBar = (MySideBar) findViewById(R.id.country_sidebar);
        mySideBar.setTextViewDialog(tvDialog);
    }
}

布局代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.example.view.MySideBar
            android:id="@+id/country_sidebar"
            android:layout_width="30.0dip"
            android:layout_height="match_parent"
            android:layout_gravity="right|center"
           />

        <TextView
            android:id="@+id/tv_dialog"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_gravity="center"
            android:textSize="20dp"
            android:gravity="center"
            android:visibility="gone"
            android:background="@color/bg_color"/>

    </FrameLayout>

</LinearLayout>

com.example.view.MySideBar就是自定义的MySideBar控件,放在包com.example.view下。tv_dialog就是在屏幕正中间显示的文字。
测试效果与文章开头的gif图效果一至。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值