自定义ViewGroup需注意 解决ViewPager设置高度无效

476 阅读2分钟

自定义View重点函数: image.png

/*
* 1.在度量的时候 度量子控件 或者 自己。(大部分控件都是先度量子控件,再度量自己,注意:ViewPager是先度量自己再度量子控件)
* 2.为啥会先度量自己? (因为度量子控件后才能确定自己的宽高)
* 3.度量的目的: 将 xml中 match_parent、wrap_content、10dp等,转成能使用的宽高
* 4.可能存在调用多次(调用次数是父控件决定的)
*/
onMeasure -> 测量控件大小 (度量宽高)

onLayout -> 对控件位置进行摆放(布局)
MeasureSpec 是什么?
MeasureSpec是View中内部类,基本都是二进制运算。 组成是 : int32位, 用高两位表示model,低30位表示size, MODE_SHIFT = 30的作用是位移

/*
* 在 onMeasure 里面进行计算
*/
//1 . 此函数 计算 父控件 传下来的值进行计算获取 30位大小
int selfWidth = MeasureSpec.getSize(widthMeasureSpec);

//2 . 将 LayoutParams 转成 MeasureSpec;(计算子控件的实际站位大小)
// 第一个参数 是 父控件宽高
// 第二个参数 是 父控件 的边距
// 第三个参数 是 子控件的大小
// 此方法计算子控件 占居父控件宽高多少
int childW = getChildMeasureSpec(widthMeasureSpec, paddingL + paddingR
        , params.width);
        
//3 . 调用 measure 传入计算出来的 大小
childView.measure(childW, childH);

/*
* childView.getMeasuredWidth();
* childView.getWidth();
* 1. 以上两者并无联系
* 2. getMeasuredWidth() -> 是 控件调用measure 后能获取到的值
*。  getWidth() -> 控件 运行childView的layout 布局方法后能获取的值
*/
//4 . 获取 view 测量后的宽度 高度
int widthSpec = childView.getMeasuredWidth();

/*
* MeasureSpec.EXACTLY //模式:固定的宽高
* MeasureSpec.UNSPECIFIED //-> 未指定尺寸 (一般系统使用)
* MeasureSpec.AT_MOST//-> 最大尺寸,控件的宽高为WRAP_CONTENT,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸
*/
//5 . 获取当前控件的模式
int widthModel = MeasureSpec.getMode(widthMeasureSpec);

//6 . realWidth、realHeight度量自己,将计算出来的结果保存起来
setMeasuredDimension(realWidth, realHeight);
处理ViewPager 显示高度不正确的处理
/**
 * 处理ViewPager 显示高度不正确的处理
 */
public class CustomerInvalidHeightViewPager extends ViewPager {

    public CustomerInvalidHeightViewPager(@NonNull Context context) {
        super(context);
    }

    public CustomerInvalidHeightViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int height = 0;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View view = getChildAt(i);
            ViewGroup.LayoutParams layoutParams = view.getLayoutParams();

            int childSpecW = getChildMeasureSpec(widthMeasureSpec, 0, layoutParams.width);
            int childSpecH = getChildMeasureSpec(heightMeasureSpec, 0, layoutParams.height);
            view.measure(childSpecW, childSpecH);
            height = Math.max(height, view.getMeasuredHeight());
        }

        // 需要固定 ViewPager的高度
        height = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, height);
    }
}