转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/24252901

非常Android入门程序员AndroidView。可能都是比較恐惧的。可是这又是高手进阶的必经之路。全部准备在自己定义View上面花一些功夫,多写一些文章。

先总结下自己定义View的步骤:

1、自己定义View的属性

2、在View的构造方法中获得我们自己定义的属性

[ 3、重写onMesure ]

4、重写onDraw

我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是须要重写的。

1、自己定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。

<?xml version="1.0" encoding="utf-8"?

>
<resources> <attr name="titleText" format="string" />
<attr name="titleTextColor" format="color" />
<attr name="titleTextSize" format="dimension" /> <declare-styleable name="CustomTitleView">
<attr name="titleText" />
<attr name="titleTextColor" />
<attr name="titleTextSize" />
</declare-styleable> </resources>

我们定义了字体。字体颜色,字体大小3个属性,format是值该属性的取值类型:

一共同拥有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;不清楚的能够google一把。

然后在布局中声明我们的自己定义View

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"
android:layout_width="match_parent"
android:layout_height="match_parent" > <com.example.customview01.view.CustomTitleView
android:layout_width="200dp"
android:layout_height="100dp"
custom:titleText="3712"
custom:titleTextColor="#ff0000"
custom:titleTextSize="40sp" /> </RelativeLayout>

一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我们的命名空间,后面的包路径指的是项目的package

2、在View的构造方法中,获得我们的自己定义的样式

/**
* 文本
*/
private String mTitleText;
/**
* 文本的颜色
*/
private int mTitleTextColor;
/**
* 文本的大小
*/
private int mTitleTextSize; /**
* 绘制时控制文本绘制的范围
*/
private Rect mBound;
private Paint mPaint; public CustomTitleView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
} public CustomTitleView(Context context)
{
this(context, null);
} /**
* 获得我自己定义的样式属性
*
* @param context
* @param attrs
* @param defStyle
*/
public CustomTitleView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
/**
* 获得我们所定义的自己定义样式属性
*/
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.CustomTitleView_titleText:
mTitleText = a.getString(attr);
break;
case R.styleable.CustomTitleView_titleTextColor:
// 默认颜色设置为黑色
mTitleTextColor = a.getColor(attr, Color.BLACK);
break;
case R.styleable.CustomTitleView_titleTextSize:
// 默认设置为16sp。TypeValue也能够把sp转化为px
mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
break; } }
a.recycle(); /**
* 获得绘制文本的宽和高
*/
mPaint = new Paint();
mPaint.setTextSize(mTitleTextSize);
// mPaint.setColor(mTitleTextColor);
mBound = new Rect();
mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); }

我们重写了3个构造方法。默认的布局文件调用的是两个參数的构造方法,所以记得让全部的构造调用我们的三个參数的构造,我们在三个參数的构造中获得自己定义属性。

3、我们重写onDraw,onMesure调用系统提供的:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} @Override
protected void onDraw(Canvas canvas)
{
mPaint.setColor(Color.YELLOW);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTitleTextColor);
canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
}

此时的效果是:

是不是认为还不错。基本已经实现了自己定义View。可是此时假设我们把布局文件的宽和高写成wrap_content,会发现效果并非我们的预期:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

系统帮我们測量的高度和宽度都是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);
}

如今我们改动下布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"
android:layout_width="match_parent"
android:layout_height="match_parent" > <com.example.customview01.view.CustomTitleView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:titleText="3712"
android:padding="10dp"
custom:titleTextColor="#ff0000"
android:layout_centerInParent="true"
custom:titleTextSize="40sp" /> </RelativeLayout>

如今的效果是:

全然复合我们的预期,如今我们能够对高度、宽度进行随便的设置了,基本能够满足我们的需求。

当然了,这样下来我们这个自己定义View与TextView相比岂不是没什么优势,全部我们认为给自己定义View加入一个事件:

在构造中加入:

this.setOnClickListener(new OnClickListener()
{ @Override
public void onClick(View v)
{
mTitleText = randomText();
postInvalidate();
} });
private String randomText()
{
Random random = new Random();
Set<Integer> set = new HashSet<Integer>();
while (set.size() < 4)
{
int randomInt = random.nextInt(10);
set.add(randomInt);
}
StringBuffer sb = new StringBuffer();
for (Integer i : set)
{
sb.append("" + i);
} return sb.toString();
}

以下再来执行:

我们加入了一个点击事件,每次让它随机生成一个4位的随机数,有兴趣的能够在onDraw中加入一点噪点。然后改写为验证码。是不是感觉非常不错。

好了,各位学习的,打酱油的留个言。顶个呗~

源代码点击此处下载

版权声明:本文博主原创文章,博客,未经同意不得转载。

Android 它们的定义View (一)的更多相关文章

  1. 【Android】自己定义View、画家(画布)Canvas与画笔Paint的应用——绘图、涂鸦板app的实现

    利用一个简单的绘图app来说明安卓的图形处理类与自己定义View的应用. 例如以下图,有一个供用户自己随意绘图.涂鸦的app. 这里不做那么花俏了,仅提供黑白两色.但能够改变笔尖的粗细. 实质上这里的 ...

  2. Android 它们的定义View它BounceProgressBar

    转载请注明出处:http://blog.csdn.net/bbld_/article/details/41246247 [Rocko's blog] 之前几天下载了非常久没用了的桌面版酷狗来用用的时候 ...

  3. Android 开发 -------- 自己定义View 画 五子棋

    自己定义View  实现 五子棋 配图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG92ZV9KYXZjX3lvdQ==/font/5a6L5L2T ...

  4. 【Android】自己定义View

    翻译自:http://developer.android.com/training/custom-views/index.html 一)创建view类 一个设计良好的自己定义view与其它的类一样.它 ...

  5. Android 它们的定义View

    安卓开发过程,安卓官方控制有时来自往往不能满足我们的需求.这一次,我必须定义自己.下面我们就来看看他们的定义View: package com.example.myview; import andro ...

  6. Android 它们的定义View视图

    创建一个新视图将满足我们独特UI需求. 本文介绍的发展将指南针罗盘接口使用UI,通过继承View定义自己的视图类工具,为了深入了解自己的自定义视图. 实现效果图: 源码: 布局文件activity_m ...

  7. 【Android】利用自己定义View的重绘实现拖动移动,获取组件的尺寸

    以下利用一个app来说明怎样利用自己定义View的重绘实现拖动移动.获取组件的尺寸. 例如以下图,触摸拖动,或者轻轻点击屏幕都能移动图片.假设碰到文字,则会弹出提示. 这里是利用自己定义View的重绘 ...

  8. Android 自己定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自己定义View之旅.前面已经介绍过一个自己定义View的基础 ...

  9. 【android自己定义控件】自己定义View属性

    1.自己定义View的属性 2.在View的构造方法中获得我们自己定义的属性 3.重写onMesure 4.重写onDraw 3这个步骤不是必须,当然了大部分情况下还是须要重写的. 1.自己定义Vie ...

随机推荐

  1. tls和ssl

    一个存在于 SSL 3.0 协议中的新漏洞于被披露,通过此漏洞,第三方可以拦截通过采用 SSL 3.0 的服务器传输的重要信息. 问题出在哪里? 与此问题相关的不是 SSL 证书本身,而是进行加密处理 ...

  2. 杭电oj 3361

    Tips:字符在计算机中都是以ASCII码形式保存,直接以char形式输出ASCII码即可. #include<stdio.h> int main() { int T; scanf(&qu ...

  3. 如何不让oracle使用linux的swap分区

    经常看到swap分区被使用,被缓存的内容本来是为了增加命中率,结果去不断换入换出,导致本地磁盘IO增加,影响访问速度.所以在内存充足的情况下,如果我们觉得不需要使用swap分区的时候,那就要想办法尽量 ...

  4. odd number、 even number

    odd number 奇数 even number 偶数

  5. OpenCV——PS 图层混合算法(一)

    详细的算法原理能够參考 PS图层混合算法之中的一个(不透明度,正片叠底,颜色加深,颜色减淡) // PS_Algorithm.h #ifndef PS_ALGORITHM_H_INCLUDED #de ...

  6. Swift的初始化方法

    我们在深入初始化方法之前,不妨先再想想Swift中的初始化想要达到一种怎样的目的. 其实就是安全.在Objective-C中,init方法是非常不安全的:没有人能保证init只被调用一次,也没有人保证 ...

  7. Format类及其子类功能和使用方法具体解释

    Format类及其子类功能和使用方法具体解释 1.   Format类结构: ·        java.lang.Object ·        java.text.Format ·         ...

  8. POJ 3468 A Simple Problem with Integers(线段树区间求和)

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  9. 从Ecma规范深入理解js中的this的指向

    this是面向对象编程中的一个概念,它一般指向当前方法调用所在的对象,这一点在java.c++这类比较严格的面向对象编程语言里是非常明确的.但是在javascript中,this的定义要灵活许多,如果 ...

  10. Oracle使用imp/exop远程导入导出dmp数据

    在导入导出数据之前,习惯性的检查一下,看看我们自己的机器可不可以连接远程的Oracle主机,检测方法是tnsping SERVICE_NAME.我的机器如下: C:\Users\zx>tnspi ...