i have web-view that i need to create for it context menu when click on link type this what i did :
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Webview);
wv = (WebView)FindViewById(Resource.Id.WV);
RegisterForContextMenu(wv);
wv.SetWebChromeClient(new WebChromeClient());
wv.SetWebViewClient(new WebViewClient());
wv.Settings.JavaScriptEnabled = true;
wv.Settings.DomStorageEnabled = true;
wv.Settings.SetSupportZoom(true);
wv.Settings.DisplayZoomControls = false;
wv.Settings.BuiltInZoomControls = true;
wv.Settings.CacheMode = CacheModes.Default;
wv.Settings.UseWideViewPort = true;
wv.Settings.LoadWithOverviewMode = true;
wv.SetInitialScale(1);
wv.LoadUrl("file:///android_asset/index.html");
}
public override void OnCreateContextMenu(IContextMenu menu, View v, IContextMenuContextMenuInfo menuInfo)
{
base.OnCreateContextMenu(menu, v, menuInfo);
WebView webView = (WebView)v;
result = webView.GetHitTestResult();
if (result.GetType().ToString().Equals("SRC_ANCHOR_TYPE") || result.GetType().ToString().Equals("ANCHOR_TYPE"))
{
var item = menu.Add("copylink");
item.SetOnMenuItemClickListener(this);
}
}
but "result.GetType()" its its not detect anchor type link the "result.GetType()" is not detect any link in webview when it get pressed longtoch..
If you want to add a item to the menu, you should override OnActionModeStarted method. then add the SetOnMenuItemClickListenerlike following code.
public override void OnActionModeStarted(ActionMode mode)
{
IMenu menu = mode.Menu;
menu.Add("Add To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this));
base.OnActionModeStarted(mode);
}
internal class MyMenuItemOnMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener
{
private MainActivity mainActivity;
public MyMenuItemOnMenuItemClickListener(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public bool OnMenuItemClick(IMenuItem item)
{
Toast.MakeText(mainActivity, "You click the Add To Notes", ToastLength.Short).Show();
return true;
}
}
Here is running GIF.
If you want to create a new menu, you can use menu.Clear();
public override void OnActionModeStarted(ActionMode mode)
{
IMenu menu = mode.Menu;
menu.Clear();
menu.Add("Add To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this));
base.OnActionModeStarted(mode);
}
Here is running screenshot.
Update
If you want to get the Type of long click, you should make sure type of result.Type is Webkit.HitTestResult, you use result.GetType(), Type is System.Type. So you can get the correct type, you can refer to the following code.
WebView.HitTestResult result = webView.GetHitTestResult();
Android.Webkit.HitTestResult myresult = result.Type;
You can refer to the debug gif.
Related
so I'm trying to make an android app that starts with a login page (that I thought could be a dialog fragment) and if the user's credentials are correct, then he'll be directed to the main app that is supposed to be a navigation drawer app. I tried to use the dialog fragment but I didn't know how to set it to appear at the very beginning. what should I do?
You should create a Activity as a MainLauncher, Activity you can use a blank Layout.xml like following code, then pop a DialogFragment like following code. Note: you should add MainLauncher = true,NoHistory =true in your Activity attribute. NoHistory =true will make the back button navigate to the desktop.
namespace App2
{
[Activity(Label = "LoginActivity", Theme = "#style/AppTheme.NoActionBar",MainLauncher = true,NoHistory =true)]
public class LoginActivity : AppCompatActivity, OnLoginInforCompleted
{
public void inputLoginInforCompleted(string userName, string passWord)
{
//You can get the username and password here
StartActivity(new Intent(this,typeof(MainActivity)));
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.LoginLayout);
MyDialogFragment dialogFragment = new MyDialogFragment();
dialogFragment.setOnLoginInforCompleted(this);
dialogFragment.Cancelable = false;
var SupportFragmentManager = this.FragmentManager;
dialogFragment.Show(SupportFragmentManager, "dialog");
}
}
}
I achieve the a callback interface OnLoginInforCompleted, If User click the Login Button, will navigate to the navigation drawer page.
public interface OnLoginInforCompleted
{
void inputLoginInforCompleted(String userName, String passWord);
}
Here is code about MyDialogFragment .
public class MyDialogFragment : DialogFragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.Inflate(Resource.Layout.layout3, container, false);
Button button = view.FindViewById<Button>(Resource.Id.button1);
EditText MyeditText1 = view.FindViewById<EditText>(Resource.Id.editText1);
EditText MyeditText2 = view.FindViewById<EditText>(Resource.Id.editText2);
button.Click += delegate {
//set the data to the loginpage
mOnLoginInforCompleted.inputLoginInforCompleted(MyeditText1.Text.ToString(), MyeditText2.Text.ToString());
Dismiss();
};
return view;
}
//set for Callback
private OnLoginInforCompleted mOnLoginInforCompleted;
public void setOnLoginInforCompleted(OnLoginInforCompleted onLoginInforCompleted)
{
mOnLoginInforCompleted = onLoginInforCompleted;
}
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
return base.OnCreateDialog(savedInstanceState);
}
}
Here is running GIF.
Here is my demo, you can refer to it.
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/App2.zip
I have WebView which works fine for file upload but when I click on files to open or download, nothing happens. but in normal browser when I click on file it is opened successfully. the intention of code is to open the file when it is clicked. file choose chrome extension is fine. I think there is need to add some code in WebViewListner block.
The activity code is here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Net;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Webkit;
using Android.Widget;
namespace smartbookapp
{
[Activity(Label = "JobActivity")]
public class JobActivity : Activity
{
public WebView webview;
public IValueCallback mUploadMessage;
public static ProgressBar progressBar;
public static int FILECHOOSER_RESULTCODE = 1;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Jobs);
webview = FindViewById<WebView>(Resource.Id.JobView);
// show progress bar
progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar);
//
webview.Settings.JavaScriptEnabled = true;
webview.Settings.SetAppCacheEnabled(true);
webview.Settings.AllowFileAccess = true;
webview.Settings.BuiltInZoomControls = true;
webview.SetWebViewClient(new WebViewListener());
webview.SetWebChromeClient(new JobWebChromeClient(this));
webview.LoadUrl("https://smartbook.pk/Jobs/index");
//
}
//
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
if (requestCode == FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage) return;
Android.Net.Uri[] result = data == null || resultCode != Result.Ok ? null : new Android.Net.Uri[] { data.Data };
try
{
mUploadMessage.OnReceiveValue(result);
}
#pragma warning disable CS0168 // Variable is declared but never used
catch (Exception e)
#pragma warning restore CS0168 // Variable is declared but never used
{
}
mUploadMessage = null;
}
base.OnActivityResult(requestCode, resultCode, data);
}
// webview listener code here
public class WebViewListener : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return true;
}
public override void OnPageStarted(WebView view, string url, Android.Graphics.Bitmap favicon)
{
progressBar.Progress = view.Progress;
}
public override void OnLoadResource(WebView view, string url)
{
progressBar.Progress = view.Progress;
}
public override void OnPageFinished(WebView view, string url)
{
progressBar.Progress = 0;
}
}
public override bool OnKeyDown(Keycode keyCode, KeyEvent e)
{
if (keyCode == Keycode.Back && webview.CanGoBack())
{
webview.GoBack();
return true;
}
return base.OnKeyDown(keyCode, e);
}
}
// download files from webview
public class JobWebChromeClient : WebChromeClient
{
JobActivity WebViewActivity;
public JobWebChromeClient(JobActivity activity)
{
WebViewActivity = activity;
}
public override bool OnShowFileChooser(WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
{
WebViewActivity.mUploadMessage = filePathCallback;
Intent i = new Intent(Intent.ActionGetContent);
i.AddCategory(Intent.CategoryOpenable);
i.SetType("*/*");
WebViewActivity.StartActivityForResult(Intent.CreateChooser(i, "File Chooser"), JobActivity.FILECHOOSER_RESULTCODE);
return true;
}
}
}
First of all, make sure your WebView has enabled javascript and the WebViewClient is set correctly.
WebView mWebview = FindViewById<WebView>(Resource.Id.webView1);
mWebview.Download += MWebview_Download;
var client = new WebViewClient();
mWebview.Settings.JavaScriptEnabled = true;
mWebview.SetWebViewClient(client);
mWebview.LoadUrl("your url");
Then, we shouldd achieve WebView.Download event(use DownloadManager to download the file)
private void MWebview_Download(object sender, DownloadEventArgs e)
{
var url = e.Url;
DownloadManager.Request request = new
DownloadManager.Request(Uri.Parse(url));
request.AllowScanningByMediaScanner();
request.SetNotificationVisibility(DownloadManager.Request.VisibilityVisibleNotifyCompleted); //Notify client once download is completed!
request.SetDestinationInExternalPublicDir(Environment.DirectoryDownloads, "CPPPrimer");
DownloadManager dm = (DownloadManager)GetSystemService("download");
dm.Enqueue(request);
Toast.MakeText(ApplicationContext, "Downloading File",ToastLength.Long//To notify the Client that the file is being downloaded
).Show();
}
I'm trying to make a little android app showing a webview loading a website.
I got it to show it with the following code snippets. But what I need now is to hide some elements on the header and the footer(a menu for example). I thought I could do it not loading some classes from the webpage, but I'm not sure how to properly do it. Do anyone have some experience on this to share some light? :)
Thanks in advance.
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;
DrawerLayout drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, Resource.String.navigation_drawer_open, Resource.String.navigation_drawer_close);
drawer.AddDrawerListener(toggle);
toggle.SyncState();
NavigationView navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
navigationView.SetNavigationItemSelectedListener(this);
wbv = FindViewById<WebView>(Resource.Id.webView1);
wbv.SetWebViewClient(new ExtendWebViewClient());
WebSettings webSettings = wbv.Settings;
webSettings.JavaScriptEnabled = true;
wbv.LoadUrl(txtUrl);
}
internal class ExtendWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
view.LoadUrl(url);
return true;
}
}
edit: Just to reflect the changes to the second class
public class ExtendWebViewClient : WebViewClient
{
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
string js = "var myElements = document.getElementsByClassName('fusion-main-menu');" +
" myElements[0].style.display = 'none'; ";
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
{
view.EvaluateJavascript(js, null);
}
else
{
view.LoadUrl(js);
}
}
}
Since you have enabled javascript, there will be a function to run the script in the webview.
This is the code of WebView using Xamarin.Forms.WebView and this is how you can hide any element of webview using it's id.
var hide = await webview.EvaluateJavaScriptAsync("document.getElementById('UserName').style.display = 'none';");
I have the following problem:
My method opens a JDialog with a bunch of buttons (only one in example code). I want to click a button and thereby choose an ImageIcon for my method to return. But the Method does not wait for me to click a button. It opens the window and then returns an empty ImageIcon.
public class Kartenauswahl {
ImageIcon bandit;
public ImageIcon auswahlfenster() {
int bwidth = new Integer(150);
int bheight = new Integer(225);
bandit = new ImageIcon("cover/Bandit.jpe");
bandit.setImage(bandit.getImage().getScaledInstance(bwidth,bheight,Image.SCALE_DEFAULT));
final JDialog kartenwahl = new JDialog();
kartenwahl.setTitle("Kartenwahl");
kartenwahl.setSize(1500,1000);
kartenwahl.setVisible(true);
kartenwahl.setLayout(new FlowLayout());
ImageIcon returnicon= new ImageIcon();
final JButton b1 = new JButton(); //just to get the Icon out of the void loop
JButton B1 = new JButton(bandit); //this is going to be the button I want to click to choose the ImageIcon which is returned
B1.setContentAreaFilled(false);
B1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
b1.setIcon(bandit);
kartenwahl.dispose();
}
});
kartenwahl.add(B1);
returnicon = (ImageIcon) b1.getIcon();
return returnicon;
}
}
Question: can I bind the return statement to a condition? Like "only return after I clicked that Button B1"?
Hi sorry for the long wait. I have written an custom JDialog that should work for you.
public class CustomDialog extends JDialog {
JButton[] buttons;
ImageIcon selectedImageIcon;
public CustomDialog() {
setSize(500, 500);
setLayout(new GridLayout(4, 6));
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
selectedImageIcon = ((ImageIcon) ((JButton) e.getSource()).getIcon());
dispose();
}
};
buttons = new JButton[24];
for(int i = 0; i < 24; i++) {
buttons[i] = new JButton(new ImageIcon("path_to_your_image_file"));
buttons[i].addActionListener(actionListener);
add(buttons[i]);
}
setVisible(true);
}
public ImageIcon getSelectedImageIcon() {
return selectedImageIcon;
}
}
The initial size is not that important the GridLayout is. you mentioned that you would need 24 buttons so I created an grid with 4 rows and 6 columns.
Then I create the buttons in a loop and adding the same Listener to set the selection icon with the icon of the pressed button. Afterwards I dispose the screen triggering an windowClosed event.
You could simply create this Dialog from your main class and wait for the response like so:
public class main {
public static void main(String[] args) {
CustomDialog customDialog = new CustomDialog();
customDialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
ImageIcon icon = customDialog.getSelectedImageIcon();
//do something with your icon
}
});
}
}
Don't forget to mark this answer as correct if it fixes your problem.
Have a good one!
I am developing an app for iOS using MvvmCross. On one of my Views I have some basic report data that is displayed in a tableview.
When the table row is touched a new view containing a detail report is displayed by making the call to ShowViewModel passing some parameters in a Dictionary. This works fine.
When the user swipes left or right the app needs to show the detail report for the next or previous item in the original list. I am doing this by updating some parameters and calling ShowViewModel again. The logic behind this is all working fine.
My problem; ShowViewModel animates the new view coming in from the right. This is perfect when the user has swiped left. However when swiping right it seems counter intuitive. How can I make ShowViewModel animate or transition in from the left side?
if you look to the MvvmCross source code here you see how the default behavior is showing the ViewControllers
You need to change that by doing something like the following:
How to change the Push and Pop animations in a navigation based app
for that, one idea is to have a custom view presenter and catch navigation to that particular view-model (override Show(IMvxTouchView view) )
or, maybe derive from UINavigationController, set it to MvvmCross to use it (look to the MvxSetup), and on some events change transition to that particular view
similar to this question
How to specify view transitions on iPhone
This is the solution I was able to come up with following the helpful pointers in the answer from Andrei N. In the end I opted for a TransitionFlipFromRight and TransitionFlipFromLeft when scrolling between detail reports. Hopefully it is useful to somebody else.
I already had a presenter class that was inherited from MvxModalSupportTouchViewPresenter
public class BedfordViewPresenter : MvxModalSupportTouchViewPresenter
Within this class I added a property of MvxPresentationHint.
private MvxPresentationHint _presentationHint;
In the override of method ChangePresentation the above property is used to store the passed in parameter
public override void ChangePresentation (MvxPresentationHint hint)
{
_presentationHint = hint;
base.ChangePresentation (hint);
}
Two new MvxPresentationHint class were declared (see later)
In the presenter class the Show method was overridden
public override void Show(IMvxTouchView view)
{
if (_presentationHint is FlipFromRightPresentationHint) {
var viewController = view as UIViewController;
MasterNavigationController.PushControllerWithTransition (viewController, UIViewAnimationOptions.TransitionFlipFromRight);
}
else
if (_presentationHint is FlipFromLeftPresentationHint) {
var viewController = view as UIViewController;
MasterNavigationController.PushControllerWithTransition (viewController, UIViewAnimationOptions.TransitionFlipFromLeft);
}
else {
base.Show (view);
}
_presentationHint = null;
}
A new class that provides extensions to a UINavigationController was created with the method PushControllerWithTransition
public static class UINavigationControllerExtensions
{
public static void PushControllerWithTransition(this UINavigationController
target, UIViewController controllerToPush,
UIViewAnimationOptions transition)
{
UIView.Transition(target.View, 0.75d, transition, delegate() {
target.PushViewController(controllerToPush, false);
}, null);
}
}
All that needs to be defined now are the two new MvxPresentationHint class derivations. These belong in your Core class library project rather than the iOS application project.
public class FlipFromLeftPresentationHint : MvxPresentationHint
{
public FlipFromLeftPresentationHint ()
{
}
}
and
public class FlipFromRightPresentationHint: MvxPresentationHint
{
public FlipFromRightPresentationHint ()
{
}
}
I hope this is a help to someone else trying to do something similar
Share my solution for android:
On view:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = base.OnCreateView(inflater, container, savedInstanceState);
var layout = view.FindViewById<LinearLayout>(Resource.Id.swippeable);
var swipeListener = new SwipeListener(this.Activity);
swipeListener.OnSwipeLeft += (sender, e) => this.ViewModel.LeftCommand?.Execute(); //Here use command into view model
swipeListener.OnSwipeRight += (sender, e) => this.ViewModel.RightCommand?.Execute();
layout.SetOnTouchListener(swipeListener);
return view;
}
Gesture listener:
public class SwipeListener : SimpleOnGestureListener, View.IOnTouchListener
{
private const int SWIPE_THRESHOLD = 100;
private const int SWIPE_VELOCITY_THRESHOLD = 100;
private readonly GestureDetector gestureDetector;
public SwipeListener(Context ctx)
{
this.gestureDetector = new GestureDetector(ctx, this);
}
public Boolean OnTouch(View v, MotionEvent e)
{
return this.gestureDetector.OnTouchEvent(e);
}
public event EventHandler OnSwipeRight;
public event EventHandler OnSwipeLeft;
public event EventHandler OnSwipeTop;
public event EventHandler OnSwipeBottom;
public override Boolean OnDown(MotionEvent e)
{
return true;
}
public override Boolean OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
Boolean result = false;
float diffY = e2.GetY() - e1.GetY();
float diffX = e2.GetX() - e1.GetX();
if (Math.Abs(diffX) > Math.Abs(diffY))
{
if (Math.Abs(diffX) > SWIPE_THRESHOLD && Math.Abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
{
if (diffX > 0)
{
SwipeRight();
}
else
{
SwipeLeft();
}
result = true;
}
}
else if (Math.Abs(diffY) > SWIPE_THRESHOLD && Math.Abs(velocityY) > SWIPE_VELOCITY_THRESHOLD)
{
if (diffY > 0)
{
SwipeBottom();
}
else
{
SwipeTop();
}
result = true;
}
return result;
}
public void SwipeRight()
{
this.OnSwipeRight?.Invoke(this, EventArgs.Empty);
}
public void SwipeLeft()
{
this.OnSwipeLeft?.Invoke(this, EventArgs.Empty);
}
public void SwipeTop()
{
this.OnSwipeTop?.Invoke(this, EventArgs.Empty);
}
public void SwipeBottom()
{
this.OnSwipeBottom?.Invoke(this, EventArgs.Empty);
}
}