Android自定义View自定义view

自定义View - 字母索引列表

2018-07-07  本文已影响2人  Peakmain
效果图

自定义view

public class LetterSideBar extends View {
    private Paint mPaint;
    // 定义26个字母
    public static String[] mLetters = {"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 String mCurrentTouchLetter = "A";

    public LetterSideBar(Context context) {
        this(context, null);
    }

    public LetterSideBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LetterSideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        // 自定义属性,颜色  字体大小
        // 设置的是像素
        mPaint.setTextSize(sp2px(12));
        // 默认颜色
        mPaint.setColor(Color.BLUE);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //计算其宽度,和画笔有关
        //measure获取宽度
        int textWidth = (int) mPaint.measureText("A");
        int width = getPaddingLeft() + getPaddingRight() + textWidth;
        //高度,直接获取即可
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //每个文字的高度
        int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / mLetters.length;
        for (int i = 0; i < mLetters.length; i++) {
            int textWidth = (int) mPaint.measureText(mLetters[i]);
            //每个字母的中心线
            int letterCenter = i * itemHeight + itemHeight / 2 + getPaddingTop();
            @SuppressLint("DrawAllocation") Paint.FontMetricsInt fontMetricsInt = new Paint.FontMetricsInt();
            int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
            float baseLine = letterCenter + dy;

            // x 绘制在最中间 = 宽度/2 - 文字/2
            float x = getWidth() / 2 - textWidth / 2;

            //高亮
            if (mLetters[i].equals(mCurrentTouchLetter)) {
                mPaint.setColor(Color.RED);
                canvas.drawText(mLetters[i], x, baseLine, mPaint);
            } else {
                mPaint.setColor(Color.BLUE);
                canvas.drawText(mLetters[i], x, baseLine, mPaint);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                // 计算出当前触摸字母  获取当前的位置
                float currentMoveY = event.getY();
                //每个文字的高度
                int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / mLetters.length;
                int currentPosition = (int) (currentMoveY / itemHeight);
                if(currentPosition<0){
                    currentPosition=0;
                }
                if(currentPosition>mLetters.length-1){
                    currentPosition=mLetters.length-1;
                }
                mCurrentTouchLetter=mLetters[currentPosition];
                if (mListener != null) {
                    mListener.touch(mCurrentTouchLetter, true);
                }
                // 重新绘制
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                if (mListener != null) {
                    mListener.touch(mCurrentTouchLetter, false);
                }
                break;
            default:
                break;
        }

        return true;
    }
    private LetterTouchListener mListener;

    public void setOnLetterTouchListener(LetterTouchListener listener) {
        this.mListener = listener;
    }

    public interface LetterTouchListener {
        void touch(CharSequence letter, boolean isTouch);
    }
}

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
    <TextView
        android:id="@+id/letter_tv"
        android:layout_width="wrap_content"
        android:layout_centerInParent="true"
        android:text="A"
        android:visibility="gone"
        android:textSize="16sp"
        android:textColor="#FF0000"
        android:layout_height="wrap_content" />

    <com.peakmain.view.lettersidebar.LetterSideBar
        android:id="@+id/letter_side_bar"
        android:layout_width="wrap_content"
        android:layout_alignParentRight="true"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:background="@color/colorPrimary"
        android:layout_height="match_parent" />
</RelativeLayout>

使用

public class MainActivity extends AppCompatActivity implements LetterSideBar.LetterTouchListener {

    private TextView mLetterTv;
    private LetterSideBar mLetterSideBar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLetterTv = (TextView) findViewById(R.id.letter_tv);
        mLetterSideBar = (LetterSideBar) findViewById(R.id.letter_side_bar);
        mLetterSideBar.setOnLetterTouchListener(this);
    }


    @Override
    public void touch(CharSequence letter, boolean isTouch) {
        if(isTouch) {
            mLetterTv.setVisibility(View.VISIBLE);
            mLetterTv.setText(letter);
        }else{
            mLetterTv.setVisibility(View.GONE);
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读