Android-WebView默认选定的工具栏的“复制”按钮不起作用

时间:2019-12-02 13:13:54

标签: android xamarin xamarin.forms webview

如您所知,选择文本时,它会出现一个弹出菜单。

当我单击菜单上的“复制”时,无法选择/复制文本,但事件被触发。 (在MyMenuItemOnMenuItemClickListener类中> OnMenuItemClick方法中)

default menu

-

如果使用“共享>复制到剪贴板”菜单将其复制,则可以获取它。该事件未触发。 (这不是我们的目标。只是为了比较。)

select text > share > copy to clipboard menu

如果我复制WebView以外的任何文本,然后单击“复制”按钮(而不是“复制到剪贴板”),则可以获得上次复制的文本。 Webview的复制按钮有什么问题?为什么我无法选择文本?

iOS没问题。

-

Xaml;

CustomWebView类;

public class CustomWebView : WebView
        {
            public static readonly BindableProperty UriProperty = BindableProperty.Create(
                propertyName: "Uri",
                returnType: typeof(string),
                declaringType: typeof(CustomWebView),
                defaultValue: default(string));

            public string Uri
            {
                get { return (string)GetValue(UriProperty); }
                set { SetValue(UriProperty, value); }
    }
}

自定义渲染器;

[assembly: ExportRenderer(typeof(CustomWebView), typeof(WebViewRendererDroid))]
    namespace TApp.Droid
    {
        public class WebViewRendererDroid : ViewRenderer<CustomWebView, Android.Webkit.WebView>, IOnPrimaryClipChangedListener /* ViewRenderer<CustomWebView, Android.Webkit.WebView>*/
        {
            Context _context;
            public WebViewRendererDroid(Context context) : base(context)
            {
                _context = context;
            }

            protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
            {
                base.OnElementChanged(e);

                if (Control == null)
                {
                    var webView = new Android.Webkit.WebView(_context);
                    webView.Settings.JavaScriptEnabled = true;
                    webView.Settings.AllowContentAccess = true;
                    webView.LoadUrl("https://docs.microsoft.com/en-us/xamarin/ios/");

                    SetNativeControl(webView);
                }
                if (e.NewElement != null)
                {
                    Control.LoadUrl("https://docs.microsoft.com/en-us/xamarin/ios/");
                }
            }

        ClipboardManager myClipBoard;
        public void OnPrimaryClipChanged()       
        {
            ClipData clipData = myClipBoard.PrimaryClip;
            ClipData.Item item = clipData.GetItemAt(0);
            MessagingCenter.Send<object, string>(this, "Hi", item.Text);
        }
        }
    }

MainActivity.cs;

namespace TApp.Droid
    {
        [Activity(Label = "TApp", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
        public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
        {
            protected override void OnCreate(Bundle savedInstanceState)
            {
                TabLayoutResource = Resource.Layout.Tabbar;
                ToolbarResource = Resource.Layout.Toolbar;

                base.OnCreate(savedInstanceState);

                global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
                LoadApplication(new App());
            }

            public override void OnActionModeStarted(ActionMode mode)
            {
                IMenu menu = mode.Menu;
                menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this));
                base.OnActionModeStarted(mode);
            } 
        }

        public class MyMenuItemOnMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener
        {
            private MainActivity mContext;

            public MyMenuItemOnMenuItemClickListener(MainActivity activity)
            {
                this.mContext = activity;
            }

            public bool OnMenuItemClick(IMenuItem item)
            {
                var clipboard = (ClipboardManager)mContext.GetSystemService(Context.ClipboardService);

                var clipboard2 = (Android.Text.ClipboardManager)Android.App.Application.Context.GetSystemService(Context.ClipboardService);

                var pasteData = "";

                string aaa = clipboard.Text;

                if (!(clipboard.HasPrimaryClip))
                {
                    // If it does contain data, decide if you can handle the data.
                }
                else if (!(clipboard.PrimaryClipDescription.HasMimeType(ClipDescription.MimetypeTextPlain)))
                {
                    // since the clipboard has data but it is not plain text
                }
                else
                {
                    //since the clipboard contains plain text
                    var copiedText = clipboard.PrimaryClip.GetItemAt(0);
                    // Gets the clipboard as text
                    pasteData = copiedText.Text;
                }

                Toast.MakeText(mContext, pasteData, ToastLength.Short).Show();
                return true;
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

我写了一个简单的示例,您可以检查一下:

1。在Android.Project中定义接口 ActionSelectListener

public interface ActionSelectListener
{ 
    void onClick(string selectText);
}

2。在Android.Project中自定义 WebView CustomActionWebView

class CustomActionWebView:WebView,IMenuItemOnMenuItemClickListener
{

    public CustomActionWebView(Context context):base(context)
    {
        _context = context;
    }

    public CustomActionWebView(Context context, IAttributeSet attrs):base(context,attrs)
    {
        _context = context;
    }

    public CustomActionWebView(Context context, IAttributeSet attrs, int defStyleAttr):base(context,attrs,defStyleAttr)
    {
        _context = context;
    }
    private Context _context;
    ActionMode mActionMode;

   static ActionSelectListener mActionSelectListener;
    private ActionMode resolveActionMode(ActionMode actionMode)
    {
        if (actionMode != null)
        {
            IMenu menu = actionMode.Menu;
            mActionMode = actionMode;
            IMenuItem menuItem = menu.GetItem(0);//here only handle the copy button
            menuItem.SetOnMenuItemClickListener(this);

        }
        mActionMode = actionMode;
        return actionMode;
    }

    public override ActionMode StartActionMode(ActionMode.ICallback callback)
    {
        ActionMode actionMode = base.StartActionMode(callback);
        return resolveActionMode(actionMode);
    }

    public override ActionMode StartActionMode(ActionMode.ICallback callback, [GeneratedEnum] ActionModeType type)
    {
        ActionMode actionMode = base.StartActionMode(callback, type);
        return resolveActionMode(actionMode);
    }
private void releaseAction()
{
    if (mActionMode != null)
    {
        mActionMode.Finish();
        mActionMode = null;
    }
}
    /**
     * When you click, get the selected text from the page and drop it back to the native js interface
     * @param passes in the text of the clicked item, which is returned to the native interface via js
     */
    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.callback(txt);" +
            "})()";
    if (Build.VERSION.SdkInt >= Build.VERSION_CODES.Kitkat)
    {
        EvaluateJavascript( js, null);
    }
    else
    {
        LoadUrl("javascript:" + js);
    }
}

public void linkJSInterface()
{
    AddJavascriptInterface(new ActionSelectInterface(_context), "JSInterface");
}
/**
 * click call back
 * @param actionSelectListener
 */
public void setActionSelectListener(ActionSelectListener actionSelectListener)
{
     mActionSelectListener = actionSelectListener;
}


    public bool OnMenuItemClick(IMenuItem item)
    {
        getSelectedData();
        releaseAction();
        return true;

    }


    /**
     * js call back interface
     */
    class ActionSelectInterface : Java.Lang.Object
    {

    Context mContext;

   public ActionSelectInterface(Context c)
    {
        mContext = c;
    }

    [JavascriptInterface]
    [Export]
    public void callback(string value)
    {
        if (mActionSelectListener != null)
        {
            mActionSelectListener.onClick(value);
        }
    }
 }
}

3。在您的 CustomRenderer 中使用:

 [assembly: ExportRenderer(typeof(CustomWebView), typeof(WebViewRendererDroid))]
namespace TApp.Droid
{
    public class WebViewRendererDroid : ViewRenderer<CustomWebView, Android.Webkit.WebView>, ActionSelectListenerr /* ViewRenderer<CustomWebView, Android.Webkit.WebView>*/
    {
        Context _context;
        public WebViewRendererDroid(Context context) : base(context)
        {
            _context = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var webView = new CustomActionWebView(_context);
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.AllowContentAccess = true;
                webView.linkJSInterface();
                webView.LoadUrl("https://docs.microsoft.com/en-us/xamarin/ios/");
                SetNativeControl(webView);
            }

        }

  public void onClick(string selectText)
    {
        ClipboardManager cm = (ClipboardManager)_context.GetSystemService(Context.ClipboardService);
        // Place the text in the system clipboard.
        ClipData clipData = ClipData.NewPlainText(null, selectText);
        // Set (copy) the dataset to the clipboard
        cm.PrimaryClip = clipData;
    }

}