Android软键盘Android知识Android进阶之旅

有换行时切换软键盘,TextView宽度抖动问题

2017-05-12  本文已影响114人  sollian

浸淫Android这么多年,收敛君表示第一次碰到这么基础而又棘手的问题。

情景再现

MainActivity

public class TestListActivity extends Activity {
    private ListView vList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b2);

        List<Map<String, CharSequence>> data = new ArrayList<>();
        Map<String, CharSequence> map = new HashMap<>();
        map.put("title", "uuuuu\nuu");
        data.add(map);

        vList = (ListView) findViewById(R.id.list);
        SimpleAdapter adapter = new SimpleAdapter(this,
                data,
                R.layout.item_list,
                new String[]{"title"},
                new int[]{android.R.id.text1}
        );
        vList.setAdapter(adapter);
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="demo.com.demoapp.TestListActivity">

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@android:id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

这个简单的显示一个ListView的小例子,初学Java时恐怕都写过。我们运行看看效果,为了看的明白,打开显示布局边界开关:


1.png

现在让我们点击EditText,打开软键盘:


2.png
这个小问题在这个例子中的表现还算温和,TextView的宽度只会抖动一次。但是在收敛君的工作中,每次切换软键盘都会出现!快跑!boss要发飙了!!!

刨根问底

这个小问题陪伴我两天两夜,其中的辛酸就不啰嗦了,且看把它扒光的结果吧。
先来看一段TextView.onMeasure方法的片段:

//……此处省略几行
Layout mLayout = getLayout();
TextUtils.TruncateAt mEllipsize = getEllipsize();
 if (mLayout != null && mEllipsize == null) {
     des = desired(mLayout);
 }
//……此处省略若干行
if (des < 0) {
   des = (int) Math.ceil(Layout.getDesiredWidth(mTransformed, mTextPaint));
}

首次执行onMeasure方法时,mLayout==null,此时des从第二段代码取值;当切换软键盘,页面重新布局,再次调用onMeasure方法时,mLayout!=null,此时des从第一段代码取值。而des就是宽度的值。
讲道理两段代码获取的尺寸应该是一样的,BUT!!!第一段代码会计算\n也就是换行符的宽度,第二段代码不会。

这也就是今天收敛君想分享的Android系统的BUG


了解了问题的根源,解决起来也就方便了。只要每次都从第二段代码取值就可以了。别问我为什么不从第一段代码取值,我肯定不会告诉你是因为第一次mLayout==null
简单的修改方法是每次执行onMeasure方法时,都通过反射把mLayout置为null

今天记录这么多,有什么错误的地方还请各位大大指正!

今天受同事提醒,因为mEllipsize == null时才会执行第一段代码进行测量,所以直接给TextView设置ellipsize属性也可以解决。不过常在河边走,哪有不湿鞋,总有遗忘的时候,想一劳永逸的话,还是继承一下TextView吧,然后在内部设置ellipsize属性。

上一篇下一篇

猜你喜欢

热点阅读