How do I disable bouncing on ScrollView in Xamarin Forms for iOS? - xamarin.forms

I'm using a ScrollView in Xamarin Forms and on iOS, the scrollview bounces (often too far) when you hit the top or the bottom. My understanding is this is default iOS behavior? Is there a way I can disable this so there is no bounce on scroll?

Yes, disabling the bouncing effect is possible. But you will need to create a Custom Renderer.
In your specific case, you have to use ScrollViewRenderer as a base class for your custom renderer. Then, in your custom renderer, you can simply set Bounces to false.
An example of a Custom Renderer can be found here. Your result should look something like this:
PCL:
public class CustomScrollView : ScrollView
{
public CustomScrollView() {}
}
iOS:
[assembly: ExportRenderer(typeof(CustomScrollView), typeof(CustomScrollViewRenderer))]
namespace Test.iOS
{
public class CustomScrollViewRenderer : ScrollViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
Bounces = false;
}
}
}
On Android, you will need to implement a Custom Renderer as well which simply does nothing.

Related

Proper Page.Loaded event in Xamarin.Forms

For the past 2 month I have been searching tirelessly for a way to implement a proper Page.Loaded event when using Xamarin.Forms but I couldn't implement or find a way to do it.
Most people suggest overriding Page.OnAppearing or adding an event handler for Page.Appearing both of which are not the answers or the proper way to achieve the desired effect and don't event behave as a real Page.Loaded event would.
I would like to know the following:
Why doesn't Xamarin.Forms have a built-in Page.Loaded event?
Is there's a work around?
Can I implement it from the native side?
Edit:
What I mean by "proper Page.Loaded" event is:
It must be called ONCE AND ONLY ONCE the page has loaded all of it's controls, laid them out, initialized them and rendered them for the first time.
It must NOT be called when returning from modal pages.
1.Why not load the data/controls in the constructor of the ContentPage? The constructor method is call only once and it is also called before Page.OnAppearing.
Can I implement it from the native side?
Yes, I think you can.
In iOS, override the ViewDidLoad method in custom renderer:
[assembly:ExportRenderer (typeof(ContentPage), typeof(MyPageRenderer))]
namespace App487.iOS
{
public class MyPageRenderer : PageRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
//call before ViewWillAppear and only called once
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
}
}
}
In Android, try to override the OnAttachedToWindow method:
[assembly: ExportRenderer(typeof(ContentPage), typeof(MyPageRenderer))]
namespace App487.Droid
{
public class MyPageRenderer : PageRenderer
{
public MyPageRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
}
protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
}
}
}
Currently Xamarin.Forms doesn't not provide a proper/complete life cycle events to fulfill all specific requirements, but things are improving, the Dev team is currently working on to address this issue, below mentioned issues and recent pull request on the official GitHub Repos (you may follow, get ideas and maybe implement it yourself before they even ship it), they will for sure provide that in the future, although it is not clear when it will be ready.
Specification: Enhancement Add better life cycle events #2210.
Issue: LifeCycle events for controls #556.
Pull request: Life cycle events for controls
GitHub Branch where currently working on.
MAUI repo (Next evolution of Xamarin) Cross-Platform LifeCycle.
Specification Add Loaded/Unloaded to VisualElement.

Xamarin.Forms - getting Control from ImageButtonRenderer

I am trying to create a subclass of ImageButton called TintedImageButton that (surprise) can tint the image. I am following the basic structure of some TintedImage code I have found.
TintedImageButton has three renderers for iOS, Android and UWP.
The Android version of TintedImageButtonRenderer isn't working because it can't access the "Control" property of its superclass, ImageButtonRenderer. The Control should be the native widget.
I have been unable to locate the class documentation for ImageButtonRenderer but decompiling seems to indicate that the Control property has been made private for Android, but not for iOS. Does anyone know why this might be? How can I get the native widget so I can modify it?
The ImageButtonRenderer inherits from AppCompatImageButton, so the class myImageButtonRender itself is a native control which is a subclass of AppCompatImageButton.
[assembly: ExportRenderer(typeof(TintedImageButton), typeof(myImageButtonRender))]
namespace App261.Droid
{
class myImageButtonRender : ImageButtonRenderer
{
public myImageButtonRender(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ImageButton> e)
{
base.OnElementChanged(e);
this.SetImageResource(Resource.Drawable.sample);
AppCompatImageButton imagV = this as AppCompatImageButton;
}
}
}

iOS 11 large titles in Xamarin.Forms

How do I enable iOS 11 prefersLargeTitles throughout my Xamarin.Forms app?
I tried creating a custom renderer derived from PageRenderer for NavigationPage, setting:
ViewController.NavigationController.NavigationBar.PrefersLargeTitles = true;
This didn't have any effect, however.
Voila
[assembly: ExportRenderer(typeof(NavigationPage), typeof(NavBarRenderer))]
namespace LargeTitleSample.iOS
{
public class NavBarRenderer : NavigationRenderer
{
protected override void OnElementChanged(Xamarin.Forms.Platform.iOS.VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
NavigationBar.PrefersLargeTitles = true;
}
}
}
You have to create a custom renderer for the NavigationPage inheriting the NavigationRenderer. Then set the PrefersLargeTitles property on the NavigationBar to true.
It seems that when you add some scrollable control to the page, it will automatically have to 'big to small' effect when scrolling up, at least for a ListView.
Working example repo is here: https://github.com/jfversluis/LargeTitleSample
For XAML:
<NavigationPage Title="..." xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" ios:NavigationPage.PrefersLargeTitles="true">

Tabbed Page OnAppearing()

I have a Tabbed Page Xamarin Form application that I am trying to customize. I am migrating from an IOs only app to all platforms. In iOS there are a couple function that I used ViewDidDisappear(), ViewDidAppear() and ViewDidLoad();
The application today loads the tabbed page as follows:
{
Children.Add(new MyPage1());
Children.Add(new MyPage2());
Children.Add(new MyPage3());
Children.Add(new MyPage4());
}
Each of the child pages are declared as follows all inheriting from ContentPage.
class MyPage1: ContentPage
{
…
protected override void OnAppearing()
{
base.OnAppearing();
Content = SomeContentPage;
}
}
The problem that I am running into is that the OnAppearing() is called for all pages when only MyPage1 is currently displayed. I need to know when each child page is loaded.
I have read about message center but I am not sure how to implement it in this particular case. Would the message center be the best solution for this?
How do I implement a solution that will allow me to know which of the four pages is displayed?
Possible workaround would be to override OnCurrentPageChanged in your TabbedPage.
protected override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
if ( CurrentPage is YourContentPage page)
{
page.YourCustomCode();
}
}
On the main TabbedPage, after you've added child pages, setting the CurrentPage property to null should fix the problem.

disable back button xamarin.forms

I am sorry, if this question is asked before, but I am unable to find my answer that is why I am asking again this question.
My Scenario is I have placed a back button on my axml views from which I am performing Navigation of Going back on previous views using GoBack() Method.
what I need I want to disable back button on my hardware so that my app should not go back to previous screens which are available in the navigation stack. I am using Prism MVVM for my app, so is there any possibility to disable this button or have some overrideable action method on my ViewModel from which I should stop it.
Hope you could understand my question.
B.R
I found the best way to do this was to use the provided override of OnBackPressed in the android MainActivity and then access a bool I saved somewhere. I use the settings plugin personally but the example below uses the built in application properties (it should work but I haven't tested it).
public class MainActivity : FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Forms.Init(this, bundle);
LoadApplication(new App());
}
public override void OnBackPressed()
{
var disable = (bool) App.Current.Properties["isBackButtonDisabled"];
if (disable) return;
base.OnBackPressed();
}
}

Resources