自定义view及优化

参考链接:自定义View,有这一篇就够了 - 简书

1.2 自定义 View | 菜鸟教程

自定义view

当Android系统内置的View无法实现我们的需求时,我们可以根据要求制订自己的View。自定义view大约需要这几步:

  1. 继承View类

  2. 至少重写两个构造函数

  3. 重写onMeasure(),onDraw(),onLayout()(可不写)

具体:

onMeasure():

@Override
    protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
        //接下来就是根据父view的MeasureSpec和一些条件确定大小
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
       。。。。
        setMeasuredDimension(width,height);//传入的参数为最终view的大小
    }

onDraw():

例如绘制一个圆

 @Override
    protected void onDraw(Canvas canvas) {
        //调用父View的onDraw函数,因为View这个类帮我们实现了一些
        // 基本的而绘制功能,比如绘制背景颜色、背景图片等
        super.onDraw(canvas);
        int r = getMeasuredWidth() / 2;//也可以是getMeasuredHeight()/2,本例中我们已经将宽高设置相等了
        //圆心的横坐标为当前的View的左边起始位置+半径
        int centerX = getLeft() + r;
        //圆心的纵坐标为当前的View的顶部起始位置+半径
        int centerY = getTop() + r;
        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        //开始绘制
        canvas.drawCircle(centerX, centerY, r, paint);
    }

自定义布局

有些属性希望用户指定,而在用户不指定的时候,我们也可以硬编码上一个默认值。

基本步骤:

  1. 在style.xml文件中声明一个自定义的属性

  2. 用户就可以在布局上使用该属性了

  3. 用AttributeSet在自定义View的构造函数中将自定义上的属性取出来

  4. 设置默认值

 public MyView(Context context, AttributeSet attrs) {
      super(context, attrs);
      //第二个参数就是我们在styles.xml文件中的<declare-styleable>标签
        //即属性集合的标签,在R文件中名称为R.styleable+name
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
        
        //第一个参数为属性集合里面的属性,R文件名称:R.styleable+属性集合名称+下划线+属性名称
        //第二个参数为,如果没有设置这个属性,则设置的默认的值
        defalutSize = a.getDimensionPixelSize(R.styleable.MyView_default_size, 100);
        
        //最后记得将TypedArray对象回收
        a.recycle();
   }

自定义ViewGroup

实现一个View容器的自定义,除了要设定好其自身的位置以外,还要兼顾他的子view,将childview放到该放的位置中。

步骤:

  1. 知道子view的大小

  2. 根据子view大小决定ViewGroup大小

  3. 大小确定后,设置其摆放方式

  4. 最后写一个布局文件

(详细代码见链接)

关于自定义优化建议:

  1. 调用invalidate()时,会调用onDraw()重绘界面,因此如果不更新界面最好不要调用invalidate,重新测量可以调用requestLayout,防止浪费资源。

  2. 不要在onDraw()方法中声明变量,onDraw()会随着页面view刷新而频繁被调用,会导致分配大量空间触发gc,影响性能。

  3. 不要重复绘制。可以按照层级去设计整个视图,但对于程序来说,不可见部分的绘制明显是多余的,因此需在onDraw()方法中计算哪些view是被覆盖的,只绘制可见的部分。

  4. 要使用不支持Hardware Acceleration的draw方法。这些方法会使用CPU来绘制界面,速度相比GPU绘制是非常非常慢的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值