Xamarin issue "self.isModalInPresentation = false" not working - xamarin

I was trying to disable swiping effect on popover controller.My xamarin application running ios 13 getting some issue while swipping down the popover controller,So I need to disable default swipe effect on popover controller. In objective c and swift it has a property "isModelInPresentation" but in xamarin it is not available. Can any body help to disable swipe popover ?

modalInPresentation : A Boolean value indicating whether the view controller enforces a modal behavior.
The default value of this property is NO. When you set it to YES, UIKit ignores events outside the view controller's bounds and prevents the interactive dismissal of the view controller while it is onscreen.
In Xamarin.iOS ,If setting ModalInPresentation = True , when swipping the viewController will not disappear . Else will disappear .
public override void ViewDidLoad()
{
View = new UniversalView();
base.ViewDidLoad();
this.Title = "Second";
View.BackgroundColor = UIColor.Yellow;
ModalInPresentation = true;
// Perform any additional setup after loading the view
}
The effect :

Use ModalInPresentation = true; in the ViewDidLoad of the presented page.
Or,
Use YourPresentingPage.ModalInPresentation = true; just before the code for presenting the page.

Related

How to initally hide searchbar in Navigation controller on iOS 13?

In iOS 13 the behavior has changed so that by default when Navigation controller appears the search bar is visible (when UISearchController is assigned to a navigationItem.searchController). Some system apps appear with the search bar hidden (you need to swipe down for it to appear), but I don't see any specific property that would allow this. How to achieve this - maybe there is some property or some method to do that?
Via experimentation, I have discovered that if you delay assigning the search controller to the navigation item until viewWillLayoutSubviews or viewDidLayoutSubviews, the search controller starts out hidden, as desired. However, this if you do this on iOS 12 or earlier, the search controller will not be revealed when scrolling down.
I ended up doing the following with a messy version check, which is working for me:
override func viewDidLoad() {
super.viewDidLoad()
searchController = /* make search controller... */
if #available(iOS 13, *) {
// Attaching the search controller at this time on iOS 13 results in the
// search bar being initially visible, so assign it later
}
else {
navigationItem.searchController = searchController
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
navigationItem.searchController = searchController
}
To start with a hidden searchBar, simply set the navigationItem.searchController property after your table view (or collection view) has been populated with data.
Inspired by bunnyhero's answer I put the code responsible for setting the UISearchController in navigationItem inside the viewDidAppear method. Seems to be working every time for me on iOS 14/15
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if navigationItem.searchController == nil {
navigationItem.searchController = searchController
}
}
Edit: I was overly optimistic. On iOS 15.2 this method stopped working for me. What I did to fix it was to move the code after reloading my table/collection view.
I find this works:
self.searchController.searchBar.hidden = YES;
You will need to unhide at the appropriate time.
I managed to make this work by setting isTransculent false on the navigationBar and having initial data on UITableView or UICollectionView. If you have 0 cells initially and trigger reloadData after some time (maybe a network call), SearchBar is visible initially. So have a dummy cell or something similar initially and load the data later, if that's the case for you.
navigationController?.navigationBar.isTranslucent = false
One should set searchController after tableView gets frame
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
super.scrollViewDidScroll(scrollView)
if !scrollView.frame.isEmpty, navigationItem.searchController == nil {
navigationItem.searchController = searchController
}
}
This is what works for me. I have a UISegmentedControl that reloads the tableView when filter changes.
With FRC:
guard let count = try? fetchedResultsController.managedObjectContext.count(for: request) else { return }
called after tableView.reloadData()
navigationItem.searchController = count > 20 ? searchController : nil
Swift 5.2 & iOS 13.3.1:-
Try like this. It works fine
navigationItem.hidesSearchBarWhenScrolling = false

How to create a action for UIReturnKeyType.Done in UITextView in xamarin iOS

I am trying to change the UITextView keyboard return button in to Done button.
I need to close the keyboard when I press the Done button.
I have create a UITextView and change the return button in to Done button.
This is my code
PhotoTitle = new UITextView
{
TranslatesAutoresizingMaskIntoConstraints = false, Editable = true, AccessibilityIdentifier = "PhotoTitle",
ReturnKeyType = UIReturnKeyType.Done
}
The keyboard showing Done button successfully. if I press it just behave like return button.
And I can not find a particuler event for fire when tap on Done button.
First of all you have to keep remember that, UITexiView is a scrollable UI widget. So, when you change the keyboard's default Return key in to Done button, you are hiding the opportunity of go to new line inside your UITextView. Therefore my suggestion is, if you are using a UITextView and you need a Done button by keeping the default keyboard, you should add a UIToolBar on top of the keyboard where you can place the Done button.
Since I'm not aware of your real need, which may do not need go to a new line and just need to exit the keyboard when user tap on the Return/Done button, here how you need to do it.
public override void ViewDidLoad()
{
base.ViewDidLoad();
TextView.WeakDelegate = this;
}
[Export("textView:shouldChangeTextInRange:replacementText:")]
public bool ShouldChangeText(UITextView textView, NSRange range, string text)
{
if (text.Equals("\n"))
{
TextView.ResignFirstResponder();
return false;
}
return true;
}
That is quite easy actually subscribe to the ShouldReturn event of the UITextField with a delegate or anonymous method that will call ResignFirstResponder on the field.
You can check this example project that shows how to do it
this.txtDefault.ShouldReturn += (textField) => {
textField.ResignFirstResponder();
return true;
};

Change background color (of entire view) on button click in Xamarin

I'm using iOS/Xamarin
When the user clicks a button, I'd like to change the background color of my view controller's main view (View).
In the button click event, I tried this:
partial void MyButton_TouchUpInside(UIButton sender)
{
InvokeOnMainThread(() =>
{
SetBackgroundColor(View);
});
}
but it doesn't work. I tried a few other main thread/uithread things but no luck.
If I call SetBackgroundColor(View) from the ViewDidLoad of course it works. I suspect this is a UI thread issue.
Any advice?
Thanks!
You can use the BackgroundColor property on the UIViewController's View property.
partial void MyButton_TouchUpInside(UIButton sender)
{
View.BackgroundColor = UIColor.Red;
}
Turns out the above code is good - somewhere else in the code someone was setting another layer on top of the background so I never saw it =/

How to present an iOS Modal View in MvvmCross

How can I present a modal view on iOS using MvvmCross?
Using Xamarin Studio on iOS and the MvvmCross NuGet version 4.2.2, none of the MvxModalSupportTouchViewPresenter, MvxModalNavSupportTouchViewPresenter or IMvxModalTouchView are even available.
Does the ViewModel even need to know about the fact that a particular view is presented as a modal view on iOS?
MvvmCross is a strong Page navigation framework. Default navigation using ShowViewModel<AViewModel> will use the stack metaphor: one on top of another on Android, slide atop each other on iOS, and use < on either platform to go back.
You can tell the ViewPresenter that a given view is modal by giving it a hint, in the form of an interface marker, by adopting IMvxModalIosView.
At the View Level
Adopt the IMvxModalIosView protocol:
public partial class AView : MvxViewController, IMvxModalIosView
At the AppDelegate Level
Replace var setup = new Setup(this, Window) by:
var presenter = new MvxModalSupportIosViewPresenter(this, Window);
var setup = new Setup(this, presenter);
setup.Initialize();
At the ViewModel Level
No change required. The ViewModel is actually not made aware of the modal presentation. Invoke:
ShowViewModel<AViewModel> // May be modal on certain platforms
To close a Page and go back to the previous one, regardless of your presentation style, use Close(this) on that very ViewModel. This will close a modal dialog, or pop a pushed view. A complete, bindable ICommand may look like this:
public ICommand BackCommand {
get { return new MvxCommand(() => Close(this)); }
}
Notes: In MvvmCross 4.2.2, Touch has been renamed iOS, so IMvxModalTouchView is now IMvxModalIosView. The new using are:
using MvvmCross.iOS.Platform;
using MvvmCross.iOS.Views.Presenters;
Using MvvmCross 5.5.2 all I had to get a modal was to add the following MvxModalPresentation attribute to my iOS view:
[Register("ExampleModalView")]
[MvxModalPresentation(
ModalPresentationStyle = UIModalPresentationStyle.PageSheet,
ModalTransitionStyle = UIModalTransitionStyle.CoverVertical
)]
public class ExampleModalView : MvxViewController
{
public ExampleModalView() {
}
...
}
Launching the modal is simple with the IMvxNavigationService service
await _navigationService.Navigate<ExampleModalViewModel>();
ExampleModalViewModel just needs to be a plain MvvmCross view model inheriting from MvxViewModel.
A useful reference for this is ModalView.cs in the iOS playground project: https://github.com/MvvmCross/MvvmCross/blob/develop/TestProjects/Playground/Playground.iOS/Views/ModalView.cs#L12

NSViewController disable resize when presented as Sheet?

So I am presenting an NSViewController as a sheet of a window that has resize disabled.
The view controller that is presented as a sheet can still be resized.
How do I disable resizing of a NSViewController?
Swift 4:
override func viewDidAppear() {
// any additional code
view.window!.styleMask.remove(.resizable)
}
By the way you can do this without writing code, here is how:
Drag a Window Controller element to the Storyboard from the Object
Library.
Connect the Window Controller to the specific View Controller which you want to disable resize.
On the Window Controller's Attributes uncheck Resize option.
After some more trying I found out this did the trick in viewDidLoad:
self.preferredContentSize = NSMakeSize(self.view.frame.size.width, self.view.frame.size.height);
If you add these methods, the issue will be fixed.
- (void)updateViewConstraints NS_AVAILABLE_MAC(10_10) {
[super updateViewConstraints];
}
- (void)viewWillLayout NS_AVAILABLE_MAC(10_10) {
self.preferredContentSize = NSMakeSize(self.view.frame.size.width, self.view.frame.size.height);
}

Resources