Toolbar from MasterDetailPage - xamarin.forms

How can I get navigation back button event if I have MasterDetailPage?
Toolbar toolbar = FindViewById(Resource.Id.toolbar) return null

If want to get event of the hardware back button, you can use OnBackButtonPressed method in ContentPage to get navigation back button event as follow:
protected override bool OnBackButtonPressed()
{
Console.WriteLine("Press back button.");
return base.OnBackButtonPressed();
}
Event that is raised when the hardware back button is pressed. This event is not raised on iOS.
=====================================Update==================================
Else if want to get back event from ToolBar , you should use Android.Support.V7.Widget for Toolbar.
In Acitivity OnCreate:
Android.Support.V7.Widget.Toolbar toolbar = this.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
Override OnOptionsItemSelected method :
public override bool OnOptionsItemSelected(IMenuItem item)
{
if(item.ItemId == Android.Resource.Id.Home)
{
Console.WriteLine("Here is back button event.");
}
return base.OnOptionsItemSelected(item);
}

Related

How to hide the scroller in a Xamarin Forms Custom PickerRenderer

Not sure if it is a Xamarin IOS bug but on the same panel we have a custom control that pops a modal view of choices(like a picker) and a standard Xamarin Forms Picker. If the standard picker is displaying the scroller at the bottom and then then custom modal control is tapped and receives focus the modal view pops up but the standard picker never disappears creating a hung panel.
The standard IOS picker does lose focus but never disappears. I have a renderer created but can't figure how to close the IOS picker.
namespace HCMobile.iOS.CustomRenderers
{
public class CustomPickerRenderer : PickerRenderer
{
public CustomPickerRenderer() { }
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var isFocused = ((Picker)sender).IsFocused;
// This fires when the IOS picker looses focus but never closes the picker at the bottom of the panel. Scroller disappears if ANY other control receives focus.
if (Control != null && !isFocused)
{
UIPickerView pickerView = (UIPickerView)Control.InputView;
}
else
{
UIPickerView pickerView = (UIPickerView)Control.InputView;
}
}
}
}
Has anyone else ran into this problem?

How to handle multiple tapping on toolbar item in xamarin forms?

I want to implement enable/disable property of toolbar item.
Here is the scenario,
On toolbar item activation I want to open dialog box.
issue:
When I tapped the toolbar item multiple times then it call multiple times dialog box. Please give some solution to handle the multiple calling of dialog box.
To prevent the multiple clicks, you can use a variable, to prevent calling the Dialog while waiting for the result confirmation.
first, in your class declare a variable canTap;
private bool _canTap = true;
Assuming your method when tapping the toolbar is like this:
private void ItemTapped(object sender, EventArgs args)
{
if(_canTap)
{
_canTap= false;
Device.BeginInvokeOnMainThread(async () => {
var response = await
UserDialogs.Instance.ConfirmAsync(new ConfirmConfig { Message = "Are you sure you want to logout from this app?", Title = "Logout", OkText = "YES", CancelText = "NO" );
if(response)
{
}
else
{
}
_canTap = true;)};
}

How to handle navigation back button event in xamarin iOS/Android?

I am creating xamarin form app and I want to perform some action on navigation back button.Is there any approach to do that?
P.S :> Software back button, not Hardware back button.
In this article, you'll find everything.
IF the article disappears or changes at some point, here you will find the specifics of the solution.
You'll need to create a Custom ContentPage
namespace WhateverYourNamespace
{
public class CoolContentPage : ContentPage
{
/// <summary>
/// Gets or Sets the Back button click overriden custom action
/// </summary>
public Action CustomBackButtonAction { get; set; }
public static readonly BindableProperty EnableBackButtonOverrideProperty =
BindableProperty.Create(
nameof(EnableBackButtonOverride),
typeof(bool),
typeof(CoolContentPage),
false);
/// <summary>
/// Gets or Sets Custom Back button overriding state
/// </summary>
public bool EnableBackButtonOverride
{
get
{
return (bool)GetValue(EnableBackButtonOverrideProperty);
}
set
{
SetValue(EnableBackButtonOverrideProperty, value);
}
}
}
}
As you see, there's an action event that we are going to subscribe to in our Xamarin Forms code level and to be invoked from Xamarin native project level.
There is also a bool property to enable or disable the overriding of the Back Button click event so that you can decide whether to subscribe to the overriding event or not as a page property.
Android :
You'll need to override the OnOptionsItemSelected() event in our MainActivity class in order to capture the nav bar back button click in Android for Xamarin Forms.
public override bool OnOptionsItemSelected(IMenuItem item)
{
// check if the current item id
// is equals to the back button id
if (item.ItemId == 16908332)
{
// retrieve the current xamarin forms page instance
var currentpage = (CoolContentPage)
Xamarin.Forms.Application.
Current.MainPage.Navigation.
NavigationStack.LastOrDefault();
// check if the page has subscribed to
// the custom back button event
if (currentpage?.CustomBackButtonAction != null)
{
// invoke the Custom back button action
currentpage?.CustomBackButtonAction.Invoke();
// and disable the default back button action
return false;
}
// if its not subscribed then go ahead
// with the default back button action
return base.OnOptionsItemSelected(item);
}
else
{
// since its not the back button
//click, pass the event to the base
return base.OnOptionsItemSelected(item);
}
}
public override void OnBackPressed()
{
// this is not necessary, but in Android user
// has both Nav bar back button and
// physical back button its safe
// to cover the both events
// retrieve the current xamarin forms page instance
var currentpage = (CoolContentPage)
Xamarin.Forms.Application.
Current.MainPage.Navigation.
NavigationStack.LastOrDefault();
// check if the page has subscribed to
// the custom back button event
if (currentpage?.CustomBackButtonAction != null)
{
currentpage?.CustomBackButtonAction.Invoke();
}
else
{
base.OnBackPressed();
}
}
iOS :
iOS you need to override the ViewWillAppear() method in your CoolContentPageRenderer class.
So the below code should be placed inside your CoolContentPageRenderer class.
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
if (((CoolContentPage)Element).EnableBackButtonOverride)
{
SetCustomBackButton();
}
}
private void SetCustomBackButton()
{
// Load the Back arrow Image
var backBtnImage =
UIImage.FromBundle("iosbackarrow.png");
backBtnImage =
backBtnImage.ImageWithRenderingMode
(UIImageRenderingMode.AlwaysTemplate);
// Create our Button and set Edge
// Insets for Title and Image
var backBtn = new UIButton(UIButtonType.Custom)
{
HorizontalAlignment =
UIControlContentHorizontalAlignment.Left,
TitleEdgeInsets =
new UIEdgeInsets(11.5f, 15f, 10f, 0f),
ImageEdgeInsets =
new UIEdgeInsets(1f, 8f, 0f, 0f)
};
// Set the styling for Title
// You could set any Text as you wish here
backBtn.SetTitle("Back", UIControlState.Normal);
// use the white color in ios back button text
backBtn.SetTitleColor(UIColor.White,
UIControlState.Normal);
backBtn.SetTitleColor(UIColor.LightGray,
UIControlState.Highlighted);
backBtn.Font = UIFont.FromName("HelveticaNeue",
(nfloat)17);
// Set the Image to the button
backBtn.SetImage(backBtnImage, UIControlState.Normal);
// Allow the button to Size itself
backBtn.SizeToFit();
// Add the Custom Click event you would like to
// execute upon the Back button click
backBtn.TouchDown += (sender, e) =>
{
// Whatever your custom back button click handling
if(((CoolContentPage)Element)?.
CustomBackButtonAction != null)
{
((CoolContentPage)Element)?.
CustomBackButtonAction.Invoke();
}
};
//Set the frame of the button
backBtn.Frame = new CGRect(
0,
0,
UIScreen.MainScreen.Bounds.Width / 4,
NavigationController.NavigationBar.Frame.Height);
// Add our button to a container
var btnContainer = new UIView(
new CGRect(0, 0,
backBtn.Frame.Width, backBtn.Frame.Height));
btnContainer.AddSubview(backBtn);
// A dummy button item to push our custom back button to
// the edge of screen (sort of a hack)
var fixedSpace =
new UIBarButtonItem(UIBarButtonSystemItem.FixedSpace)
{
Width = -16f
};
// wrap our custom back button with a UIBarButtonItem
var backButtonItem = new UIBarButtonItem("",
UIBarButtonItemStyle.Plain, null)
{
CustomView = backBtn
};
// Add it to the ViewController
NavigationController.TopViewController.
NavigationItem.LeftBarButtonItems
= new[] { fixedSpace, backButtonItem };
}
How to use it :
<WhateverYourNamespace:CoolContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:WhateverYourNamespace=
"clrnamespace:XFNavBarBackBtnClickOverride;
assembly=XFNavBarBackBtnClickOverride"
x:Class="XFNavBarBackBtnClickOverride.Page2"
Title="Page 3"
EnableBackButtonOverride="True"
BackgroundColor="#00bfff">
<StackLayout
Spacing="20"
Padding="20,10,20,10"
VerticalOptions="Center"
HorizontalOptions="Center" >
<Label Text="This is the cool page,
which has the Navigation Bar Back button
click overriden. How go ahead and click that Back
button! ;)"
FontSize="20"
HorizontalTextAlignment="Center"
TextColor="White"/>
</StackLayout>
</WhateverYourNamespace:CoolContentPage>
For ANDROID add this in you main activity OnCreate() after LoadApplication(new App()) line.
Android.Support.V7.Widget.Toolbar toolbar
= this.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbarSetSupportActionBar(toolbar);

How to disable back button When ActivityIndicator Is Running

I am using Xamrin.forms PLC Project,
So,I am trying to disable back button when Activity Indicator is Running then I will enable back button when Activity Indicator is finished.
this is My Code:
protected override void OnAppearing()
{
activityIndicator.IsRunning = true;
activityIndicator.IsVisible = true;
//I need to disable back button here
activityIndicator.IsRunning = false;
activityIndicator.IsVisible = false;
//I need to enable back button here
}
You can use the static NavigationPage.SetHasBackButton method (See here) to hide the back button of your page.
Furthermore you can override OnBackButtonPressed
protected override bool OnBackButtonPressed()
{
if(activityIndicator.IsRunning = true)
{
return true;
}
return false;
}
(see here) to prevent going back when the user presses the hardware back button.

In ADF Mobile, How to change the button text when the button is clicked?

First, in the page, the Button text is set to "Edit" and show.
When I clicked the "Edit" button, then the Button text will change to "Done", meanwhile, it will do a action to render some checkBoxs on the page.
After I pick some checkBox, and click the "Done" button, it will do another action.
I don't know how to do it in ADF Mobile. Can we just using this one button to do all these?
Thanks!
I chose to use two button, here is my code:
<amx:facet name="secondary">
<amx:commandButton id="cb2" text="#{viewcontrollerBundle.EDIT}" rendered="#{viewScope.editMode == ''}">
<amx:setPropertyListener id="spl1" from="EditMode" to="#{viewScope.editMode}" type="action"/>
</amx:commandButton>
<amx:commandButton id="cb3" text="#{viewcontrollerBundle.DONE}" rendered="#{viewScope.editMode == 'EditMode'}">
<amx:actionListener id="al1" binding="#{bindings.removeFromImageList.execute}"/>
<amx:setPropertyListener id="spl2" from="" to="#{viewScope.editMode}" type="action"/>
</amx:commandButton>
</amx:facet>
This code can show the DONE button when click the edit button. And in my test page, it works.
But when I put them into my project page, it cannot show the DONE button immediately. I should turn to the previous page, and go back to the page again, then the DONE button will show.
Do you know why?
You can do it using the same button. You can set the value of text field for the button as a property of a bean. And in the action listener which is a function in the same bean, you can do different actions based on the text.
AMX Page will look something like
<amx:commandButton text="{applicationScope.myBean.buttonText}" id="cb3" styleClass="actions-button" actionListener="#{applicationScope.myBean.myListener}"></amx:commandButton>
The bean should look something like
public class Class1 {
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public Class1() {
super();
}
private String textButton;
public void myListener(ActionEvent ae) {
if (textButton.equals("Edit")) {
//DO THE ACTION WHICH NEEDS TO BE DONE FOR EDIT BUTTON
setTextButton("Done");
} else if (textButton.equals("Done")) {
//DO THE ACTION FOR DONE BUTTON
}
}
public void setTextButton(String textButton) {
String oldTextButton = this.textButton;
this.textButton = textButton;
propertyChangeSupport.firePropertyChange("textButton", oldTextButton, textButton);
}
public String getTextButton() {
return textButton;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}

Resources