Android自定义View

2020-03-05  本文已影响0人  Itachi001

自定view分两种:

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)
上一篇下一篇

猜你喜欢

热点阅读