Add pressed and released events to Button (#446)
authorKangho <rookiejava+github@gmail.com>
Thu, 2 Feb 2017 18:23:31 +0000 (03:23 +0900)
committerKangho Hur <kangho.hur@samsung.com>
Fri, 24 Mar 2017 04:18:57 +0000 (13:18 +0900)
* Add pressed and released events to Button

* Update ButtonRenderer.cs

* Apply safely casting to android button renderer

* Use safety casting for Android buttin renderer

* [Windows] Fix modal pages being laid out below soft buttons (#395)

* Add sample HanselForms and TwitterDemo to ControlGallery (#651)

* [Controls] Add Hanselforms sample

* Remove extra twitter sample

* [Controls]Add TwitterDemo sample

* [Controls] Fix build

* Slider should show user-set value on initial load (#378)

* [UWP] Use toolbar foreground color on primary items (#640)

* Avoid duplicating code in OmPlatform (#591)

* [iOS] Entry should not pass a newline to the next responder (#397)

* UITextField should not return so that the next field does not get passed a newline

* Added code sample

* [XamlC] import members on x:Static and factories (#642)

* [Xaml] support short Properties for PropertyCondition (#645)

* Xamlc compile data triggers (#648)

* [Xaml] DataTrigger and PropertyCondition no longer use a ServiceProvider

* [XamlC] avoid generating ServiceProvider for unused ProvideValue

* fix tests

* Fix comment typo

* [UWP] Fix TextBox style for foreground focus color (#618)

* Adding image to use for CellsGalleryImageUrlCellList UI test

* Update ImageCellListPage to use an image we control;
Update CellsGalleryImageUrlCellList test to wait longer than 1s for images
to load if necessary

* fix nre when changing content in datepickerselected (#494)

* Make CellsGalleryImageUrlCellList test finish early if possible

* [iOS] Change keyboard type while keyboard is visible (#443)

* Change keyboard while changing text

* add sample code

* [Android] Fix NavigationPage dispose crash when it parents a MasterDetailPage (#577)

* fix navigation page dispose crash

* changes after review

* [XamlC] detect duplicate x:Name at compile time (#655)

* [XamlC] detect duplicate x:Name at compile time

* invoking methods with the right arguments produces better results

* Make UWP toolbar display rules consistent with other platforms (#638)

* Allow subscriber to be collected if MessagingCenter is the only reference to it (#617)

* Repro

* Make messaging center callbacks weak references

* Preserve attribute

* Fix test method name

* Watch for collection of actual delegate target instead of wrapper delegate

* Preserve the original platform instance when changing main page

* Better tests for lambda situations

* Update tests, make callback target a weakreference if it's the subscriber

* Ensure old Platform MessagingCenter subs are gone before creating new Platform

* [iOS] Prevent multiple ListView cells from being swiped simultaneously (#578)

* disable multiple cell swipe

* add sample code

* refactored

* convert to weakreference

* remove null setting

* change weakreference setting place

* remove if

* revert isopen changes

* add instructions

* [WinRT/UWP] Apply BackgroundColor to Stepper buttons (#581)

* [WinRT/UWP] Apply BackgroundColor to Stepper buttons

* Add explanatory text; use nameof

* Move explanatory text to a label

* Return group instead of internal class (#461)

* [iOS/Android] Move Map camera to correct region on layout change (#548)

* Move to region on layout change

* remove visibility check

* [iOS] Platform specifics for controlling Picker SelectedIndex change behavior (#540)

* picker selected index could change when picker view is dismissed

* use enum

* [iOS] Ignore intermittent failing test on XTC (#666)

* [UITest] Update to UITest 2.0.5 (#665)

* Rebase the current branch onto upstream latest

Xamarin.Forms.Core.UnitTests/ButtonUnitTest.cs
Xamarin.Forms.Core/Button.cs
Xamarin.Forms.Core/IButtonController.cs
Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs
Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs
Xamarin.Forms.Platform.WP8/ButtonRenderer.cs
Xamarin.Forms.Platform.WinRT/ButtonRenderer.cs
Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs
docs/Xamarin.Forms.Core/Xamarin.Forms/Button.xml
docs/Xamarin.Forms.Core/Xamarin.Forms/IButtonController.xml

index d590f8c..eef9dfc 100644 (file)
@@ -35,7 +35,7 @@ namespace Xamarin.Forms.Core.UnitTests
                }
 
                [Test]
-               public void TestTappedEvent ()
+               public void TestClickedvent ()
                {
                        var view = new Button ();
 
@@ -47,6 +47,32 @@ namespace Xamarin.Forms.Core.UnitTests
                        Assert.True (activated);
                }
 
+               [Test]
+               public void TestPressedEvent ()
+               {
+                       var view = new Button();
+
+                       bool pressed = false;
+                       view.Pressed += (sender, e) => pressed = true;
+
+                       ((IButtonController)view).SendPressed();
+
+                       Assert.True(pressed);
+               }
+
+               [Test]
+               public void TestReleasedEvent ()
+               {
+                       var view = new Button();
+
+                       bool released = false;
+                       view.Released += (sender, e) => released = true;
+
+                       ((IButtonController)view).SendReleased();
+
+                       Assert.True(released);
+               }
+
                protected override Button CreateSource()
                {
                        return new Button();
index 97d774c..bcd593e 100644 (file)
@@ -116,13 +116,18 @@ namespace Xamarin.Forms
 
                void IButtonController.SendClicked()
                {
-                       ICommand cmd = Command;
-                       if (cmd != null)
-                               cmd.Execute(CommandParameter);
+                       Command?.Execute(CommandParameter);
+                       Clicked?.Invoke(this, EventArgs.Empty);
+               }
 
-                       EventHandler handler = Clicked;
-                       if (handler != null)
-                               handler(this, EventArgs.Empty);
+               void IButtonController.SendPressed()
+               {
+                       Pressed?.Invoke(this, EventArgs.Empty);
+               }
+
+               void IButtonController.SendReleased()
+               {
+                       Released?.Invoke(this, EventArgs.Empty);
                }
 
                public FontAttributes FontAttributes
@@ -146,6 +151,10 @@ namespace Xamarin.Forms
 
                public event EventHandler Clicked;
 
+               public event EventHandler Pressed;
+
+               public event EventHandler Released;
+
                public Button()
                {
                        _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<Button>>(() => new PlatformConfigurationRegistry<Button>(this));
index c88907b..b7e3bc4 100644 (file)
@@ -3,5 +3,7 @@ namespace Xamarin.Forms
        public interface IButtonController : IViewController
        {
                void SendClicked();
+               void SendPressed();
+               void SendReleased();
        }
 }
\ No newline at end of file
index 4c33df8..aef56e1 100644 (file)
@@ -9,11 +9,14 @@ using Android.Support.V7.Widget;
 using Android.Util;
 using GlobalResource = Android.Resource;
 using Object = Java.Lang.Object;
+using AView = Android.Views.View;
+using AMotionEvent = Android.Views.MotionEvent;
+using AMotionEventActions = Android.Views.MotionEventActions;
 using static System.String;
 
 namespace Xamarin.Forms.Platform.Android.AppCompat
 {
-       public class ButtonRenderer : ViewRenderer<Button, AppCompatButton>, global::Android.Views.View.IOnAttachStateChangeListener
+       public class ButtonRenderer : ViewRenderer<Button, AppCompatButton>, AView.IOnAttachStateChangeListener
        {
                TextColorSwitcher _textColorSwitcher;
                float _defaultFontSize;
@@ -28,12 +31,12 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
 
                global::Android.Widget.Button NativeButton => Control;
 
-               void IOnAttachStateChangeListener.OnViewAttachedToWindow(global::Android.Views.View attachedView)
+               void IOnAttachStateChangeListener.OnViewAttachedToWindow(AView attachedView)
                {
                        UpdateText();
                }
 
-               void IOnAttachStateChangeListener.OnViewDetachedFromWindow(global::Android.Views.View detachedView)
+               void IOnAttachStateChangeListener.OnViewDetachedFromWindow(AView detachedView)
                {
                }
 
@@ -74,6 +77,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
                                if (Control != null)
                                {
                                        Control.SetOnClickListener(null);
+                                       Control.SetOnTouchListener(null);
                                        Control.RemoveOnAttachStateChangeListener(this);
                                        Control.Tag = null;
                                        _textColorSwitcher = null;
@@ -98,6 +102,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
                                        AppCompatButton button = CreateNativeControl();
 
                                        button.SetOnClickListener(ButtonClickListener.Instance.Value);
+                                       button.SetOnTouchListener(ButtonTouchListener.Instance.Value);
                                        button.Tag = this;
                                        _textColorSwitcher = new TextColorSwitcher(button.TextColors);  
                                        SetNativeControl(button);
@@ -292,11 +297,34 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
 
                        #endregion
 
-                       public void OnClick(global::Android.Views.View v)
+                       public void OnClick(AView v)
                        {
                                var renderer = v.Tag as ButtonRenderer;
                                ((IButtonController)renderer?.Element)?.SendClicked();
                        }
                }
+
+               class ButtonTouchListener : Object, IOnTouchListener
+               {
+                       public static readonly Lazy<ButtonTouchListener> Instance = new Lazy<ButtonTouchListener>(() => new ButtonTouchListener());
+
+                       public bool OnTouch(AView v, AMotionEvent e)
+                       {
+                               var renderer = v.Tag as ButtonRenderer;
+                               if (renderer != null)
+                               {
+                                       var buttonController = renderer.Element as IButtonController;
+                                       if (e.Action == AMotionEventActions.Down)
+                                       {
+                                               buttonController?.SendPressed();
+                                       }
+                                       else if (e.Action == AMotionEventActions.Up)
+                                       {
+                                               buttonController?.SendReleased();
+                                       }
+                               }
+                               return false;
+                       }
+               }
        }
-}
\ No newline at end of file
+}
index 4f384b3..e07a2be 100644 (file)
@@ -7,6 +7,8 @@ using Android.Util;
 using static System.String;
 using AButton = Android.Widget.Button;
 using AView = Android.Views.View;
+using AMotionEvent = Android.Views.MotionEvent;
+using AMotionEventActions = Android.Views.MotionEventActions;
 using Object = Java.Lang.Object;
 
 namespace Xamarin.Forms.Platform.Android
@@ -96,6 +98,7 @@ namespace Xamarin.Forms.Platform.Android
                                {
                                        button = CreateNativeControl();
                                        button.SetOnClickListener(ButtonClickListener.Instance.Value);
+                                       button.SetOnTouchListener(ButtonTouchListener.Instance.Value);
                                        button.Tag = this;
                                        SetNativeControl(button);
                                        _textColorSwitcher = new TextColorSwitcher(button.TextColors);
@@ -303,5 +306,28 @@ namespace Xamarin.Forms.Platform.Android
                                        ((IButtonController)renderer.Element).SendClicked();
                        }
                }
+
+               class ButtonTouchListener : Object, IOnTouchListener
+               {
+                       public static readonly Lazy<ButtonTouchListener> Instance = new Lazy<ButtonTouchListener>(() => new ButtonTouchListener());
+
+                       public bool OnTouch(AView v, AMotionEvent e)
+                       {
+                               var renderer = v.Tag as ButtonRenderer;
+                               if (renderer != null)
+                               {
+                                       var buttonController = renderer.Element as IButtonController;
+                                       if (e.Action == AMotionEventActions.Down)
+                                       {
+                                               buttonController?.SendPressed();
+                                       }
+                                       else if (e.Action == AMotionEventActions.Up)
+                                       {
+                                               buttonController?.SendReleased();
+                                       }
+                               }
+                               return false;
+                       }
+               }
        }
 }
\ No newline at end of file
index a84a3db..e44d244 100644 (file)
@@ -2,6 +2,7 @@
 using System.ComponentModel;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using Xamarin.Forms.Internals;
@@ -20,7 +21,9 @@ namespace Xamarin.Forms.Platform.WinPhone
                        base.OnElementChanged(e);
 
                        var button = new WButton();
+                       button.ClickMode = ClickMode.Press;
                        button.Click += HandleButtonClick;
+                       button.AddHandler(UIElement.TapEvent, new EventHandler<GestureEventArgs>(HandleButtonTap), true);
                        SetNativeControl(button);
 
                        UpdateContent();
@@ -60,9 +63,13 @@ namespace Xamarin.Forms.Platform.WinPhone
 
                void HandleButtonClick(object sender, RoutedEventArgs e)
                {
-                       Button buttonView = Element;
-                       if (buttonView != null)
-                               ((IButtonController)buttonView).SendClicked();
+                       ((IButtonController)Element)?.SendPressed();
+               }
+
+               void HandleButtonTap(object sender, GestureEventArgs e)
+               {
+                       ((IButtonController)Element)?.SendReleased();
+                       ((IButtonController)Element)?.SendClicked();
                }
 
                void UpdateBackground()
index aff1196..acc41db 100644 (file)
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.ComponentModel;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
@@ -8,6 +8,7 @@ using Xamarin.Forms.Internals;
 using WThickness = Windows.UI.Xaml.Thickness;
 using WButton = Windows.UI.Xaml.Controls.Button;
 using WImage = Windows.UI.Xaml.Controls.Image;
+using Windows.UI.Xaml.Input;
 
 #if WINDOWS_UWP
 
@@ -31,6 +32,7 @@ namespace Xamarin.Forms.Platform.WinRT
                                {
                                        var button = new FormsButton();
                                        button.Click += OnButtonClick;
+                                       button.AddHandler(PointerPressedEvent, new PointerEventHandler(OnPointerPressed), true);
                                        SetNativeControl(button);
                                }
 
@@ -99,12 +101,16 @@ namespace Xamarin.Forms.Platform.WinRT
 
                void OnButtonClick(object sender, RoutedEventArgs e)
                {
-                       Button buttonView = Element;
-                       if (buttonView != null)
-                               ((IButtonController)buttonView).SendClicked();
+                       ((IButtonController)Element)?.SendReleased();
+                       ((IButtonController)Element)?.SendClicked();
                }
 
-               void UpdateBackground()
+               void OnPointerPressed(object sender, RoutedEventArgs e)
+               {
+                       ((IButtonController)Element)?.SendPressed();
+               }
+
+                       void UpdateBackground()
                {
                        Control.BackgroundColor = Element.BackgroundColor != Color.Default ? Element.BackgroundColor.ToBrush() : (Brush)Windows.UI.Xaml.Application.Current.Resources["ButtonBackgroundThemeBrush"];
                }
index 3e99cd5..5eb9b77 100644 (file)
@@ -38,7 +38,10 @@ namespace Xamarin.Forms.Platform.iOS
                protected override void Dispose(bool disposing)
                {
                        if (Control != null)
+                       {
                                Control.TouchUpInside -= OnButtonTouchUpInside;
+                               Control.TouchDown -= OnButtonTouchDown;
+                       }
 
                        base.Dispose(disposing);
                }
@@ -60,6 +63,7 @@ namespace Xamarin.Forms.Platform.iOS
                                        _buttonTextColorDefaultDisabled = Control.TitleColor(UIControlState.Disabled);
 
                                        Control.TouchUpInside += OnButtonTouchUpInside;
+                                       Control.TouchDown += OnButtonTouchDown;
                                }
 
                                UpdateText();
@@ -103,9 +107,15 @@ namespace Xamarin.Forms.Platform.iOS
 
                void OnButtonTouchUpInside(object sender, EventArgs eventArgs)
                {
+                       ((IButtonController)Element)?.SendReleased();
                        ((IButtonController)Element)?.SendClicked();
                }
 
+               void OnButtonTouchDown(object sender, EventArgs eventArgs)
+               {
+                       ((IButtonController)Element)?.SendPressed();
+               }
+
                void UpdateBorder()
                {
                        var uiButton = Control;
index ba24341..3df8f8f 100644 (file)
@@ -1,6 +1,6 @@
 <Type Name="Button" FullName="Xamarin.Forms.Button">
-  <TypeSignature Language="C#" Value="public class Button : Xamarin.Forms.View, Xamarin.Forms.IButtonController, Xamarin.Forms.IElementConfiguration&lt;Xamarin.Forms.Button&gt;" />
-  <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Button extends Xamarin.Forms.View implements class Xamarin.Forms.IButtonController, class Xamarin.Forms.IElementConfiguration`1&lt;class Xamarin.Forms.Button&gt;, class Xamarin.Forms.IElementController, class Xamarin.Forms.IViewController, class Xamarin.Forms.IVisualElementController" />
+  <TypeSignature Language="C#" Value="public class Button : Xamarin.Forms.View, Xamarin.Forms.IButtonController, Xamarin.Forms.IElementConfiguration&lt;Xamarin.Forms.Button&gt;, Xamarin.Forms.IFontElement" />
+  <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Button extends Xamarin.Forms.View implements class Xamarin.Forms.IButtonController, class Xamarin.Forms.IElementConfiguration`1&lt;class Xamarin.Forms.Button&gt;, class Xamarin.Forms.IElementController, class Xamarin.Forms.IFontElement, class Xamarin.Forms.IViewController, class Xamarin.Forms.IVisualElementController" />
   <AssemblyInfo>
     <AssemblyName>Xamarin.Forms.Core</AssemblyName>
     <AssemblyVersion>1.0.0.0</AssemblyVersion>
@@ -21,6 +21,9 @@
     <Interface>
       <InterfaceName>Xamarin.Forms.IElementConfiguration&lt;Xamarin.Forms.Button&gt;</InterfaceName>
     </Interface>
+    <Interface>
+      <InterfaceName>Xamarin.Forms.IFontElement</InterfaceName>
+    </Interface>
   </Interfaces>
   <Attributes>
     <Attribute>
@@ -669,6 +672,37 @@ namespace FormsGallery
         <remarks>A Button triggers this by itself. An inheritor only need to call this for properties without BindableProperty as backend store.</remarks>
       </Docs>
     </Member>
+    <Member MemberName="Pressed">
+      <MemberSignature Language="C#" Value="public event EventHandler Pressed;" />
+      <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Pressed" />
+      <MemberType>Event</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.EventHandler</ReturnType>
+      </ReturnValue>
+      <Docs>
+        <summary>Occurs when the Button is pressed.</summary>
+        <remarks>
+        </remarks>
+      </Docs>
+    </Member>
+    <Member MemberName="Released">
+      <MemberSignature Language="C#" Value="public event EventHandler Released;" />
+      <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Released" />
+      <MemberType>Event</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.EventHandler</ReturnType>
+      </ReturnValue>
+      <Docs>
+        <summary>Occurs when the Button is released.</summary>
+        <remarks>The released event always occur before the clicked event.</remarks>
+      </Docs>
+    </Member>
     <Member MemberName="Text">
       <MemberSignature Language="C#" Value="public string Text { get; set; }" />
       <MemberSignature Language="ILAsm" Value=".property instance string Text" />
@@ -777,5 +811,37 @@ namespace FormsGallery
         <remarks>To be added.</remarks>
       </Docs>
     </Member>
+    <Member MemberName="Xamarin.Forms.IButtonController.SendPressed">
+      <MemberSignature Language="C#" Value="void IButtonController.SendPressed ();" />
+      <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IButtonController.SendPressed() cil managed" />
+      <MemberType>Method</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.Void</ReturnType>
+      </ReturnValue>
+      <Parameters />
+      <Docs>
+        <summary>Sends a press event.</summary>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
+    <Member MemberName="Xamarin.Forms.IButtonController.SendReleased">
+      <MemberSignature Language="C#" Value="void IButtonController.SendReleased ();" />
+      <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IButtonController.SendReleased() cil managed" />
+      <MemberType>Method</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.Void</ReturnType>
+      </ReturnValue>
+      <Parameters />
+      <Docs>
+        <summary>Sends a release event.</summary>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
   </Members>
 </Type>
index 2b66481..6e4e1c2 100644 (file)
         <remarks>To be added.</remarks>
       </Docs>
     </Member>
+    <Member MemberName="SendPressed">
+      <MemberSignature Language="C#" Value="public void SendPressed ();" />
+      <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SendPressed() cil managed" />
+      <MemberType>Method</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.Void</ReturnType>
+      </ReturnValue>
+      <Parameters />
+      <Docs>
+        <summary>To be added.</summary>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
+    <Member MemberName="SendReleased">
+      <MemberSignature Language="C#" Value="public void SendReleased ();" />
+      <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SendReleased() cil managed" />
+      <MemberType>Method</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.Void</ReturnType>
+      </ReturnValue>
+      <Parameters />
+      <Docs>
+        <summary>To be added.</summary>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
   </Members>
 </Type>