WebView 中的 startActionMode(在文本 select 上)在 KitKat 中调用但在 Marshmallow 中不调用

startActionMode (on text select) in WebView called in KitKat but not in Marshmallow

我用

@Override public ActionMode startActionMode(Callback callback) {

拦截 WebView 中的文本选择。 不幸的是,这段代码在 Android 4.0.4 ICS 和 Android 4.4.4 KitKat 中有效,但在 Android 6.0.1 Marshmallow 中无效。

在 Android 6.0.1 上,当用户长按文中的一个词。

我 post 下面的代码重现了这个问题。

A class MainActivity :

package com.example.test07;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ";
        String c = "<p>"+s+s+s+"</p>"+"<p>"+s+s+"</p>";

        WebView gd_web = (WebView) findViewById(R.id.gd_web);

        gd_web.loadDataWithBaseURL("file:///", c, "text/html", "utf-8", null);
    }

}

A class CustomWebView :

package com.example.test07;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ActionMode.Callback;
import android.webkit.WebView;


public class CustomWebView extends WebView {

    public CustomWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    @Override
    public ActionMode startActionMode(Callback callback) {
        Log.w("TEST", "ææ startActionMode");
        return super.startActionMode(new ActionMode.Callback() {
            @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                Log.w("TEST", "ææ onCreateActionMode");
                return false;
            }

            @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                Log.w("TEST", "ææ onPrepareActionMode");
                return false;
            }

            @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                Log.w("TEST", "ææ onActionItemClicked");
                return false;
            }

            @Override public void onDestroyActionMode(ActionMode mode) {

            }

        });
    }

}

和测试布局 activity_main.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    tools:context="${relativePackage}.${activityClass}" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="--" />

    <com.example.test07.CustomWebView
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         android:id="@+id/gd_web"
        />
</LinearLayout>

如何使此代码适用于最近的 Android 版本?

Android 的最新版本调用此方法的 startActionMode(ActionMode.Callback, int) 版本。

https://issuetracker.google.com/issues/79394037

Also, on API level 17 and 19, the WebView is very different from current WebView, Chromium based update-able WebView is on L and above, so we can't do anything for that. That's probably why startActionMode() wasn't called on these devices.

On the other hand, if you want to support API leve 23 and above, you will also need to override the other startActionMode(ActionMode.Callback, int).