自定义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); }}
阅读全文
1 0
- 自定义view
- 自定义View
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义View
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- day_09_继承
- 面向对象三大特性、五大基本原则
- 1043. 输出PATest
- C++多态性与虚函数
- ZK7+Spring4+Hibernate4框架整合并实现基本查询
- 自定义View
- CC2640R2F BLE5.0 蓝牙协议栈GAP Bond管理和LE安全连接
- IDEA 使用SVN时忽略class文件
- C++ 通过WIN32 API 获取逻辑磁盘详细信息
- 一次性计时器和间隔性计时器实现永久性计时器
- Java实现Find All Numbers Disappeared in an Array
- Shell 命令行统计 apache 网站日志访问IP以及IP归属地
- js导出数据,浏览器(内核必须支持<a> download 属性或Blob对象创建)兼容
- linux中yum命令的使用