Android自定义view学习笔记
来源:互联网 发布:95式自动步枪弹道数据 编辑:程序博客网 时间:2024/06/05 09:04
1. 重写OnMesure()用于测量view宽度和高度
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
当自定义view设置固定数值或者设置为 MATCH_PARENT时不需要重写OnMesure(),系统测量为屏幕大小。 当设置了WRAP_CONTENT时,我们需要自己进行测量。
1.1 重写前先了解下MeasureSpec的specMode
MeasureSpec的specMode,一共三种类型:
- EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
- AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
- UNSPECIFIED:表示子布局想要多大就多大,很少使用
2. 自定义View
layout.xml
<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" tools:context="com.example.lee.myapp.MyviewActivity"> <com.example.lee.myapp.MyTextView xmlns:my="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:padding="10dp" android:text="Title" android:textColor="@android:color/holo_orange_dark" android:textSize="16sp" my:mySubText="subTitle" my:mySubTextColor="@android:color/darker_gray" my:subMarginTop="10dp" my:mySubTextSize="12sp"/></RelativeLayout>
attr.xml
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="MyTextView"> <!--使用android自带语义明确属性 --> <attr name="android:text"></attr> <attr name="android:textColor"></attr> <attr name="android:textSize"></attr> <!--自定义个性化属性 --> <attr name="mySubText" format="string"></attr> <attr name="mySubTextColor" format="color"></attr> <attr name="mySubTextSize" format="dimension"></attr> <attr name="subMarginTop" format="dimension"></attr> </declare-styleable></resources>
MyTextView.java
private String mTitleText, mSubTitleText;//内容文字 private int mTitleTextColor, mSubTitleTextColor;//内容文本颜色 private int mTitleTextSize, mSubTitleTextSize;//内容文本大小 private int subMarginTop;//副标题距主标题margin private Rect mBounds, mSubBounds;//文本区域范围 private Paint mPaint;//画笔 private Paint mSubPaint;//副标题画笔 public MyTextView(Context context) { super(context); init(context, null); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView); //屏幕密度 final float density = getResources().getDisplayMetrics().density; mTitleText = typedArray.getString(R.styleable.MyTextView_android_text); mTitleTextColor = typedArray.getColor(R.styleable.MyTextView_android_textColor, Color.BLACK); mTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_android_textSize, (int) (16 * density)); mSubTitleText = typedArray.getString(R.styleable.MyTextView_mySubText); mSubTitleTextColor = typedArray.getColor(R.styleable.MyTextView_mySubTextColor, Color.BLACK); mSubTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_mySubTextSize, (int) (12 * density)); subMarginTop = typedArray.getDimensionPixelSize(R.styleable.MyTextView_subMarginTop, (int) (10 * density)); typedArray.recycle(); mPaint = new Paint(); mPaint.setTextSize(mTitleTextSize); mBounds = new Rect(); //mBound为主标题范围 mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBounds); mSubPaint = new Paint(); mSubPaint.setTextSize(mSubTitleTextSize); mSubPaint.setColor(mSubTitleTextColor); //mSubBounds为副标题范围 mSubBounds = new Rect(); mSubPaint.getTextBounds(mSubTitleText, 0, mSubTitleText.length(), mSubBounds); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); //最终测量的宽高 int width; int height; //EXACTLY模式下直接使用系统测量值 if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { //主标题 float textWidth = mBounds.width(); //副标题 float textSubWidth = mSubBounds.width(); int mWidth = (int) (getPaddingLeft() + Math.max(textWidth, textSubWidth) + getPaddingRight()); width = mWidth; } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { //主标题 float textHeight = mBounds.height(); //副标题 float textSubHeight = mSubBounds.height(); //textHeight + subMarginTop + textSubHeight 内容全部高度 int mHeight = (int) (getPaddingTop() + (textHeight + subMarginTop + textSubHeight) + getPaddingBottom()); height = mHeight; } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.YELLOW); //测量完后再布局 canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); mPaint.setColor(mTitleTextColor); canvas.drawText(mTitleText, getWidth() / 2 - mBounds.width() / 2, (getHeight() - subMarginTop) / 2 , mPaint); canvas.drawText(mSubTitleText, getWidth() / 2 - mSubBounds.width() / 2,(getHeight() + subMarginTop) / 2 + mSubBounds.height(), mSubPaint); }
绘制文本函数:canvas.drawText(“”, x, y, paint);
x:默认是字符的左边在屏幕的位置,如果设置了paint.setTextAlign(Paint.Align.CENTER);那就是字符的中心
y:是指定这个字符baseline在屏幕上的位置
最后
简单的自定义view就这样实现了。 自定义View还一个原因是需要适配屏幕,在不同设备上能自动缩放满足要求,接下来加上缩放。
1 0
- 【Android学习笔记】自定义View
- Android自定义view学习笔记
- Android学习笔记-自定义view
- android 学习笔记(1) ExpandableListActivity 自定义view
- android学习笔记3:自定义view
- Android自定义view学习笔记01
- Android自定义view学习笔记02
- Android自定义View学习笔记03
- Android自定义View学习笔记04
- Android自定义view学习笔记01
- Android自定义view学习笔记02
- Android自定义View学习笔记03
- Android自定义View学习笔记04
- android学习笔记-自定义View的属性
- Android学习笔记-自定义view保存状态
- android自定义view学习笔记1
- 自定义view学习笔记
- android自定义view笔记
- CodeForces 17EPalisection
- Javascript内存优化
- php导出excel报表
- 单击部署hadoop
- 记忆化搜索之Longest Run on a Snowboard
- Android自定义view学习笔记
- 消息队列MQ
- css常用命名参考
- 反射机制获取方法的参数类型和返回值类型
- 新手笔记:java集合汇总
- Linux下/etc/fstab文件详解
- 理解MySQL——索引与优化
- CodeForces 25E Test
- 系统重装后恢复MySQL数据库文件