Once the Rg.Plugin.Popup is displayed, with
PopupNavigation.Instance.PushAsync(new PopupPage());
Once its displayed, and on pressing Device Back button. screen getting hanged.
No OnBackPressed in declared in the code.
Once its displayed, and on pressing Device Back button. screen getting hanged. No OnBackPressed in declared in the code.
From this article, for Android back button to work with the plugin, you should invoke Rg.Plugins.Popup.Popup.SendBackPressed in your MainActivity in override method OnBackPressed.
public async override void OnBackPressed()
{
if (Rg.Plugins.Popup.Popup.SendBackPressed(base.OnBackPressed))
{
// Do something if there are some pages in the `PopupStack`
await PopupNavigation.Instance.PopAsync();
}
else
{
// Do something if there are not any pages in the `PopupStack`
}
}
I have some problems in my Xamarin.Forms app related to invoking async method in the page constructor so when I test something trying to figure out the reason I just realized DisplayAlert method does not even work in the page constructor so I am wondering why is that happening?
Here is my code:
public MainPage ()
{
InitializeComponent ();
DisplayAlert("An alert", "Why I don't show up?", "Ok");
}
and I also tried to call async method that has DisplayAlert method but didn't work too, here is the code:
public MainPage ()
{
InitializeComponent ();
Async_Function_Has_DisplayAlert();
}
async void Async_Function_Has_DisplayAlert()
{
// I tried both and neither of them worked
await DisplayAlert("An alert", "Why I don't show up?", "Ok");
await Task.Run(()=> DisplayAlert("An alert", "Why I don't show up?", "Ok"));
}
So can someone explain why that is happening please?
Normally, you should not call an awaitable method like DisplayAlert() from the constructor.
What you can do is have a method that returns void (still not best practice) and call that method from your constructor.
Tweaking my recommendation after trying it out.
I used Device.Timer to delay the alert.
I think some components have not finished loading (in this case, the DisplayAlert) before trying to call it.
public MainPage()
{
InitializeComponent();
Device.StartTimer(TimeSpan.FromSeconds(4), () =>
{
ShowMessage();
return false; // True = Repeat again, False = Stop the timer
});
}
public async void ShowMessage()
{
await DisplayAlert("Alert", "I show here", "OK");
}
There seems to be a misconception on what is happening in the constructor.
The constructor simply creates a new Page class.
CustomMainPage mainpage = new CustomMainPage();
(App.Current as App).MainPage = new NavigationPage(mainpage);
So before we add the mainpage class to the NavigationPage, all that has happened is that the CustomMainPage class was initialized and is ready to be inserted into an appropriate container.
However after creating the new page, there is no actual UI on the screen, yet. For instance, the mainpage object wouldn't have width or height set, no layout has been done, etc...
If you run a UI related task, such as presenting an Alert, there isn't simply any foundation for it there, which could do anything resonable.
Of course you could already set members of the mainpage, such as labels or buttons to certain values, colors, styles or whatever you want, from within the constructor, but these wouldn't do anything at that point of time.
All of those values will be taken into account when the page is being layouted and presented but none of that will happen in the constructor.
However, back to your problem: You seemingly want to inform the user that something has gone wrong during the initialization.
I see two ways of adressing that issue:
Check the preconditions on the page or within the code before initializing your view and present the Alert from the page or class, which is initializing your page.
create a private variable in your page class, which you will set from within your page constructor if something goes wrong. This could be a simple bool flag, a string containing an error message, an enum or whatever suits your needs. Then override the OnAppearing() method, check that flag you set earlier and call DisplayAlert depending on the flag's value.
If you want any interactivity on your page, then you should consider Jason's comment to your question and implement it within OnAppearing, because this method will be called once your page has been fully layouted and is being presented on your screen.
Sample code for Jason's recommendation
public async void ShowMessage()
{
await DisplayAlert("Alert", "I show here", "OK");
}
protected override void OnAppearing()
{
ShowMessage();
}
I have a fragment_A with tabs, consider tabs as fragment_B and C. And am implementing custom keypad with "Done" key in it. In my main Activity iam calling the listener to press the done button
// Used when "Done" button pressed in keyboard
#Override
public void keylisten() {
((Housing) fragmentStack.lastElement()).whenokkeypressed();
}
Now i want to call a method from fragment_B which goes into the whenokkeypressed() of the fragment_A;
There are 2 things you should do
Make whenonkeypressed() static and call it from class name of the fragment like Fragment_A.whenonkeypressed()
(optional) instead of using keylisten of done in mainActivity you should prefer an anonymous inner class like
editText.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
whenonkeypressed();
} });
I am new to Android developing and there it is not very clear to me the difference between the Click, Touch and Gesture classes in Android.
Is on the generalization of the other?
If you're talking about specific classes its always good to include the fully qualified name so as to avoid ambiguity.
Click is pretty generic so I assume your talking about
android.view.View.OnClickListener. This is an interface your widget class can implement to use the call back method onClick(). Any code inside the onClick() method is executed when you press that view (button).
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
Touch android.view.View.OnTouchListener
The onTouchListener is an interface that exposes the onTouch() callback method and gives you access to the android.view.MotionEvent members like ACTION_BUTTON_RELEASE. The MotionEvent class is very powerful for movement related behaviour.
Below example is from thread https://stackoverflow.com/a/11690679/1005142
imageButton.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
// Do what you want
return true;
}
return false;
}
});
Gesture android.view.GestureDetector.OnGestureListener
This class is used to pick up how the user gestures their finger with your UI. There is already a lot of information on the Android dev site in the gesture section http://developer.android.com/training/gestures/detector.html.
An example of using this class would be if you were writing fluidly with your finger on the keyboard where you need to listen for touch, movement and acceleration.
I have two VM - View (inherited from Screen) and Edit (inherited from Screen). View is used to display grid with data and Edit - add/edit new items into grid.
In my ShellViewModel I have the following code to activate View.
public void WorkstationView()
{
this.ActivateItem(ServiceLocator.Current.GetInstance<WorkstationViewModel>());
}
In WorkstationViewModel when user clicks on the Create button the following code is invoked
public void CreateAction()
{
EditableObject = new WorkstationDto();
TryClose(true);
}
And there is a listener to Deactivated event property, see code below (InitViewModels is invoked in ShellViewModel constructor).
private void InitViewModels()
{
#region Init
WorkstationViewModel = ServiceLocator.Current.GetInstance<WorkstationViewModel>();
WorkstationEditViewModel = ServiceLocator.Current.GetInstance<WorkstationEditViewModel>();
#endregion
#region Logic
WorkstationViewModel.Deactivated += (o, args) =>
{
if (WorkstationViewModel.EditableObject == null)
{
return;
}
WorkstationEditViewModel.EditableObject = WorkstationViewModel.EditableObject;
ActivateItem(WorkstationEditViewModel);
};
#endregion
}
The problem here is a StackOverflow exception when I close Edit view (see create action).
“Since the Conductor does not maintain a “screen collection,” the activation of each new item causes both the deactivation and close of the previously active item.” Caliburn.Micro documentation
If you are using Conductor<T>, then ActivateItem(WorkstationEditViewModel); inside of the Deactivated handler is implicitly re-triggering the deactivation of the previous viewmodel - giving you an infinite loop. Try changing your conductor to inherit from Conductor<IScreen>.Collection.OneActive instead. However, you will still have two deactivations: the one from the original TryClose operation, and a second one when you activate the new screen. Overriding DetermineNextItemToActivate can help you avoid that.