本文主要记录博主在平日工作中遇到的各种困惑,以及对应的解决方案。
ScrollView嵌套Listview时引起冲突的解决办法
通常情况下,不建议两个或以上带滚动功能的控件嵌套使用。解决此问题的一种常用方法是手动设定ListView的高度为所有子项的总高度。
/**
* 重新计算ListView的高度
*/
public void calcListViewHeight()
{
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.UNSPECIFIED);
View view = null;
for (int i = 0; i < adapter.getCount(); i++)
{
view = adapter.getView(i, view, listview);
if (i == 0)
{
view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
}
view.measure(View.MeasureSpec.makeMeasureSpec(desiredWidth, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));// 计算子项View 的宽高
totalHeight += view.getMeasuredHeight(); // 统计所有子项的总高度
}
ViewGroup.LayoutParams params = listview.getLayoutParams();
params.height = totalHeight+ (listview.getDividerHeight() * (listview.getCount() - 1) );
listview.setLayoutParams(params);
//显示定位到顶部(因为设定后,焦点会转移到listview上)
globalLayout.setFocusable(true);
globalLayout.setFocusableInTouchMode(true);
globalLayout.requestFocus();
}
这里要求ListView中的每个Item必须是LinearLayout布局,因为其他的Layout都没有重写onMeasure()方法,所以会在调用measure()时抛出异常。
在onCreate()中无法得到自适应的测量宽度和测量高度的解决办法
使用getMeasuredWidth()和getMeasuredHeight()获取控件和布局的测量高度和测量宽度需要在它们自身调用onMeasure()之后。在Activity中的onCreate()方法进行时,是无法拿到自适应宽高控件的测量宽度和测量高度的。可通过加回调的方法获取,代码如下。
//这里当layout发生布局改变时,测量convertView的高度(这段代码源自一个ViewHolder,因此两者是同一个布局)
layout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
int height = convertView.getMeasuredHeight();
ViewGroup.LayoutParams lps = linePostfix.getLayoutParams();
lps.height = height;
linePostfix.setLayoutParams(lps);
}
});
设置光标显示时,EditText是否弹出软键盘
在一些IM软件中,有时需要在EditText显示输入光标时,软键盘不弹出(比如在输入颜文字的情况下,打开表情布局即可)。TextView类中有一个名为setShowSoftInputOnFocus的方法,可以设置软键盘在获得焦点时是否弹出,但这个方法在API21时才开放为公有的。在API21之前,需要使用反射来调用这个函数,代码如下。
/**
* 设置光标显示时,Edittext是否弹出软件盘,
*/
private void setEnableShowSoftInput(boolean enable)
{
Class<EditText> cls = EditText.class;
Method method;
try
{
method = cls.getMethod("setShowSoftInputOnFocus", boolean.class);
method.setAccessible(true);
method.invoke(editMsg, enable); //editMsg为EditText控件实例
}
catch (Exception e) {}
}
在StringBuilder中使用HTML格式
显示在TextView中的文本,如果希望不同部分显示不同的颜色或者不同的字号的话,使用Html类中的fromHtml静态方法是个不错的选择。不过对于字符串比较长的情况,我们通常会先使用StringBuilder来构建这个字符串,但是StringBuilder并不能渲染Html格式,需要使用SpannableStringBuilder这个类代替StringBuilder来构建字符串。代码如下:
TextView txt = (TextView) findViewById(R.id.txt_test);
SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append("你今天已经吃了").append(Html.fromHtml("<font color=#000080>"+"20"+"</font>")).append("斤米饭")
.append(",和").append(Html.fromHtml("<font color=#800000>" + "10" + "</font>")).append("斤肉")
.append(",外加").append(Html.fromHtml("<font color=#008000>" + "15" + "</font>")).append("斤水果");
txt.setText(sb);
效果如下图所示:
ScrollView嵌套自定义ViewGroup时高度为0的问题
在使用自定义的ViewGroup时,需要在onMeasure()方法中测量ViewGroup的宽度和高度,之后需要根据测量模式返回不同的结果。通常情况下,只会针对EXACTLY(match_parent,20dp…)和AT_MOST(wrap_content)两种测量模式进行判断。然而,当ViewGroup嵌套在ScrollView中的时候,其高度(假设ScrollView是纵向滚动的)的测量模式将变为UNSPECIFIED。因此在onMeasure()方法的最后,执行setMeasuredDimension()方法时,需要对这种测量模式进行兼容,返回计算好的高度。