[关闭]
@ZeroGeek 2015-08-18T02:29:47.000000Z 字数 4173 阅读 601

从Zero开始自定义View (二 )

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绘制流程的源码解析

Android是如何绘制View的?(建议先看上述系列文章)

如果不能理解这个,很难自己定义出无Bug的View.
每一个视图的绘制过程都必须经历三个最主要的阶段,即onMeasure()、onLayout()和onDraw()。
测量,确定位置,绘制。

1.1 onMeasure()

  1. public class MyView extends View {
  2. ......
  3. @Override
  4. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  5. setMeasuredDimension(200, 200);
  6. }
  7. }

这样的话就把View默认的测量流程覆盖掉了,不管在布局文件中定义MyView这个视图的大小是多少,最终在界面上显示的大小都将会是200*200。
需要注意的是,在setMeasuredDimension()方法调用之后,我们才能使用getMeasuredWidth()和getMeasuredHeight()来获取视图测量出的宽高,以此之前调用这两个方法得到的值都会是0。
由此可见,视图大小的控制是由父视图、布局文件、以及视图本身共同完成的,父视图会提供给子视图参考的大小,而开发人员可以在XML文件中指定视图的大小,然后视图本身会对最终的大小进行拍板。

1.2 onLayout()

1.3 onDraw()

注意

OnMeasure()比较容易理解,对于刚入门来说,先好好学习onDraw(),Canvas和Paint的一些用法,一般不会用到onLayout()。

2. 一起来写个小demo

  1. package com.zero.apptest;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.Paint;
  6. import android.graphics.Rect;
  7. import android.util.AttributeSet;
  8. import android.view.View;
  9. /**
  10. * 简易点赞计数器
  11. * Created by zero on 15-8-18.
  12. */
  13. public class ClickCountView extends View implements View.OnClickListener{
  14. private Paint mPaint; //画笔
  15. private Rect mBounds; //用来包裹文本的矩形,计算中心,居中显示
  16. private static int mCount = 0; //统计点击的次数
  17. private boolean isClicked; //判断点赞或取消
  18. public ClickCountView(Context context) {
  19. super(context);
  20. initView();
  21. }
  22. public ClickCountView(Context context, AttributeSet attrs) {
  23. super(context, attrs);
  24. initView();
  25. }
  26. public ClickCountView(Context context, AttributeSet attrs, int defStyleAttr) {
  27. super(context, attrs, defStyleAttr);
  28. initView();
  29. }
  30. private void initView() {
  31. isClicked = false;
  32. setOnClickListener(this);
  33. }
  34. @Override
  35. protected void onDraw(Canvas canvas) {
  36. super.onDraw(canvas);
  37. mPaint = new Paint();
  38. mBounds = new Rect();
  39. mPaint.setColor(Color.parseColor("#1ABC9C"));
  40. canvas.drawCircle(100, 100, 100, mPaint); //绘制坐标为(100,100),半径为100的圆(第三参数为半径)
  41. mPaint.setTextSize(100);
  42. String text = String.valueOf(mCount);
  43. mPaint.getTextBounds(text, 0, text.length(), mBounds);
  44. mPaint.setColor(Color.parseColor("#7F8C8D"));
  45. final float textWidth = mBounds.width();
  46. final float textHeight = mBounds.height();
  47. //绘制文本,居中显示
  48. canvas.drawText(Integer.toString(mCount), getWidth()/2 - textWidth/2, getHeight()/2 + textHeight/2, mPaint);
  49. }
  50. /**
  51. *限制大小,无论xml中如何设置,都为200*200
  52. */
  53. @Override
  54. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  55. setMeasuredDimension(200,200);
  56. }
  57. @Override
  58. public void onClick(View v) {
  59. if (!isClicked) {
  60. mCount++;
  61. isClicked = true;
  62. } else {
  63. mCount--;
  64. isClicked = false;
  65. }
  66. //每次点击后,重绘视图
  67. invalidate();
  68. }
  69. }

main.xml 代码:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6. <com.zero.apptest.ClickCountView
  7. android:layout_width="match_parent"
  8. android:layout_height="wrap_content"
  9. android:layout_gravity="center" />
  10. <com.zero.apptest.ClickCountView
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:layout_gravity="center" />
  14. <com.zero.apptest.ClickCountView
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:layout_gravity="center" />
  18. <com.zero.apptest.ClickCountView
  19. android:layout_width="match_parent"
  20. android:layout_height="wrap_content"
  21. android:layout_gravity="center" />
  22. </LinearLayout>

尝试运行下吧,哈哈,看看是否如下:
效果图

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注