一.问题描述
<ScrollView
android:id="@+id/pop_common_sl_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never">
<LinearLayout
android:id="@+id/pop_common_ll_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp" />
</ScrollView>
这是PopupWindow布局文件中的部分代码,目的是实现LinearLayout中的子控件通过代码动态添加,当内容较少时,ScrollView适应内容高度,当内容较多时,ScrollView保持固定高度并显示滚动条。然而实现过程中发现ScrollView并没有提供maxHeight这个属性,导致显示出来的ScrollView在内容较多时撑满屏幕。
二.解决方法
方法一
在LinearLayout添加完子控件后,主动调用measure方法得出测绘高度,然后判断是否大于设置的高度值,大于的话就固定ScrollView的高度,代码如下:
//LinearLayout测绘
ui_ll_container.measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
//拿到测绘高度
int height = ui_ll_container.getMeasuredHeight();
//判断是否大于最大高度
if (height > 500) {
ViewGroup.LayoutParams layoutParams = ui_sl_container.getLayoutParams();
layoutParams.height = 500;
ui_sl_container.setLayoutParams(layoutParams);
}
应用中发现主动去调用measure方法测绘出来的高度并不和最后显示出来相等,尤其是LinearLayout子控件包含TextView时相差很大,所以这种方法也只能适用于高度固定的子控件。
方法二
通过给LinearLayout控件注册GlobalLayoutListener,布局变化时在回调中获取高度,这样就能获取到显示的高度
ui_ll_container.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int height = ui_ll_container.getMeasuredHeight();
if (height > 500) {
ViewGroup.LayoutParams layoutParams = ui_sl_container.getLayoutParams();
layoutParams.height = 500;
ui_sl_container.setLayoutParams(layoutParams);
}
//移除监听器 避免多次调用
ui_ll_container.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
测试中发现高度没错,但显示出来的布局高度发生改变会造成页面出现闪烁的情况。
方法三(可行)
自定义ScrollView,重写onMeasure方法。布局中ScrollView改为MyScrollView,通过代码来设置最大高度
public class MyScrollView extends ScrollView {
public static final String TAG = "MyScrollView";
private int maxHeight = -1;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = getMeasuredHeight();
int width = getMeasuredWidth();
if (maxHeight > 0 && height > maxHeight) {
setMeasuredDimension(width, maxHeight);
}
}
public void setMaxHeight(int height) {
this.maxHeight = height;
}
}
MyScrollView ui_sl_container = view.findViewById(R.id.pop_common_sl_container);
ui_sl_container.setMaxHeight(500);