2011-05-19 151 views
13

我希望允許用戶從webview中選擇一些文本,並且需要將其作爲文本消息發送。請找到方法來選擇文本並複製到剪貼板並從剪貼板中提取。我看到很多例子,但沒有使用提供的鏈接從@ orangmoney52代碼幫助我真的... TIAAndroid:如何從webview中選擇文本

編輯
。以下更改

getmethod的第二個參數和調用方法的第二個參數。如果我給予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 
+0

請添加完整片段 – 2016-08-26 20:19:50

回答

14

以上答案看起來完全正常,似乎你缺少的東西,而選擇文本。所以你需要仔細檢查代碼,並找到你覆蓋的任何TouchEvent webview。

我試過下面,它工作正常代碼...

功能是

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); 
     } 
    } 

致電上述方法,無論你想(你可以把一個按鈕,並在其click事件中調用此方法):emulateShiftHeld (mWebView);

+1

在Android 4+上不起作用。 http://stackoverflow.com/questions/21101181/android-webview-how-to-correctly-copy-selected-text – 2014-01-13 20:59:00

+10

我什至不明白這個答案試圖說。 – Michael 2014-09-26 22:18:59

+0

請在這裏添加整個片段,以便新手可以輕鬆使用 – 2016-08-26 09:44:15

0

@vnshetty,使用從@ orangmoney52中的鏈接提供的代碼,我能在幾個月前完成了這個問題。您可以在菜單中創建一個允許您複製文本的按鈕。然後,在onOptionsItemSelected,你可以有這樣的條款:

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

是在顯示烤麪包之後,我按下shift鍵並嘗試使用鼠標選擇webview內容,但沒有選擇任何內容?我錯過了什麼? – vnshetty 2011-05-26 11:08:08

+0

沒有必要按shift鍵。只需在顯示吐司消息後選擇文本即可。 – Phil 2011-05-26 19:55:25

5

最簡單的方法,雖然沒有漂亮的東西似乎是每一個製造商實現的複製/粘貼功能,如下:

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"); 
} 
+0

在我的情況下,它也不是workng.I重寫onTouch(),但它返回false。真正的問題是什麼,你是否違反了觸摸事件? – DroidBot 2013-05-29 12:06:56

+0

我的建議是不重寫onTouch()。您是否設置了自己的自定義WebChromeClient? – 2013-05-29 16:40:10

+0

嘿,這真的有用! – Bruce 2013-11-24 03:59:52

6

步驟:1 創建自定義的WebView類。 此類將在webview文本上長按覆蓋本機操作欄。 此外,它處理不同版本的機器人的選擇案例(在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: 創建web視圖接口單獨的類。從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步事件 該類listnes: 添加菜單。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> 

我把下面列出來實現這個幾個環節的幫助: 感謝你們。

如何使用JavaScript的網頁流量 http://developer.android.com/guide/webapps/webview.html#UsingJavaScript

注入的JavaScript Why can't I inject this javascript in the webview on android?

用於覆蓋默認操作欄 How to override default text selection of android webview os 4.1+?

4.0版本。 4.3文本選擇 Webview text selection not clearing

+0

如何啓用長按webview的選擇?請幫我解決:) – 2016-08-26 19:46:30

相關問題