Android 自定义View (一)
笑对人生,能穿透迷雾;笑对人生,能坚持到底;笑对人生,能化解危机;笑对人生,能照亮黑暗。
本讲内容:自定义View(可以在布局文件多次用)
一、步骤:
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
3、重写onMesure (可有可无,一般需要重写,无写默认调用系统提供的)
4、重写onDraw
注意:
第二步:我们重写了3个构造方法,默认的布局文件调用的是两个参数的构造方法,所以记得让所有的构造方法调用我们的三个参数的构造方法,我们在三个参数的构造中获得自定义属性。
第三步:系统帮我们测量的高度和宽度都是MATCH_PARNET,所以不重写我们无法设置测量的高度和宽度。当我们设置为WRAP_CONTENT,也会显示为MATCH_PARNET。
MeasureSpec的specMode,一共三种类型:
EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED:表示子布局想要多大就多大,很少使用
示例效果图:
下面是res/layout/activity_main.xml
布局文件:
<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.customview1" android:layout_width="match_parent" android:layout_height="match_parent" > <com.view.CustomTitleView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" custom:titleText="1314" custom:titleTextColor="#ff0000" custom:titleTextSize="50sp" /> </RelativeLayout>一定要引入xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我们的命名空间,后面的包路径指的是项目的package
下面是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
下面是自定义CustomTitleView.java文件:
public class CustomTitleView extends View { // 文本 private String mTitleText; // 文本的颜色 private int mTitleTextColor; // 文本的大小 private int mTitleTextSize; // 绘制时控制文本绘制的范围 private Rect mBound; private Paint mPaint; public CustomTitleView(Context context) { this(context, null); } public CustomTitleView(Context context, AttributeSet attrs) { this(context, attrs, 0); } // 获得我自定义的样式属性 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与TextView相比岂不是没什么优势,所以给自定义View添加一个事件: this.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { 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(); } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = 0; int height = 0; // 设置宽度 int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明确指定了 width = getPaddingLeft() + getPaddingRight() + specSize; break; case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT width = getPaddingLeft() + getPaddingRight() + mBound.width(); break; } // 设置高度 specMode = MeasureSpec.getMode(heightMeasureSpec); specSize = MeasureSpec.getSize(heightMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明确指定了 height = getPaddingTop() + getPaddingBottom() + specSize; break; case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT height = getPaddingTop() + getPaddingBottom() + mBound.height(); break; } setMeasuredDimension(width, height); } 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); } }
我们添加了一个点击事件,每次让它随机生成一个4位的随机数,可以在onDraw中添加一点噪点,然后改写为验证码
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Take your time and enjoy it
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。