I have created a custom menu item which appears in the default menu which pops up when selecting text on my custom WebView.
On clicking on the menu item it calls EvaluateJavascript to get the selected WebView text, and then passes the text to another page.
However after performing this action once or twice, some text on certain areas of the screen start to become unresponsive to clicks eg. text on the parts of the WebView become unselectable, clicks on that part of the screen on other pages becomes unresponsive and even the soft keyboard becomes unclickable in some spots. If this continues for a while sometimes my app will then suddenly freeze the entire operating system and I have to soft reset my phone. It appears that there maybe some serious memory leakage going on.
I create my custom menu item in the MainActivity class:
public override void OnActionModeStarted(ActionMode mode)
{
if (Root.IsCurrentPageType<DictPage>() && DictP.IsWebViewFocused())
{
IMenu menu = mode.Menu;
menu.Add("To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this, mode));
}
base.OnActionModeStarted(mode);
}
It is then handled in the Listener class...
public class MyMenuItemOnMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener
{
private MainActivity mContext;
ActionMode _mode;
public MyMenuItemOnMenuItemClickListener(MainActivity activity, ActionMode mode)
{
this.mContext = activity;
_mode = mode;
}
public bool OnMenuItemClick(IMenuItem item)
{
WEB.CopyToMainNotes();
Device.BeginInvokeOnMainThread(() =>
{
//close menu if clicked
_mode?.Finish();
});
return true;
}
}
...which calls CopyToMainNotes on my derived WebView class and its associated Renderer and EventHandler classes:
public class WebViewEx : Xamarin.Forms.WebView
{
public static WebViewEx WEB;
//Namespace
//YourClass
public event WebViewExEventHandler CallNativeMethodEvent;
public void CallNativeMethod(WebViewExEventType type)
{
WebViewExEventArgs e = new WebViewExEventArgs();
e.EventType = type;
CallNativeMethodEvent?.Invoke(this, e);
}
public WebViewEx()
{
WEB = this;
}
public void CopyToMainNotes()
{
Device.BeginInvokeOnMainThread(() =>
{
CallNativeMethod(WebViewExEventType.copyToMainNotes);
});
}
}
public delegate void WebViewExEventHandler(object sender, WebViewExEventArgs e);
public class WebViewExEventArgs : EventArgs
{
public enum WebViewExEventType { copyToMainNotes };
public WebViewExEventType EventType = WebViewExEventType.copyToMainNotes;
public WebViewExEventArgs() : base()
{
}
}
public class WebViewExRenderer : WebViewRenderer
{
public WebViewExRenderer(Android.Content.Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
WebViewEx ex = e.NewElement as WebViewEx;
ex.CallNativeMethodEvent += WebViewEx_CallNativeMethodEvent;
}
}
internal class JavascriptCallback : Java.Lang.Object, IValueCallback
{
public JavascriptCallback(Action<string> callback)
{
_callback = callback;
}
private Action<string> _callback;
public void OnReceiveValue(Java.Lang.Object value)
{
_callback?.Invoke(Convert.ToString(value));
}
}
private void WebViewEx_CallNativeMethodEvent(object sender, WebViewExEventArgs e)
{
switch (e.EventType)
{
case WebViewExEventType.copyToMainNotes:
{
CopyToMainNotes();
break;
}
}
}
public void CopyToMainNotes()
{
string script = "(function(){ return window.getSelection().toString()})()";
var response = string.Empty;
Control?.EvaluateJavascript(script, new JavascriptCallback((r) =>
{
response = r;
Device.BeginInvokeOnMainThread(() =>
{
DPage.CopyThisTextToAnotherPage(response.ToString().Trim('\"'));
});
}));
}
}
The CopyToMainNotes method above is where the EvaluateJavascript takes place and the selected text finally gets sent to another page.
Any ideas where I might be going wrong here? Thanks in advance!