奇怪的行为:TextView的getText()方法重新调整的对象的类类型在创建TextView的AccessibilityNodeInfo后发生更改

时间:2014-05-12 13:28:52

标签: android android-layout textview

我有一个TextView文本" Hello World!"在布局xml中定义

TextView textView = (TextView)findViewById(R.id.textView);

TextView的getText()方法返回Class java.lang.String

的对象
//Returns object of String class
Toast.makeText(getApplicationContext(), textView.getText().getClass().getName(), Toast.LENGTH_LONG).show();

如果在创建AccessibilityNodeInfo后调用它,则返回android.text.SpannableString的对象

//Creating AccessibilityNodeInfo
AccessibilityNodeInfo info = textView.createAccessibilityNodeInfo();

//Returns object of SpannableString
Toast.makeText(getApplicationContext(), "After creating AccessibilityNodeInfo: " + textView.getText().getClass().getName(), Toast.LENGTH_LONG).show();

如何创建AccessibilityNodeInfo与getText()方法返回的对象相关?

注意: 这只发生在Android 4.3及以上

2 个答案:

答案 0 :(得分:3)

这是由于select添加了cutcopypasteAccessibilityNodeInfo等新功能。它是在Android 4.3中引入的,并记录在案here

  

选择文字并复制/粘贴

     

AccessibilityNodeInfo现在提供允许的API   AccessibilityService用于选择,剪切,复制和粘贴节点中的文本。

     

指定要剪切或复制的文本的选择,您的可访问性   服务可以使用新动作ACTION_SET_SELECTION,随之传递   选择开始和结束位置   ACTION_ARGUMENT_SELECTION_START_INT和   ACTION_ARGUMENT_SELECTION_END_INT。或者,您可以选择文本   通过使用现有操作操纵光标位置,   ACTION_NEXT_AT_MOVEMENT_GRANULARITY(以前仅用于移动   光标位置),并添加参数   ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN。

     

然后可以使用ACTION_CUT,ACTION_COPY进行剪切或复制,然后再进行剪切或复制   使用ACTION_PASTE粘贴。

     

注意:这些新API也适用于以前的版本   Android通过Android支持库,用   AccessibilityNodeInfoCompat类。

要实施select功能,需要将styleable / markup个对象附加到基础文本。因此,文本类型已从String更改为SpannableString

以下是引入此功能的View.java代码。以下代码将类型更改为SpannableString

@Override
public CharSequence getIterableTextForAccessibility() {
    if (!(mText instanceof Spannable)) {
        setText(mText, BufferType.SPANNABLE);
    }
    return mText;
}

答案 1 :(得分:2)

通过查看ViewTextView的来源(至少对于API级别19),可以确定"罪魁祸首"是TextView.getIterableTextForAccessibility()。在TextView类中,它定义为:

/**
 * @hide
 */
@Override
public CharSequence getIterableTextForAccessibility() {
    if (!(mText instanceof Spannable)) {
        setText(mText, BufferType.SPANNABLE);
    }
    return mText;
}

此方法作为createAccessibilityNodeInfo()序列的一部分调用,特别是来自View.onInitializeAccessibilityNodeInfoInternal()

由于没有记录,很难确切地知道原因(或者即使它是有意的还是只是副作用),但很明显,文本必然会结束成为Spannable,即使之前不是。{/ p>

从AOSP存储库的GitHub镜像中的history of TextView.java开始,引入此逻辑的the commit似乎是Svetoslav Ganov。没有问他,我不知道你还能做些什么来了解更多。 :)

至于"为什么你需要知道整个事件的这个" 方面(除了好奇心),TextView的文本的确切类别不应该和" #39;是相关的......我假设遗留代码正在执行类似String x = (String)textView.getText()的操作。如果您需要String而不是CharSequence,那么用getText().toString()替换这些来电就足够了。