How to use a NSTextView in the background of an Xamarin.Forms application and feed it with key events so that it behaves (input wise) like it was part of a window and is focused?
I already tried to create an instance and feed it all key events but this was not enough (didn't fire any event)
_textView = new NSTextView();
//...
public override void DidFinishLaunching(NSNotification notification)
{
NSEvent.AddLocalMonitorForEventsMatchingMask(NSEventMask.KeyDown, #event =>
{
_textView.KeyDown(#event);
return #event;
});
NSEvent.AddLocalMonitorForEventsMatchingMask(NSEventMask.KeyUp, #event =>
{
_textView.KeyUp(#event);
return #event;
});
Forms.Init();
LoadApplication(new App());
base.DidFinishLaunching(notification);
}
I found a solution to this problem.
I created a KeyHandlingContentView derived from ContentView in Xamarin.Forms and a custom Renderer for Mac that implements INSTextInputClient.
This way the key events can be passed from that custom renderer to the Xamarin.Forms control.
Related
In Xamarin for mac, I decided to make multiple views to be used within my main view using the MVVM pattern.
The thing is that I have a ListView within my MainPage which pulls a List of items from a model, and the list is populated within a child view, with its own ViewModel.
When I add a new service from the child view, I would like for the OnPropertyChanged event on the parent view model to trigger.
It is working by navigating to the parent view and setting the animation to false, but this is not really nice looking. It worked though when I had all code within one ViewModel.
How I tried to achieve this, and the errors I got:
0 - Accessing the command within the child model from the parent model, and passing the propertychanged event handler along.
I Couldn't do it. I tried this by making a bindable command like below, but this is not doable for me as I don't think it is possible for the command to know when the property will be changed, which is the whole point of this problem.
If it is doable, I don't know how.
//public static readonly BindableProperty SaveServiceClickedCommandProperty =
// BindableProperty.Create(
// "SaveServiceClicked",
// typeof(Command),
// typeof(NewServiceViewModel),
// null);
1 - Passing the parent view model on the child view model, and put a OnPropertyChanged(nameof(parentModel.List)) at the clicked event handler.
public class ChildViewModel : INotifyPropertyChanged
{
public ICommand AddEntryClickedCommand { get; private set; }
private MainModel mainModel;
// property changed handler
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public NewServiceViewModel()
{
Navigation = MainPage;
//async void execute() => await OpenPage();
//OpenPageCommand = new Command(execute, () => !IsBusy);
//async Task OpenPage()
//{
// await Navigation.PushAsync(new MainPage());
//}
// Here I tried to access the data from within the main model.
mainModel = new MainModel(Navigation);
InitMainModel();
void InitMainModel()
{
MainPage mainView = new MainPage();
mainView.BindingContext = mainModel;
}
async void c1() => await AddEntryClicked();
AddEntryClickedCommand = new Command(c1);
}
public async Task<bool> AddEntryClicked()
{
OnPropertyChanged(nameof(mainModel.List))
}
The attempt above created some errors as the object is already populated.
Leading to me thinking that I don't have the right approach altogether.
My solution being to re-introduce the child view within the parent view, and change IsVisible according to the button being clicked or not, as I already did with other smaller component.
I have thought about pulling the list from the child view, but that's raises the same issue of non-null collection.
Of course, the code has been modified to show only the gist.
Thanks in advance.
I am creating app in Xamarin.Forms shared proeject. I want to detect app when it comes from background
currently, I have implemented OnActivated method in AppDelegate but this method is also called when we open control center in iphone. I want my app to reconnect with my server when app comes to foreground from background and show message accordingly but this message is also shown when I swipe up and open control center.
In native Xamarin.iOS app, there is a method WillEnterForegroundNotification but this method is not available here.
Is there any method that's called only if app comes from background ?
in App.xaml.cs
protected override void OnResume()
In native Xamarin.iOS app, there is a method
WillEnterForegroundNotification but this method is not available here.
You can access WillEnterForegroundNotification method in Xamarin.forms project, just override it in AppDelegate.cs:
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override void WillEnterForeground(UIApplication uiApplication)
{
//handle your event here
base.WillEnterForeground(uiApplication);
}
}
I'm trying to make use of the new SearchHandler implemented as part of Xamarin Forms 4. I've found it pretty easy so far to get suggestions populated but now I want to raise an event, or follow the suggested method of handling when a search is confirmed.
public class FoodSearchHandler: SearchHandler
{
IFoodDataStore dataStore = new FoodDataStore();
protected override void OnQueryConfirmed()
{
base.OnQueryConfirmed();
// What to do here?
}
protected override void OnQueryChanged(string oldValue, string newValue)
{
base.OnQueryChanged(oldValue, newValue);
if(!string.IsNullOrWhiteSpace(newValue)
{
// Populate suggestions
ItemsSource = dataStore.GetSuggestions(newValue);
}
else
{
ItemsSource = null;
}
}
}
public partial class FoodsPage : ContentPage
{
ObservableCollection<Food> Foods = new ObservableCollection<Food>();
public ItemsPage()
{
InitializeComponent();
// Wire up the search handler
Shell.SetSearchHandler(this, new FoodSearchHandler());
BindingContext = this;
}
}
Unfortunately, althought the alpha docs mention the search handler they don't contain any details on how to use it and the sample apps only demonstrate populating the suggestions.
Does anyone out there have a pointer to offer on how I should be notifying my ContentPage that my SearchHandler confirmed a search?
So, after reading the Shell docs some more, it seems what I want to do in this situation is use of Shell's new Navigation and navigate to a route passing the search text as a query, for example:
protected override void OnQueryConfirmed()
{
base.OnQueryConfirmed();
var shell = Application.Current.MainPage as Shell;
shell.GoToAsync($"app:///fructika/search?query={Query}", true);
}
N.B. It doesn't look like passing data works right now or if it does I'm doing it wrong but I'll raise a separate question about that.
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.