自定义View

来源:互联网 发布:网络婚姻网 编辑:程序博客网 时间:2024/06/03 19:39

一直都是看别人的博客,昨天自己写了一个字母索引列表的View,就想自己也写一个博客供大家相互交流。好了,废话不多说开始吧!

一、分析一下字母索引列表需要的自定义属性

字母索引列表就是A-Z#这27个字符,在这里只要设置字体大小和字体颜色就行了。

1、在res下的values文件夹下新建一个attrs.xml(名称可以自定义),在xml文件中写入下面代码就行
<declare-styleable name="LetterIndexView">        <attr name="letterTextSize" format="dimension"/>        <attr name="letterTextColor" format="color"/>    </declare-styleable>
2、在自定义的View中获取自定义的属性
public class LetterIndexView extends View {        private int mTextSize = 10;        private int mTextColor = Color.BLACK;private Paint mPaint;        public LetterIndexView(Context context) {            this(context, null);        }        public LetterIndexView(Context context, @Nullable AttributeSet attrs) {            this(context, attrs, 0);        }        public LetterIndexView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {            super(context, attrs, defStyleAttr);            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LetterIndexView);            mTextSize = typedArray.getDimensionPixelSize(R.styleable.LetterIndexView_letterTextSize, mTextSize);            mTextColor = typedArray.getColor(R.styleable.LetterIndexView_letterTextColor, mTextColor);            typedArray.recycle();      mPaint = new Paint();//初始化画笔            mPaint.setColor(mTextColor);            mPaint.setTextSize(mTextSize);            mPaint.setAntiAlias(true);//抗锯齿 } }

这样自定义属性就写好了。

二、重新onDraw()方法进行绘制

 @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //每个字母所占用的高度        float singleHeight = mViewHeight / mLetters.length;        for (int i = 0; i < mLetters.length; i++) {            String letter = mLetters[i];            //判断加上mCurrentIsTouch可使手指抬起颜色变回去            if (letter.equals(mCurrentTouchLetter)){                mPaint.setColor(Color.RED);            }else {                mPaint.setColor(mTextColor);            }            //获取字体的宽度            float measureTextWidth = mPaint.measureText(letter);            //获取内容的宽度            int contentWidth = getWidth() - getPaddingLeft() - getPaddingRight();            float x = getPaddingLeft() + (contentWidth-measureTextWidth) / 2;            //计算基线位置            Paint.FontMetrics fontMetrics=mPaint.getFontMetrics();            float baseLine=singleHeight/2+(singleHeight*i)+(fontMetrics.bottom-fontMetrics.top)/2-fontMetrics.bottom;            canvas.drawText(letter,x,baseLine,mPaint);        }    }

三、重写onTouch()方法设置触摸监听

    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:            case MotionEvent.ACTION_MOVE:                float fingerY=event.getY();                float singleHeight = mViewHeight / mLetters.length;                int position= (int) (fingerY/singleHeight);                if (mLetters[position].equals(mCurrentTouchLetter)){                    return true;                }                mCurrentTouchLetter = mLetters[position];                mCurrentIsTouch = true;                if (mTouchListener!=null){                    mTouchListener.onTouch(mCurrentTouchLetter,mCurrentIsTouch);                }                break;            case MotionEvent.ACTION_UP:                mCurrentIsTouch = false;                if (mTouchListener!=null){                    mTouchListener.onTouch(mCurrentTouchLetter,mCurrentIsTouch);                }                break;        }        invalidate();//重新绘制,调用onDraw()方法        return true;    }    private SideBarTouchListener mTouchListener;    public void setTouchListener(SideBarTouchListener mTouchListener) {        this.mTouchListener = mTouchListener;    }    public interface SideBarTouchListener{        void onTouch(String litter,boolean isTouch);    }

四、重新onMeasure()方法

在onMeasure()方法中计算要绘制的View的大小
    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        mViewWidth = widthSize;        if (heightMode == MeasureSpec.AT_MOST) {            mViewHeight = getHeight();        } else {            mViewHeight = heightSize;        }        setMeasuredDimension(mViewWidth, mViewHeight);    }

下面是完整的控件代码:
public class LetterIndexView extends View {    private int mTextSize = 10;    private int mTextColor = Color.BLACK;    private Paint mPaint;    private 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 int mViewHeight;    private int mViewWidth;    private String mCurrentTouchLetter;    private boolean mCurrentIsTouch;    public LetterIndexView(Context context) {        this(context, null);    }    public LetterIndexView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public LetterIndexView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LetterIndexView);        mTextSize = typedArray.getDimensionPixelSize(R.styleable.LetterIndexView_letterTextSize, mTextSize);        mTextColor = typedArray.getColor(R.styleable.LetterIndexView_letterTextColor, mTextColor);        typedArray.recycle();        mPaint = new Paint();        mPaint.setColor(mTextColor);        mPaint.setTextSize(mTextSize);        mPaint.setAntiAlias(true);//抗锯齿    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        mViewWidth = widthSize;        if (heightMode == MeasureSpec.AT_MOST) {            mViewHeight = getHeight();        } else {            mViewHeight = heightSize;        }        setMeasuredDimension(mViewWidth, mViewHeight);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //每个字母所占用的高度        float singleHeight = mViewHeight / mLetters.length;        for (int i = 0; i < mLetters.length; i++) {            String letter = mLetters[i];            //判断加上mCurrentIsTouch可使手指抬起颜色变回去            if (letter.equals(mCurrentTouchLetter)){                mPaint.setColor(Color.RED);            }else {                mPaint.setColor(mTextColor);            }            //获取字体的宽度            float measureTextWidth = mPaint.measureText(letter);            //获取内容的宽度            int contentWidth = getWidth() - getPaddingLeft() - getPaddingRight();            float x = getPaddingLeft() + (contentWidth-measureTextWidth) / 2;            //计算基线位置            Paint.FontMetrics fontMetrics=mPaint.getFontMetrics();            float baseLine=singleHeight/2+(singleHeight*i)+(fontMetrics.bottom-fontMetrics.top)/2-fontMetrics.bottom;            canvas.drawText(letter,x,baseLine,mPaint);            //Log.e("===LetterIndexView==","字体的宽度:measureTextWidth="+measureTextWidth+",内容的宽度:contentWidth="+contentWidth+",x="+x);            Log.e("===LetterIndexView==","fontMetrics.top="+fontMetrics.top+",fontMetrics.bottom="+fontMetrics.bottom+",baseLine="+baseLine);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:            case MotionEvent.ACTION_MOVE:                float fingerY=event.getY();                float singleHeight = mViewHeight / mLetters.length;                int position= (int) (fingerY/singleHeight);                if (mLetters[position].equals(mCurrentTouchLetter)){                    return true;                }                mCurrentTouchLetter = mLetters[position];                mCurrentIsTouch = true;                if (mTouchListener!=null){                    mTouchListener.onTouch(mCurrentTouchLetter,mCurrentIsTouch);                }                break;            case MotionEvent.ACTION_UP:                mCurrentIsTouch = false;                if (mTouchListener!=null){                    mTouchListener.onTouch(mCurrentTouchLetter,mCurrentIsTouch);                }                break;        }        invalidate();        return true;    }    private OnLitterTouchListener mTouchListener;    public void setOnLetterTouchListener(OnLitterTouchListener mTouchListener) {        this.mTouchListener = mTouchListener;    }    public interface OnLitterTouchListener{        void onTouch(String litter,boolean isTouch);    }}







原创粉丝点击