@ZeroGeek
2015-08-18T02:29:47.000000Z
字数 4173
阅读 713
view
android
参考:
http://blog.csdn.net/guolin_blog/article/details/17357967 郭霖的View系列文章(1~4)
http://www.codekk.com/open-source-project-analysis/detail/Android/lightSky/%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%20View%20%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B View绘制流程的源码解析
如果不能理解这个,很难自己定义出无Bug的View.
每一个视图的绘制过程都必须经历三个最主要的阶段,即onMeasure()、onLayout()和onDraw()。
测量,确定位置,绘制。
public class MyView extends View {
......
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(200, 200);
}
}
这样的话就把View默认的测量流程覆盖掉了,不管在布局文件中定义MyView这个视图的大小是多少,最终在界面上显示的大小都将会是200*200。
需要注意的是,在setMeasuredDimension()方法调用之后,我们才能使用getMeasuredWidth()和getMeasuredHeight()来获取视图测量出的宽高,以此之前调用这两个方法得到的值都会是0。
由此可见,视图大小的控制是由父视图、布局文件、以及视图本身共同完成的,父视图会提供给子视图参考的大小,而开发人员可以在XML文件中指定视图的大小,然后视图本身会对最终的大小进行拍板。
OnMeasure()比较容易理解,对于刚入门来说,先好好学习onDraw(),Canvas和Paint的一些用法,一般不会用到onLayout()。
package com.zero.apptest;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
/**
* 简易点赞计数器
* Created by zero on 15-8-18.
*/
public class ClickCountView extends View implements View.OnClickListener{
private Paint mPaint; //画笔
private Rect mBounds; //用来包裹文本的矩形,计算中心,居中显示
private static int mCount = 0; //统计点击的次数
private boolean isClicked; //判断点赞或取消
public ClickCountView(Context context) {
super(context);
initView();
}
public ClickCountView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public ClickCountView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
isClicked = false;
setOnClickListener(this);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint = new Paint();
mBounds = new Rect();
mPaint.setColor(Color.parseColor("#1ABC9C"));
canvas.drawCircle(100, 100, 100, mPaint); //绘制坐标为(100,100),半径为100的圆(第三参数为半径)
mPaint.setTextSize(100);
String text = String.valueOf(mCount);
mPaint.getTextBounds(text, 0, text.length(), mBounds);
mPaint.setColor(Color.parseColor("#7F8C8D"));
final float textWidth = mBounds.width();
final float textHeight = mBounds.height();
//绘制文本,居中显示
canvas.drawText(Integer.toString(mCount), getWidth()/2 - textWidth/2, getHeight()/2 + textHeight/2, mPaint);
}
/**
*限制大小,无论xml中如何设置,都为200*200
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(200,200);
}
@Override
public void onClick(View v) {
if (!isClicked) {
mCount++;
isClicked = true;
} else {
mCount--;
isClicked = false;
}
//每次点击后,重绘视图
invalidate();
}
}
main.xml 代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.zero.apptest.ClickCountView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<com.zero.apptest.ClickCountView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<com.zero.apptest.ClickCountView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<com.zero.apptest.ClickCountView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
尝试运行下吧,哈哈,看看是否如下: