开发中不免会遇到android自带UI控件无法满足需求的情况,这时候就需要我们来自定义一个view。对于我这个不专业的新手来说还是有一定的挑战性的,所以看了很多人写的博客,自己也尝试着写了一个比较简单的自定义view.
参考博客:http://blog.csdn.net/lmj623565791/article/details/24252901
自定义view总的来说就是自定义属性,重写构造方法。在构造方法中获得我们自定义的属性值,重写onMesure和onDraw方法。
首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。
<span style="font-size:18px;color:#009900;"><span style="font-size:14px;color:#009900;"><?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- format的作用就是定义属性 大概有这几种类型(1. reference:参考某一资源ID,2color:颜色值,3boolean:布尔值,
4,dimension:尺寸值,5. float:浮点值,6. integer:整型值,7.string:字符串,8. fraction:百分数,9. enum:枚举值 ,
10. flag:位或运算) 定义属性时可以指定多种类型值,中间用"|"隔开。 这里我 定义了字体,字体颜色,字体大小3个属性
-->
<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></span></span>
然后自定义一个view,重写构造方法
<span style="font-size:14px;color:#009900;background-color: rgb(255, 255, 255);"><span </span>
<span style="font-size:14px;color:#009900;background-color: rgb(255, 255, 255);">style="font-size:14px;color:#009900;">package com.example.viewtext;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class CustomTitleView extends View {
/**
* 文本
*/
private String mTitleText;
/**
* 文本的颜色
*/
private int mTitleTextColor;
/**
* 文本的大小
*/
private int mTitleTextSize;
/**
* 绘制时控制文本绘制的范围
*/
private Rect mBound; //绘制矩形
// Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色 样式等绘制信息,指定了如何绘制文本和图形,
// 画笔对象有很多设置方法大体上可以分为两类,一类与图形绘制相关,一类与文本绘制相关。
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);
//给此view添加点击事件
this.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
mTitleText = randomText();
postInvalidate();
}
});
}
@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(mTitleText, 0, mTitleText.length(), mBound);
float textWidth = mBound.width();
int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
width = desired;
}
if (heightMode == MeasureSpec.EXACTLY)
{
height = heightSize;
} else
{
mPaint.setTextSize(mTitleTextSize);
mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
float textHeight = mBound.height();
int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());
height = desired;
}
setMeasuredDimension(width, height); }
@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);
}
//获取随机数
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();
}
}
</span></span>
最后,布局中调用自定义的view, 一定要引入我们的命名空间( xmlns:custom="http://schemas.android.com/apk/res/com.example.viewtext" )com.example.viewtext是自定义view所在的包名。
<span style="font-size:18px;color:#009900;"><span style="font-size:14px;color:#009900;"><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.viewtext"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context="com.example.viewtext.MainActivity" >
<com.example.viewtext.CustomTitleView
android:layout_width="200dp"
android:layout_height="100dp"
custom:titleText="0000"
custom:titleTextColor="#ff0000"
android:layout_centerInParent="true"
custom:titleTextSize="40sp" />
</RelativeLayout></span></span>
最后运行的效果图: