I'm creating some web/native hybrid iOS App with some C# background task on MonoTouch.
For a starter, I tried to create very simple webView sample referring
http://docs.xamarin.com/recipes/ios/content_controls/web_view/load_local_content/
http://docs.xamarin.com/recipes/ios/content_controls/web_view/load_local_content/Resources/Loading_Local_Content_(WebView).zip
(The above sample project code works, but I just need a webView without NavigatorView)
and
http://yobriefca.se/blog/2011/12/05/rolling-your-own-phonegap-with-monotouch/
My code so far is:
AppDelegate.cs
using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace iostest
{
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
UIWindow window;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
window.RootViewController = new WebViewController();
// make the window visible
window.MakeKeyAndVisible ();
return true;
}
}
}
WebViewController.cs
using System;
using System.IO;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace iostest
{
public class WebViewController : UIViewController {
UIWebView webView;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
Console.WriteLine ("WebView Launched"); //this works
webView = new UIWebView(View.Bounds);
webView.ScalesPageToFit = false;
webView.LoadRequest (new NSUrlRequest
(new NSUrl (Path.Combine(NSBundle.MainBundle.BundlePath,
"www/app.html"), false)));
this.View.AddSubview(webView);
}
}
}
This code runs without an error, but results with only a blank white page, without showing my HTML content "www/app.html" (or, "http://google.com" whatever).
I don't see what logic I miss. Any thought? Thanks.
OK, things has been fuzzy, but I resolved by myself.
The problem is the local resource files ("www/app.html") should be flagged as 'content' at BuildAction Property of IDE.
I remember I was trapped by this a few years ago, and still see many people are trapped.
Lack of documentation cause wasting time. Please document Xamarin.
The current code for future reference:
AppDelegate.cs
using System;
//using System.Collections.Generic;
//using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace iOStest2
{
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
UIWindow window;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);
window.RootViewController = new WebViewController ();
window.MakeKeyAndVisible ();
return true;
}
}
}
WebViewController.cs
using System;
using System.IO;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace iOStest2
{
public class WebViewController : UIViewController
{
UIWebView webView;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
Console.WriteLine ("WebView Launched");
View.BackgroundColor = UIColor.Gray;
//string url = "http://google.com";
string url= Path.Combine(NSBundle.MainBundle.BundlePath,
"Content/app.html");
webView = new UIWebView(View.Bounds);
webView.LoadRequest(new NSUrlRequest(new NSUrl(url,false)));
webView.ScalesPageToFit = false;
View.AddSubview(webView);
}
}
}
Related
I am making a cross-platform hybrid app, basically rescuing a website in IOS, with Xamarin. The problem is that within this website there is a "Login with Facebook" section and this is an API, it is NOT a JavaScript "window.open" method.
I would like to know if I am doing this correctly, since I have tried different methods, and none have worked for me. I have already tried implementing the following:
WKWebViewRenderer with the CreateWebView () function and class (Actual code)
WebViewRenderer <CustomWebView, WKWebView> with the DecidePolicy () function and class
Basic WebView enabling JavaScriptEnable and JavaScriptCanOpenWindow
The combinations between these
Thank you very much in advance, I leave my CustomWebView.
Note: I can't use UIWebView, it's banned from AppStore
using Foundation;
using MobileApp.iOS.Name;
using MobileApp.Models;
using System;
using UIKit;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(CustomWebViewIOS), typeof(CustomWebViewRenderer))]
namespace MobileApp.iOS.Name
{
public class CustomWebViewRenderer : WkWebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
WKWebView wKWebView = this;
WKPreferences pref = new WKPreferences() { JavaScriptCanOpenWindowsAutomatically = true, JavaScriptEnabled = true, };
var config = new WKWebViewConfiguration();
config.Preferences = pref;
if (NativeView != null)
{
((WKWebView)NativeView).UIDelegate = new MyWKUIDelegate();
}
}
}
public class MyWKUIDelegate : WKUIDelegate
{
public override WKWebView CreateWebView(WKWebView webView, WKWebViewConfiguration configuration, WKNavigationAction navigationAction, WKWindowFeatures windowFeatures)
{
var url = navigationAction.Request.Url;
if (navigationAction.TargetFrame == null)
{
webView.LoadRequest(navigationAction.Request);
}
return null;
}
}
}
I found this class at Centering ProgressBar Programmatically in Android which would display a progressbar programmatically, problem is it's an Xamarin Android Studio example and I'm trying to convert it to Xamarin for Visual Studio 2017. This is the code that I have successfully converted with those lines that I can't seem to find a Xamarin VS 2017 equivalent for.
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace OML_Android
{
class ProgressBarHandler
{
private ProgressBar mProgressBar;
private Context mContext;
public ProgressBarHandler(Context context)
{
mContext = context;
ViewGroup layout = (ViewGroup)((Activity)context).FindViewById(Android.Resource.Id.Content).RootView;
mProgressBar = new ProgressBar(context, null, Android.Resource.Attribute.ProgressBarStyleLarge);
// there is no setIndeterminate method for progressbar
mProgressBar.setIndeterminate(true);
// I cannot find an equivilent for LayoutParams
RelativeLayout.LayoutParams params = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MatchParent, RelativeLayout.LayoutParams.MatchParent);
RelativeLayout rl = new RelativeLayout(context);
// No equivalent for Gravity.CENTER
rl.SetGravity(Gravity.CENTER);
rl.AddView(mProgressBar);
layout.AddView(rl, params);
hide();
}
public void show()
{
mProgressBar.Visibility = Android.Views.ViewStates.Visible;
}
public void hide()
{
mProgressBar.Visibility = Android.Views.ViewStates.Invisible;
}
}
}
Once I have this converted and working I want it to overlay my logon view until the view finishes processing.
I help you transform Java code to C#, there is running GIF.
There is code.
class ProgressBarHandler
{
private ProgressBar mProgressBar;
private Context mContext;
public ProgressBarHandler(Context context)
{
mContext = context;
ViewGroup layout = (ViewGroup)((Activity)context).FindViewById(Android.Resource.Id.Content).RootView;
mProgressBar = new ProgressBar(context, null, Android.Resource.Attribute.ProgressBarStyleLarge);
// there is no setIndeterminate method for progressbar
// mProgressBar.SetIndeterminate(true);
mProgressBar.Indeterminate = true;
// I cannot find an equivilent for LayoutParams
RelativeLayout.LayoutParams layoutparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MatchParent, RelativeLayout.LayoutParams.MatchParent);
RelativeLayout rl = new RelativeLayout(context);
// No equivalent for Gravity.CENTER
rl.SetGravity(GravityFlags.Center );
rl.AddView(mProgressBar);
layout.AddView(rl, layoutparams);
hide();
}
public void show()
{
mProgressBar.Visibility = Android.Views.ViewStates.Visible;
}
public void hide()
{
mProgressBar.Visibility = Android.Views.ViewStates.Invisible;
}
}
You can use it directly like following code in Activity.
var progress= new ProgressBarHandler(this);
progress.show();
I am using an image picker in my xamarin forms in order to pick an image from gallery to my program...
But, only in IOS device, when I close the image picker using
imagePicker.DismissModalViewController(true);
all my pop ups that is opened are closed with the imagePicker...
Does someone know why? or how I can solve that?
I am using DependencyService to do that in both
This is the code in IOS project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foundation;
using UIKit;
using neoFly_Montana.iOS;
using Xamarin.Forms;
using neoFly_Montana.Interface;
using System.Threading.Tasks;
using System.IO;
[assembly: Dependency(typeof(PicturePickerImplementation))]
namespace neoFly_Montana.iOS
{
public class PicturePickerImplementation : IPicturePicker
{
TaskCompletionSource<Stream> taskCompletionSource;
UIImagePickerController imagePicker;
public Task<Stream> GetImageStreamAsync()
{
// Create and define UIImagePickerController
imagePicker = new UIImagePickerController
{
SourceType = UIImagePickerControllerSourceType.PhotoLibrary,
MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary)
};
// Set event handlers
imagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia;
imagePicker.Canceled += OnImagePickerCancelled;
// Present UIImagePickerController;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
var viewController = window.RootViewController;
viewController.PresentModalViewController(imagePicker, true);
// Return Task object
taskCompletionSource = new TaskCompletionSource<Stream>();
return taskCompletionSource.Task;
}
void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)
{
UIImage image = args.EditedImage ?? args.OriginalImage;
if (image != null)
{
// Convert UIImage to .NET Stream object
NSData data = image.AsJPEG(1);
Stream stream = data.AsStream();
// Set the Stream as the completion of the Task
taskCompletionSource.SetResult(stream);
}
else
{
taskCompletionSource.SetResult(null);
}
imagePicker.DismissModalViewController(true);
}
void OnImagePickerCancelled(object sender, EventArgs args)
{
taskCompletionSource.SetResult(null);
imagePicker.DismissModalViewController(true);
}
}
}
I am using RG.PLUGIN.POPUP
I have created a custom renderer for a WebView in my Xamarin.Forms project. The WebView works great on Android. Unfortunately, on iOS, when the device is rotated, the webpage (any webpage) does not correctly adjust to the new dimensions of the WebView. If I use the built in WebView for Forms, the pages correctly resize on rotate.
What am I doing wrong with my custom renderer?
Below is a stripped down version of my custom renderer (the issue still occurs):
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using UIKit;
using Foundation;
[assembly: ExportRenderer(typeof(WebView), typeof(MyProject.iOS.WebViewRenderer))]
namespace MyProject.iOS {
public class WebViewRenderer : ViewRenderer<WebView, UIWebView> {
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) {
if (Control == null) {
var webView = new UIWebView(Frame);
webView.AutoresizingMask = UIViewAutoresizing.All;
SetNativeControl(webView);
webView.LoadRequest(new NSUrlRequest(new NSUrl("http://cnn.com")));
}
}
}
}
To fix the issue, add the following to the custom renderer:
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) {
return new SizeRequest(Size.Zero, Size.Zero);
}
To fix the rotate problem you need to use the NativeView.Bounds when you create the UIWebView.
[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespaceMobile.App.iOS
{
public class CustomWebViewRenderer : ViewRenderer<CustomWebView, UIWebView>
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var webView = new UIWebView(NativeView.Bounds);
webView.ShouldStartLoad += HandleShouldStartLoad;
webView.AutoresizingMask = UIViewAutoresizing.All;
webView.ScalesPageToFit = true;
SetNativeControl(webView);
webView.LoadRequest(new NSUrlRequest(new NSUrl(Element.Url)));
}
}
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
return new SizeRequest(Size.Zero, Size.Zero);
}
}
}
Hi i easily created custom renderer for Forms Entry control, but when i tried to create one to Picker i get this error:
Error CS0115: `Punteam.iOS.PunteamPickerRederer.OnElementChanged(Xamarin.Forms.Platform.iOS.ElementChangedEventArgs<Xamarin.Forms.Picker>)' is marked as an override but no suitable method found to override (CS0115) (Punteam.iOS)
this is my code on Forms project:
using System;
using Xamarin.Forms;
namespace Punteam
{
public class PunteamPicker : Picker
{
}
}
on IOS Project:
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform;
using Punteam;
using Punteam.iOS;
using UIKit;
using EventKitUI;
[assembly: ExportRenderer (typeof(PunteamPicker), typeof(PunteamPickerRederer))]
namespace Punteam.iOS
{
public class PunteamPickerRederer : PunteamPicker
{
protected override void OnElementChanged (ElementChangedEventArgs<Picker> e)
{
/* base.OnElementChanged (e);
this.Control.TextAlignment = MonoTouch.UIKit.UITextAlignment.Center;
this.Control.TextColor = UIColor.White;
this.Control.BackgroundColor = UIColor.Clear;
this.Control.BorderStyle = UITextBorderStyle.RoundedRect;
this.Layer.BorderWidth = 1.0f;
this.Layer.CornerRadius = 4.0f;
this.Layer.MasksToBounds = true;
this.Layer.BorderColor = UIColor.White.CGColor;*/
}
}
}
Any body know's Why i get this error?
public class PunteamPickerRederer : PunteamPicker
should be
public class PunteamPickerRederer : PickerRenderer