How to remove volume HUD on Xamarin Forms? - c#

I have made a customrenderer to render a MPVolumeView inside of a xamarin.forms app. Whenever I adjust the volume, I get this big system HUD on screen that is blocking the content on screen. Looks something like this:
How do I remove this? This is my custom renderer:
public class AudioOutputViewRenderer : ViewRenderer<AudioOutputView, UIView>
{
MPVolumeView view;
protected override void OnElementChanged(ElementChangedEventArgs<AudioOutputView> e)
{
base.OnElementChanged(e);
TintColor = UIColor.FromRGB(54, 66, 94);
if (Control == null)
{
view = new MPVolumeView()
{
ShowsRouteButton = false,
ShowsVolumeSlider = true
};
SetNativeControl(view);
}
}
}

I didnt understand perpose of the AudioOutputViewRenderer
But to hide the MPVolumeView you need next:
in your IosProject -> AppDelegate -> method FinishedLaunching add next code
var volumeView = new MPVolumeView(new CGRect(-1000,0,0,0));// -1000 will hide your view from user
volumeView.ClipsToBounds = true;
var slider = volumeView.Subviews.First(x => x is UISlider) as UISlider;
UIApplication.SharedApplication.KeyWindow.RootViewController.View.AddSubview(volumeView);
After you can use var slider to change volume like this
slider.Value = [your vlm];

Related

Xamarin Forms Custom SearchbarRenderer with Loadingcircle like Netflix

I really want to implement a loading circle in the searchbar (overriding the cancel button while loading) on android like Netflix.
Currently Im getting the cancel button with
var searchBttId = searchView.Resources.GetIdentifier("android:id/search_close_btn", null, null);
var imbCancel = (searchView.FindViewById(searchBttId) as Android.Widget.ImageView)
but I dont know how to add a progresscircle and how to interact with it. I thought of adding it with AddView, but nothing pops up when testing.
Test:
var _v = new Android.Widget.ImageView(Context) { };
_v.SetBackgroundColor(new Android.Graphics.Color(200, 0, 0));
var c = new LayoutParams(500, 500);
_v.LayoutParameters = c;
searchView.AddView(_v);
I really want to implement a loading circle in the searchbar (overriding the cancel button while loading) on android like Netflix.
According to your description, you want to override searchbar's search_close_btn using other icon, like loading circle? Am I right?
If yes, I suggest you can use custom render to change searchbar's search_close_btn image.
Firstly, create custom Searchbar that inherit SearchBar in Form.cs.
public class MySearchBar:SearchBar
{
}
Then implementing custom render in Android platform.
[assembly: ExportRenderer(typeof(MySearchBar), typeof(MySearchBarRenderer))]
namespace demo3.Droid
{
public class MySearchBarRenderer: SearchBarRenderer
{
public MySearchBarRenderer(Context context):base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var searchView = Control;
int searchViewCloseButtonId = Control.Resources.GetIdentifier("android:id/search_close_btn", null, null);
var closeIcon = searchView.FindViewById(searchViewCloseButtonId);
(closeIcon as ImageView).SetImageResource(Resource.Drawable.plu3);
}
}
}
}
Please see the gif:
About Custom Render, you can take a look:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/entry

Change status bar colour on iOS13

Before iOS 13 I could change the status bar colour using the following bit of code:
UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.BackgroundColor = UIColor.Clear.FromHex(0x323232);
statusBar.TintColor = UIColor.White;
app.StatusBarStyle = UIStatusBarStyle.BlackOpaque;
}
However, on iOS13 I get the following runtime error
Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.
Any idea on how to change the status bar on iOS13?
EDIT: Just to point out, this is for Xamarin and not for Swift. To clarify the duplicate marker.
From error , you need to use UIStatusBarManager in IOS 13.
If you have updated VS to the latest version(Visual Studio 2019 version 16.3.0/Visual Studio 2019 for Mac version 8.3 above), you can change color as follow:
UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
statusBar.BackgroundColor = UIColor.Yellow;
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
Else the follow methods can make it works .
UIView statusBar = new UIView(UIApplication.SharedApplication.StatusBarFrame);
statusBar.BackgroundColor = UIColor.Yellow;
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
If the view is not fully rendered , UIApplication.SharedApplication.KeyWindow will return null .So you can change status bar color after fully rendered . Here is the sample .
===================================Update=================================
If in Forms project , you can have a try with invoking method in AppDelegate.cs
public override void OnActivated(UIApplication uiApplication)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
// If VS has updated to the latest version , you can use StatusBarManager , else use the first line code
// UIView statusBar = new UIView(UIApplication.SharedApplication.StatusBarFrame);
UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
statusBar.BackgroundColor = UIColor.Red;
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
}
else
{
UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.BackgroundColor = UIColor.Red;
UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.BlackOpaque;
}
}
base.OnActivated(uiApplication);
}
Note :
Not sure this solurion will always work in AppDelegate.cs, better invoked in Controller.cs's method , because from iOS 13 , Apple have modified the architure of AppDelegate and added SceneDelegate to project.
This also works, if used in ViewDidAppear override in a UIViewController. I previously tested in ViewWillAppear and even that was too soon to have a KeyWindow non-null:
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
//Obj-C:
// UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
// statusBar.backgroundColor = [UIColor redColor];
// [[UIApplication sharedApplication].keyWindow addSubview:statusBar];
// Xamarin.iOS:
UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
statusBar.BackgroundColor = UIColor.Red;
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
}
else
{
UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.BackgroundColor = UIColor.Red;
statusBar.TintColor = UIColor.White;
UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.BlackOpaque;
}
}
}
And that is the same solution provided in the duplicate question: https://stackoverflow.com/a/58028658/2913599
Could you please try the below solution. it works fine for me in the same scenario
if (#available(iOS 13.0, *)) {
UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame];
statusBar.backgroundColor = [UIColor redColor];
[[UIApplication sharedApplication].keyWindow addSubview:statusBar];
} else {
// Fallback on earlier versions
UIView *statusBar=[[UIApplication sharedApplication] valueForKey:#"statusBar"];
statusBar.backgroundColor = [UIColor redColor];
[statusBar setNeedsDisplay];
}

How to change the title of Timepicker and localization in custom renderer

I have Xamarin forms time picker following custom renderer for IOS
[assembly: ExportRenderer(typeof(TimePicker), typeof(Time24PickerRenderer))]
namespace LabOraTimeStamp.iOS.Renderers
{
public class Time24PickerRenderer:TimePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
{
base.OnElementChanged(e);
var timePicker = (UIDatePicker)Control.InputView;
timePicker.Locale = new NSLocale("no_nb");
//Get the Done button
var toolbar = (UIToolbar)Control.InputAccessoryView;
var doneBtn = toolbar.Items[1];
//Set the Done to OK
doneBtn.Title = "OK";
}
}
}
I wanted to change the default "done" to "Ok".
1) How can I do that? the line mentioned above for setting the title does not affect anything.
2) I already implemented localization for xamarin forms.I just wanted to use existing Resx values from custom renderer to show the string for appropriate culture.How can I achieve that?
So the reason why your code isn't working is because the done button is created with the UIBarButtonSystemItem.Done style. It doesn't care about the Title property. Renderer code here.
To work around that issue you could try replacing the Xamarin created done button with your own custom Ok button.
//Get the Done button
var toolbar = (UIToolbar)Control.InputAccessoryView;
// Replace Xamarin's buttons with custom ones.
var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
var doneButton = new UIBarButtonItem();
doneButton.Title = "OK";
doneButton.Clicked += (o, a) => Control.ResignFirstResponder();
toolbar.SetItems(new [] { spacer, doneButton}, false);

Is there any way to pre-render a WebView control with Xamarin Forms?

I've created a set of custom html5 audio controls which I'm using in my iOS and Android Xamarin Forms app.
When I navigate to the page in my app where this content is located, the WebView renders as a white box for a fraction of a second before it renders the html content. Is there any way to render this view before it is visible to the user?
public partial class TutorialPage : ContentPage
{
private readonly ITutorialViewModel _dataModel;
public TutorialPage(ITutorialViewModel dataModel)
{
InitializeComponent();
Title = "Tutorial";
var browser = new WebView() { HeightRequest = 150, WidthRequest = 400, HorizontalOptions = LayoutOptions.CenterAndExpand };
browser.Source = DependencyService.Get<IBaseUrl>().Get();
mainStack.Children.Add(browser);
}
}
You can always use the events of the webview for that.
Take a look at them:
Navigated - Event that is raised after navigation completes.
Navigating - Event that is raised when navigation starts.
So what you have to do is set the webview's "IsVisible" property to false at the start, and when the Navigated event fires, set it back to true.
Example:
public partial class TutorialPage : ContentPage
{
private readonly ITutorialViewModel _dataModel;
private WebView browser;
public TutorialPage(ITutorialViewModel dataModel)
{
InitializeComponent();
Title = "Tutorial";
browser = new WebView() { HeightRequest = 150, WidthRequest = 400, HorizontalOptions = LayoutOptions.CenterAndExpand, IsVisible = false };
browser.Source = DependencyService.Get<IBaseUrl>().Get();
browser.Navigated += Browser_Navigated:
mainStack.Children.Add(browser);
}
void Browser_Navigated (object sender, WebNavigatedEventArgs e)
{
browser.IsVisible = true;
}
}
If you don't want to make the WebView as a global class variable, you can get it from the sender parameter of the Navigated event, as shown below:
void Browser_Navigated (object sender, WebNavigatedEventArgs e)
{
((WebView)sender).IsVisible = true;
}
I bypassed my problem by making the background transparent. The controls still pop in but it's better than having a white box on the page in the meantime.

Monotouch - NavigationBar with extra padding ios 7

I'm trying to adapt my app for iOS 7. It's written with Xamarin and C#.
I'm having trouble with extra padding for the left button in the navigationbar.
I have a helper method for rendering my back-button which looks like this:
public static UIBarButtonItem GetBackButton (this UIViewController controller)
{
var backImage = new UIImage ("Images/back.png");
var backButton = new UIButton (UIButtonType.Custom);
backButton.Frame = new RectangleF (0, 0, 44, 44);
backButton.SetImage (backImage, UIControlState.Normal);
backButton.TouchUpInside += (object sender, EventArgs e) => {
var cancelBackNavigation = false;
if (controller is UIViewControllerBase) {
if (((UIViewControllerBase)controller).PrepareNavigateBack () != true) {
cancelBackNavigation = true;
}
}
if (cancelBackNavigation == false) {
controller.NavigationController.PopViewControllerAnimated (true);
}
};
return new UIBarButtonItem (backButton);
}
The navigationbar adds lots of padding before the back-button and making the image inside the back-button look very far away from its real position. The code above works fine in iOS 6.
I don't wanna use ContentEdgeInsets cause it will stretch the image and making it ugly.
Anyone with an idea of what to do?
I tried looking up your issue and found out that first, you need to hide the back button as follows:
NavigationItem.HidesBackButton = true;
Then for setting the button, you need to set it this way:
NavigationItem.BackBarButtonItem = yourButton;
That way, you won`t have the extra indentation.
Also you might find the following question useful:
Make a custom back button for UINavigationController
This is how I setup my NavigationBar
controller.View.BackgroundColor = Theme.BackgroundColor;
controller.NavigationItem.SetHidesBackButton (true, false);
controller.NavigationController.Toolbar.TintColor = Theme.BackgroundColor;
controller.NavigationController.NavigationBar.TintColor = Theme.BackgroundColor;
controller.NavigationController.SetNavigationBarHidden (show == false, false);
controller.NavigationController.NavigationBar.BackgroundColor = Theme.BackgroundColor;
controller.NavigationController.NavigationBar.SetTitleTextAttributes (Theme.NavigationBarTextAttributes);
controller.NavigationController.NavigationBar.Subviews [0].Alpha = 0.01f;

Categories

Resources