From aa9bca1341d4233a0fb3428968d31531c371d834 Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Thu, 1 Jun 2017 11:27:12 +0100 Subject: [PATCH] Fix border on android buttons (#941) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * [Android] Add a button background tracker to handle background and border properties and be shared between button renderers * [Android]Fix border radius dependency * [Android] Make sure we always create or updated the background button tracker --- .../AppCompat/ButtonRenderer.cs | 61 ++++------ .../ButtonBackgroundTracker.cs | 125 +++++++++++++++++++++ .../FastRenderers/ButtonRenderer.cs | 79 ++++--------- .../Properties/AssemblyInfo.cs | 1 - .../Renderers/ButtonDrawable.cs | 3 +- .../Renderers/ButtonRenderer.cs | 64 ++--------- .../Xamarin.Forms.Platform.Android.csproj | 1 + 7 files changed, 176 insertions(+), 158 deletions(-) create mode 100644 Xamarin.Forms.Platform.Android/ButtonBackgroundTracker.cs diff --git a/Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs index 394f332..81357fa 100644 --- a/Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs +++ b/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; @@ -19,6 +14,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat { public class ButtonRenderer : ViewRenderer, AView.IOnAttachStateChangeListener { + ButtonBackgroundTracker _backgroundTracker; TextColorSwitcher _textColorSwitcher; float _defaultFontSize; Typeface _defaultTypeface; @@ -27,6 +23,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat public ButtonRenderer() { + System.Diagnostics.Debug.WriteLine("Slow Button!"); AutoPackage = false; } @@ -83,6 +80,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat Control.Tag = null; _textColorSwitcher = null; } + _backgroundTracker?.Dispose(); } base.Dispose(disposing); @@ -111,8 +109,12 @@ namespace Xamarin.Forms.Platform.Android.AppCompat button.AddOnAttachStateChangeListener(this); } + if (_backgroundTracker == null) + _backgroundTracker = new ButtonBackgroundTracker(Element, Control); + else + _backgroundTracker.Button = e.NewElement; + UpdateAll(); - UpdateBackgroundColor(); } } @@ -139,42 +141,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat 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() @@ -184,6 +151,16 @@ namespace Xamarin.Forms.Platform.Android.AppCompat UpdateBitmap(); UpdateTextColor(); UpdateEnabled(); + UpdateBackgroundColor(); + UpdateDrawable(); + } + + void UpdateDrawable() + { + if (Element == null || Control == null) + return; + + _backgroundTracker?.UpdateDrawable(); } void UpdateBitmap() diff --git a/Xamarin.Forms.Platform.Android/ButtonBackgroundTracker.cs b/Xamarin.Forms.Platform.Android/ButtonBackgroundTracker.cs new file mode 100644 index 0000000..e8b9b49 --- /dev/null +++ b/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(); + } + } + + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/FastRenderers/ButtonRenderer.cs b/Xamarin.Forms.Platform.Android/FastRenderers/ButtonRenderer.cs index 3c08f4b..3248a5f 100644 --- a/Xamarin.Forms.Platform.Android/FastRenderers/ButtonRenderer.cs +++ b/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 { @@ -30,6 +26,7 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers readonly AutomationPropertiesProvider _automationPropertiesProvider; readonly EffectControlProvider _effectControlProvider; VisualElementTracker _tracker; + ButtonBackgroundTracker _backgroundTracker; public event EventHandler ElementChanged; public event EventHandler ElementPropertyChanged; @@ -124,6 +121,11 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers 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) { @@ -182,6 +184,8 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers _automationPropertiesProvider?.Dispose(); _tracker?.Dispose(); + _backgroundTracker?.Dispose(); + if (Element != null) { Element.PropertyChanged -= OnElementPropertyChanged; @@ -206,11 +210,14 @@ namespace Xamarin.Forms.Platform.Android.FastRenderers protected virtual void OnElementChanged(ElementChangedEventArgs