产品需求:
一个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冲突,仅此记录。
网友评论