How to set Icon of Page in Xamarin Forms - c#

I try set Icon for my Pages in Xaml:
Icon="icon.png
But it's not working, so I found other solution: How to add an icon in navigation bar for navigation page in xamarin forms for android?
It's custom render and working:
[assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomMapRenderer))]
namespace XamarinFormsMaps.Droid
{
public class CustomMapRenderer : NavigationPageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
{
base.OnElementChanged(e);
var bar = (Android.Support.V7.Widget.Toolbar)typeof(NavigationPageRenderer)
.GetField("_toolbar", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(this);
bar.SetLogo(Resource.Drawable.icon); //how to load other icon, when Page is changing?
}
}
}
But I want set other Icon for other Pages... It's code set the same Icon for all pages. How to resolve it?

You can be notified when the current page of Navigation is changed by using below code.
It's a method in NavigationPageRenderer.
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "CurrentPage")
{
var page = Element.CurrentPage as ContentPage;
if (page != null)
{
//do what you want.
}
}
}

Related

How to change the toolbar back icon in xamarin forms android

I am working on xamarin forms. I wanted to change the Toolbar back icon how to do it. I searched lot about it. I didn't get proper solution. Any help would be appreciated.
Thanks
praveen
Try this
LoadApplication(new App());
var upArrow = Resources.GetDrawable(Resource.Drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.SetColorFilter(Resources.GetColor(Resource.Color.white), PorterDuff.Mode.SrcIn);
ActionBar.SetHomeAsUpIndicator(upArrow);
References
https://forums.xamarin.com/discussion/57791/cant-change-android-back-button-in-xamarin-forms
https://forums.xamarin.com/discussion/103317/change-navigation-bar-back-button-color-in-xamarin-android
How to change the toolbar back icon in xamarin forms android
You could refer to my answer: How to change navigation page back button in xamarin forms.
I write it here again:
We need to custom a NavigationPageRenderer, override the OnPushAsync method to set the Toolbar's navigation icon.
using AToolbar = Android.Support.V7.Widget.Toolbar;
[assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(NavigationPageRendererDroid))] // APPCOMP
...
public class NavigationPageRendererDroid : Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer // APPCOMP
{
public AToolbar toolbar;
public Activity context;
protected override Task<bool> OnPushAsync(Page view, bool animated)
{
var retVal = base.OnPushAsync(view, animated);
context = (Activity)Xamarin.Forms.Forms.Context;
toolbar = context.FindViewById<Android.Support.V7.Widget.Toolbar>(Droid.Resource.Id.toolbar);
if (toolbar != null)
{
if (toolbar.NavigationIcon != null)
{
toolbar.NavigationIcon = Android.Support.V4.Content.ContextCompat.GetDrawable(context, Resource.Drawable.Back);
//toolbar.SetNavigationIcon(Resource.Drawable.Back);
}
}
return retVal;
}
}
The CustomNavigationPage are defined in PCL :
public class CustomNavigationPage : NavigationPage
{
public CustomNavigationPage(Page startupPage) : base(startupPage)
{
}
}
Usage :
public App()
{
InitializeComponent();
MainPage = new CustomNavigationPage(new MainPage());
}
...
// In MainPage
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new TestPage());
}
[Effect].

Xamarin Custom renderer update value

I've custom renderer in Xamarin and I wonder how to dynamically update its value.
Here is my control in the main class:
public class MainControl : View
{
public double A
{
get;
set;
}
}
Here is my custom renderer, defined in Android:
[assembly: Xamarin.Forms.ExportRenderer(typeof(MainApplication.MainControl), typeof(MainApplication.Droid.CustomRenderer))]
namespace MainApplication.Droid
{
public class CustomRenderer : ViewRenderer<MainControl,
MainApplication.Droid.ControlAndroid>
{
private ControlAndroid control;
public CustomRenderer(Context context) : base(context)
{
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
protected override void OnElementChanged(ElementChangedEventArgs<MainControl> e)
{
base.OnElementChanged(e);
if (Control == null)
{
control = new ControlAndroid(Context);
SetNativeControl(control);
}
}
}
}
The method OnElementChanged does only update when creating the object. OnElementPropertyChanged are not trigged.
I expected that something should be trigged when changing the value of the property A from the main class.
I found the answer by my own. I figured out that I needed a bindable property (connected to my regular property "A") in order to get a call on OnElementPropertyChanged.

Xamarin.Forms Android DatePicker/TimePicker button listener

I need to know if a user tapped on the Cancel or Ok button
in a Date/Time picker of an xamarin.Forms Android app.
I have tried to add a function to the Click event but this is never triggered.
This is my code (similar for the TimePicker):
using Android.Content;
using MyApp.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using MyApp.Models;
using Java.Util;
[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerCustomRenderer))]
namespace MyApp.Droid {
public class DatePickerCustomRenderer : DatePickerRenderer {
public DatePickerCustomRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e) {
base.OnElementChanged(e);
Locale locale = new Locale(Utente.FormatoPerDateTimePicker);
Control.TextLocale = locale;
Control.Click += Control_Click;
}
private void Control_Click(object sender, System.EventArgs e) {
// This function is never called :(
throw new System.NotImplementedException();
}
}
}
How can I do this?
Using the following Android DatePicker custom renderer you have total control over OK and CANCEL.
using Android.App;
using Android.Content;
using ???.Android.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using DatePicker = Xamarin.Forms.DatePicker;
[assembly: ExportRenderer(typeof(DatePicker), typeof(FixedDatePickerRenderer))]
namespace ???.Android.Renderers
{
public class FixedDatePickerRenderer : Xamarin.Forms.Platform.Android.DatePickerRenderer
{
public FixedDatePickerRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.DatePicker> e)
{
base.OnElementChanged(e);
//Disposing
if (e.OldElement != null)
{
_element = null;
}
//Creating
if (e.NewElement != null)
{
_element = e.NewElement;
}
}
protected Xamarin.Forms.DatePicker _element;
protected override DatePickerDialog CreateDatePickerDialog(int year, int month, int day)
{
var dialog = new DatePickerDialog(Context, (o, e) =>
{
_element.Date = e.Date;
((IElementController)_element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
}, year, month, day);
dialog.SetButton((int)DialogButtonType.Positive, Context.Resources.GetString(global::Android.Resource.String.Ok), OnOk);
dialog.SetButton((int)DialogButtonType.Negative, Context.Resources.GetString(global::Android.Resource.String.Cancel), OnCancel);
return dialog;
}
private void OnCancel(object sender, DialogClickEventArgs e)
{
_element.Unfocus();
//((FixedDatePicker) _element)?.CallOnCancel();
}
private void OnOk(object sender, DialogClickEventArgs e)
{
//need to set date from native control manually now
_element.Date = ((DatePickerDialog)sender).DatePicker.DateTime;
_element.Unfocus();
//((FixedDatePicker)_element)?.CallOnOk();
}
}
}
Just for people looking for a complete solution to avoid searching for iOS, there's an option already included out-of-the box: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/ios/datepicker-selection
I need to know if a user tapped on the "cancel" or on the "ok" button in a date/time picker of an xamarin.Forms Android app.
With Xamarin.Form's DatePicker, you can't do that. Xamarin.Forms.DatePicker is renderered into an EditText control. The pop up DatePickerDialog is unfortunately not exposed to user. You can see that from Source Codes of DatePickerRenderer.
So if you really want to detect the OK/Cancel button click events. You need to implement your own DatePickerRenderer according to the source codes.
Nick Kovalsky' solution (using a custom renderer) above for Android works fine for me.
For iOS, the iOS specifics out-of-the-box solution didn't work for me,
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/ios/datepicker-selection
I've used the custom renderer approach for iOS also,
Looking at the Xamarin custom renderer (On iOS platform), we can see the InputAccessoryView is set to UIToolbar, and the toolbar contains the Done button (UIBarButtonItem). So, we can use the Done button and listen for click event,
https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs
[assembly: ExportRenderer(typeof(CustomDatePicker), typeof(MyApp.iOS.CustomRenderers.CustomDatePickerRenderer))]
public class CustomDatePickerRenderer : DatePickerRenderer
{
CustomDatePicker _datePickerElement ;
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
if (e.NewElement is CustomDatePicker datePickerElement && Control != null)
{
_datePickerElement = datePickerElement;
var toolbar = Control.InputAccessoryView as UIToolbar;
foreach (var button in toolbar?.Items)
{
if (button.Style == UIBarButtonItemStyle.Done)
{
button.Clicked -= OnDoneButtonClicked;
button.Clicked += OnDoneButtonClicked;
}
}
}
}
private void OnDoneButtonClicked(object sender, EventArgs e)
{
if(_datePickerElement.NullableDate != _datePickerElement.Date)
{
_datePickerElement.NullableDate = _datePickerElement.Date;
}
}
}

how to change navigation bar title icon on xamarin.forms ios?

i want to change navigation bar title icon on my xamarin.forms ios application.You can find requested point at the attached image.app_screenshot
You can achieve this by using Custom Renderers on Xamarin.Forms. Since each UIViewController has its own NavigationItem, you should do this in your particular page which you want to modify its LeftBarButtonItem. Here is my Renderer for you referring to:
[assembly: ExportRenderer(typeof(CustomPage), typeof(CustomPageRenderer))]
namespace UIBarButtomItemsForms.iOS
{
public class CustomPageRenderer : PageRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var navigationItem = NavigationController.TopViewController.NavigationItem;
UIBarButtonItem leftItem = new UIBarButtonItem(UIImage.FromBundle("Image.png"), UIBarButtonItemStyle.Plain, (sender, args) =>
{
});
navigationItem.SetLeftBarButtonItem(leftItem, false);
}
}
}
Then on Forms you can use this CustomPage, please notice that you should make your MainPage wrapped in a NavigationPage: MainPage = new NavigationPage(new MainPage());
Take a look at Change the Back Button: https://developer.xamarin.com/recipes/ios/content_controls/navigation_controller/change_the_back_button/

Bypass Page.VerifyRenderingInServerForm

I am trying to render a Wizard control to a HTML string on the click of a Button (using Control.Render). I am already disabling event validation with the following, which works fine and enables me to render the entire Page to the string. I do this within the user control that contains the Wizard:
protected void Page_Init(object sender, EventArgs e)
{
if (Request.Form["__EVENTTARGET"] != null
&& Request.Form["__EVENTTARGET"] == btnPrint.ClientID.Replace("_", "$"))
{
Page.EnableEventValidation = false;
}
}
While this works, I'd like to render the Wizard control on its own. I understand that I can override Page.VerifyRenderingInServerForm in order to prevent the page from throwing an exception when I attempt to render this control on its own (without runat="server" form tags), like so:
public override void VerifyRenderingInServerForm(Control control)
{
// base.VerifyRenderingInServerForm(control);
}
However, I don't want to override this completely. Is there a way I can bypass this dynamically, either:
For the specific PostBack in which the button in question is clicked, or...
Specifically for the Wizard control?
How about something like:
public override void VerifyRenderingInServerForm(Control control)
{
if (!SkipVerifyRenderingInServerForm)
{
base.VerifyRenderingInServerForm(control);
}
}
public bool SkipVerifyRenderingInServerForm
{
get
{
object o = HttpContext.Current.Items["SkipVerifyRenderingInServerForm"];
return (o == null) ? false : (bool) o;
}
set
{
HttpContext.Current.Items["SkipVerifyRenderingInServerForm"] = value;
}
}
You could then set SkipVerifyRenderingInServerForm to true in your button click event handler.

Categories

Resources