自定义View

自定义View的常用技巧

Posted by candy1126xx on April 18, 2017

获取View的准确尺寸位置

  • onMeasure():可能在自测量阶段被调用,此时获取到的measuredWidth/measuredHeight是自测量尺寸;也可能在再测量阶段被调用,此时获取到的是准确尺寸。
  • onLayout()及之后:获取到的measuredWidth/measuredHeight或getWidth()都是准确尺寸。
  • getMeasuredWidth()、getWidth()只有尺寸信息;getMeasuredWidthAndState()包含尺寸信息和MEASURED_STATE_TOO_SMALL。
  • getLeft():获得的是左边相对于父View左上角的位置;即相对坐标系下左边的x轴坐标。
  • getRawLeft():获得的是左边相对于屏幕左上角的位置;即绝对坐标系下左边的x轴坐标。
  • getTranslationX():获得的是内容偏移量
  • getX():获得的是内容偏移量 + 相对坐标系下左边的x轴坐标。
  • getLocationOnScreen():获得的是绝对坐标系下四边的x/y轴坐标。
  • onSizeChanged():只在尺寸改变时被回调。

SPEC_MODE

  • MeasureSpec.UNSPECIFIED:子View可以无视指导尺寸;
  • MeasureSpec.EXACTLY:子View的尺寸必须取指导尺寸,当MATCH_PARENT或确定值时是这个;
  • MeasureSpec.AT_MOST:子View不能大于指导尺寸,当WRAP_CONTENT时是这个;

ViewTreeObserver回调

  • OnWindowFocusChangeListener:当控件树所在窗口从有焦点变为无焦点,或从无焦点变为有焦点时被执行;
  • OnWindowAttachListener:当控件树添加到窗口上时被执行;
  • OnGlobalFocusListeners:当控件树中的焦点从一个控件跳到另一个控件时被执行;
  • OnGlobalLayoutListener:当控件树完成布局后被执行;
  • OnScrollChangedListener:在绘制阶段,当计算出Scroll值有变化时被执行;
  • OnPreDrawListener:返回值是进入绘制阶段当条件之一;
  • OnWindowShownListener:当窗口的入场动画结束时被执行,只用于非Activity窗口;对于Activity窗口,可以重写onEnterAnimationComplete()达到同样效果;
  • OnDrawListener:在绘制阶段,在设置完脏区域后、判断软硬绘制前被执行。

View回调

  • OnFocusChangeListener:当控件从有焦点变为无焦点,或从无焦点变为有焦点时被执行;
  • OnLayoutChangeListener:当控件的mLeft/mTop/mRight/mBottom改变时,onLayout才会被调用,然后OnLayoutChangeListener被执行;
  • OnScrollChangeListener:在绘制阶段,当计算出Scroll值有变化时被执行;
  • OnAttachStateChangeListener:当控件第一次测布绘,在自测量之前,会执行一次;
  • OnSystemUiVisibilityChangeListener:当状态栏的可见性发生变化时被执行;
  • OnApplyWindowInsetsListener:当控件第一次测布绘,在自测量之前,紧接着OnAttachStateChangeListener会执行一次;

圆角View/ViewGroup

  1. 重写onSizeChanged();
    • 调用Rect.set(0,0,w,h)记录控件尺寸;
    • 调用Path.addRoundRect(Rect, r, r, Path.Direction.CW)创建圆角矩形路径;
  2. 对ViewGroup重写dispatchDraw(),对View重写onDraw();
    • 依次调用canvas.save() -> canvas.clipPath(Path) -> super.dispatchDraw(canva) -> canvas.restore()。

Bitmap和Drawable的区别

  • Bitmap是一张图片的真实数据;它直接来自于图片文件,占用大量内存;不能直接被控件操作,必须转化为BitmapDrawable;
  • Drawable是一个抽象的“可以画在屏幕上的东西”的概念;不仅一张图片可以画(BitmapDrawable)、一块颜色(ColorDrawable)、一个形状(ShapDrawable)也可以画;它是直接被控件操作的对象。