Xamarin forms, iOS custom renderer font size - xamarin.forms

I'm using code below to set custom font to all of my buttons, all buttons have my new font and everything is good, the problem is font size, when I change it in xaml, nothing changes.
using System;
using System.Diagnostics;
using LAVA.iOS.CustomRenderer;
using LAVA.Utils.CustomRenderer;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
namespace LAVA.iOS.CustomRenderer
{
public class CustomButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control == null || e.NewElement == null) return;
Control.Layer.BorderColor = e.NewElement.BorderColor.ToCGColor();
Control.Layer.BorderWidth = (nfloat) e.NewElement.BorderWidth;
Control.Layer.CornerRadius = e.NewElement.BorderRadius;
try
{
Control.Font = AppDelegate.GetFont(Control.Font.PointSize);
}
catch (Exception exception)
{
Debug.WriteLine(exception.Message);
}
}
}
}
this is my AppDelegate.GetFont() method:
public static UIFont GetFont(nfloat fontSize)
{
if (AppFont == null)
AppFont = UIFont.FromName(Constants.FONT_IOS, fontSize);
else if (AppFont.PointSize != fontSize)
AppFont.WithSize(fontSize);
return AppFont;
}
but the font size does not change.

You should use a property on e.NewElement (e.g. e.NewElement.FontSize) to get the desired font size. Control is the native control, so you're just getting a font with the same size that was already there.

Related

WebView AlertDialog is not getting closed in Xamarin Forms

I was using HybridWebviewRenderer for loading a url on WebView for my application using Xamarin forms. Currently when I click a button in web view, it shows a alert popup with one closeButton. when I click on the closeButton , I'm currently navigating to a page and the navigation is working properly, but when I come back to the same screen, the alert Is not dismissed.? The alert is all done on the web view side , not code is done for creating alert in Xamarin forms. how can we dismiss the alert in web view for Xamarin forms??
I have checked your code, you need to put the if (Control == null) inside the if (e.NewElement != null).You can check the code snippet below for your reference:
using System;
using System.ComponentModel;
using Android.Content;
using Android.Service.Controls;
using Android.Webkit;
using HybridWebView.Droid.Renderer;
using HybridWebView.Renderer;
using Java.Interop;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(CustomWebView), typeof(HybridWebViewRenderer))]
namespace HybridWebView.Droid.Renderer
{
public class HybridWebViewRenderer : ViewRenderer<CustomWebView, Android.Webkit.WebView>
{
const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
Context _context;
public string BaseUrl = "file:///android_asset/";
public HybridWebViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Source")
{
Control.LoadDataWithBaseURL(BaseUrl, Element.Source, "text/html", "UTF-8", null);
}
}
protected override void OnElementChanged(ElementChangedEventArgs<CustomWebView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
var hybridWebView = e.OldElement as CustomWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
if (Control == null)
{
var webView = new Android.Webkit.WebView(_context);
webView.Settings.JavaScriptEnabled = true;
webView.SetWebViewClient(new JavascriptWebViewClient($"javascript: {JavascriptFunction}"));
SetNativeControl(webView);
}
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadDataWithBaseURL(BaseUrl, Element.Source, "text/html", "UTF-8", null);
}
}
}

How to change the color of searchbar search icon and cancel button color in xamarin forms

How to change the color of searchbar icon from xaml, I want to change the cancel and search icon color of a search bar in xamarin forms application.How to implement this. Please help on this
As adamm said, you can modify the "cancel button color" via CancelButtonColor.
Similarly, if you want to implement a custom SearchBar in iOS, you can also create a custom renderer for it.
For UISearchBar, you can modify the color of the icon via SearchTextField.LeftView.TintColor.
[assembly: ExportRenderer(typeof(MySearchBar), typeof(MySearchBarRenderer))]
namespace searchbar.iOS
{
public class MySearchBarRenderer : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.BackgroundColor = UIColor.Yellow;
UISearchBar searchbar = Control as UISearchBar;
searchbar.SearchTextField.LeftView.TintColor = UIColor.Orange;
// UPDATE
var clearButton = searchbar.SearchTextField.ValueForKey((Foundation.NSString)"clearButton") as UIButton;
//clearButton.SetTitleColor(UIColor.Blue, UIControlState.Normal);
//clearButton.TintColor = UIColor.Orange;
clearButton.SetImage(UIImage.FromBundle("CloseIcon.png"), UIControlState.Normal);
}
}
}
}
Cancel button color can be change by setting CancelButtonColor:
<SearchBar Placeholder="Search items..."
CancelButtonColor="Orange"
PlaceholderColor="Orange"
TextColor="Orange"
TextTransform="Lowercase"
HorizontalTextAlignment="Center"
FontSize="Medium"
FontAttributes="Italic" />
For the icon color you need to use custom renderers.
For example, on Android you can create a new file (something like SearchBar.Droid.cs) and add this in it:
using Android.Content;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Xamarin.Forms.SearchBar), typeof(MyApp.Renderers.SearchBarIconColorCustomRenderer))]
namespace MyApp.Renderers
{
public class SearchBarIconColorCustomRenderer : SearchBarRenderer
{
public SearchBarIconColorCustomRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
var icon = Control?.FindViewById(Context.Resources.GetIdentifier("android:id/search_mag_icon", null, null));
(icon as ImageView)?.SetColorFilter(Color.Orange.ToAndroid());
}
}
}
Edit:
For iOS, try something like this (I didn't test it):
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(Xamarin.Forms.SearchBar), typeof(MyApp.iOS.Renderers.iOSSearchBarIconColorCustomRenderer))]
namespace MyApp.iOS.Renderers
{
public class iOSSearchBarIconColorCustomRenderer : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var searchbar = (UISearchBar)Control;
searchbar.TintColor = UIColor.Orange;
}
}
}
}

Xamarin Forms overriding Android switch property using Effects

I would like to override the On/Off text of a switch using an Effect rather than a custom renderer.
In Android, I have the following code:
protected override void OnAttached()
{
try
{
if (Control is Android.Widget.Switch control)
{
control.TextOn = "Yes";
control.TextOff = "No";
}
}
OnAttached executes as expected but 'Control' is not an Android.Widget.Switch control but of a related type, e.g. 'android.support.v7.widget.SwitchCompat'. How can I make the code recognize that it should update the text in this case?
Do you want to achieve the result like following effect?
You can achieve it like following code.
using Android.Runtime;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(SwitchDemo.Droid.ClickEffect), nameof(SwitchDemo.Droid.ClickEffect))]
namespace SwitchDemo.Droid
{
public class ClickEffect : PlatformEffect
{
protected override void OnAttached()
{
// throw new NotImplementedException();
if (Control is SwitchCompat control)
{
control.ShowText = true;
control.TextOn = "Yes";
control.TextOff = "No";
}
}
protected override void OnDetached()
{
//throw new NotImplementedException();
}
}
}
Here is PCL code.
ClickEffect.cs
public class ClickEffect: RoutingEffect
{
public ClickEffect() : base($"MyCompany.{nameof(ClickEffect)}")
{
}
}
Use it in xaml.
<Switch>
<Switch.Effects>
<local:ClickEffect/>
</Switch.Effects>
</Switch>

Rounded corner for Entry - Xamarin forms UWP

Is there anything possible to customize the radius of Entry to having a slightly rounded corner?
You can use Custom Renderer in xamarin.forms
in iOS
//...
using App11;
using App11.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyiOSEntry))]
namespace App11.iOS
{
public class MyiOSEntry:EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Layer.MasksToBounds = true;
Control.Layer.CornerRadius = 10; //set the rounded corner
Control.Layer.BorderColor = UIColor.Red.CGColor;
Control.Layer.BorderWidth = 3;
}
}
}
}
in Android
creat a xml file in the folder Resource->drawable edit_text_style.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="rectangle">
<solid
android:color="#ffffff" />
<corners
android:radius="10dp" />
<stroke
android:width="2dp"
android:color="#3bbdfa" />
</shape>
</item>
in Custom Renderer
using Android.Support.V4.Content.Res;
using App11;
using App11.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyAndriodEntry))]
namespace App11.Droid
{
public class MyAndriodEntry:EntryRenderer
{
public MyAndriodEntry(Context context):base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.SetBackground(ResourcesCompat.GetDrawable(Resources, Resource.Drawable.edit_text_style, null) );
}
}
}
}
in UWP
create a folder named Styles and add a new item as type Resource Dictionary and name it Dictionary1.xaml
in Dictionary1.xaml put this code for a rounded Textbox .
in Custom Renderer
using App11;
using App11.UWP;
using Windows.UI.Xaml.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyUWPEntry))]
namespace App11.UWP
{
public class MyUWPEntry:EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.Style = (Windows.UI.Xaml.Style)App11.UWP.App.Current.Resources["StyleRoundedTextBox"];
}
}
}
}
how do I changed this style and how do I create this code ?
It's simple , in msdn.com search for "objectName" default style in uwp then you will find default style for the object you need . change it in the way you want and add it to application resources directly or link it (like what I did here) then load your style in CustomRenderer
for more detail about UWP yo can refer here
in Forms
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace App11
{
public class MyEntry : Entry
{
public MyEntry()
{
}
}
}
in xxx.cs file
Content = new StackLayout
{
Children = {
new MyEntry {Text = "In Shared Code",}
},
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
For Windows app you can customize an entry using a renderer.
public class CustomEntryRenderer : ViewRenderer<CustomEntry, TextBox>
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomEntry> e)
{
base.OnElementChanged(e);
var textBox = new TextBox();
textBox.BorderThickness = new Windows.UI.Xaml.Thickness(1);
textBox.BorderBrush = new SolidColorBrush(GetSolidColorBrush("#444444").Color);
textBox.CornerRadius = new Windows.UI.Xaml.CornerRadius(10);
this.SetNativeControl(textBox);
}
public SolidColorBrush GetSolidColorBrush(string hex)
{
hex = hex.Replace("#", string.Empty);
byte r = (byte)(Convert.ToUInt32(hex.Substring(0, 2), 16));
byte g = (byte)(Convert.ToUInt32(hex.Substring(2, 2), 16));
byte b = (byte)(Convert.ToUInt32(hex.Substring(4, 2), 16));
SolidColorBrush myBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, r, g, b));
return myBrush;
}
}
Holy shmoley it's not that hard.
Unless I'm missing something, just wrap it in a Frame that has IsClippedToBounds set to true and then put a corner radius on the frame.
Maybe there's some reason that's not a good solution, I guess, but it's one I use a lot.

Custom Layout under Editor / Entry

I have an Entry/Editor in Xamarin.Forms, and I want a layout to appear underneath it, as long as it is focused.
The layout consists of a Grid with multiple Buttons in it.
I have added the Grid underneath the Editor in my Layout and toggle its visibility based on the IsFocused property of the Editor.
Sadly, when I press one of the Grids buttons, the Editor loses focus and thus the Layout will go invisibile.
EDIT:
Another very important point is, that the Grid can overlap other controls, currently this is happening, since im adding both the Editor and the Grid into another Grid as the last children.
I might have to workaround this as well, maybe just put this Grid into an android relative layout and add this layout to the native EditText?
I want it to remain visible after clicking one of the buttons. How should I approach this scenario?
I would write EditorRenderer for each platform and there add all buttons, it should fix Focus problem (as you never lost focus :))
Implementation example:
using System;
using Xamarin.Forms;
namespace Common
{
public class CustomEditor : Editor
{
public Action<string> ButtonXCallback { get; set; }
}
}
IOS:
using Common.iOS;
using Common;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof (CustomEditor), typeof (CustomEditorRenderer))]
namespace Common.iOS
{
public class CustomEditorRenderer : EditorRenderer
{
private UIButton ButtonX { get; set; }
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
var element = Element as CustomEditor;
if (Control != null && element != null)
{
if (ButtonX == null)
{
ButtonX = new UIButton();
ButtonX.SetImage(UIImage.FromBundle("ico_x.png"), UIControlState.Normal);
ButtonX.TouchUpInside += (sender, f) => {
var text = Control.Text;
if (element.ButtonXCallback != null)
element.ButtonXCallback.Invoke(text);
};
Control.AddSubview(ButtonX);
}
}
}
}
}
Droid:
using System;
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Graphics.Drawables.Shapes;
using Common.Droid;
using Common;
using Android.Text;
using Android.Widget;
using Android.Runtime;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Views;
[assembly: ExportRenderer(typeof (CustomEditor), typeof (CustomEditorRenderer))]
namespace Common.Droid
{
public class CustomEditorRenderer : EditorRenderer
{
private ImageButton ButtonX { get; set; }
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
if (Control == null)
return;
if (Element == null)
return;
var element = (CustomEditor) Element;
if (element == null)
return;
if (ButtonX == null)
{
ButtonX = new ImageButton(Context);
ButtonX.SetImageResource(Resource.Drawable.ico_x);
ButtonX.SetBackgroundColor(Android.Graphics.Color.Transparent);
ButtonX.Click += (sender, f) =>
{
var text = Control.Text;
if (element.ButtonXCallback != null)
element.ButtonXCallback.Invoke(text);
};
AddView(ButtonX);
}
}
}
}

Resources