使用ACTION_PROCESS_TEXT创建自定义文本选择动作

2161次阅读  |  发布于5年以前

原文链接 : Creating custom Text Selection actions with ACTION_PROCESS_TEXT

使用ACTION_PROCESS_TEXT创建自定义文本选择动作

Android 6.0引入了一个新的浮动文本选择工具栏,带来了标准的文本选择动作,如剪切,复制,和粘贴,可以更方便处理你选择的文本。甚至更好的是可以通过新的_ACTION_PROCESSTEXT任何应用 添加自定义actions(动作)到文本选择工具栏上成为可能。

text_selection_toolbar

Android 6.0上的文本选择工具栏

Wikipedia (维基百科)和 Google Translate (谷歌翻译)应用已经利用它用来立即查找或翻译选中的文本。

你可能已经看到了关于确保文本选择工具条出现在你的应用中的文档博客。简而言之:使用一个标准的TextView/EditText就可以了,需要注意的是如果你使用的是 AppCompatActivity 并且想在API 23+的设备上使用本地悬浮文本选择工具条,EditText 需要设置android:id并且得调用getDelegate().setHandleNativeActionModesEnabled(false)

但是怎么找到实现 _ACTION_PROCESSTEXT 的信息并且添加你自己的actions (动作)呢?这就是本文要介绍的内容。

跨应用之间的通信-> Intent Filters

如您所料,当构建跨应用的功能时,其它应用可以查询你的Android清单和每个组件的intent filters作为一个公共API。

ACTION_PROCESS_TEXT 也一样。你得在清单文件添加一个intent filter到一个Activity上。

<activity android:name=”@string/process_text_action_name”>
  <intent-filter>
    <action android:name=”android.intent.action.PROCESS_TEXT”/
    <category android:name=”android.intent.category.DEFAULT” />
    <data android:mimeType=”text/plain” />
  </intent-filter>
</activity>

如果你想要多个actions ,你需要添加对应的activities 。如果你的应用构建了特定的功能不想被其它应用使用,你可以添加android:exported=”false”来确保action 只会出现在你的应用中。

注意你的Activity 的 android:name 将会作为action 显示在文本选择工具栏上,因此应该确保它是简短的,一个动作动词,并且能辨认出你的应用。例如,Google翻译使用了‘Translate’,这是一个不太常见的action(有多少人安装了多个翻译应用?),Wikipedia 使用的是 ‘Search Wikipedia’ 作为搜索,这可能对于很多应用来说是一个更常见的action 。

获取选择的文本

一旦你设置了intent filter,其它应用就可以通过选择文本然后从文本选择工具栏选择你的action 打开你的activity 。但这并没有任何价值,除非你用到了所选择的文本。

_EXTRA_PROCESSTEXT 的出现:它是一个包含在Intent 内的 CharSequence表示选择的文本。不要被欺骗——尽管你使用了text/plain intent filter,你会得到包含Spannable的完整CharSequence,如果你在你的应用中直接使用CharSequence,你可能会注意到一些样式,因此不必惊讶(你也可以调用toString()来移除所有格式)。

因此你的_onCreate()_方法可能和下面类似:

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.process_text_main);
  CharSequence text = getIntent()
      .getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT);
  // process the text
}

如果你使用_android:launchMode=”singleTop”_会有一个警告,你也可以在onNewIntent()处理文本——常见的做法是在onCreate()onNewIntent() 都调用 handleIntent() 方法。

如果你使用 ACTION_PROCESS_TEXT作为进入你应用的入口,上面就是所有你需要知道的:之后用来做什么取决于你。

返回一个结果

在ACTION_PROCESS_TEXT Intent还有一个extra :_EXTRA_PROCESS_TEXTREADONLY。这个额外的boolean 值表示你接收到的选择的文本是否可以被用户编辑(例如在一个_EditText_内)。

你可以像下面的代码一样接收这个额外的值

boolean readonly = getIntent()
  .getBooleanExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, false);

你可以使用提供返回修改后的文本给发送的应用的能力作为一个提示,替换选择的文本。当你Activity 使用startActivityForResult()方式开启才会起作用——你可以在Activity 结束之前调用setResult()返回一个结果

Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_PROCESS_TEXT, replacementText);
setResult(RESULT_OK, intent);

你可以想象一个‘Replace’按钮调用 setResult() 随后调用finish()返回到调用的Activity。

常见问题

在你写回复之前,这有一些关于ACTION_PROCESS_TEXT的常见问题:

Q:我能使用ACTION_PROCESS_TEXT开启一个Service 吗?

A: 不能直接开启——系统只会检查包含正确的intent filter的Activities。这不意味着你不能用一个Theme.Translucent.NoTitleBar主题或Theme.NoDisplay(只要你立即销毁Activity)主题的Activity 开启Service ,但要确保它们的action 可以接收到一些用户可见的提示——开启一个notification ,Toast等。

Q:我能只用某些类型的文本触发它吗?

A: 不能。任何人选择文本的时候你的选项都会出现。当然,用户可以不选择 ‘Translate’ 选项,除非他们想翻译等,当你不能确定你将会接收到什么类型的文本时需要很小心地作出处理。

Q:每个应用都应该实现ACTION_PROCESS_TEXT吗?会不会有点疯狂?

A:是的,确实有点疯狂,不用每个应用都实现ACTION_PROCESS_TEXT。确保你实现的actions 是通用的并且对于安装你应用的用户来说是真正有用的

了解更多

除了上面提到的WikipediaGoogle Translate包含了很好真实的例子,你也可以看看安装在Marshmallow 模拟器上的ApiDemos 应用或直接查看代码

开发优秀的应用

Google+加入讨论并且关注Android Development Patterns Collection了解更多!

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8