andorid 自定义view的学习

今天学习了一下自定义view,根据提供的官方文档。

首先,我建立了一个自定义的class文件(Customview),继承View。然后我们对构造函数进行重写。这里问题来了:如果我们重写以这种方式


public CustomView(Context context) { 
           super(context,null);
        }

然后对xml去引用咱们自定的view

那么就会报错。 为什么呢?在xml文件引用我们的CustomView类时为其指定了两个android自带的两个属性:layout_width和layout_height,当我们需要使用类似的属性(比如更多的什么id啊、padding啊、margin啊之类)时必须在自定义View的构造方法中添加一个AttributeSet类型的签名来解析这些属性:

public class CustomView extends View {
​
  public CustomView(Context context) {
​
    super(context);
​
  }
  
​
  public CustomView(Context context, AttributeSet attrs) {
​
    super(context, attrs);
​
  }
​
}

ok,接下来添加一些东西,我们需要做的是创建画布和画笔

关于画布Canvas,我们可以看到在onDraw方法中,画布Canvas作为签名被传递进来,也就是说这个画布是Android为我们准备好的,不需要你去管.所以我们只需要设置画笔相关的就ok了。Paint类。这里为了节省性能,防止画笔反复被创建,我们在外部声明,用init方法去初始化他。

代码块
public class CustomView extends View {
​
  private Paint mPaint;
​
 
​
  public CustomView(Context context) {
​
    this(context, null);
​
  }
​
 
​
  public CustomView(Context context, AttributeSet attrs) {
​
    super(context, attrs);
​
 
​
    // 初始化画笔
​
    initPaint();
​
  }
​
 
​
  /**
​
   * 初始化画笔
​
   */
​
  private void initPaint() {
​
    // 实例化画笔并打开抗锯齿
​
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
​
  }
​
 
​
  @Override
​
  protected void onDraw(Canvas canvas) {
​
    super.onDraw(canvas);
​
  }
​
}
我们可以用 画笔对象名.setXXX()的方式去为我们的画笔设置一些颜色,样式等。

然后在onDraw方法里对图像绘制。

@Override

protected void onDraw(Canvas canvas) {

	super.onDraw(canvas);

 

	// 绘制圆环

	canvas.drawCircle(float x, float y, 200, mPaint);

}

x,y分别是需要传入的float形参数,表示圆心的坐标,第三个是半径,第四个是画笔对象。

不错吧?我们的第一个view完成啦。

在Android中提供了一个叫invalidate()的方法来让我们重绘我们的View。利用它,我们好像可以让view动起来。

我们可以在主线程中刷新它,但是好像过于繁琐,我们直接用它implent runnable 接口试试。

我们修改一下代码


public class CustomView extends View implements Runnable {
​
  private Paint mPaint;// 画笔
​
  private Context mContext;// 上下文环境引用
​
 
​
  private int radiu;// 圆环半径
​
 
​
  public CustomView(Context context) {
​
    this(context, null);
​
  }
​
 
​
  public CustomView(Context context, AttributeSet attrs) {
​
    super(context, attrs);
​
    mContext = context;
​
 
​
    // 初始化画笔
​
    initPaint();
​
  }
​
 
​
  /**
​
   * 初始化画笔
​
   */
​
  private void initPaint() {
​
    // 实例化画笔并打开抗锯齿
​
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
​
 
​
    /*
​
     * 设置画笔样式为描边,圆环嘛……当然不能填充不然就么意思了
​
     * 
​
     * 画笔样式分三种:
​
     * 1.Paint.Style.STROKE:描边
​
     * 2.Paint.Style.FILL_AND_STROKE:描边并填充
​
     * 3.Paint.Style.FILL:填充
​
     */
​
    mPaint.setStyle(Paint.Style.STROKE);
​
 
​
    // 设置画笔颜色为浅灰色
​
    mPaint.setColor(Color.LTGRAY);
​
 
​
    /*
​
     * 设置描边的粗细,单位:像素px
​
     * 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
​
     */
​
    mPaint.setStrokeWidth(10);
​
  }
​
 
​
  @Override
​
  protected void onDraw(Canvas canvas) {
​
    super.onDraw(canvas);
​
 
​
    // 绘制圆环
​
    canvas.drawCircle(MeasureUtil.getScreenSize((Activity) mContext)[0] / 2, MeasureUtil.getScreenSize((Activity) mContext)[1] / 2, radiu, mPaint);
​
  }
​
 
​
  @Override
​
  public void run() {
​
    /*
​
     * 确保线程不断执行不断刷新界面
​
     */
​
    while (true) {
​
      try {
​
        /*
​
         * 如果半径小于200则自加否则大于200后重置半径值以实现往复
​
         */
​
        if (radiu <= 200) {
​
          radiu += 10;
​
 
​
          // 刷新View,不能直接用invalid,因为主线程才能刷新ui
​
          postInvalidate()
​
        } else {
​
          radiu = 0;
​
        }
​
 
​
        // 每执行一次暂停40毫秒
​
        Thread.sleep(40);
​
      } catch (InterruptedException e) {
​
        e.printStackTrace();
​
      }
​
    }
​
  }
​
}

这里将postInvalid()我们不去深究,应该是通知主线程去刷了,但是这样开发会降低耦合? 个人观点。这样就实现了动画view开发!!!

但是我也有一些疑问如下,

context到底是什么用?

-----------------------分界线-----------------------

栋哥告诉我,最好不要把组件放在线程里,这是典型的内存泄漏场景。好吧,老老实实用handler吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值