美文网首页
Android自定义View

Android自定义View

作者: Itachi001 | 来源:发表于2020-03-05 12:13 被阅读0次

    自定view分两种:

    • 自定义ViewGroup,主要覆写onMeasureonLayoutonTouch
    • 自定义View,主要覆写onMeasureonDrawonTouch

    onMeasure(int widthMeasureSpec, int heightMeasureSpec):

    onMeasure方法接收的两个int型参数是你在xml中给该View设置的宽高,但是注意这两个参数的值是与你设置的值不同
    在这里需要首先了解一下MeasureSpec
    它是View中的内部类,里面都是二进制运算
    由于int是32位的,用高两位表示mode低30位表示size,而mode有三种:

    UNSPECIFIED:不对View大小做限制
    EXACTLY:确切的大小,如100dp或者match_parent
    AT_MOST:大小不超过某数值,如wrap_content
    

    可以通过MeasureSpecgetModegetSize方法获取modesize

    int selfWidth = MeasureSpec.getSize(widthMeasureSpec);//View解析的宽度
    int selfHeight = MeasureSpec.getSize(heightMeasureSpec);//View解析的高度
    

    在这里,假如你是想自定义ViewGroup,你需要对子view进行测量,还得了解一个方法:

    getChildMeasureSpec(int spec, int padding, int childDimension)
    

    子view的MeasureSpec是由ViewGroup的MeasureSpec和子view的LayoutParams 共同决定的

    LayoutParams layoutParams = childAt.getLayoutParams();
    int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, layoutParams.width);
    int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, layoutParams.height);
    childAt.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    

    子view测量完毕,便可获取子view测量后的宽高

    //获取子View宽高
    int childAtMeasuredWidth = childAt.getMeasuredWidth();
    int childAtMeasuredHeight = childAt.getMeasuredHeight();
    

    最后根据子view的总宽高以及ViewGroup的mode确定ViewGroup的宽高,并调用以下方法保存

    setMeasuredDimension(int measuredWidth, int measuredHeight)
    

    onLayout(boolean changed, int left, int top, int right, int bottom):

    changed:ViewGroup的大小或位置是否改变,left、top、right、bottom:ViewGroup的四个角的坐标
    在该方法中通过子view的layout()方法对子view进行布局

    itemView.layout(itemViewLeft, itemViewTop, itemViewRight, itemViewBottom);
    

    onDraw(Canvas canvas)

    canvas参数为画布,可以理解为一张纸,你需要在View初始化时创建画笔Paint,对Paint设置不同的属性以达到画出不同的图形的目的,关于Android Paint调用canvas的如下方法进行绘制

    RectF(float left, float top, float right, float bottom)
    drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
    drawText(@NonNull String text, int start, int end, float x, float y,@NonNull Paint paint)
    drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint)
    

    onTouchEvent(MotionEvent event)

    稍后再说

    思考:视图还未绘制完成,怎么获取view的信息?

    1. 在View的事件回调里获取
    2. onWindowFocusChanged回调方法中获取
    3. 在onResume方法最后开线程300毫秒左右后获取(不推荐)
    4. 通过getViewTreeObserver().addOnGlobalLayoutListener()方法为View添加回调来获取,用完记得删除回调
    view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    // doing
                }
            });
    
    1. 手动对view进行measure来得到view的宽高
    view.measure(int widthMeasureSpec,int heightMeasureSpec)
    

    相关文章

      网友评论

          本文标题:Android自定义View

          本文链接:https://www.haomeiwen.com/subject/sxhblhtx.html