Android:如何从网络视图中选择文本

发布于 2024-11-08 13:57:23 字数 841 浏览 3 评论 0原文

我希望允许用户从网络视图中选择一些文本,并且需要将其作为短信发送。请找到选择文本并复制到剪贴板并从剪贴板提取的方法。我看到了很多例子,但没有什么能真正帮助我......TIA

编辑
使用 @orangmoney52 链接中提供的代码。通过以下更改

getmethod 的第二个参数和 invoke 方法的第二个参数。如果我给 null 就会出现警告..哪一个是正确的?

 public void selectAndCopyText() {
     try {
         Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE); 
            m.invoke(BookView.mWebView, false); 
        } catch (Exception e) {
            e.printStackTrace();
            // fallback
            KeyEvent shiftPressEvent = new KeyEvent(0,0,
                 KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);
            shiftPressEvent.dispatch(this);
        }

}

出现此错误:

 05-26 16:41:01.121: WARN/System.err(1096): java.lang.NoSuchMethodException: emulateShiftHeld  

i want allow user to select some texts from webview and it need to be send as a text message. pls find way to select text and copy to clipboard and extracting from clipboard. i saw many example but nothing helped me really...TIA

Edit
using the code provided in the link from @orangmoney52. with following changes

getmethod's second parameter and invoke method second parameter. if i give null there warning will come.. which one is correct?

 public void selectAndCopyText() {
     try {
         Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE); 
            m.invoke(BookView.mWebView, false); 
        } catch (Exception e) {
            e.printStackTrace();
            // fallback
            KeyEvent shiftPressEvent = new KeyEvent(0,0,
                 KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);
            shiftPressEvent.dispatch(this);
        }

}

Getting this error:

 05-26 16:41:01.121: WARN/System.err(1096): java.lang.NoSuchMethodException: emulateShiftHeld  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

怎樣才叫好 2024-11-15 13:57:23

上面的答案看起来非常好,并且您在选择文本时似乎遗漏了一些东西。因此,您需要仔细检查代码并找到您覆盖的 webview 的任何 TouchEvent

我尝试了下面的代码,它工作正常...

函数是

 private void emulateShiftHeld(WebView view)
    {
        try
        {
            KeyEvent shiftPressEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
                                                    KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0);
            shiftPressEvent.dispatch(view);
            Toast.makeText(this, "select_text_now", Toast.LENGTH_SHORT).show();
        }
        catch (Exception e)
        {
            Log.e("dd", "Exception in emulateShiftHeld()", e);
        }
    }

在您想要的任何地方调用上面的方法(您可以放置​​一个按钮并在其单击事件中调用此方法): emulateShiftHeld(mWebView);

The above answers looks perfectly fine and it seems you're missing something while selecting text. So you need to double check the code and find your overridden any TouchEvent of webview.

i Tried below code it works fine...

Function is

 private void emulateShiftHeld(WebView view)
    {
        try
        {
            KeyEvent shiftPressEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
                                                    KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0);
            shiftPressEvent.dispatch(view);
            Toast.makeText(this, "select_text_now", Toast.LENGTH_SHORT).show();
        }
        catch (Exception e)
        {
            Log.e("dd", "Exception in emulateShiftHeld()", e);
        }
    }

Call Above method wherever you want (You can put a button and call this method in its click event): emulateShiftHeld(mWebView);

剪不断理还乱 2024-11-15 13:57:23

步骤:1
创建自定义 WebView 类。
此类将在长按 Web 视图文本时覆盖本机操作栏。
它还处理不同版本的 android 的选择情况(在 4.0 及以上版本上测试)
此代码使用 JavaScript 获取选定的文本。

public class CustomWebView extends WebView {
private Context context;
// override all other constructor to avoid crash
public CustomWebView(Context context) {
    super(context);
    this.context = context;
    WebSettings webviewSettings = getSettings();
    webviewSettings.setJavaScriptEnabled(true);
    // add JavaScript interface for copy
    addJavascriptInterface(new WebAppInterface(context), "JSInterface");
}

// setting custom action bar
private ActionMode mActionMode;
private ActionMode.Callback mSelectActionModeCallback;
private GestureDetector mDetector;

// this will over ride the default action bar on long press
@Override
public ActionMode startActionMode(Callback callback) {
    ViewParent parent = getParent();
    if (parent == null) {
        return null;
    }
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        String name = callback.getClass().toString();
        if (name.contains("SelectActionModeCallback")) {
            mSelectActionModeCallback = callback;
            mDetector = new GestureDetector(context,
                    new CustomGestureListener());
        }
    }
    CustomActionModeCallback mActionModeCallback = new CustomActionModeCallback();
    return parent.startActionModeForChild(this, mActionModeCallback);
}

private class CustomActionModeCallback implements ActionMode.Callback {

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mActionMode = mode;
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; 
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

        switch (item.getItemId()) {
        case R.id.copy:
            getSelectedData();
            mode.finish(); 
            return true;
        case R.id.share:
            mode.finish();
            return true;
        default:
            mode.finish();
            return false;
        }
    }
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            clearFocus();
        }else{
             if (mSelectActionModeCallback != null) {
                 mSelectActionModeCallback.onDestroyActionMode(mode);
             }
             mActionMode = null;
        }
    }
}
private void getSelectedData(){

    String js= "(function getSelectedText() {"+
            "var txt;"+
            "if (window.getSelection) {"+
                "txt = window.getSelection().toString();"+
            "} else if (window.document.getSelection) {"+
                "txt = window.document.getSelection().toString();"+
            "} else if (window.document.selection) {"+
                "txt = window.document.selection.createRange().text;"+
            "}"+
            "JSInterface.getText(txt);"+
          "})()";
    // calling the js function
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        evaluateJavascript("javascript:"+js, null);
    }else{
        loadUrl("javascript:"+js);
    }
}

private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        if (mActionMode != null) {
            mActionMode.finish();
            return true;
        }
        return false;
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Send the event to our gesture detector
    // If it is implemented, there will be a return value
    if(mDetector !=null)
        mDetector.onTouchEvent(event);
    // If the detected gesture is unimplemented, send it to the superclass
    return super.onTouchEvent(event);
}

2 步:
为 WebView 接口创建单独的类。
一旦 javascript 代码被执行,这个类就会监听事件

public class WebAppInterface {
Context mContext;

WebAppInterface(Context c) {
    mContext = c;
}

@JavascriptInterface
public void getText(String text) {
    // put selected text into clipdata
    ClipboardManager clipboard = (ClipboardManager)
            mContext.getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clip = ClipData.newPlainText("simple text",text);
    clipboard.setPrimaryClip(clip);
    // gives the toast for selected text
    Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
}
}

第 3 步:
在res>中添加自定义菜单的menu.xml菜单文件夹

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
    android:id="@+id/copy"
    android:icon="@drawable/ic_action_copy"
    android:showAsAction="always" 
    android:title="copy">
</item>
<item
    android:id="@+id/share"
    android:icon="@drawable/ic_action_share"
    android:showAsAction="always" 
    android:title="share">
</item>

我借助下面列出的几个链接来实现此目的:
谢谢你们。

如何在webview上使用javascript
http://developer.android.com/guide/webapps/webview.html#UsingJavaScript

用于注入 javascript
为什么可以我不能在 android 上的 webview 中注入这个 javascript 吗?

来覆盖默认操作栏
如何覆盖android的默认文本选择webview 操作系统 4.1+?

版本 4.0。 4.3 文本选择
Web 视图文本选择未清除

Step: 1
Create custom WebView class.
This class will override the native action bar on long press on the webview text.
Also it handles the the selection case for different version of android (tested on 4.0 onwards)
This code takes the selected text using javascript.

public class CustomWebView extends WebView {
private Context context;
// override all other constructor to avoid crash
public CustomWebView(Context context) {
    super(context);
    this.context = context;
    WebSettings webviewSettings = getSettings();
    webviewSettings.setJavaScriptEnabled(true);
    // add JavaScript interface for copy
    addJavascriptInterface(new WebAppInterface(context), "JSInterface");
}

// setting custom action bar
private ActionMode mActionMode;
private ActionMode.Callback mSelectActionModeCallback;
private GestureDetector mDetector;

// this will over ride the default action bar on long press
@Override
public ActionMode startActionMode(Callback callback) {
    ViewParent parent = getParent();
    if (parent == null) {
        return null;
    }
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        String name = callback.getClass().toString();
        if (name.contains("SelectActionModeCallback")) {
            mSelectActionModeCallback = callback;
            mDetector = new GestureDetector(context,
                    new CustomGestureListener());
        }
    }
    CustomActionModeCallback mActionModeCallback = new CustomActionModeCallback();
    return parent.startActionModeForChild(this, mActionModeCallback);
}

private class CustomActionModeCallback implements ActionMode.Callback {

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mActionMode = mode;
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; 
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

        switch (item.getItemId()) {
        case R.id.copy:
            getSelectedData();
            mode.finish(); 
            return true;
        case R.id.share:
            mode.finish();
            return true;
        default:
            mode.finish();
            return false;
        }
    }
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            clearFocus();
        }else{
             if (mSelectActionModeCallback != null) {
                 mSelectActionModeCallback.onDestroyActionMode(mode);
             }
             mActionMode = null;
        }
    }
}
private void getSelectedData(){

    String js= "(function getSelectedText() {"+
            "var txt;"+
            "if (window.getSelection) {"+
                "txt = window.getSelection().toString();"+
            "} else if (window.document.getSelection) {"+
                "txt = window.document.getSelection().toString();"+
            "} else if (window.document.selection) {"+
                "txt = window.document.selection.createRange().text;"+
            "}"+
            "JSInterface.getText(txt);"+
          "})()";
    // calling the js function
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        evaluateJavascript("javascript:"+js, null);
    }else{
        loadUrl("javascript:"+js);
    }
}

private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        if (mActionMode != null) {
            mActionMode.finish();
            return true;
        }
        return false;
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Send the event to our gesture detector
    // If it is implemented, there will be a return value
    if(mDetector !=null)
        mDetector.onTouchEvent(event);
    // If the detected gesture is unimplemented, send it to the superclass
    return super.onTouchEvent(event);
}

}

Step 2:
create separate class for WebView interface.
This class listnes for event from once javascript code is getting executed

public class WebAppInterface {
Context mContext;

WebAppInterface(Context c) {
    mContext = c;
}

@JavascriptInterface
public void getText(String text) {
    // put selected text into clipdata
    ClipboardManager clipboard = (ClipboardManager)
            mContext.getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clip = ClipData.newPlainText("simple text",text);
    clipboard.setPrimaryClip(clip);
    // gives the toast for selected text
    Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
}
}

Step 3:
Add menu.xml for custom menu in res > menu folder

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
    android:id="@+id/copy"
    android:icon="@drawable/ic_action_copy"
    android:showAsAction="always" 
    android:title="copy">
</item>
<item
    android:id="@+id/share"
    android:icon="@drawable/ic_action_share"
    android:showAsAction="always" 
    android:title="share">
</item>

I took help of several links listed below to achieve this:
Thanks to you guys.

how to use javascript on webview
http://developer.android.com/guide/webapps/webview.html#UsingJavaScript

for injecting javascript
Why can't I inject this javascript in the webview on android?

for overriding default action bar
How to override default text selection of android webview os 4.1+?

for version 4.0. to 4.3 text selection
Webview text selection not clearing

你好,陌生人 2024-11-15 13:57:23

最简单的方法虽然不像每个制造商实现的复制/粘贴功能那么漂亮,但如下:

https ://bugzilla.wikimedia.org/show_bug.cgi?id=31484

基本上,如果您通过设置自己的 WebChromeClient webview.setWebChromeClient(...) 那么默认情况下禁用文本选择。要启用它,您的 WebChromeClient 需要实现以下方法:

//@Override
/**
* Tell the client that the selection has been initiated.
*/
public void onSelectionStart(WebView view) {
    // Parent class aborts the selection, which seems like a terrible default.
    //Log.i("DroidGap", "onSelectionStart called");
}

The easiest way, although not as pretty as what seems like a per manufacturer implemented copy/paste feature, is the following:

https://bugzilla.wikimedia.org/show_bug.cgi?id=31484

Basically, if you're setting your own WebChromeClient via webview.setWebChromeClient(...) then text selection is disabled by default. To enable it your WebChromeClient needs to have to following method implemented:

//@Override
/**
* Tell the client that the selection has been initiated.
*/
public void onSelectionStart(WebView view) {
    // Parent class aborts the selection, which seems like a terrible default.
    //Log.i("DroidGap", "onSelectionStart called");
}
傲娇萝莉攻 2024-11-15 13:57:23

@vnshetty,使用@orangmoney52 链接中提供的代码,我几个月前就能够完成这个问题。您可以在菜单中创建一个按钮来复制文本。然后,在 onOptionsItemSelected 中,您可以有这样的子句:

    case R.id.select_and_copy: {
        Toast.makeText(getApplicationContext(), "Select Text", Toast.LENGTH_SHORT).show();
        selectAndCopyText();
        return true;
    }

@vnshetty, using the code provided in the link from @orangmoney52, I was able to complete this problem a few months ago. You can create a button in your menu that allows you to copy text. Then, in onOptionsItemSelected, you can have a clause like this:

    case R.id.select_and_copy: {
        Toast.makeText(getApplicationContext(), "Select Text", Toast.LENGTH_SHORT).show();
        selectAndCopyText();
        return true;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文