 So, good evening everyone. How are you doing today? Yeah, doing good? Great. Awesome. Yeah, all right. That's the spirit. So, this is what I'm going to talk about today. Samaritan forms custom renderers. Well, a little introduction to myself. I'm Uddara Alvis. And fun fact, Singaporeans find it very hard to pronounce my name. So if you happen to be one of them, it's all cool. I get that a lot. So I've got some... Well, I'm here in Singapore working as a Samaritan developer. And I must admit, I'm a crazy enthusiast in Samaritan and got some mad love for mobile development. And of course, Microsoft for the win. And I'm not much of a grown-up, just a 23-year-old kid causing trouble here and there. And in fun times, during my leisure times, I go on nature walks, adventures, running and stuff like that. And yeah, so today we are going to go through a little journey during this presentation. So this is the journey that I'm going to take you guys through. First of all, we are going to talk about what Samaritan and Samaritan forms is all about. Actually, Sohail gave a really good introduction to it. But so I wouldn't go much into details on that. Then I'm going to tell you guys a little story about a Samaritan forms developer. That's going to be fun. All right. Then of course, we're going to talk about custom renderers. And I'm going to show you guys how to create a sample custom renderer. And of course, at the end, I'm going to walk you guys through some very important facts that you need to keep in mind when you create custom renderers. All right. So let's get started, right? Well, Samaritan is, of course, it's great. All right. Let's you create mobile applications using our good .NET framework. And also, most importantly, it gives you native performance, native look and feel just by developing from Samaritan. And it's got true cross-platform capabilities. And next, let's talk about Samaritan forms. Samaritan forms is more like the true cross-platform extension of Samaritan. If you take a look at it, Samaritan forms is like the approach of Samaritan where they want to create this concept right once, run everywhere, and not suck. And they have delivered it exactly as it is. And Samaritan forms, what this differs from, what Samaritan forms differs from normal native Samaritan is that Samaritan forms has a shared UI layer. So that allows you to share almost up to 100% of your code base among the three platforms. So no more separation of the UI layer between the native levels. Now, some people are a little confused about Samaritan and Samaritan forms. Let me put it this way. With ordinary Samaritan, you get this shared C sharp background, sorry, back end. But you still have to implement the native UI separately for each platform, as you can see in the left-hand side diagram. And now if you take a look at the right side, you can see there's a shared UI code across the three mobile platforms. And the native level has narrowed down. So in that way, you get to share almost up to 100% code, to share the code between the three platforms. Now, if you are still confused, okay, I don't remember why I put two ones. Okay, anyways, if you take a look at this side, that's the normal native approach where you get to share up to 70% to 80% code base with separate UI implementations. And Samaritan forms, you get the UI layer as well, which fills up the next 20 to 30%. So yeah, hope that clears any confusion. Now we go to this story time. All right, so there's this developer who started working on a mobile application, all being all enthusiastic about Samaritan forms. And so he starts off developing, right? And he's given all the UI sketches by the UX lead and so on. So he starts implementing with the ordinary UI controls that's given with the Samaritan forms layer. And he manages to implement the basic UI design. But then slowly, he gets into the complex UI implementation of the designs, right? Then having a little confusion, he actually starts going through the available properties of these UI controls in order to fine tune the design as complex as the UX lead has given him. But unfortunately, he looks up and down here and there. He cannot find enough properties to customize the UI according to his complex UI design requirement. So, oh boy, he's in trouble. He realizes that using Samaritan forms default controls is unable to optimize the UI exactly as he needs. So, well, any solutions for this? Well, sadly, he's in a lot of trouble, right? Now, he could actually go back to the native development and, of course, he'll have to go through the trouble of implementing the same UI in all three platforms separately. That's not an option at all. So what do we do? So, ladies and gentlemen, let me tell you this is where Samaritan forms custom renderers comes for your rescue. All right, let me explain. Now, first of all, let me tell you a little bit about how Samaritan forms UI rendering is taking place. Now, every single control that Samaritan forms provides you has a renderer that associates with the Samaritan forms level to the native level of the mobile platform, where it maps every single property of the Samaritan forms controls to the native level properties. So that's why we get the actual native performance and native looks and feel through Samaritan development, right? So, in my opinion, this Samaritan forms, this rendering process is more like the magic behind Samaritan forms. Now, if you take a look at this diagram here, you can see the entry control here, right, which is something like the text view in Samaritan forms. So you can see how it goes down through these renderers that Samaritan provides, and they get converted down to the native level controls. As in, like, in iOS, you get the UI text field at the end of the rendering, and edit text user control and in Android and Windows phone respectively, right? So next, this, now Samaritan being such a good guy, they have allowed us developers to override this rendering process, tap into this rendering process and customize it according to our needs and requirements, right? Look what a good guy Samaritan is. Now, thanks to that, we developers get to customize the default properties and the behaviors of these Samaritan forms control by tapping into the rendering process for each and every platform according to our requirements. Now, what is a custom renderer, right? Now, in order to tap into the Samaritan forms rendering process, we need to create custom renderers by subclassing the base renderers that Samaritan has provided us. And by doing that, we get to create custom renderers and, you know, tap into the rendering process to edit the properties and behaviors of those controls. Now, well, why do we need them? You already have the answer to, you know, customize the controls from the native level itself. Now, if you take a look at this diagram here, here we have control, created a custom entry, which is my entry base, that derives from the entry control of Samaritan forms, and it goes through our custom renderer, my entry renderer, and goes down to the base renderer level. So at this level, we get to customize it as we want before passing into the base class renderer level. So that's how the whole rendering process and custom renderers work. So now, how to create a custom renderer? It's very simple. A lot of people are very, you know, they're scared of this whole custom renderers thing because they think it's very complex. In my opinion, no, it's super simple because what you need to do is, first of all, the first step, you create a custom control in Samaritan forms level by subclassing a, you know, default Samaritan forms control. You create a custom control, and then you consume that control, that custom control in Samaritan forms project, your normal UI. Then after that, as a third step or the final step, you implement the custom renderer in the native project level. So it's that simple. It's not very hard. So now, time for the demo. And as Sohail said, I'm going to show you guys in all three platforms. Hopefully. All right. So what we are going to do here, all right. Now, you can see I have a sample, you know, a Samaritan forms project opened up, which has a normal label and a button, right? Now, if you run this, first of all, let's run this in Android. And, yeah, just give it a little time. Do I talk too fast? Sorry, guys. Yeah, it's just a habit, a bad old habit. All right. Oh, so there we go. This is the normal output we get by the default Samaritan forms control, right? Now, if we take a look at the iOS, we set the, towards the iOS project, and we run it. OK. Come on. Oh, yeah. There we go. So that's how it's rendered in iOS. Now, let's take a look at Windows Phone. There goes Windows Phone. Now, what I'm going to do is, all right. Now, imagine my UX lead asks me to make these buttons corners even more curved than how it's normally rendered in these three platforms. If you can see in the normal, wait, I forgot to tell that in Android. All right. Let's set it to Android, and I'll show you. Oh, yeah. See, it has this but normal, the default button has squared corners, right? So what I'm going to do is make these corners even more curved, more towards like an ellipse corners. So in order to do this, I'm going to implement a custom renderer. So what I'm going to do is, first of all, the first step. Here we go. Create a new class. Let's call this corner, corner button. Oh, no, wait. That's a nice name around corners button. Let's call this round corners button. All right. We're going to create a button that has round corners. I'm going to make this public. And now, so as a first step, we need to inherit our custom control from default Samarin button, Samarin Forms button. So that is button, as you can see, Samarin Forms button. There we go. We subclass it from there. And that is done. So now we can straight away go ahead and consume this custom control in our UI implementation. So there we go. Boom. Sorry. Phone size. Oh, yeah. Let me. Sorry, guys. 120. Let's put it like 130. Is it good now? Let's put an increase a little bit more. 50. 150. Yeah. That's good, right? Yeah. OK. And alignment. Come on. Oh, nice. All right. So I'm going to use the same properties here. Why not? And click this normal button. No. Let's call it curved. No, rounded corners button. Rounded corners button. OK. There we go. So now the first step is done. The second step is done. We consumed it in our UI. And next what I'm going to do is the last step that is implementing in the native level, creating the custom renderer in the native level. So in order to do this, you need to dive down to the native project, native Samarin project level. That is, you know, Samarin.Android. Here we go. We create a new class called. Now the usual naming standard of custom renderers is that you take the name of our custom control button and you add the renderer keyword at the end. So here we go. We'll call it round corners button. And as a suffix, you add renderer keyword. That's more like the standard, you know? All right. That is done. Public. I'm going to make this sheet need to be visible. And yeah. So now if you remember, I told you guys earlier, when we create a custom renderer, we need to subclass it from the Samarin default renderers. So in this case, since this is a button, we need to subclass this custom renderer from button renderer that is the default renderer class for Samarin forms button, button renderer. There we go. Hope you can see. Yeah. That is done. And I'm going to do the same for on iOS and Windows phone also. Public. Now iOS is done. Let's go to Windows phone. And I'm not going to, you know, demonstrate about normal Windows and universal Windows platforms because it's almost the same. But and we are a little out of time right now. So yeah. And we create the custom renderer on Windows phone as well. Public renderer extend from the button renderer. Oh, yeah. Make it. All right. Now we have created the custom renderers basic skeleton. Now before I go ahead, I'm going to walk you guys through some very important facts that you need to keep in mind when you implement custom renderers. So the first one is now actually I'm going to go. I'm going to get back to the code while I go through this fact so you get a better understanding about each point and how to do it at the same time. So whenever you create a custom renderer, you need to export it and register it with the Samarin forms rendering process. If you don't do it, then Samarin would not recognize your custom renderer and it will go ahead with the default base class renderer. Now let's do that in our project. So how do you export your render is that you call the assembly and you use the export renderer and you pass in the type name of, you pass in the type name of your custom control, that is this one, the rounded corners button. Import it and then you need to pass in the renderer name. All right, that's good. Okay, there we go. And we need to do this in all three platforms as we need to implement this renderer in all three platforms. Okay, import off. Okay, all right. Okay, that's good. All right, now to the next point. So whenever a custom renderer starts its execution, the first method that gets fired is the one element changed method. This method is where we need to access all the properties and create, do all our customizations however we want to. And also something to be noted is that this method consumes some very important parameter that is called element changed event arcs which has two important properties, new element and old element. So what these properties are about is that the new element property contains a reference to the submarine forms level control and, sorry, the new element gives you a reference to the submarine forms control that is that this renderer is currently attached to. Like now if you take a look at the old element, it gives you a reference to the renderer that the submarine forms control was attached to. There's a distinct difference there. So this matters because whenever you create a renderer and you implement events and stuff like that, you need to keep an eye on these two properties and do the proper subscribing and unsubscribing of those events. So in order to, of course, to avoid memory leaks, we don't need to keep references to the objects that are not being used anymore. So let's do that in, implement that in our project, in our custom renderer. There you go. I'm just going to take this right here and let's start overriding. There you go. It's good. Now, usually this is the place where you need to do all your customizations and everything that according to your requirement. And let's do the same here. All right. I want it to be changed. OK. Good. That is good. All right. Now we have overridden the method that we need to write our custom customizations on. So next, all right. Now, a custom renderer is more like a middle guy in between the submarine forms level and the native level. So this middle guy has hooks for the both sides for the same submarine forms and the native level. So this normal base class renderer always has these two important properties that is called element and the control. The element property provides you a reference to the submarine forms level control. And the control property provides you a hook to the native level control, that this renderer is going to convert that submarine forms control to the native level. So whenever you do the customizations, you need to use this property and inject whatever the customizations you need straight away access the properties that according to your requirement. So let's go ahead and try that out in our project. So what you do here is you need to... Oh, before that, I need to do something. Yeah. I hope you remember about the new element and the old element. So I'm going to implement that here. First thing and let's say you take the... There we go. You need to check whether the element is present or not. If it is present, well, according to... I mean, during this demo, we are not going to use any events implementation here. We're just going to implement a customization of the UI. Therefore, I'm not going to do anything, any of those events here. So let's just say, subscribe to the events stuff. And if not, then you need to check for the old elements presents. Old element. See whether that's available or not. If it gives you the old elements, then you need to unsubscribe. Okay. All right. That's how it is done. All right. Now let's take a look at the control. Before you go into the controls properties, you need to check whether the control is available or not. Do a little check there. And inside this condition, only you need to do all the required customization. So I'm not going to go through the whole code, so I'll just get from my sample project here. That is... All right. Okay. Let's get this one. Get the gradient drawable. Okay. So if you are familiar with Android development, the way to set a button's background is by creating a gradient drawable, right? So here we have... I have created a gradient drawable where it sets the corner radius to the value we have given and so on, the background color and stuff like that. Now if you take a look at this code here, you can see at the set color method, I have gained the access to the element property, which is the Samurian forms level. Now what happens here is that this code, this piece of code, gains access to the background color property of the Samurian forms level here. Remember we set it here, background color property. And it gains access to that and it set it to the native level properties that we are creating here. Now that's how you use the control and the element. Now in order to set this gradient drawable to the native control that we are customizing here, what you need to do is gain access to the control property. You set background. As you can see, the control property has all the required native level methods and properties whatever available for this Android native button. So we go and set background and just as a normal Android application, you set up the gradient drawable. There we go. Now it should work like a charm. There we go. While it's compiling since we are out of time, I'm going to get the same code. It's already done. All right, there we go. As you can see, the new custom renderer button that we created, it has curved corners. So yeah, it looks better. All right, now that is Android. Let me show you the same on iOS next. Here we go. All right. So always keep in mind, you need to keep an eye out for the new element and the old element properties if you're using any events, stuff like that. So the next Windows Phone code is a little bit longer. So it's going to take a long time to code the whole thing from scratch. I would rather. Yeah, here we go. Okay, so here I need to show you guys something. Now if you take a look at this, you can see inside the, wait, let me copy the method, actual customization method. Okay, so in the Windows Phone renderer, what we do is we check for the old elements presence and the new elements presence, and we are using the method, the summit forms level event here. So, and we are unsubscribing to that event based on the presence of these two properties. And inside this method only we are doing the required changes. So these customizations depends on each platform's control's behaviors. It differs. So you need to have some native level look around knowledge in order to do extended customizations. However, so I hope you get the point of the new element and the old element properties. Well, that is done. And let's see how this gets executed. All right, on Windows Phone, here we go. Come on. There we go. Custom renderer successful on Windows Phone. And let's take a look at iOS. There we go. Come on. We don't have the whole day. Come on. There we go. Oh, yeah, there we go. Look how pretty it is. So that's the custom renderer implementation. Hope you get the idea. And don't worry, even though this seems pretty confusing for now, give it a try. Play around with it. And you can do awesome stuff. Now, yeah, the next point that you need to keep in mind is that like, now let's say the scenario like this. What if you wanted to get rid of the default native control that's given through the base class renderer, through the custom renderer, right? Well, and create your own native control and use it in our custom renderer. All right. That seems pretty complex. And let me give you a little example. So let's say you need to have a text box with a background shadow with it. So in something like IOS, what you do is you get the UI text field and you create another UI view that's going to hold the background shadow. And you put those views together and you form one native control in order to get that effect. So in scenarios like that, you need to override the natively provided element, right? So to do that, you can use the setNativeControl method that's available in custom renderers and directly put your own custom native control and override the defaultly given native control. So, yeah. And also keep in mind, since you're overriding the default given native control, you need to handle all the events and the behaviors manually all by yourself. So, yeah. So as long as you stick to those control and element properties that's defaultly given by Samaritan forms, you're good to go. But if you're going to even more deeper level customizations, you need to keep in mind to handle all the events and the behaviors. And last, but this is also very important to some fact to keep in mind, let's say you need to create something, some very, very complex customization control, right? And in this process, you might probably want to create your own base class renderer. So what you do is, now, is that even possible? I mean, we've been using button renderers and label renderers the whole time. That's defaultly provided by Samaritan. And now we want to create our own renderer and override the entire rendering process. That is possible. Yes, it is possible, even though it's not very recommended by Samaritan. What you need to do is you need to use the default view renderer that's provided by Samaritan and use the generic pre-renderer and pass in the custom control and the native control that's going to associate with your own renderer. So, yeah, there you go. Just something to keep in mind if you ever come across such a requirement. It is possible to create your own base renderer. Well, now that's been said. This is something I really need to mention, guys. For Samaritan forms mobile development, you don't need so much of in-depth mobile knowledge and experience, but it's quite, in scenarios like Samaritan custom renderers, it's pretty useful. So, if you're someone who's looking to move towards Samaritan forms mobile development, I would suggest that you take, at the same time, just take a little look around of the native platforms that are available, just a little look around while you are moving towards Samaritan. It's going to be very useful. So, that's a little sharing of the experience and wisdom. Next. All right. So, we've arrived at the last part of our presentation. That is things to keep in mind before you decide to go towards custom renderer implementation. Now, this is something very important. You need to think twice before you move towards custom renderer implementation. That is because some untold truth about custom renderers is that it's a little bit process-intensive. And I know it's very tempting to go for custom renderers whenever you get comfortable with it. I experience that myself all the time. But try your best to solve your requirement from the Samaritan forms level itself. So, you save a lot of resources and processing time. And also, you can try out the alternatives by sub-classing the default controls in the Samaritan forms level. Try to put all the stuff together in Samaritan forms level itself. Or else, you can try out Samaritan forms effects. That's been released last few months. Something introduced new. And it's something similar to custom renderers. But it's more simplified and less process-intensive. So, always look for the alternatives before moving towards renderers. Now, whenever you create a custom renderer, you need to focus on the re-usability as much as possible. Because, I mean, as I mentioned earlier, it's very clear that custom renderers process-intensive. So, try your best to keep it low as much as possible, the number of renderers that you use in your application. And try to merge the possible renderers together and use less number of renderers in your application. So, as such an example, let's say you have an image renderer that renders an image control as a circle. And you have another renderer that renders the images' corners, images' squared corners as curved corners. Now, why don't you just merge those together and keep only, maintain only one renderer? You can do that. It's the same type of properties that you're using for the both renderers. So, try to keep it, try to unify as much as possible behaviors and properties to one renderer. So, yeah, that's something to keep in mind. And the last thing, last point to keep in mind when you're implementing custom renderers is that before you move towards rendering renderers implementation, try to take a look at the renderer hierarchy starting from the sampling forms level towards the actual native control level. Go through the properties that are available in the native level in all three platforms before you decide to go for custom renderers and see whether it is possible to achieve your requirement through the renderer. By doing that, you'll have a better understanding of how we are going to implement more efficiently. So, now after that, that's been said, we've reached the conclusion of our little journey. So, well, something to mention here is that Samarin Forms custom renderers is extremely important in Samarin Forms mobile development. In my opinion, Samarin Forms custom renderers is more like the magic behind the actual awesomeness of Samarin because it gives you an ultimate flexibility on customizations for your mobile applications. And, guys, it's nothing to be scared about custom renderers. Once you get used to it and you start playing around with it, you're going to love them and they're going to be very, very useful. And, yeah, keep in mind, custom renderers are there to rescue you. And also keep in mind the important facts that I explained today. And, yeah, that will give you a better understanding about how to implement more efficiently and effectively. So, well, that brings to the end of our presentation, the journey today during the presentation. And thank you so much for listening. And don't forget to check out my blog. I post these custom renderer implementations almost every week and a lot of interesting stuff there. So, yeah, thank you so much for listening and thank you for the organizers for the opportunity. Thanks, guys. All right.