Android 自定义控件学习之一 基础知识
来源:互联网 发布:js修改font的值 编辑:程序博客网 时间:2024/06/06 18:19
基本实现 步骤1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
[ 3、重写onMesure ]
4、重写onDraw
在最新的andriod studio 中,选择自定义空间,它会生成相应的attr 文件,布局文件,属性实现文件,通过这三个文件,我们就可以设计自己的控件。
- <resources>
- <declare-styleable name="MyTextView">
- <attr name="codeString" format="string" />
- <attr name="codeDimension" format="dimension" />
- <attr name="codeColor" format="color" />
- <attr name="codeDrawable" format="color|reference" />
- </declare-styleable>
- </resources>
我们定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:
一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;不清楚的可以google一把。
然后在布局中声明我们的自定义View
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="com.selftextview.MainActivity">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="@dimen/activity_vertical_margin"
- android:id="@+id/codes_linear">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1">
- <EditText
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/codes"
- android:hint="@string/codes"
- android:textSize="21sp"/>
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:weightSum="1">
- <com.selftextview.MyTextView
- android:layout_width="match_parent"
- android:layout_height="58dp"
- android:background="#c1c7c3"
- app:codeColor="#33b5e5"
- app:codeDimension="24sp"
- app:codeString="@string/codes"
- />
- </LinearLayout>
- </LinearLayout>
- <Button
- android:layout_below="@id/codes_linear"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/sureBtn"
- android:text="@string/sure"
- />
- </RelativeLayout>
- <span style="color:#555555;"> private Paint paint = new Paint();
- /**
- * 验证码内容
- */
- private String[] content = null;
- /**
- * 验证码图片
- */
- private Bitmap bitmap = null;
- private String mCodeString;
- private int mCodeColor = Color.RED;
- private float mCodeDimension = 0;
- private Drawable mCodeDrawable;
- private TextPaint mTextPaint;
- private float mTextWidth;
- private float mTextHeight;
- public MyTextView(Context context) {
- super(context);
- init(null, 0);
- }
- public MyTextView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(attrs, 0);
- }
- public MyTextView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init(attrs, defStyle);
- }
- private void init(AttributeSet attrs, int defStyle) {
- // Load attributes
- final TypedArray a = getContext().obtainStyledAttributes(
- attrs, R.styleable.MyTextView, defStyle, 0);
- //mCodeString = a.getString(
- // R.styleable.MyTextView_codeString);
- mCodeString = randomText();
- mCodeColor = a.getColor(
- R.styleable.MyTextView_codeColor,
- mCodeColor);
- // Use getDimensionPixelSize or getDimensionPixelOffset when dealing with
- // values that should fall on pixel boundaries.
- mCodeDimension = a.getDimension(
- R.styleable.MyTextView_codeDimension,
- mCodeDimension);
- if (a.hasValue(R.styleable.MyTextView_codeDrawable)) {
- mCodeDrawable = a.getDrawable(
- R.styleable.MyTextView_codeDrawable);
- mCodeDrawable.setCallback(this);
- }
- a.recycle();
- // Set up a default TextPaint object
- mTextPaint = new TextPaint();
- mTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- mTextPaint.setTextAlign(Paint.Align.LEFT);
- invalidateTextPaintAndMeasurements();
- this.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCodeString = randomText();
- postInvalidate(); /</span><span style="color:#ff6666;">/通过这个方法重新绘制</span><span style="color:#555555;">
- }
- });
- }</span>
3.绘制该View
- private void invalidateTextPaintAndMeasurements() {
- mTextPaint.setTextSize(mCodeDimension);
- mTextPaint.setColor(mCodeColor);
- mTextWidth = mTextPaint.measureText(mCodeString);
- Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
- mTextHeight = fontMetrics.bottom;
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- // allocations per draw cycle.
- int paddingLeft = getPaddingLeft();
- int paddingTop = getPaddingTop();
- int paddingRight = getPaddingRight();
- int paddingBottom = getPaddingBottom();
- int contentWidth = getWidth() - paddingLeft - paddingRight;
- int contentHeight = getHeight() - paddingTop - paddingBottom;
- // Draw the text.
- canvas.drawText(mCodeString,
- paddingLeft + (contentWidth - mTextWidth) / 2,
- paddingTop + (contentHeight + mTextHeight) / 2,
- mTextPaint);
- // Draw the example drawable on top of the text.
- if (mCodeDrawable != null) {
- mCodeDrawable.setBounds(paddingLeft, paddingTop,
- paddingLeft + contentWidth, paddingTop + contentHeight);
- mCodeDrawable.draw(canvas);
- }
- }
4.关于onmeasure 的相关介绍
把布局文件的宽和高写成wrap_content ,会发生铺满全屏的现象。
这里是鸿洋大神写的解释
系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。
所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:
重写之前先了解MeasureSpec的specMode,一共三种类型:
EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED:表示子布局想要多大就多大,很少使用
下面是我们重写onMeasure代码:
- @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 ;
- if (widthMode == MeasureSpec.EXACTLY)
- {
- width = widthSize;
- } else
- {
- mPaint.setTextSize(mTitleTextSize);
- mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);
- float textWidth = mBounds.width();
- int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
- width = desired;
- }
- if (heightMode == MeasureSpec.EXACTLY)
- {
- height = heightSize;
- } else
- {
- mPaint.setTextSize(mTitleTextSize);
- mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);
- float textHeight = mBounds.height();
- int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());
- height = desired;
- }
- setMeasuredDimension(width, height);
- }
通过上面的实现可以实现文字的wrap_conent
0 0
- Android 自定义控件学习之一 基础知识
- Android 自定义控件学习之一 基础知识
- Android自定义控件之一
- android 自定义控件之一
- android 自定义控件基础知识1
- Android 自定义控件 基础概述之一
- android 自定义控件学习
- Android自定义控件学习
- android自定义控件--学习
- Android自定义控件基础知识----View的生命周期
- Android自定义控件前导基础知识学习(一)——Canvas
- android 自定义控件系列之一 圆形图控件
- 学习STL之一 基础知识
- android学习笔记之一常用控件
- android学习笔记之一常用控件
- android listView控件学习之一
- 自定义控件基础知识
- 自定义控件基础知识
- linux下命令与文件的查询
- 将博客搬至CSDN
- 浏览器缓存机制
- List去掉重复对象
- Eclipse tomcat 配置问题
- Android 自定义控件学习之一 基础知识
- 基因数据处理48之ART使用实例
- Android : AlarmManager
- object-c中#import #include @class的区别
- Android APP 禁用横竖屏切换
- iOS_如何画1px的线
- 嵌入式Linux基础知识0(什么是真正的实时操作系统--硬实时 软实时)
- linux系统c++线程池的实现
- 用异步获取网络数据Json