自定义View

View基类呈现一个100x100像素的空白正方形,要改变控件的大小并呈现一个不同的界面则需要分别对onMesure和onDraw方法进行重写。
onMesure方法中,新的视图将会计算一系列给定的边界条件下占据的高度和宽度。
onDraw方法用于在画布上进行绘图。

实例代码

下面代码中定义了一个MyView继承自View:

public class MyView extends View {

  // 代码中创建View时调用的构造函数
  public MyView(Context context) {
    super(context);
  }

  // 根据xml中的定义的资源创建View是调用的构造函数,定义默认样式
  public MyView (Context context, AttributeSet ats, int defaultStyle) {
    super(context, ats, defaultStyle );
  }

  //同上,无定义样式
  public MyView (Context context, AttributeSet attrs) {
    super(context, attrs);
  }

//  @Override
//  protected void onMeasure(int wMeasureSpec, int hMeasureSpec) {
//    int measuredHeight = measureHeight(hMeasureSpec);
//    int measuredWidth = measureWidth(wMeasureSpec);
//
//    // 必须调用setMeasuredDimension这个方法
//    // 否则当要显示视图时会报一个运行时的错误
//    setMeasuredDimension(measuredHeight, measuredWidth);
//  }
//  
//  private int measureHeight(int measureSpec) {
//    int specMode = MeasureSpec.getMode(measureSpec);
//    int specSize = MeasureSpec.getSize(measureSpec);
//
//     // [ ... 计算View的高度 ... ]
//
//     return specSize;
//  }
//
//  private int measureWidth(int measureSpec) {
//    int specMode = MeasureSpec.getMode(measureSpec);
//    int specSize = MeasureSpec.getSize(measureSpec);
//
//     // [ ... 计算View的宽度 ... ]
//
//     return specSize;
//  }
//
//  @Override
//  protected void onDraw(Canvas canvas) {
//    // [ ... 绘制的自己定义的视图 ... ]
//  }

  /**
   * Listing 4-16: Drawing a custom View
   */
  @Override
  protected void onDraw(Canvas canvas) {
    // 根据最后一次调用onMeasure方法获得的大小.
    int height = getMeasuredHeight();
    int width = getMeasuredWidth();

    // 获取视图中心点
    int px = width/2;
    int py = height/2;

    // 创建一个新的画刷
    // 注意: 考虑性能的话,应该在视图初始化调用的构造函数
    // 中初始化Paint
    Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mTextPaint.setColor(Color.WHITE);

    //定义要显示的文本
    String displayText = "Hello World!";

    // 计算文本的宽度
    float textWidth = mTextPaint.measureText(displayText);

    //在视图中心绘制文本
    canvas.drawText(displayText, px-textWidth/2, py, mTextPaint);
  }

  /**
   * Listing 4-17: 常见视图绘制的实现
   */
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int measuredHeight = measureHeight(heightMeasureSpec);
    int measuredWidth = measureWidth(widthMeasureSpec);

    setMeasuredDimension(measuredHeight, measuredWidth);
  }

  private int measureHeight(int measureSpec) {
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    //  如果没有限定大小的话,默认为500
    int result = 500;

    if (specMode == MeasureSpec.AT_MOST) {
      // Calculate the ideal size of your
      // control within this maximum size.
      // If your control fills the available
      // space return the outer bound.
      result = specSize;
    } else if (specMode == MeasureSpec.EXACTLY) {
      // If your control can fit within these bounds return that value.
      result = specSize;
    }
    return result;
  }

  private int measureWidth(int measureSpec) {
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    //  Default size if no limits are specified.
    int result = 500;

    if (specMode == MeasureSpec.AT_MOST) {
      // Calculate the ideal size of your control
      // within this maximum size.
      // If your control fills the available space
      // return the outer bound.
      result = specSize;
    } else if (specMode == MeasureSpec.EXACTLY) {
      // If your control can fit within these bounds return that value.
      result = specSize;
    }
    return result;
  }

  /**
   * Listing 4-18: 视图的输入事件
   */
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
    // 如果onKeyDown这个事件被处理了则返回true
    return true;
  }

  @Override
  public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
    // 如果onKeyUp事件被处理了则返回true
    return true;
  }

  @Override
  public boolean onTrackballEvent(MotionEvent event ) {
    // 获取当前事件表示的动作
    int actionPerformed = event.getAction();
    //如果当前事件被处理则返回true
    return true;
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    // 获取当前事件表示的动作
    int actionPerformed = event.getAction();
    // 返回true,如果当前事件被处理的话
    return true;
  }
}

小结

从上面的实例可以看出,自定义View的基本步骤:
1. 自定义View类继承自View;
2. 重写onMesure方法,新的视图将会计算一系列给定的边界条件下占据的高度和宽度。
3. 重写onDraw方法用于在画布上进行绘图,绘制你想展示的界面。
4. 常用的类:Paint(画笔) 和 onDraw方法中的参数Canvas canvas (画布)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值