Android使用ClipBoardManager提供对复制和粘贴功能的支持。 developer.android.com提供了简短的说明以及一张有助于理解“复制粘贴”框架的图像。
“要复制数据,应用程序将ClipData对象放在ClipboardManager全局剪贴板上。 ClipData包含一个或多个ClipData.Item对象和一个ClipDescription对象。 要粘贴数据,应用程序获取ClipData,从ClipDescription获取其MIME类型,并从ClipData.Item或ClipData.Item引用的内容提供程序获取数据。”
本教程介绍了JellyBean中引入的最新功能,支持样式文本。 我们将介绍下面列出的方法。 HTML支持的方法
- ClipData.newHtmlText()与剪贴板
- Intent.putExtra()与Intent.EXTRA_HTML_TEXT
- Intent.setClipData()与newHtmlText()方法
项目信息:有关项目的元数据。 平台版本: Android API级别16。 IDE: Eclipse Helios服务版本2 模拟器: Android 4.1(API 16) 先决条件:对Android应用程序框架和Intent有初步了解。 示例源代码
首先,通过Eclipse> File> New Project> Android Application Project创建项目。 将出现以下对话框。 填写必填字段,即“应用程序名称”,“项目名称”和“包”。 现在按下一步按钮。
出现对话框后,选择BlankActivity,然后单击下一步 。
在下面显示的对话框中填写“活动名称”和“布局”文件名称,然后单击“ 完成”按钮。
此过程将设置基本项目文件。 现在,我们将在布局activity_jbclipboard.xml文件中添加视图组件。 您可以使用图形布局编辑器或xml编辑器来修改布局文件。 在此布局中,我们将添加四个按钮,分别是CopyHtml,pasteHtml,sendHtmlIntent和sendClipdataIntent按钮,分别是复制,粘贴,发送html Intent和发送clipdata目的并附加onClick方法。 这些方法将在JBClipboard类中定义。 我们还将包括两个单选按钮,即“粘贴HTML”和“粘贴文本”。 这些单选按钮有助于选择要从剪贴板提取的所需文本类型。 我们也有三个EditViews来显示文本。 第一个Editview包含样式文本,第二个显示HTML或文本字符串。 第三个显示了Coerce HTML字符串。 布局文件如下所示。
<LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
xmlns:tools='http://schemas.android.com/tools'
android:layout_width='match_parent'
android:layout_height='match_parent'
android:orientation='vertical'>
<EditText
android:id='@+id/etCopy'
android:layout_width='fill_parent'
android:layout_height='wrap_content'
android:padding='@dimen/padding_medium'
android:gravity='top'
android:scrollHorizontally='false'
android:inputType='textMultiLine'
/>
<RadioGroup
android:id='@+id/rbgTextHTML'
android:orientation='horizontal'
android:layout_width='fill_parent'
android:layout_height='wrap_content'
>
<RadioButton
android:id='@+id/rbHtml'
android:layout_weight='.5'
android:layout_width='0dp'
android:layout_height='wrap_content'
android:checked='true'
android:text='@string/rbHtml'/>
<RadioButton
android:id='@+id/rbText'
android:layout_weight='.5'
android:layout_width='0dp'
android:layout_height='wrap_content'
android:text='@string/rbText'/>
</RadioGroup>
<LinearLayout
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:orientation='horizontal'>
<Button
android:layout_width='0dp'
android:layout_height='wrap_content'
android:layout_weight='.5'
android:onClick='copyHtml'
android:text='@string/btCopy'/>
<Button
android:layout_width='0dp'
android:layout_height='wrap_content'
android:layout_weight='.5'
android:onClick='pasteHtml'
android:text='@string/btPaste'/>
</LinearLayout>
<LinearLayout android:layout_width='fill_parent'
android:layout_height='wrap_content'
android:orientation='horizontal'>
<Button
android:layout_width='0dp'
android:layout_weight='.5'
android:layout_height='wrap_content'
android:onClick='sendHtmlIntent'
android:text='@string/btSendHtmlIntent'/>
<Button
android:layout_width='0dp'
android:layout_weight='.5'
android:layout_height='wrap_content'
android:onClick='sendClipdataIntent'
android:text='@string/btSendClipdataIntent'/>
</LinearLayout>
<TextView
android:layout_width='fill_parent'
android:layout_height='wrap_content'
android:text='@string/tvCopiedText'/>
<EditText
android:id='@+id/etPaste'
android:layout_width='fill_parent'
android:layout_height='wrap_content'
android:inputType='textMultiLine'
android:gravity='top'
android:scrollHorizontally='false'
/>
<TextView
android:layout_width='fill_parent'
android:layout_height='wrap_content'
android:text='@string/tvcoerceText'/>
<EditText
android:id='@+id/etPasteCoerceText'
android:layout_width='fill_parent'
android:layout_height='wrap_content'
android:gravity='top'
android:scrollHorizontally='false'
android:inputType='textMultiLine'/>
</LinearLayout>
现在,我们需要为两个不同的活动添加另外两个布局文件。 让我们通过Eclipse> File> Android XML file定义第一个Layout 文件 。 最终,我们得到以下对话框。 确保选择了布局资源类型。 将布局文件命名为activity_htmlintent,然后单击Finish 。
添加两个用于显示文本标签的TextViews和两个用于显示HTML和文本字符串的EditTexts视图。 此布局文件将与HTMLIntentActivity.java附加在一起,一旦广播“ text / html”类型的意图,即会调用该布局文件。 下面给出了activity_htmlintent.xml的内容:
<LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
android:layout_width='match_parent'
android:layout_height='match_parent'
android:orientation='vertical' >
<TextView
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:text='@string/tvIntentHtml' />
<EditText
android:id='@+id/etHtml'
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:inputType='textMultiLine'
android:padding='@dimen/padding_medium'
android:scrollHorizontally='false' />
<TextView
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:text='@string/tvIntentText' />
<EditText
android:id='@+id/etText'
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:inputType='textMultiLine'
android:padding='@dimen/padding_medium'
android:scrollHorizontally='false' />
</LinearLayout>
现在,我们将定义另一个名为activity_clipdataintent.xml的布局文件。 按照上面给出的类似步骤生成布局xml文件。 该文件与上面的文件相似,并且包含两个EditView和两个TextViewThe。 该文件的内容如下。 该布局文件将附加到ClipdataIntentActivity类,该类在传递带有Clipdata对象的Intent时被调用。
<LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
android:layout_width='match_parent'
android:layout_height='match_parent'
android:orientation='vertical' >
<TextView
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:text='@string/tvIntentClipdataHtml' />
<EditText
android:id='@+id/etClipBoardHtml'
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:inputType='textMultiLine'
android:padding='@dimen/padding_medium'
android:scrollHorizontally='false' />
<TextView
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:text='@string/tvIntentClipdataText' />
<EditText
android:id='@+id/etClipBoardText'
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:inputType='textMultiLine'
android:padding='@dimen/padding_medium'
android:scrollHorizontally='false' />
</LinearLayout>
您可能已经注意到,布局文件中已使用了字符串资源。 如下所示在string.xml中定义此字符串常量。
<resources>
<string name='app_name'>JellyBeanClipboard</string>
<string name='menu_settings'>Settings</string>
<string name='title_activity_jbclipboard'>JBClipboard</string>
<string name='title_activity_htmlintent'>Html Intent Activity</string>
<string name='title_activity_clipdataintent'>ClipData Intent Activity</string>
<!-- CDATA tag is required otherwise you can't have the html text
properly parsed in Textview -->
<string name='tvHtml'><![CDATA[<b>Link:</b> <a href='http://www.code4reference.com'>Code4Reference</a>]]></string>
<!-- Text string for button -->
<string name='btCopy'>Copy</string>
<string name='btPaste'>Paste</string>
<string name='btSendHtmlIntent'>send HTML Intent</string>
<string name='btSendClipdataIntent'>send ClipData Intent</string>
<!-- Text string for RadioButton -->
<string name='rbHtml'>Paste Html</string>
<string name='rbText'>Paste Text</string>
<!-- Text string for Text View -->
<string name='tvCopiedText'><b><i>Copied text</i></b></string>
<string name='tvcoerceText'><b><i>Copied coerce Text</i></b></string>
<string name='tvIntentText'><b><i>Intent Text</i></b></string>
<string name='tvIntentHtml'><b><i>Intent Html</i></b></string>
<string name='tvIntentClipdataText'><b><i>Intent Clipdata Text</i></b></string>
<string name='tvIntentClipdataHtml'><b><i>Intent Clipdata Html</i></b></string>
</resources>
一旦完成了布局文件,就可以定义活动类了。 让我们定义称为JBClipboard的主要活动。 此活动有使用HTML支持的API的各种方法。 嵌入的注释将有助于理解代码。
package com.code4reference.rakesh.jellybeanclipboard;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.Spannable;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Toast;
import com.example.jellybeanclipboard.R;
public class JBClipboard extends Activity {
EditText etCopy;
EditText etPaste;
EditText etPasteCoerceText;
RadioButton rbText;
RadioButton rbHtml;
ClipboardManager mClipboard;
ClipboardManager.OnPrimaryClipChangedListener mPrimaryChangeListener = new ClipboardManager.OnPrimaryClipChangedListener() {
/**
* This method is a callback. It get called when the primary clip
* on the clipboard changes.
*/
public void onPrimaryClipChanged() {
//Toast message will appear whenever the clipboad
//primary data changes.
Utility.showToastMessage(getApplicationContext(),
'Primary clipdata changed', Toast.LENGTH_SHORT);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jbclipboard);
etCopy = (EditText) findViewById(R.id.etCopy);
etPaste = (EditText) findViewById(R.id.etPaste);
etPasteCoerceText = (EditText) findViewById(R.id.etPasteCoerceText);
etCopy.setText(Html.fromHtml(getString(R.string.tvHtml)));
rbText = (RadioButton) findViewById(R.id.rbText);
rbHtml = (RadioButton) findViewById(R.id.rbHtml);
mClipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
mClipboard.addPrimaryClipChangedListener(mPrimaryChangeListener);
}
/**
* This method gets called when 'Copy' button get pressed.
* @param view
*/
public void copyHtml(View view) {
String htmlText = getHtmltxt(etCopy);
String plainText = getOnlyText(etCopy);
mClipboard.setPrimaryClip(ClipData.newHtmlText('HTML Text', plainText,
htmlText));
}
/**
* This method gets called when 'Paste' button get pressed.
* @param view
*/
public void pasteHtml(View view) {
// Check if there is primary clip exsiting.
// If it does then echeck the mime type to make sure
// it has HTML content.
if (mClipboard.hasPrimaryClip()
&& mClipboard.getPrimaryClipDescription().hasMimeType(
ClipDescription.MIMETYPE_TEXT_HTML)) {
// Get the very first item from the clip.
ClipData.Item item = mClipboard.getPrimaryClip().getItemAt(0);
// If 'Paste HTML' radio button is selected then paste
// HTML in the Textview.
if (rbHtml.isChecked()) {
etPaste.setText(item.getHtmlText());
} else {
// Paste the only text version.
etPaste.setText(item.getText());
}
// Paste the CoerceText .
etPasteCoerceText.setText(item.coerceToText(this));
}
}
/**
* This method gets called when 'send Html Intent' button get pressed.
* @param view
*/
public void sendHtmlIntent(View view) {
// This kind of intent can be handle by this application
// Or other application which handle text/html type Intent
Intent intent = new Intent(Intent.ACTION_SEND);
String htmlText = getHtmltxt(etCopy);
String text = getOnlyText(etCopy);
intent.putExtra(Intent.EXTRA_HTML_TEXT, htmlText);
intent.putExtra(Intent.EXTRA_TEXT, text);
intent.setType('text/html');
startActivity(Intent.createChooser(intent, null));
}
/**
* This method gets called when 'send Clipdata Intent' button get pressed.
*
* @param view
*/
public void sendClipdataIntent(View view) {
String htmlText = getHtmltxt(etCopy);
String plainText = getOnlyText(etCopy);
Intent intent = new Intent(this, ClipdataIntentActivity.class);
//create a clipdata object with HTML text.
//and associate with the intent.
intent.setClipData(ClipData.newHtmlText(
'HTML text in Intent's clipdata', plainText, htmlText));
//Start the activity which can handle clipData object.
startActivity(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
//Remove the ClipChanged Listener to save the resources.
mClipboard.removePrimaryClipChangedListener(mPrimaryChangeListener);
}
/**
* This method gets the EditText object and returns the HTML text. It
* can be called only with EditTexts having spannable object with
* the HTML text.
*
* @param editText
* @return
*/
private String getHtmltxt(EditText editText) {
//get the spannable object from EditText
Spannable spannable = (Spannable) editText.getText();
//return the HTML text from spannable object.
return Html.toHtml(spannable);
}
/**
* This method takes the EditText object which has spannable object with HTML
* text and returns the simple text without HTML tags.
*
* @param editText
* @return
*/
private String getOnlyText(EditText editText) {
return editText.getText().toString();
}
}
现在,我们将定义用于处理HTML文本意图的HTMLIntentActivity 。 预期意图将由主要活动(JBClibboard)触发
package com.code4reference.rakesh.jellybeanclipboard;
import com.example.jellybeanclipboard.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.EditText;
public class HtmlIntentActivity extends Activity {
private EditText etHtml;
private EditText etText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_htmlintent);
etHtml = (EditText) findViewById(R.id.etHtml);
etText = (EditText) findViewById(R.id.etText);
//Get the intent that started this activity
Intent intent = getIntent();
//Make sure intent and its type is not null.
if (intent != null && intent.getType() != null
&& intent.getType().equals('text/html')) {
//This contition will full-fill when this application receive the
//intent who's type is 'test/html'. In this application sendHtmlIntent
//method sends this type of Intent.
Bundle bundle = intent.getExtras();
if(bundle != null){
etHtml.setText(bundle.getCharSequence(Intent.EXTRA_HTML_TEXT));
etText.setText(bundle.getCharSequence(Intent.EXTRA_TEXT));
}
}
}
}
现在,我们将定义另一个名为ClipdataIntentActivity的活动,该活动处理具有clilpdata对象的Intent。 ClipdataIntentActivity类的内容如下。
package com.code4reference.rakesh.jellybeanclipboard;
import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.Toast;
import android.content.ClipData;
import android.content.ClipDescription;
import com.example.jellybeanclipboard.R;
public class ClipdataIntentActivity extends Activity {
private EditText etHtml;
private EditText etText;
ClipboardManager mClipboard;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clipdataintent);
etHtml = (EditText) findViewById(R.id.etClipBoardHtml);
etText = (EditText) findViewById(R.id.etClipBoardText);
//Get the intent that started this activity
Intent intent = getIntent();
if (intent != null) {
ClipData clipdata = intent.getClipData();
//Make sure clipdata object is not null and it has HTML MIME type.
if (clipdata != null
&& clipdata.getDescription().hasMimeType(
ClipDescription.MIMETYPE_TEXT_HTML)) {
ClipData.Item item = clipdata.getItemAt(0);
etHtml.setText(item.getHtmlText());
etText.setText(item.getText());
} else {
Utility.showToastMessage(this,
'Intent clipdata doesn't have HTML', Toast.LENGTH_SHORT);
}
}
}
}
创建另一个名为Utility的类。 它包含显示烤面包消息的方法。 您可能已经注意到此函数是静态的,因此无需创建对象来调用此方法。 将实用程序方法放在单独的文件中,然后在不同位置访问此文件始终是一个好主意。 这样,您的代码将井井有条。
package com.code4reference.rakesh.jellybeanclipboard;
import android.content.Context;
import android.widget.Toast;
public class Utility {
public static void showToastMessage(Context context, String message, int duration){
Toast.makeText(context, message, duration).show();
}
}
最后定义Anroid Manifest文件,该文件主要向Android系统提供应用程序信息。 在这里,您应该注意到,HtmlIntentActivity活动具有一个意图过滤器,并且将意图类型指定为“ text / html”。 这基本上意味着该活动可以处理类型为text / html的意图。 文件的其余部分简单易懂。
<manifest xmlns:android='http://schemas.android.com/apk/res/android'
package='com.example.jellybeanclipboard'
android:versionCode='1'
android:versionName='1.0' >
<uses-sdk
android:minSdkVersion='16'
android:targetSdkVersion='16' />
<application
android:icon='@drawable/ic_launcher'
android:label='@string/app_name'
android:theme='@style/AppTheme' >
<activity
android:name='com.code4reference.rakesh.jellybeanclipboard.JBClipboard'
android:label='@string/title_activity_jbclipboard' >
<intent-filter>
<action android:name='android.intent.action.MAIN' />
<category android:name='android.intent.category.LAUNCHER' />
</intent-filter>
</activity>
<activity android:name='com.code4reference.rakesh.jellybeanclipboard.ClipdataIntentActivity'
android:label='@string/title_activity_clipdataintent' >
</activity>
<activity android:name='com.code4reference.rakesh.jellybeanclipboard.HtmlIntentActivity'
android:label='@string/title_activity_htmlintent' >
<intent-filter>
<action android:name='android.intent.action.SEND' />
<category android:name='android.intent.category.DEFAULT' />
<!-- This activity will get launched when proper Intent type will match.
In this case Intent type is 'text/html' -->
<data android:mimeType='text/html' />
</intent-filter>
</activity>
</application>
</manifest>
一旦完成编码,就执行它。 您可以在Android设备或模拟器上启动此应用程序。 确保Android版本为16(Jelly Bean)或更高版本,然后此应用程序才能运行。 应用程序的屏幕截图如下所示。
您可以在github上获取源代码。
祝您编程愉快,别忘了分享!
参考: 具有Intent的复制粘贴功能,并支持Android上HTML。 从我们的JCG合作伙伴 Rakesh Cusat在Code4Reference博客上获得。
翻译自: https://www.javacodegeeks.com/2012/09/android-copy-paste-with-intent-and.html