自定义View相关问题

1,自定义View的绘制流程?

  • 第一步:复写onMeasure方法。
    先measureChild方法 测量出所有子控件的moMeasure,
 //1,测量自身
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //2,为每个子view计算测量的限制信息
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        //3,把上一步确定的限制信息,传递给每一个子view,然后子view开始measure自己的尺寸
        int childCount = getChildCount();//子view的个数
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            ViewGroup.LayoutParams lp = child.getLayoutParams();
            int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
            int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
            child.measure(childWidthSpec, childHeightSpec);
        }
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            //测量子view 获取到当前子view的测量的宽度和高度
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
    }  
}

调用 setMeasuredDimension(int measuredWidth, int measuredHeight)设置测绘后的大小。

 Log.i("tag","width = " + width );
        Log.i("tag","height = " + height );
        // 6,保存自身的尺寸
        setMeasuredDimension(width, height);
  • 第二步:onLayout方法
    在方法调用getChildCount方法 获取到子条目数量。
    用for循环遍历出每一个子条目的对象。 通过对象.layout方法 给子控件设置摆放位置。
  @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //1,遍历子view的
        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            left = i * OFFSET;
            right = left + child.getMeasuredWidth();
            bottom = top + child.getMeasuredHeight();
            child.layout(left, top, right, bottom);//不考虑padding,margin等
            top += child.getMeasuredHeight();
        }

    }
  • 第三步:首先调用ViewGroup的disPatchDraw方法绘制ViewGroup。然后调用View中的onDraw方 进行绘制。

2,自定义View是如何测量的 MeasureSpec

方法内部需要调用MeasureSpec类 可以获取到view的模式 和 大小;
MeasureSpec.getMode()获取模式
MeasureSpec.getSize()获取大小​
模式:

  • MeasureSpec.EXACTLY 精确值模式: 表示父控件已经确切的指定了子视图的大小。
  • MeasureSpec.AT_MOST 最大值模式:表示子查看具体大小没有尺寸限制,但是存在上限,上限一般为父视图大小。
  • MeasureSpec.UNSPECIFIED 父控件没有给子视图任何限制,子视图可以设置为任意大小
    什么时候这个模式会用到呢,看这边文章https://www.cnblogs.com/liushilin/p/11055741.html

onDraw方法:
用于绘制自定义View。
主要使用到了Canvas 画布对象。 和Paint 画笔对象 进行的绘制。

3,invalidate和postInvalidate方法的区别?requestLayout

  • requestLayout方法会导致View的onMeasure、onLayout、onDraw方法被调用;
  • invalidate方法则只会导致View的onDraw方法被调用;
  • invalidate方法和postInvalidate方法都是用于进行View的刷新,invalidate方法应用在UI线程中,而postInvalidate方法应用在非UI线程中,用于将线程切换到UI线程,postInvalidate方法最后调用的也是invalidate方法。
  • 我们在自定义View时,当需要刷新View时,如果是在UI线程中,那就直接调用invalidate方法,如果是在非UI线程中,那就通过postInvalidate方法来刷新View
  • postInvalidate方法实现了消息机制,最终调用的也是invalidate方法来刷新View
  • invalidate方法最终调用的是ViewRootImpl中的performTraversals来重新绘制View

4 View的Touch事件分发流程?

Touch事件的一般传递流程Activity->window(唯一实现类PhoneWindow)->顶级View(DecorView)->VIewGroup->View
详情:预留

4,图片圆角怎么实现

5,LinearLayout、RelativeLayout源码;他们是怎么计算的,绘制方法流程;

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容