使用DialogFragment 实现嵌套ViewPager,按照最高高度布局,适配列表布局

产品需求:

一个dialog中有个点击显示详情按钮,而详情要是在弹窗内部展示,产品需要的效果是想页面跳转一样有一个向右的动画效果,这个时候就想到了在dialog中嵌套viewpager来完成

碰到的问题:

  • 选择方案
    在dialog中嵌套viewpager会存在报错的异常,网上有很多多说了,给出的解决方案是使用dialogfragment来替代dialog嵌套viewpager,由于自身项目中fragment使用也很多,所以就直接选用这套方案。
  • 高度匹配问题
    由于viewpager里面的布局高度为wrap_content时并没作用,会出现高度撑不满或者空白区域很多的情况,这个时候需要一个复写viewpager的自定义控件,计算子空间高度,取最大高度设置会viewapager高度,复写onMeasure方法,代码如下
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    int height = 0;
    for(int i = 0; i < getChildCount(); i++) {
        View child = getChildAt(i);
        child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = child.getMeasuredHeight();
        if(h > height) height = h;
    }

    heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
  • 新问题的出现
    本以为就此可以结束,但是在添加了详情界面的列表是,出现了高度铺满屏幕的问题,新出现的问题是,列表界面的height测量出来是无效高的,只要没有设置指定的高度,是会把所有的高度给到列表的,所以通过上诉的重写onMeasure测量出来的最大child的高度就是撑屏幕的高度。仔细研究需求,根据我们界面,详情列表的展示区域是和当前界面的展示区域是一样高度的,所以改造onMeasure方法 之测量第一个pager的高度作为viewpager的高度,代码如下

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

    var height = 0
    //下面遍历所有child的高度
    for (i in 0 until childCount) {
        if (i == 0) {
            val child = getChildAt(i)
            child.measure(widthMeasureSpec,
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
            val h = child.measuredHeight
            if (h > height)
            //采用最大的view的高度。
                height = h
        }
    }

    var heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)

    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
  • 额外的需求
    去除viewpager的滑动效果,只有在点击的时候进行跳转,实现点击右滑动画,只需要在刚才自定义viewpager的控件中添加:

fun setNoScroll(noScroll: Boolean) {

    this.noScroll = noScroll
}

override fun onTouchEvent(arg0: MotionEvent): Boolean {
    return if (noScroll)
        false
    else
        super.onTouchEvent(arg0)
}

override fun onInterceptTouchEvent(arg0: MotionEvent): Boolean {
    return if (noScroll)
        false
    else
        super.onInterceptTouchEvent(arg0)
}
  • 边距问题
    最后碰到一个非常奇怪的问题,设置viewpager内部pager的边距时 直接设置在跟布局viewpager上,在内部pager设置边距可能会和跟布局padding冲突,仅此记录。

你可能感兴趣的:(使用DialogFragment 实现嵌套ViewPager,按照最高高度布局,适配列表布局)