I have an iPad only application that I'm trying to allow users to select images from their PhotoLibrary, near as I can tell I have to use the UIImagePickerController in a UIPopOverController. I have attempted many different ways to do this but I can get anything to work. I've seen a lot of code snippets but I can't seem to get them working under Monotouch.
Could somebody point me at the correct way to do this? I greatly appreciate it.
I had to call the code that creates the image picker and the code that reacts to the image being picked from the main thread to get it to work:
partial void OnImport (UIButton s)
{
BeginInvokeOnMainThread(delegate
{
UIImagePickerController picker = new UIImagePickerController();
picker.ContentSizeForViewInPopover = new System.Drawing.SizeF(320,480);
UIPopoverController popover = new UIPopoverController(picker);
picker.FinishedPickingImage += delegate(object sender, UIImagePickerImagePickedEventArgs e)
{
BeginInvokeOnMainThread(delegate
{
UIImage image = (UIImage)info.ObjectForKey(new NSString("UIImagePickerControllerOriginalImage"));
picker.DismissModalViewControllerAnimated(true);
// do something with image
});
};
picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
popover.PresentFromRect(s.Frame, this.View, UIPopoverArrowDirection.Left, true);
});
}
Here is code that I've used in an app - this should serve as a good start for you to get it working.
UIImagePickerController imagePicker;
UIPopoverController popOver;
void AttachImageBtnTouched(object sender, EventArgs e)
{
if (popOver == null || popOver.ContentViewController == null)
{
imagePicker = new UIImagePickerController();
popOver = new UIPopoverController(imagePicker);
ImagePickerDelegate imgDel = new ImagePickerDelegate();
imagePicker.Delegate = imgDel;
imagePicker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
}
if (popOver.PopoverVisible)
{
popOver.Dismiss(true);
imagePicker.Dispose();
popOver.Dispose();
return;
}
else
{
popOver.PresentFromRect(btnAttachment.Frame, this.View, UIPopoverArrowDirection.Any, true);
}
}
// The Delegate class looks something like
public class ImagePickerDelegate : UIImagePickerControllerDelegate
{
public ImagePickerDelegate()
{}
public override void FinishedPickingMedia(UIImagePickerController picker, NSDictionary info)
{
UIImage image = (UIImage)info.ObjectForKey(new NSString("UIImagePickerControllerOriginalImage"));
// do whatever else you'd like to with the image
}
}
Related
I work on a Xamarin.Forms app (UWP!). It has a Master-Details architecture. The Master page has a ListView, and each item in it opens a corresponding Detail page. The first Detail page has only a WebView that plays a YouTube video upon loading. The second Detail view has just a placeholder label for now.
Where I switch from first Detail page to the second, the sound of the video from the first Detail page is still heard. And when I switch back to the first Detail page, the video loads again, and now I hear two voices. How can I stop the video upon switching to the second Detail page and resume when going back? If this is not possible, how can I just stop the video upon leaving its Detail page?
I guess I could do something in an overridden OnDisappearing() method of the detail page:
protected override void OnDisappearing()
{
MyWebView.NavigateToString(""); // This does not work, as NavigateToString() is not part of WebView.
base.OnDisappearing();
}
What can I use to stop playing video in WebView?
Could you please tell what I can use to stop playing video in WebView?
For your requirement, you could approach with injecting Eval java script.
private void Button_Clicked(object sender, EventArgs e)
{
string pausefunctionString = #"
var videos = document.querySelectorAll('video');
[].forEach.call(videos, function(video) { video.pause(); });
";
MyWebView.Eval(pausefunctionString);
}
Update
I have re-checked your issue, when you navigate to another page, the WebView has not be released correctly. If you want to stop the WebView video play, you could make it navigate to blank page via custom WebViewRenderer.
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRender))]
namespace App4.UWP
{
class CustomWebViewRender : WebViewRenderer
{
private Windows.UI.Xaml.Controls.WebView _WebView;
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var source = Element.Source as UrlWebViewSource;
_WebView = new Windows.UI.Xaml.Controls.WebView();
SetNativeControl(_WebView);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == WebView.SourceProperty.PropertyName)
{
var source = Element.Source as UrlWebViewSource;
if (source.Url == string.Empty)
{
_WebView.NavigateToString(string.Empty);
}
}
}
}
}
Usage
protected override void OnAppearing()
{
base.OnAppearing();
MyWebView.Source = "https://www.youtube.com";
}
protected override void OnDisappearing()
{
MyWebView.Source = string.Empty;
base.OnDisappearing();
}
Xaml
<WebView HeightRequest="500" WidthRequest="500" x:Name="MyWebView"/>
I have an application that crashes when the user tries to add an attachment from the camera (however it doesn't crash when they opt to load the attachment from their Photo Library).
Here's the method that gets called when an option (either Camera or Photo Library) is selected:
public void AddMedia(UIImagePickerControllerSourceType type)
{
_imagePicker = new UIImagePickerController();
// set our source to the photo library
_imagePicker.SourceType = type;
// set what media types
_imagePicker.MediaTypes = UIImagePickerController.AvailableMediaTypes(type);
_imagePicker.FinishedPickingMedia += Handle_FinishedPickingMedia;
_imagePicker.Canceled += (sender, evt) =>
{
Console.WriteLine("picker cancelled");
_imagePicker.DismissViewController(false, () =>
{
});
};
//PresentModalViewController is depreciated in iOS6 so we use PresentViewController
Parent.PresentViewController(_imagePicker, true, null);
}
And this is the line where it crashes:
_imagePicker.SourceType = type;
Why would it crash when setting it to Camera but not Photo Library? Does it have something to do with how the enum is ordered (Photo Library = 0, Camera = 1, Saved Photos Album = 2)?
Are you trying to reproduce it on simulator? Because you don't have an access to camera on it.
I try to create a custom dialog with nativescript using this link https://docs.nativescript.org/angular/code-samples/modal-page.html
All work great. But I don't know how to make the modal dialog transparent. The property backgroundcolor doesn't works with ios
Any help will be fine
Apple recommends that you don't make modals transparent, see this issue on nativescript's issue tracker: https://github.com/NativeScript/NativeScript/issues/2086#issuecomment-220629191
Nativescript's built-in modal is always fullscreen on iOS and cannot be transparent.
BUT you can workaround that if you (like us) need to.
Here is how we did it with nativescript-angular:
First inject Page in the modal-component.
On iOS override the function _showNativeModalView on the page-object like this:
import { Page } from 'ui/page';
const pageCommon = require('ui/page/page-common').Page;
import { Color } from 'color';
import * as utils from 'utils/utils';
......
in the constructor:
if (page.ios) {
// iOS by default won't let us have a transparent background on a modal
// Ugly workaround from: https://github.com/NativeScript/nativescript/issues/2086#issuecomment-221956483
page.backgroundColor = new Color(50, 0, 0, 0);
(<any>page)._showNativeModalView = function(parent, context, closeCallback, fullscreen) {
pageCommon.prototype._showNativeModalView.call(this, parent, context, closeCallback, fullscreen);
let that = this;
this._modalParent = parent;
if (!parent.ios.view.window) {
throw new Error('Parent page is not part of the window hierarchy. Close the current modal page before showing another one!');
}
if (fullscreen) {
this._ios.modalPresentationStyle = 0;
} else {
this._ios.modalPresentationStyle = 2;
this._UIModalPresentationFormSheet = true;
}
pageCommon.prototype._raiseShowingModallyEvent.call(this);
this._ios.providesPresentationContextTransitionStyle = true;
this._ios.definesPresentationContext = true;
this._ios.modalPresentationStyle = UIModalPresentationOverFullScreen;
this._ios.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
this._ios.view.backgroundColor = UIColor.clearColor;
parent.ios.presentViewControllerAnimatedCompletion(this._ios, utils.ios.MajorVersion >= 9, function completion() {
that._ios.modalPresentationStyle = UIModalPresentationCurrentContext;
that._raiseShownModallyEvent(parent, context, closeCallback);
});
};
}
You could also override that prototype of Page, but I think it's much cleaner to override it on the instance of Page instead.
I am trying to launch the default iOS camera application for video recording but it does not work.
Whenever I launch the application it crashes and and does not show any error log or any other error messages.
The following code works perfectly if I set the imagePicker.CameraCaptureMode to UIImagePickerControllerCameraCaptureMode.Photo.
var imagePicker = new UIImagePickerController();
imagePicker.SourceType = UIImagePickerControllerSourceType.Camera;
imagePicker.CameraCaptureMode = UIImagePickerControllerCameraCaptureMode.Video;
var imagePickerDelegate = new ImagePickerDelegate(this);
imagePicker.Delegate = imagePickerDelegate;
NavigationController.PresentModalViewController(imagePicker, true);
Thanks in advance
I got it to work by doing this:
var imagePicker = new UIImagePickerController();
imagePicker.SourceType = UIImagePickerControllerSourceType.Camera;
imagePicker.MediaTypes = new string[]{ UTType.Movie }; // ADD this
var imagePickerDelegate = new ImagePickerDelegate(this);
imagePicker.Delegate = imagePickerDelegate;
NavigationController.PresentModalViewController(imagePicker, true);
Also you can set your delegate calls like so:
imagePicker.FinishedPickingMedia += Handle_FinishedPickingMedia;
imagePicker.Canceled += Handle_Canceled;
Then create these methods:
protected void Handle_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e)
{
//code to handle picking media
}
void Handle_Canceled(object sender, EventArgs e)
{
imagePicker.DismissViewController(true, null);
}
Update
In iOS 10 you need to add the permissions and provide the description as to why you are asking for the permission in the info.plist
see here:
iOS 10 - Changes in asking permissions of Camera, microphone and Photo Library causing application to crash
The following code in Xamarin for iOS was working fine prior to the Xamarin for iOS update to v2.0.50727
This is the code in a custom renderer in a Xamarin Forms app
class WatchVideoRenderer : PageRenderer
{
MPMoviePlayerController moviePlayer;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
var url = new NSUrl("http://192.168.12.4:8085/MediaUploads/1/211/520140731170618/DPM202.mp4");
moviePlayer = new MPMoviePlayerController();
moviePlayer.ContentUrl = url;
moviePlayer.View.Frame = new CGRect((float)((NativeView.Bounds.Width - 600) / 2), (float)((NativeView.Bounds.Height - 450) / 2), 600, 400);
MPMoviePlayerController.Notifications.ObserveLoadStateDidChange(OnLoadStateChanged);
MPMoviePlayerController.Notifications.ObservePlaybackDidFinish(OnPlaybackComplete);
View.AddSubview(moviePlayer.View);
moviePlayer.PrepareToPlay();
moviePlayer.ShouldAutoplay = true;
moviePlayer.Play();
}
private void OnLoadStateChanged(object sender, NSNotificationEventArgs e)
{
if (moviePlayer.LoadState == MPMovieLoadState.Playable)
{
}
}
private void OnPlaybackComplete(object sender, MPMoviePlayerFinishedEventArgs e)
{
}
}
As i said this was working till day before yesterday, after which I installed 2 updates on Xamarin. iOS & this is now failing. All i see is a black canvas & the video never loads.
No notifications from the MPMoviePlayerController are ever raised.
There is a release of this app scheduled for next week & this last minute bug is causing me headaches. Any help is really appreciated.
I resolved a similar issue by pushing a new image context and that did the trick. I modified the code to include the BeginImageContext() and EndImageContext().
UIGraphics.BeginImageContext(new CGSize(1,1));
var url = new NSUrl("http://192.168.12.4:8085/MediaUploads/1/211/520140731170618/DPM202.mp4");
moviePlayer = new MPMoviePlayerController();
moviePlayer.ContentUrl = url;
moviePlayer.View.Frame = new CGRect((float)((NativeView.Bounds.Width - 600) / 2), (float)((NativeView.Bounds.Height - 450) / 2), 600, 400);
UIGraphics.EndImageContext();
Try switching to AVPlayerViewController instead of MPMoviePlayerController. Throw this code inside your OnElementChanged method.
My renderer was a view renderer and not a page renderer so you might have to tweak it a bit.
if(Control == null)
{
AVPlayerViewController avpvc;
AVPlayer avp;
var url = NSUrl.FromString("SOME URL HERE"); //or NSUrl.FromFile
avp = new AVPlayer(url);
avpvc = new AVPlayerViewController();
avpvc.Player = avp;
avpvc.ShowsPlaybackControls = true;
avp.Play();
this.SetNativeControl(avpvc.View);
}