Xamarin forms: How to access "tabBarController: shouldSelectViewController:" - c#

I need to have control of this method so that I can make a change in my app. But I couldn't make this implementation work, can anyone help?
Here is the Custom Renderer of my TabbedPage:
public class MainTabbedPageRenderer : TabbedRenderer, IUITabBarControllerDelegate
{
[Export("tabBarController:shouldSelectViewController:")]
public bool ShouldSelectViewController(UITabBarController tabBarController, UIViewController viewController)
{
return false;
}
}
The breakpoint does not stop there at all.
I have the impression that it does not stop at breakpoint because TabBarController is always null, but the screen loads and performs navigations normally, I also could not make this TabBarController be filled.
You can click on tabbar items using this method:
[Export("tabBar:didSelectItem:")]
public void ItemSelected(UITabBar tabbar, UITabBarItem item)
{
}

I don't see where you are assigning your delegate. That is likely why it is not hit, you have not assigned the delegate to the UITabBarController (which is the base class for TabbedRenderer). Also TabbedRenderer already assigns a delegate, so you likely do not want to replace it.
That said, Xamarin.iOS actually defines a C# delegate, called UITabBarSelection, for the ShouldSelectViewController protocol method. And there is a property on TabbedRenderer called ShouldSelectViewController that allows you to set this delegate method, so you should be able to just do this:
public class MainTabbedPageRenderer : TabbedRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
this.ShouldSelectViewController = ShouldSelectViewControllerHandler;
}
bool ShouldSelectViewControllerHandler(UITabBarController tabBarController, UIViewController viewController)
{
return false;
}
}

Related

Godot C# "Error calling method from signal"

Given my scene tree:
Main_control (Type:Control) (Parent)
mnk_game (Type: Control) (Child)
I can run methods in mnk_game's script using signals from Main_control, but it won’t work the other way around (calling a method in Main_control using a signal from mnk_game)
Error:
emit_signal: Error calling method from signal 'mnk_game_finished': 'Control(Main_control.cs)::mnk_show_game': Method not found..
Parent's code:
public class Main_control : Control
{
public override void _Ready()
{pass}
public void mnk_show_game()
{
GD.Print("mnk_show_game reached"); //What I want to reach
}
}
Child code:
public class mnk_game : Control
{
[Signal]
public delegate void mnk_game_finished();
private Godot.Control game_controller;
public override void _Ready()
{
game_controller = (Control)GetParent<Godot.Control>();
this.Connect("mnk_game_finished", game_controller, "mnk_show_game");
}
public void any_method()
{
this.EmitSignal("mnk_game_finished");
}
}
When I call the any_method method at the child's script, I want to be able to reach mnk_show_game method in the parent's script. Can I do this? If so, how?
I don't have much experience using Godot with C#, but I can see that mnk_game_finished was defined without parameters and mnk_show_game also does not take parameters. However, you are emitting the signal with a parameter this.EmitSignal("mnk_game_finished", ds.board). Try to emit the signal without a parameter like so: this.EmitSignal("mnk_game_finished") or define your delegate and function with parameters.

Is there a way to let a class know that something subscribed to its delegate successfully ran?

I have one class called TerminalCommandScanUtility.cs with a delegate called ScanUtility:
public static event Action scanUtilityEvent;
public void ScanUtility()
{
if (scanUtilityEvent != null)
{
scanUtilityEvent();
}
}
In another class called FolderEvent.cs, I listen for this delegate being fired as follows:
bool isScannable;
TerminalCommandScanUtility.scanUtilityEvent += StartFolderScan;
void StartFolderScan()
{
if(!isScannable)
{
return;
}
else
{
//How can I inform TerminalCommandScanUtility that this folder was scannable, and thus ran?
}
}
When the scan utility runs, I want it to be able to know that a folder's isScannable variable was true so that I can display some feedback text for the user like "Despite running the function.. nothing was scanned", or "One folder has begun scanning!"
You need to implement the INotifyPropertyChanged interface for TerminalCommandScanUtility and a corresponding event handler. There is a similar post here.

Hide an Instance of a Window

how do I hide an Instance of a Window which was created in an Method, in another Method?
I have a Login Window with a button "Register" and when you click that, the Register-Window is opening, and the Login-Window is hiding (That is working fine).
The Problem now is, i have on the Register-Window a Button "Back" which should hide the Register Window and Show the Login Window.
I Can show the Login Window with : "Application.Current.MainWindow.Show();", but i dont know how to hide the Register-Window. Normally i would just go for "Regis.Hide()", but i can´t do that because i have the instance of Regis in the Method, which opens the Register Window.
I understand, that if i create a second instance in the second Method and hide this, that that wont work because there are 2 seperate instances now.
But as i said, i dont know how i should do this either.
OpenRegistrationGui:
ICommand _RegisterBack;
public void Open()
{
Application.Current.MainWindow.Hide();
Register regis = new Register();
regis.Show();
}
public ICommand RegisBackCommand
{
get
{
if (_RegisterBack == null)
{
_RegisterBack = new RelayCommand(
param => Back()
);
}
return _RegisterBack;
}
}
public void Back()
{
Application.Current.MainWindow.Show();
//I Want to Hide the Regis here, but i cant use the Instance from above.
}
MyViewModel:
OpenRegistrierungsGUI RegisGUI = new OpenRegistrierungsGUI();
public ICommand RegisBack
{
get => RegisGUI.RegisBackCommand;
set => RegisBack = RegisGUI.RegisBackCommand;
}
The Same Thing is with the Open() Method.
The Result i want is simply that the Register Window is hiding and the Login Window shows off.
This will resolve your issue by making regis a member variable that the whole class has access to...
private Register regis;
public void Open()
{
Application.Current.MainWindow.Hide();
// Create the register window, if it doesn't exist
if (regis == null)
{
regis = new Register();
}
regis.Show();
}
public void Back()
{
// hide the register window, if it exists
if (regis != null)
{
regis.Hide();
}
Application.Current.MainWindow.Show();
}
There are different ways of doing this, but this one ensures only one instance of the register window and gives you the show/hide ability you need.
simply use regis.hide(); hopefully its work for you.
private Register regis;
public void Back()
{
Application.Current.MainWindow.Show();
regis.hide();
}
here you want to use one function variable into another
Declare regis globally than initialize it in method where you first you use it .
In this way there will be only one instance of regis .
Now you can do
regis.Hide()
or
regis.Show()
in any method of your class
I found the solution:
I fired the Open() Method (Which worked perfectly).
When I wanted to fire the Back() Method I accidentally created an Instance of "OpenRegistrationGui" and tried to Close it, which it obviousely can´t, because its another Instance.
I made the Property "RegisBackCommand" Static and fired it now directly from the ViewModel, which works now.
Anyway... Thank you all for your fast Answers and help!!!

Xamarin Android TextToSpeech.Speak doesn't say anything if run from any of the lifecycle methods

I'm using an instance of TextToSpeech to convert some text, using the Speak() method, like so:
textToSpeech = new TextToSpeech(context, this, "com.google.android.tts");
textToSpeech.SetPitch(1f);
textToSpeech.SetSpeechRate(1f);
textToSpeech.Speak(textToConvert, QueueMode.Flush, null, null);
The function runs fine with no errors, but the speech can only actually be heard (and the isSpeaking property only changes to true) when the function is not called from the lifecycle methods.
I've tried placing it in OnCreate(), OnStart(), and OnResume() all with the same results, although the function runs fine if called from a button event.
Is this a limitation of the class, or something I can fix?
It's because you're calling the Speak() method before the TTS engine has loaded. It takes a few moments for it to initialize.
Fortunately, the TextToSpeech.IOnInitListener interface provides a way to know when the engine has successfully loaded via the OnInit() method.
So, if you want your app to speak in OnCreate(), you'll need to move the Speak() method to the OnInit() method. Here's a working example I put together for you...
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Speech.Tts;
namespace XamdroidMaster.Activities {
[Activity(ParentActivity = typeof(MainActivity), Label = "Text to Speech")]
public class TextToSpeechActivity : Activity, TextToSpeech.IOnInitListener {
private TextToSpeech tts;
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.TextToSpeech);
// Create text to speech object (first parameter: context; second parameter: object implementing TextToSpeech.IOnInitListener)
// Note that it may take a few moments for the TTS engine to initialize (OnInit() will fire when it's ready)
tts = new TextToSpeech(this, this, "com.google.android.tts");
}
public void OnInit([GeneratedEnum] OperationResult status) {
if (status == OperationResult.Success) {
tts.SetPitch(1f);
tts.SetSpeechRate(1f);
tts.Speak("Hello Luke!", QueueMode.Flush, null);
}
}
}
}
Also, by initializing the TTS engine in OnCreate() as I've shown in the example, you should then be able to fire the Speak() command later in OnResume().
Hope this helps!
The problem is that TTS engine initialization takes some time. If initialization is not over, the speak method call will fail.
If you "say" something on button click, you will probably won't need this, because user will take some time to think before pressing the button, and the initialization will be over.
If you want to "say" something as soon initialization finishes, use this code:
public class MainActivity : AppCompatActivity
{
private static TextView speechtext;
private static TextToSpeech saytext;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.layout1);
speechtext = FindViewById<TextView>(Resource.Id.textView1);
saytext = new TextToSpeech(this, new MyListener(), "com.google.android.tts");
}
class MyListener : Java.Lang.Object, TextToSpeech.IOnInitListener
{
public void OnInit([GeneratedEnum] OperationResult status)
{
if(status==OperationResult.Success)
{
saytext.SetLanguage(Locale.Us);
saytext.SetPitch(1.5f);
saytext.SetSpeechRate(1.5f);
saytext.Speak(speechtext.Text, QueueMode.Flush, null, null);
}
}
}
}

Creating custom contact delegates with Xamarin SpriteKit in C#

I would like to override the didBeginContact function so as to implement custom logic when two physics objects in my scene collide.
I understand how this would be done in Swift by first setting the contact delegate to be the scene object itself and then setting up the didBeginContact function as below:
self.physicsWorld.contactDelegate = self
func didBeginContact(contact: SKPhysicsContact) {
//logic goes here
}
I am unable to work out how to implement such a system when using SpriteKit with Xamarin in C#. I have tried creating a custom Contact Delegate class which is a subclass of SKPhysicsContactDelegate and setting the scene's PhysicsWorld.ContactDelegate property to be an instance of this class but I noticed no change when running my application.
public class CollisionDelegate : SKPhysicsContactDelegate
{
public override void DidBeginContact(SKPhysicsContact contact)
{
if (contact.BodyA.CategoryBitMask == 1 &&
contact.BodyB.CategoryBitMask == 3)
{
contact.BodyB.Node.RemoveFromParent();
}
else if (contact.BodyA.CategoryBitMask == 3 &&
contact.BodyB.CategoryBitMask == 1)
{
contact.BodyA.Node.RemoveFromParent();
}
}
}
Then in my SKScene class:
public override void DidMoveToView(SKView view)
{
PhysicsWorld.ContactDelegate = new CollisionDelegate();
//Other scene initilaisation
}

Categories

Resources