Android: How to Select Texts from Webview

Android: how to select texts from webview

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

Android Webview : How to copy selected text in webview.

The only way to get text selection from a WebView is based on javascript. This is not specific to the action mode, this is how WebView text selection is supposed to be retrieved according to WebView developers' point of view. They deliberately decided to not provide an API to access text selection from Java.

The solution comprise 2 approaches.

With Android API >= 19 you can use evaluateJavascript:

webview.evaluateJavascript("(function(){return window.getSelection().toString()})()",
new ValueCallback<String>()
{
@Override
public void onReceiveValue(String value)
{
Log.v(TAG, "SELECTION:" + value);
}
});

On older builds your only resort is a custom javascript interface with a single method accepting String, which you should call via webview.loadUrl passing the same thing:

webview.loadUrl("javascript:js.callback(window.getSelection().toString())");

where js is the attached javascript interface:

webview.getSettings().setJavaScriptEnabled(true);
webview.addJavascriptInterface(new WebAppInterface(), "js");

and

public class WebAppInterface
{
@JavascriptInterface
public void callback(String value)
{
Log.v(TAG, "SELECTION:" + value);
}
}

Reference:

How to get the selected text of webview in ActionMode override

Highlight the selected text in webview. [Android]

you need to run java script

 public static String Highlightscript = " <script language=\"javascript\">" +

"function highlightSelection(){" +
"var userSelection = window.getSelection();" +
"for(var i = 0; i < userSelection.rangeCount; i++)"
+ " highlightRange(userSelection.getRangeAt(i));" +
"}" +
"function highlightRange(range){"+
"span = document.createElement(\"span\");"+
"span.appendChild(range.extractContents());"+
"span.setAttribute(\"style\",\"display:block;background:#ffc570;\");"+
"range.insertNode(span);}"+
"</script> ";

and

  webView.loadUrl("javascript:highlightSelection()");

make sure you enabled javascript

WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

webview contexual menu on select text

After much trial and error, I have come to a reasonable solution.
Just posting it here for completeness, just in case anyone faces similar issue.

The solution was creating an alternative menu that I implemented using PopupWindow.
And I, called this on long press event using a GestureDetector.

myWebView.setWebChromeClient(new MyWebChromeClient());
mGestureDetector = new GestureDetector(getActivity(), new CustomGestureListener());
mGestureDetector = new GestureListener(getActivity(),myWebView);
final GestureDetector gd = new GestureDetector(getActivity(), mGestureDetector);

//====== web-view popup menu
myWebView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
gd.onTouchEvent(motionEvent);

return false;
}
});

The Gesture Listener is quite basic, code can be found here

Rest of the interaction with the web-view data is done using JavaScript, using below code, more about it can be found in google dev guide

WebView xview = (WebView)view;
xview.loadUrl("javascript:alert(showAndroidToast('underline'))");

Well this has done the job for me, result can be seen in below image, hope it helps someone.

Or unless someone has a better solution/code.

Sample Image

How to override web view text selection menu in android

This solution is not depend on Action mode of Activity and work for all android platform

I tried to give answer but it exceeds the character limits so I am putting some code part

Reference Link 1 For Selection On Web View

https://github.com/btate/BTAndroidWebViewSelection

Reference Link 2 For Making Web View Marker

https://github.com/liufsd/WebViewMarker

Both above links really plays important role and developed by some awesome developers. First Of All Need Some Research On TextSelectionSupport Class From Reference Link 1. I customised two lines of code in TextSelectionSupport class to get rectangle of selection in Selection Listener here.

Clone the Sample Project from here
https://github.com/ab-cse-2014/WebViewSelection.git

See The implementation of CustomWebView and Use Of TextSelectionSupport class.

This is my web view class in project

 import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import android.widget.PopupWindow;
import android.widget.Toast;

import com.cse.webviewtextselection.R;
import com.cse.webviewtextselection.webviewmaker.TextSelectionSupport;

public class CustomWebView extends WebView {

private final String TAG = this.getClass().getSimpleName();

private Context mContext;

private TextSelectionSupport mTextSelectionSupport;

private PopupWindow mPopupWindow;

private int currentTop;

public CustomWebView(Context context) {
super(context);
mContext = context;
initSetUp();
preparePopupWindow();
}

public CustomWebView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initSetUp();
preparePopupWindow();
}

public CustomWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initSetUp();
preparePopupWindow();
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CustomWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
initSetUp();
preparePopupWindow();
}

private void initSetUp() {

mTextSelectionSupport = TextSelectionSupport.support((AppCompatActivity) mContext, this);
mTextSelectionSupport.setSelectionListener(new TextSelectionSupport.SelectionListener() {
@Override
public void startSelection() {

}

@Override
public void selectionChanged(String text, Rect rect) {
Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
showPopAtLocation(mPopupWindow, rect.left, rect.top);
}

@Override
public void endSelection() {
if (mPopupWindow != null) {
mPopupWindow.dismiss();
}
}
});
}

private void preparePopupWindow() {

LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View customPopupView = layoutInflater.inflate(R.layout.custom_popup_layout, null);
mPopupWindow = new PopupWindow(customPopupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);
mPopupWindow.setAnimationStyle(android.R.style.Animation_Dialog);

}

private void showPopAtLocation(PopupWindow mPopupWindow, int x, int y) {

if (mPopupWindow != null) {

if (currentTop != 0 || currentTop > ((AppCompatActivity)mContext).getWindow().getDecorView().getHeight()) {

if (y > currentTop) {

y -= currentTop;

}

}

Log.d("Current Top : ", String.valueOf(currentTop));
Log.d("Y : ", String.valueOf(y));

//mPopupWindow.showAtLocation(((AppCompatActivity)mContext).findViewById(R.id.parentRelativeLayout), Gravity.NO_GRAVITY, x, y);
mPopupWindow.showAtLocation(((AppCompatActivity)mContext).getWindow().getDecorView(), Gravity.NO_GRAVITY, x, y);

}

}

@Override
protected void onScrollChanged(int newLeft, int newTop, int oldLeft, int oldTop) {

currentTop = newTop;

super.onScrollChanged(newLeft, newTop, oldLeft, oldTop);
}
}

Custom Popup Menu XML like androids smart text selection(custom_popup_layout.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/myCustomMenuLinearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@android:color/transparent">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@android:color/white"
android:elevation="5dp"
android:layout_margin="12dp">

<TextView
android:id="@+id/menuOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mark With Color"
android:textColor="@android:color/black"
android:padding="10dp"
android:maxLines="1"/>

<TextView
android:id="@+id/menuTwo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mark As Important"
android:textColor="@android:color/black"
android:padding="10dp"
android:maxLines="1"/>

<TextView
android:id="@+id/menuThree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show More"
android:textColor="@android:color/black"
android:padding="10dp"
android:maxLines="1"/>

</LinearLayout>

</LinearLayout>

Output Screen Shots

Selection One

Selection Two

Selection Three

How to get the selected text of webview in ActionMode override

The only way to get text selection from a WebView is based on javascript. This is not specific to the action mode, this is how WebView text selection is supposed to be retrieved according to WebView developers' point of view. They deliberately decided to not provide an API to access text selection from Java.

The solution comprise 2 approaches.

With Android API >= 19 you can use evaluateJavascript:

webview.evaluateJavascript("(function(){return window.getSelection().toString()})()",
new ValueCallback<String>()
{
@Override
public void onReceiveValue(String value)
{
Log.v(TAG, "SELECTION:" + value);
}
});

On older builds your only resort is a custom javascript interface with a single method accepting String, which you should call via webview.loadUrl passing the same thing:

webview.loadUrl("javascript:js.callback(window.getSelection().toString())");

where js is the attached javascript interface:

webview.getSettings().setJavaScriptEnabled(true);
webview.addJavascriptInterface(new WebAppInterface(), "js");

and

public class WebAppInterface
{
@JavascriptInterface
public void callback(String value)
{
Log.v(TAG, "SELECTION:" + value);
}
}


Related Topics



Leave a reply



Submit