Reputation: 2273
I am developing a cross-platform app using PCL Xamarin Forms Project. My app will run on ios, android, windows 10 and windows 8.1 desktops.
I want to make a custom renderer for button control in xamarin forms in which I can specify following properties from xaml page and from code behind also-
I have tried the normal button control of xamarin forms but in that border radius does not work in android and on hover button color changes in windows 10. So how can I achieve this?
Upvotes: 1
Views: 4165
Reputation: 10226
- Create a style in Content Page resource and and add this style in button.
- CornerRadius is must be half of HeightRequest and WidthRequest.
- This is for Xamarin.Forms >= 3.4. Now BorderRadius convert into CornerRadius.
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="myRoundbutton" TargetType="Button">
<Setter Property="BackgroundColor" Value="Green"/>
<Setter Property="TextColor" Value="White" />
<Setter Property="BorderColor" Value="Blue"/>
<Setter Property="CornerRadius" Value="35"/>
<Setter Property="HeightRequest" Value="70" />
<Setter Property="WidthRequest" Value="70"/>
<Setter Property="BorderWidth" Value="2"/>
<Setter Property="FontAttributes" Value="Bold" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout HorizontalOptions="Fill"
VerticalOptions="Fill">
<Button Image="myBtn3.png"
Command="{Binding LoginCommand}"
Style="{DynamicResource myRoundbutton}" />
</StackLayout>
</ContentPage.Content>
Upvotes: 0
Reputation: 736
In Android the RadiusProperty
stops working only with AppCompat
its a known issue
If you want to use a normal button and AppCompat at the same time you will need to inherit from Button and register a CustomRenderer
.
[assembly: ExportRenderer(typeof(RoundButton), typeof(RoundButtonRenderer))]
namespace Project.Droid.Renderers
{
public class RoundButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
ButtonDrawable _backgroundDrawable;
Drawable _defaultDrawable;
bool _drawableEnabled;
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_backgroundDrawable != null)
{
_backgroundDrawable.Dispose();
_backgroundDrawable = null;
}
}
base.Dispose(disposing);
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);
if (e.OldElement != null && _drawableEnabled)
{
_drawableEnabled = false;
_backgroundDrawable.Reset();
_backgroundDrawable = null;
}
UpdateDrawable();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_drawableEnabled &&
(e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName || e.PropertyName == Xamarin.Forms.Button.BorderColorProperty.PropertyName || e.PropertyName == Xamarin.Forms.Button.BorderRadiusProperty.PropertyName ||
e.PropertyName == Xamarin.Forms.Button.BorderWidthProperty.PropertyName))
{
_backgroundDrawable.Reset();
Control.Invalidate();
}
base.OnElementPropertyChanged(sender, e);
}
private void UpdateDrawable()
{
if (Element.BackgroundColor == Color.Default)
{
if (!_drawableEnabled)
return;
if (_defaultDrawable != null)
Control.SetBackground(_defaultDrawable);
_drawableEnabled = false;
}
else
{
if (_backgroundDrawable == null)
_backgroundDrawable = new ButtonDrawable();
_backgroundDrawable.Button = Element;
if (_drawableEnabled)
return;
if (_defaultDrawable == null)
_defaultDrawable = Control.Background;
Control.SetBackground(_backgroundDrawable.GetDrawable());
_drawableEnabled = true;
}
Control.Invalidate();
}
}
public class ButtonDrawable : IDisposable
{
object _backgroundDrawable;
PropertyInfo ButtonProperty;
public Xamarin.Forms.Button Button
{
get
{
return (Xamarin.Forms.Button)ButtonProperty.GetMethod.Invoke(_backgroundDrawable, null);
}
set
{
ButtonProperty.SetMethod.Invoke(_backgroundDrawable, new object[] { value });
}
}
public ButtonDrawable()
{
_backgroundDrawable = typeof(Xamarin.Forms.Platform.Android.ButtonRenderer).Assembly.CreateInstance("Xamarin.Forms.Platform.Android.ButtonDrawable");
this.ResetMethod = _backgroundDrawable.GetType().GetMethod("Reset", BindingFlags.Instance | BindingFlags.Public);
this.DisposeMethod = _backgroundDrawable.GetType().GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public);
this.ButtonProperty = _backgroundDrawable.GetType().GetProperty("Button", BindingFlags.Instance | BindingFlags.Public);
}
MethodInfo ResetMethod;
public void Reset()
{
ResetMethod.Invoke(_backgroundDrawable, null);
}
MethodInfo DisposeMethod;
public void Dispose()
{
DisposeMethod.Invoke(_backgroundDrawable, null);
}
public Android.Graphics.Drawables.Drawable GetDrawable()
{
return _backgroundDrawable as Android.Graphics.Drawables.Drawable;
}
}
}
if you want to remove AppCompat you must do two things
Your MainActivity
must inherit now from global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
and your style usually in resources/values/styles.xml
must inherit from a non-AppCompat style like android:Theme.Material
<resources>
<!-- inherit from the material theme -->
<style name="AppTheme" parent="android:Theme.Material">
<!-- Main theme colors -->
<!-- your app branding color for the app bar -->
<item name="android:colorPrimary">@color/primary</item>
<!-- darker variant for the status bar and contextual app bars -->
<item name="android:colorPrimaryDark">@color/primary_dark</item>
<!-- theme UI controls like checkboxes and text fields -->
<item name="android:colorAccent">@color/accent</item>
</style>
</resources>
Upvotes: 1
Reputation: 121
I using these properties on my app and for me works fine. I am using these properties with "Styles".
Example:
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="BackgroundColor" Value="{DynamicResource Snow}"/>
<Setter Property="TextColor" Value="{DynamicResource LightBlue}" />
<Setter Property="BorderColor" Value="{DynamicResource LightBlue}"/>
<Setter Property="BorderRadius" Value="15"/>
<Setter Property="BorderWidth" Value="1"/>
<Setter Property="FontAttributes" Value="Bold" />
</Style>
My Button:
<Button Text="Login" Command="{Binding LoginCommand}" Style="{DynamicResource buttonStyle}" />
Upvotes: 1