Custom Renderer feedback needed

TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

Hey duders,

We know a lot of you are having to write custom renderers for your apps. This was fully expected, and we are of course working to minimize the number of renderers you need to write (it will never reach zero for large enough apps) and making writing them easier. We have a good idea how to make it easier but what we really need feeback on is what you are writing them for!

So if you can just help us and give us some feedback on what custom renderers you wrote and what features/modifications you made with them. It would really help us understand the biggest holes in the API and were to start plugging!

Cheers!

«13

Posts

  • rmevans9rmevans9 USMember
    edited June 2014

    Not a certain custom renderer but I would like to see the creation of the native control moved out of a function filled with other code... at least on specific renderers like the button one. The reason I would like to see this is on iOS (I had to overcome it for iOS but might have similar issues on WP and Android) you guys are doing the following:

    this.SetNativeControl(new UIButton(UIButtonType.RoundedRect));

    I needed

    this.SetNativeControl(new UIButton(UIButtonType.Custom));

    The rest of the functionality would have worked fine but since I had to not let the ButtonRenderers OnModelSet get called I had to reimplement the entire renderer which was not desired. Now, I know doing something like I am suggesting could cause issues if someone decides to return a MKMapView when you are expecting a Button so you could implement it with generics at your NativeRenderer level so you can enforce that you get a UIButton back (in this example at least) by setting the return type of the function. Something like this could also be useful in other situations for example I ported MapBox's MBXMapKit over to Xamarin's C# goodness. If you open up Xamarin.Forms.Maps renderers to customization (they are currently internal I believe) I could use the above suggestion to pass in my new MapView type because MBXMapKit inherits MKMapView. This would allow me to not do a lot of the boiler plate code you guys already wrote.

    No more internal! I know there is a good reason for internal accessibility but it has tripped me up and make me have to reimplement perfectly working code because I can't make one function call on a class I am inheriting from. So I would like to see more use of Protected if you don't want the outside world to be able to get at it.

  • TaqiJaffriTaqiJaffri USMember

    I posted a separate thread here: http://forums.xamarin.com/discussion/18377/web-navigation-event-in-xamarin-forms-webview#latest

    I'm hoping this does NOT require a custom renderer... but if it does, please consider this my feedback that we should plug this hole in the WebView such that a custom renderer is not required for this simple scenario.

  • EricGroverEricGrover USMember ✭✭

    The Windows Phone Entry render has a left margin +10 which is annoying. I sub-classed it and made my own Renderer to fix it.

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    @rmevans9‌ Good suggestion will do.

  • A splash ContentPage sample/control would be a nice addition. The one that you can add, define soms action to carry out while showing a splash with a spinner.

  • The ability to use customCells in lists like the one in the Mailbox app (with swipes)

  • HugoLogmans_HugoLogmans_ NLMember ✭✭✭
    edited June 2014

    I subclassed the WebView renderers to give them a transparent background. For iOS the Opaque property needs to be set, for Android some other options if Backgroundcolor = Color.Transparent.

    Also for the renderers, I'm a bit worried about the consistency in the used names (ModelSet, ModelChanged etc), and the used structure.. Might be essential to have a few "hooks" for each renderer: a place to initialize the control (after the constructor), a common place to react to Model changes that might have platform-dependent parts.

    For the used structure: as you can see in some forum posts, the name renderer makes us believe the renderer is a container that prepares and sets a native control, instead of being a control itself. Because of the different structures (like for Entry and Webview), the learning curve goes steep up.

    (I do need to mention I am really really glad with the Xamarin.Forms project, and immediatly started rebuilding one of our easy apps, just to see what state it is in).

    (update: oops, just saw the new update post :) )

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    @Sandman we've heard this multiple times, what would you expect on windows phone out of curiosity?

  • rmevans9rmevans9 USMember

    @ermau‌ Thanks for the explanation! I was hoping it was something like this and that eventually they would make their way to an accessor that we could use. I hope to see the renderers reach a stable state here soon as I am in the middle of developing an app I hope to release in the next 2-3 months that is relying heavily on Xamarin.Forms as I feel it is an awesome step in the right direction for the mobile platform.

  • KevinFordKevinFord USUniversity, Certified XTC Partners ✭✭✭

    @JasonASmith‌ ,
    I updated my blog and first and foremost thank you for all your work on this. It's a really great idea that I think has a lot of potential, particularly in the PhoneGap/Appcellerator space. Since I am looking at the renderers like a proctologist I do have a few suggestions from a consistency perspective. :)

    • Cross platform naming of the renderers for a particular control should be the same and follow the same standard. For example: Xamarin.Forms.Platform.iOS.NavigationRenderer, Xamarin.Forms.Platform.Android.NavigationRenderer, and Xamarin.Forms.Platform.WinPhone.NavigationPageRenderer or Xamarin.Forms.Platform.iOS.BoxRenderer, Xamarin.Forms.Platform.Android.BoxRenderer and Xamarin.Forms.Platform.WinPhone.BoxViewRenderer. All names should be the same, the standard should be to either include view/page in the name or don't
    • Similar thought on the method names. For example Xamarin.Forms.Platform.Android.ViewRenderer.OnUnfocusRequested, Xamarin.Forms.Platform.iOS.ViewRenderer.ViewOnUnfocusRequested and Xamarin.Forms.Platform.WinPhone.VisualElementRenderer.OnModelUnfocusRequested. Notice the WP one is even defined in a different place, the base class of ViewRenderer.
    • A few of the Android renderers are still internal, Xamarin.Forms.Platform.Android.ListViewRenderer and Xamarin.Forms.Platform.Android.OpenGLRenderer. I'm not sure if that's on purpose.

    Looks like you guys are making a lot of improvements. Thanks!

    One question I have is how are Xamarin.Forms AbsoluteLayouts, Grids and RelativeLayouts handled? It does not appear to be that they use any sort of native renderers (that I can find). How are they figured out?

  • SandmanSandman USUniversity ✭✭
    edited June 2014

    @JasonASmith‌ On windows phone 8.1 I have seen a few instances that appear to be CarouselView vs a CarouselPage.

    1. The app switcher
    2. You can swipe left and right in IE to change tabs.
    3. In an app called weave you can swipe leave or right to get to the next result set.
    4. So I don't think there are necessarily any visible indicators that it is swipeable on WP, but the functionality is there.
  • BenStrawnBenStrawn USMember

    A simple renderer I've made is a StrikeThroughLabelRenderer, which renders the label with a strikethrough.

    Also, I'm using the RoundedBoxRenderer described in this video on custom renderers, and have RoundedBox extend StackLayout, since I frequently need borders around those. I'm having an issue though, where the first child element of the StackLayout isn't being rendered. The quick hack I've been using is to just insert an empty label as the first child, which works for now.

    Why isn't there a StackLayoutRenderer to inherit from? Is there a better solution than what I'm doing?

  • YanDuanYanDuan USMember ✭✭

    I'm looking forward to a more extensible version of the NavigationRenderer, ListViewRenderer, PhoneMasterDetailRenderer. Right now (from a glance of the iOS code), lots of the methods and associated classes (e.g. TemplatedItemsList) are marked either private or internal, which makes subclassing and extending them especially hard. A couple use cases include:

    • The possibility to extend NavigationRenderer to allow flexible calculation of widths and heights
    • unequal heights in ListViews
    • double column ListViews or Pinterest style?
    • Integration of ListViews with other existing libraries like a swipe view (e.g. SWTableViewCell)
    • Customize the Master page (it would be great if we can replace the rendering side with a third-party library, e.g. ECSlidingViewController)
  • YanDuanYanDuan USMember ✭✭

    Also: Why is VisualElement#IsFocused.set internal?

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    Layouts just use the base VisualElementRenderer. They dont need any controls or customization by defualt.

  • BenStrawnBenStrawn USMember

    @JasonASmith‌ Thanks for the response. I'm currently using just a ViewRenderer to render my custom StackLayout. This doesn't work for me though, because for my implementation, I need to hook into the UIView (on iOS) that Xamarin creates.

    But in my ViewRenderer, this.Control is null, so I must new one up, and this causes several issues for me, such as losing my events, and the bug I mentioned where the first child element isn't rendered.

  • I want to add a background image to the navigation bar(iOS)/action bar(Android), so I have extended the NavigationRenderer for the NavigationPage.

    This was fairly easy for iOS, because the NavigationRenderer has access to the UINavigationBar.
    However, for Android I can't seem to find a way to get the Action bar from the NavigationRenderer.

  • clintclint CAMember

    I second the issue on Internal scope. I have, for the time being, given up on X.F because everything I wanted to do was blocked in some fashion.

    I can understand the concern but perhaps it would have been wise to start out with a public Beta with the caveat that the public API is still being developed.

    Having it been open source would have helped me quite a bit because I could have made the changes that I needed. I would have understood that things may change and break. That is the nature of software sometimes.

    Cheers,
    Clint

  • PaulPatarinskiPaulPatarinski USUniversity ✭✭

    Is there support for Custom Renderers on Windows Phone 8?

  • CraigDunnCraigDunn USXamarin Team Xamurai

    @PaulPatarinski‌ yes, this document on Custom Renderers is being updated as I type.

    This is the Windows Phone version of the Entry custom renderer in that doc

    [assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
    namespace CustomRenderer.WinPhone
    {
        public class MyEntryRenderer : EntryRenderer
        {
            protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
            {
                base.OnElementChanged(e);
    
                if (e.OldElement == null)
                {
                    var nativePhoneTextBox = (PhoneTextBox)Control.Children[0];
                    //var nativePasswordBox = (PhoneTextBox)Control.Children[1];
                    nativePhoneTextBox.Background = new SolidColorBrush(Colors.Blue);
                }
            }
        }
    }
    
  • PaulPatarinskiPaulPatarinski USUniversity ✭✭

    @CraigDunn‌ awesome.
    p.s. That was the page I was looking at when I assumed it is not supported :)

  • PaulPatarinskiPaulPatarinski USUniversity ✭✭

    @CraigDunn It might be a good idea to add this to the sample as well:

        //Use ReadOnly instead of Enabled, so FontColor styles appropriately
            if (!editBox.IsEnabled)
            {
                editBox.IsReadOnly = true;
                editBox.IsEnabled = true;
            }
    

    Currently if you have a textbox with BackgroundColor = White and IsEnabled = false, the FontColor is set to White as well, so you can't see the text.

    Cheers

  • ChesterChester USMember

    @JasonASmith‌ I concur with the CarouselView. It would be great to have a view to swipe between multiple images. Or is there one that exists that I am not aware of?

  • rmarinhormarinho PTMember, Insider, Beta Xamurai

    Toolbar items renderer, and navigationbar renderer

  • DanZhuDanZhu CNMember ✭✭
    edited June 2014

    custom table cell renderer, like imageCell , example thank you。

  • PaulPPaulP USMember ✭✭

    Is there an existing github repo with examples of CustomRenderers?

  • AaronKingAaronKing USMember
    edited June 2014

    WebView (with HandleShouldStartLoad event) -- right now there is no way to intercept the load of a URL and determine if the WebView or Device Browser should handle it. For most hybrid apps that use a WebView for content it seems this would be essential because off-site links really should open in the device browser (typically).

    BTW - So far the Xamarin.Forms "developer experience" has been FANTASTIC!

  • rmarinhormarinho PTMember, Insider, Beta Xamurai

    @PaulP‌ it's not oficial xamarin, but you can check the comunity project XForms Toolkit that shows some CustomRenderers in all 3 platforms,

    For example, Renderer for a Label in IOS:

    https://github.com/XForms/XForms-Toolkit/blob/master/src/XForms.Toolkit/XForms.Toolkit.iOS/Controls/ExtendedLabel/ExtendedLabelRenderer.cs

  • IanGeogheganIanGeoghegan USUniversity ✭✭

    @JasonSmith‌ I would love to be able to style the text or color of all controls. I have a Cell right now that I have to write custom code for because I can't change the back ground color. I also have some text that I can't style so I might have to write a controller for that as well. Thanks.

  • IanGeogheganIanGeoghegan USUniversity ✭✭

    I just wrote a custom renderer for an ImageCell.

  • NormanChengNormanCheng USMember

    Please let us get the navigation bar on iOS when using a Navigation Page either through a custom renderer or directly through the Navigation Page.

    This already seems to work on Android for getting the ActionBar.

    Thanks!

  • BernieHabermeierBernieHabermeier USUniversity ✭✭

    @JasonSmith and @igeoghegan it would be neat to think about styling controls similar to that of CSS3. I'd suggest a much smaller set of things one could style to start with, but border, margin, and padding control for all 4 sides as well as any one side would be a great start, along with color for border, text, and background. It'd be great if the naming would be the same for all controls.

  • @NormanCheng, how did you access the ActionBar for Android?

    As stated in this question:

    http://forums.xamarin.com/discussion/18803/how-to-extend-android-actionbar-functionality-for-the-navigationpage

    I was able to access the Navigation Bar for iOS, when extending the NavigationRenderer (which the NavigationPage uses), through the property, "NavigationBar".

    However, I could not find a way to access the ActionBar for Android.

  • SeanMcKaySeanMcKay USMember

    I ended up making a Custom renderer for a MKMapView so that I could assign a delegate to the MapView which set the pin behavior (and look and feel). Also a click event on the Pin (haven't looked so closely yet to see if there or if I have to implement in my custom classes) that allows for custom display triggering. These things would be nice to have.

  • MichaelCookMichaelCook USMember ✭✭

    I ended up making a custom renderer to set a few native properties on the SearchBar for iOS (http://forums.xamarin.com/discussion/19143/searchbar-backgroundcolor-ignored-ios?new=1)

    First. it would be nice to have a method to set custom properties, without having to write a custom renderer (it's possible there is and I just missed it).

    But in the case of writing an actual custom renderer, I ended up overriding Draw() in order to set my custom properties on the base Element (in my case a UISearchBar). Since I'm not actually taking over the drawing of the object this seems clunky. It would be nice if there was a better place to set custom properties than Draw() (and again there might be and I just don't know it).

  • SturgmeisterSturgmeister USUniversity ✭✭

    @MichaelCook‌ Would it be possible to set your custom properties in the OnElementChanged? That is called when the renderer's element (the Xamarin.Form's or your custom visual element) is set for the renderer. You can use the event args' NewElement property to get the visual element and the renderer's Control property to access the native control (or create one). I think that makes sense as the place to customize the native control.

  • MarkSmith.8123MarkSmith.8123 USXamarin Team, University, XamUProfessors Xamurai
    edited June 2014

    @MichaelCook‌

    I'm not speaking for the dev team here, this is just my opinion.

    It's certainly technically possible - for example there could be a dictionary with key/value pairs of properties you want to set on the native control, but it could never be type-safe since the properties are completely unknown to the shared code and would be different per-platform anyway.

    But, it's a good idea - I could see a static event on each renderer that gets raised when creating the native view - so you could do something like this:

    // iOS project
    
    LabelRenderer.InitializeNativeView += (element, view) => {
       if (element.Name == "...")
           view.Font = UIFont.FromName("Helvetica-Bold", 20f);
    };
    

    It still feels kind of hacky to me, but maybe it will provide inspiration :)

  • KevinFordKevinFord USUniversity, Certified XTC Partners ✭✭✭
    edited June 2014

    @msmith,
    What might be nice is if the forms/controls could make calls into the platform specific renderer that is handling it. After all, at run time the platform is known along with the platform specific renderer that will be used. That would allow us to add interfaces to our renderers and do cool things like this from within our page:

    ((IMyRender)this.Renderer).DoSomePlatformSpecificStuff(stronglyTypedParametersIWantToSend);

    Then I could implement the IMyRender interface with DoSomePlatformSpecificStuff on each platform specific renderer.

Sign In or Register to comment.