Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Fix border on android buttons #941

Merged
merged 3 commits into from Jun 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 19 additions & 42 deletions Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs
@@ -1,14 +1,9 @@
using System;
using System.ComponentModel;
using Android.Content;
using Android.Content.Res;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Support.V4.Content;
using Android.Support.V7.Widget;
using Android.Util;
using Xamarin.Forms.Internals;
using GlobalResource = Android.Resource;
using Object = Java.Lang.Object;
using AView = Android.Views.View;
using AMotionEvent = Android.Views.MotionEvent;
Expand All @@ -19,6 +14,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
{
public class ButtonRenderer : ViewRenderer<Button, AppCompatButton>, AView.IOnAttachStateChangeListener
{
ButtonBackgroundTracker _backgroundTracker;
TextColorSwitcher _textColorSwitcher;
float _defaultFontSize;
Typeface _defaultTypeface;
Expand All @@ -27,6 +23,7 @@ public class ButtonRenderer : ViewRenderer<Button, AppCompatButton>, AView.IOnAt

public ButtonRenderer()
{
System.Diagnostics.Debug.WriteLine("Slow Button!");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something we also added on non app compact button so users select fast renderers, should we remove it @ez ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that should have been removed a while ago.

AutoPackage = false;
}

Expand Down Expand Up @@ -83,6 +80,7 @@ protected override void Dispose(bool disposing)
Control.Tag = null;
_textColorSwitcher = null;
}
_backgroundTracker?.Dispose();
}

base.Dispose(disposing);
Expand Down Expand Up @@ -111,8 +109,12 @@ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
button.AddOnAttachStateChangeListener(this);
}

if (_backgroundTracker == null)
_backgroundTracker = new ButtonBackgroundTracker(Element, Control);
else
_backgroundTracker.Button = e.NewElement;

UpdateAll();
UpdateBackgroundColor();
}
}

Expand All @@ -139,42 +141,7 @@ protected override void UpdateBackgroundColor()
if (Element == null || Control == null)
return;

Color backgroundColor = Element.BackgroundColor;
if (backgroundColor.IsDefault)
{
if (Control.SupportBackgroundTintList != null)
{
Context context = Context;
int id = GlobalResource.Attribute.ButtonTint;
unchecked
{
using (var value = new TypedValue())
{
try
{
Resources.Theme theme = context.Theme;
if (theme != null && theme.ResolveAttribute(id, value, true))
#pragma warning disable 618
Control.SupportBackgroundTintList = Resources.GetColorStateList(value.Data);
#pragma warning restore 618
else
Control.SupportBackgroundTintList = new ColorStateList(ColorExtensions.States, new[] { (int)0xffd7d6d6, 0x7fd7d6d6 });
}
catch (Exception ex)
{
Internals.Log.Warning("Xamarin.Forms.Platform.Android.ButtonRenderer", "Could not retrieve button background resource: {0}", ex);
Control.SupportBackgroundTintList = new ColorStateList(ColorExtensions.States, new[] { (int)0xffd7d6d6, 0x7fd7d6d6 });
}
}
}
}
}
else
{
int intColor = backgroundColor.ToAndroid().ToArgb();
int disableColor = backgroundColor.MultiplyAlpha(0.5).ToAndroid().ToArgb();
Control.SupportBackgroundTintList = new ColorStateList(ColorExtensions.States, new[] { intColor, disableColor });
}
_backgroundTracker.UpdateBackgroundColor();
}

void UpdateAll()
Expand All @@ -184,6 +151,16 @@ void UpdateAll()
UpdateBitmap();
UpdateTextColor();
UpdateEnabled();
UpdateBackgroundColor();
UpdateDrawable();
}

void UpdateDrawable()
{
if (Element == null || Control == null)
return;

_backgroundTracker?.UpdateDrawable();
}

void UpdateBitmap()
Expand Down
125 changes: 125 additions & 0 deletions Xamarin.Forms.Platform.Android/ButtonBackgroundTracker.cs
@@ -0,0 +1,125 @@
using System;
using System.ComponentModel;
using Android.Graphics.Drawables;
using AButton = Android.Widget.Button;

namespace Xamarin.Forms.Platform.Android
{
internal class ButtonBackgroundTracker : IDisposable
{
Drawable _defaultDrawable;
ButtonDrawable _backgroundDrawable;
Button _button;
AButton _nativeButton;
bool _drawableEnabled;
bool _disposed;

public ButtonBackgroundTracker(Button button, AButton nativeButton)
{
Button = button;
_nativeButton = nativeButton;
}

public Button Button
{
get { return _button; }
set
{
if (_button == value)
return;
if (_button != null)
_button.PropertyChanged -= ButtonPropertyChanged;
_button = value;
_button.PropertyChanged += ButtonPropertyChanged;
}
}

public void UpdateDrawable()
{
if (_button.BackgroundColor == Color.Default)
{
if (!_drawableEnabled)
return;

if (_defaultDrawable != null)
_nativeButton.SetBackground(_defaultDrawable);

_drawableEnabled = false;
}
else
{
if (_backgroundDrawable == null)
_backgroundDrawable = new ButtonDrawable();

_backgroundDrawable.Button = _button;

if (_drawableEnabled)
return;

if (_defaultDrawable == null)
_defaultDrawable = _nativeButton.Background;

_nativeButton.SetBackground(_backgroundDrawable);
_drawableEnabled = true;
}

_nativeButton.Invalidate();
}

public void Reset()
{
if (_drawableEnabled)
{
_drawableEnabled = false;
_backgroundDrawable.Reset();
_backgroundDrawable = null;
}
}

public void UpdateBackgroundColor()
{
if (_button == null)
return;
UpdateDrawable();
}

public void Dispose()
{
Dispose(true);
}

protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_backgroundDrawable?.Dispose();
_backgroundDrawable = null;
_defaultDrawable?.Dispose();
_defaultDrawable = null;
if (_button != null)
{
_button.PropertyChanged -= ButtonPropertyChanged;
_button = null;
}
_nativeButton = null;
}
_disposed = true;
}
}

void ButtonPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(Button.BorderColorProperty.PropertyName) ||
e.PropertyName.Equals(Button.BorderWidthProperty.PropertyName) ||
e.PropertyName.Equals(Button.BorderRadiusProperty.PropertyName) ||
e.PropertyName.Equals(VisualElement.BackgroundColorProperty.PropertyName))
{
Reset();
UpdateDrawable();
}
}

}
}
90 changes: 27 additions & 63 deletions Xamarin.Forms.Platform.Android/FastRenderers/ButtonRenderer.cs
@@ -1,19 +1,15 @@
using System;
using System.ComponentModel;
using Android.Content;
using Android.Content.Res;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Support.V7.Widget;
using Android.Util;
using Android.Views;
using Xamarin.Forms.Internals;
using GlobalResource = Android.Resource;
using AView = Android.Views.View;
using AMotionEvent = Android.Views.MotionEvent;
using AMotionEventActions = Android.Views.MotionEventActions;
using static System.String;
using Object = Java.Lang.Object;

namespace Xamarin.Forms.Platform.Android.FastRenderers
{
Expand All @@ -30,6 +26,7 @@ public class ButtonRenderer : AppCompatButton, IVisualElementRenderer, AView.IOn
readonly AutomationPropertiesProvider _automationPropertiesProvider;
readonly EffectControlProvider _effectControlProvider;
VisualElementTracker _tracker;
ButtonBackgroundTracker _backgroundTracker;

public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
public event EventHandler<PropertyChangedEventArgs> ElementPropertyChanged;
Expand Down Expand Up @@ -124,6 +121,11 @@ void IVisualElementRenderer.SetElement(VisualElement element)
oldElement.PropertyChanged -= OnElementPropertyChanged;
}

if (_backgroundTracker == null)
_backgroundTracker = new ButtonBackgroundTracker(Button, this);
else
_backgroundTracker.Button = Button;

Color currentColor = oldElement?.BackgroundColor ?? Color.Default;
if (element.BackgroundColor != currentColor)
{
Expand Down Expand Up @@ -182,6 +184,8 @@ protected override void Dispose(bool disposing)
_automationPropertiesProvider?.Dispose();
_tracker?.Dispose();

_backgroundTracker?.Dispose();

if (Element != null)
{
Element.PropertyChanged -= OnElementPropertyChanged;
Expand All @@ -206,15 +210,20 @@ protected virtual Size MinimumSize()

protected virtual void OnElementChanged(ElementChangedEventArgs<Button> e)
{
if (e.OldElement != null)
{
_backgroundTracker?.Reset();
}
if (e.NewElement != null)
{
UpdateFont();
UpdateText();
UpdateBitmap();
UpdateTextColor();
UpdateIsEnabled();
UpdateInputTransparent();
UpdateBackgroundColor();
UpdateFont();
UpdateText();
UpdateBitmap();
UpdateTextColor();
UpdateIsEnabled();
UpdateInputTransparent();
UpdateBackgroundColor();
UpdateDrawable();
}

ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
Expand Down Expand Up @@ -249,10 +258,6 @@ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEv
else if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
{
UpdateInputTransparent();
}
else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
{
UpdateBackgroundColor();
}

ElementPropertyChanged?.Invoke(this, e);
Expand Down Expand Up @@ -284,54 +289,7 @@ protected void SetTracker(VisualElementTracker tracker)

protected void UpdateBackgroundColor()
{
if (Element == null)
{
return;
}

Color backgroundColor = Element.BackgroundColor;
if (backgroundColor.IsDefault)
{
if (SupportBackgroundTintList != null)
{
Context context = Context;
int id = GlobalResource.Attribute.ButtonTint;
unchecked
{
using (var value = new TypedValue())
{
try
{
Resources.Theme theme = context.Theme;
if (theme != null && theme.ResolveAttribute(id, value, true))
#pragma warning disable 618
{
SupportBackgroundTintList = Resources.GetColorStateList(value.Data);
}
#pragma warning restore 618
else
{
SupportBackgroundTintList = new ColorStateList(ColorExtensions.States,
new[] { (int)0xffd7d6d6, 0x7fd7d6d6 });
}
}
catch (Exception ex)
{
Internals.Log.Warning("Xamarin.Forms.Platform.Android.ButtonRenderer",
"Could not retrieve button background resource: {0}", ex);
SupportBackgroundTintList = new ColorStateList(ColorExtensions.States,
new[] { (int)0xffd7d6d6, 0x7fd7d6d6 });
}
}
}
}
}
else
{
int intColor = backgroundColor.ToAndroid().ToArgb();
int disableColor = backgroundColor.MultiplyAlpha(0.5).ToAndroid().ToArgb();
SupportBackgroundTintList = new ColorStateList(ColorExtensions.States, new[] { intColor, disableColor });
}
_backgroundTracker.UpdateBackgroundColor();
}

internal virtual void OnNativeFocusChanged(bool hasFocus)
Expand Down Expand Up @@ -487,5 +445,11 @@ void UpdateTextColor()

_textColorSwitcher.Value.UpdateTextColor(this, Button.TextColor);
}

void UpdateDrawable()
{
_backgroundTracker.UpdateDrawable();
}

}
}