如何在我的Android应用程序中以编程方式复制文本?

265

我正在开发一个Android应用程序,需要复制EditText小部件的文本值。 用户可以按下Menu+A,然后按下Menu+C来复制该值,但我该如何通过编程实现此操作?


1
剪贴板管理器。http://developer.android.com/reference/android/content/ClipboardManager.html - IAdapter
这基本上是一个重复的问题:http://stackoverflow.com/a/13517876/2116185 - user2116185
15个回答

490

7
使用 import android.content.ClipboardManager; 导入剪贴板管理器。 - MatheusJardimB
这个函数在API 11+(包括棒棒糖)上能否正常工作? - Ashraf Alshahawy
41
label 是什么? - Alaa M.
2
你还可以在复制完成后添加成功提示,告诉用户文本已经被复制了。Context context = getApplicationContext(); Toast.makeText(context, "文本已复制", Toast.LENGTH_LONG).show(); - Shady Mohamed Sherif
1
@AlaaM。我认为这个剪贴板托盘是LG的选项,你无法控制它。 - Shady Mohamed Sherif
显示剩余2条评论

222

所以大家都同意应该这样做,但由于没有人想提供完整的解决方案,所以我来说:

int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
    android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    clipboard.setText("text to clip");
} else {
    android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 
    android.content.ClipData clip = android.content.ClipData.newPlainText("text label","text to clip");
    clipboard.setPrimaryClip(clip);
}

我假设您在清单文件中声明了以下内容:

<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14" />

它无法工作,因为编译器抛出了一个错误:调用需要API级别11(当前最低级别为7):android.content.ClipboardManager#setPrimaryClip第245行Android Lint问题。 - JavaRunner
2
你在清单文件中添加了目标 SDK 和最低 SDK 吗?如果是,请禁用 Lint 警告。 - Warpzit
4
在你的方法上方添加以下3行内容:@SuppressLint({ "NewApi", "NewApi", "NewApi", "NewApi" }), @SuppressWarnings("deprecation"), @TargetApi(11)......我就是这样做的,它有效。 - RRTW
4
请问newPlainText方法中的label有什么用途?根据文档,label是“剪贴板数据对用户可见的标签”。但是,在什么情况下用户才能看到label?我应该在label中放入什么样的值或名称呢? - shadyinside
避免“需要API级别11”的错误最简单的方法是将if(sdk <...)更改为以下内容:if(Build.VERSION.SDK_INT <11) - Rudolf Polzer
显示剩余2条评论

18

Android支持库更新

从Android Oreo开始,支持库只支持API 14及以上版本。大多数新应用程序的最低API也可能是14,因此不需要担心其他答案中提到的与API 11相关的问题。许多代码可以进行清理。(但如果您仍在支持较低版本,请参阅我的编辑历史记录。)

复制

ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label", selectedText);
if (clipboard == null || clip == null) return;
clipboard.setPrimaryClip(clip);

粘贴

我将这段代码作为额外奖励添加,因为复制和粘贴通常成对出现。

ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
try {
    CharSequence text = clipboard.getPrimaryClip().getItemAt(0).getText();
} catch (Exception e) {
    return;
}

笔记

  • 确保导入android.content.ClipboardManager版本而不是旧的android.text.ClipboardManager。同样适用于ClipData
  • 如果您不在活动中,则可以使用context.getSystemService()获取服务。
  • 我使用了try/catch块来获取粘贴文本,因为多个东西可能是null。如果您发现这种方式更易读,请检查每个值。

2
“文本标签”是用来做什么的? - android developer
@androiddeveloper,我从未真正使用标签做过任何事情,但请参阅此问答 - Suragch
所以即使它显示为对用户可见,实际上并不是这样的,而且需要开发人员在需要时使用它。 - android developer

17

谷歌搜索会带您到android.content.ClipboardManager,您可能会像我一样决定,在API < 11上不使用Clipboard,因为文档页面上写着“自API Level 11起”。

实际上有两个类,第二个类是扩展了第一个类 - android.text.ClipboardManager和android.content.ClipboardManager。

android.text.ClipboardManager从API 1就开始存在,但它只能处理文本内容。

android.content.ClipboardManager是与剪贴板配合的首选方法,但在API Level < 11(Honeycomb)上不可用。

要获取它们中的任何一个,您需要以下代码:

ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);

但是对于API < 11,您需要导入android.text.ClipboardManager,而对于API >= 11,则需要导入android.content.ClipboardManager


13
public void onClick (View v) 
{
    switch (v.getId())
    {
        case R.id.ButtonCopy:
            copyToClipBoard();
            break;
        case R.id.ButtonPaste:
            pasteFromClipBoard();
            break;
        default:
            Log.d(TAG, "OnClick: Unknown View Received!");
            break;
    }
}

// Copy EditCopy text to the ClipBoard
private void copyToClipBoard() 
{
    ClipboardManager clipMan = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    clipMan.setPrimaryClip(editCopy.getText());
}

你可以尝试这个...


不完整。pasteFromClipBoard() 方法在哪里? - FractalBob

8

以下是一些代码,可以实现从EditText复制和粘贴的功能(感谢Warpzit版本检查)。您可以将它们挂钩到按钮的onclick事件上。

public void copy(View v) {      
    int startSelection = txtNotes.getSelectionStart();
    int endSelection = txtNotes.getSelectionEnd();      
    if ((txtNotes.getText() != null) && (endSelection > startSelection ))
    {
        String selectedText = txtNotes.getText().toString().substring(startSelection, endSelection);                
        int sdk = android.os.Build.VERSION.SDK_INT;
        if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
            android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
            clipboard.setText(selectedText);
        } else {
            android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 
            android.content.ClipData clip = android.content.ClipData.newPlainText("WordKeeper",selectedText);
            clipboard.setPrimaryClip(clip);
        }
    }
}   

public void paste(View v) {
    int sdk = android.os.Build.VERSION.SDK_INT;
    if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
        android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        if (clipboard.getText() != null) {
            txtNotes.getText().insert(txtNotes.getSelectionStart(), clipboard.getText());
        }
    } else {
        android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        android.content.ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
        if (item.getText() != null) {
            txtNotes.getText().insert(txtNotes.getSelectionStart(), item.getText());
        }
    }
}

难道不可能像你所做的那样,调用Android的复制/粘贴/剪切方法而无需编写它们吗?我创建了一个自定义文本选择工具栏,使用户能够使所选文本变粗/斜/下划线等功能。但是在定制后,默认的复制/粘贴/剪切功能不再起作用,但它们的图标仍然出现? - user5366495
“WordKeeper”是用来做什么的? - android developer

7
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); 
ClipData clip = ClipData.newPlainText("label", "Text to copy");
if (clipboard == null || clip == null)
    return;
clipboard.setPrimaryClip(clip);

并导入 import android.content.ClipboardManager;


6
为了启用TextView的标准复制/粘贴功能,您可以选择以下其中一种方法:
在布局文件中进行更改:为您的TextView添加以下属性。
android:textIsSelectable="true"

在你的Java类中,写下以下代码以使语法正确:

myTextView.setTextIsSelectable(true);

长按TextView后,你可以看到复制/粘贴操作栏。


4

对于 Kotlin,我们可以使用以下方法。您可以将此方法粘贴到活动或片段中。

fun copyToClipBoard(context: Context, message: String) {

    val clipBoard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    val clipData = ClipData.newPlainText("label",message)
    clipBoard.setPrimaryClip(clipData)

}

谢谢!“context.”这部分是我所缺少的-可能是因为我正在片段内完成它。 - Cullub

3

或者创建一个Kotlin扩展

 fun String.copyToClipboard(context: Context) {
     val clipBoard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
     val clipData = ClipData.newPlainText("label",this)
     clipBoard.setPrimaryClip(clipData)
  }

然后调用
"stringToCopy".copyToClipboard(requireContext())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接