2016-08-06 68 views
8

chcę do mojego przypadku, gdy przycisk do wyzwalania naciśnięty i zwolniony, ale mogę tylko znaleźć Kliknij wydarzenie w Xamarin.Forms.Xamarin.Forms - wciśnięty przycisk & Wydany Event

Uważam, że aby uzyskać tę funkcjonalność, trzeba trochę popracować. Moją podstawową potrzebą jest rozpoczęcie procesu po naciśnięciu przycisku i zatrzymanie po zwolnieniu. Wydaje się, że jest to bardzo podstawowa funkcja, ale Xamarin.Forms nie ma jej w tej chwili.

Próbowałem przycisk na przycisku, ale przycisk uruchamia tylko jedno kliknięcie.

MyButton.Clicked += (sender, args) => 
{ 
    Log.V(TAG, "CLICKED"); 
}; 

var tapGestureRecognizer = new TapGestureRecognizer(); 
tapGestureRecognizer.Tapped += (s, e) => { 
    Log.V(TAG, "TAPPED"); 
}; 
MyButton.GestureRecognizers.Add(tapGestureRecognizer); 

Należy pamiętać, że potrzebne są te zdarzenia do pracy na urządzeniach z Androidem i iOS.

+0

Trzeba by napisać renderujący niestandardowy przycisk, który odsłania leżącą u podstaw przyziemienia i Touchup zdarzenia, które tworzą maski. – Jason

+0

@jason możesz zaproponować mi dobry tutorial lub próbkę niestandardowego renderera ... ??? –

+0

https://developer.xamarin.com/guides/xamarin-forms/custom-renderer/ – Jason

Odpowiedz

17

Wreszcie dostałem rozwiązanie sugerowane przez @Jason. Zaczynamy ...

  1. Tworzenie sub klasę Xamarin.Forms.Button w projekcie PCL, z możliwością obsługi zdarzeń

    public class CustomButton : Button 
    { 
        public event EventHandler Pressed; 
        public event EventHandler Released; 
    
        public virtual void OnPressed() 
        { 
         Pressed?.Invoke(this, EventArgs.Empty); 
        } 
    
        public virtual void OnReleased() 
        { 
         Released?.Invoke(this, EventArgs.Empty); 
        } 
    } 
    
  2. Tworzenie platformy renderujący konkretnego przycisku w odpowiednim projekcie

    Dla Andorid

    [assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRenderer))] 
    namespace WalkieTalkie.Droid.Renderer 
    { 
        public class CustomButtonRenderer : ButtonRenderer 
        { 
         protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e) 
         { 
          base.OnElementChanged(e); 
    
          var customButton = e.NewElement as CustomButton; 
    
          var thisButton = Control as Android.Widget.Button; 
          thisButton.Touch += (object sender, TouchEventArgs args) => 
          { 
           if (args.Event.Action == MotionEventActions.Down) 
           { 
            customButton.OnPressed(); 
           } 
           else if (args.Event.Action == MotionEventActions.Up) 
           { 
            customButton.OnReleased(); 
           } 
          }; 
         } 
        } 
    } 
    

    IOS

    [assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))] 
    namespace WalkieTalkie.iOS.Renderer 
    { 
        public class CustomButtonRenderer : ButtonRenderer 
        { 
         protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e) 
         { 
          base.OnElementChanged(e); 
    
          var customButton = e.NewElement as CustomButton; 
    
          var thisButton = Control as UIButton; 
          thisButton.TouchDown += delegate 
          { 
           customButton.OnPressed(); 
          }; 
          thisButton.TouchUpInside += delegate 
          { 
           customButton.OnReleased(); 
          }; 
         } 
        } 
    } 
    
  3. Utwórz wystąpienie swój własny przycisk na swojej stronie

    var myButton = new CustomButton 
    { 
        Text = "CustomButton", 
        HorizontalOptions = LayoutOptions.FillAndExpand 
    }; 
    myButton.Pressed += (sender, args) => 
    { 
        System.Diagnostics.Debug.WriteLine("Pressed"); 
    }; 
    myButton.Released += (sender, args) => 
    { 
        System.Diagnostics.Debug.WriteLine("Pressed"); 
    }; 
    

Nadzieja to pomaga ktoś :)

+1

Pomogło komuś :) –

2
Button button = FindViewById (Resource.Id.myButton); 
button.Touch += (object sender, View.TouchEventArgs e) => 
{ 
if (e.Event.Action == MotionEventActions.Up) 
{ 
Toast.MakeText(this, "Key Up", ToastLength.Short).Show(); 
} 
     if(e.Event.Action == MotionEventActions.Down) 
     { 
      Toast.MakeText(this, "Key Down", ToastLength.Short).Show(); 
     } 
    }; 
6

ten może być również wykonane ze skutkiem zamiast pełnoprawny niestandardowy renderer.Zobacz ten post o wyjaśnienie, jak to zrobić:

https://alexdunn.org/2017/12/27/xamarin-tip-xamarin-forms-long-press-effect/

W przypadku, dodawać coraz odchodzi, tutaj jest kod, który można wdrożyć:

we wspólnym projekcie:

/// <summary> 
/// Long pressed effect. Used for invoking commands on long press detection cross platform 
/// </summary> 
public class LongPressedEffect : RoutingEffect 
{ 
    public LongPressedEffect() : base("MyApp.LongPressedEffect") 
    { 
    } 

    public static readonly BindableProperty CommandProperty = BindableProperty.CreateAttached("Command", typeof(ICommand), typeof(LongPressedEffect), (object)null); 
    public static ICommand GetCommand(BindableObject view) 
    { 
     return (ICommand)view.GetValue(CommandProperty); 
    } 

    public static void SetCommand(BindableObject view, ICommand value) 
    { 
     view.SetValue(CommandProperty, value); 
    } 


    public static readonly BindableProperty CommandParameterProperty = BindableProperty.CreateAttached("CommandParameter", typeof(object), typeof(LongPressedEffect), (object)null); 
    public static object GetCommandParameter(BindableObject view) 
    { 
     return view.GetValue(CommandParameterProperty); 
    } 

    public static void SetCommandParameter(BindableObject view, object value) 
    { 
     view.SetValue(CommandParameterProperty, value); 
    } 
} 

W Androidzie:

[assembly: ResolutionGroupName("MyApp")] 
[assembly: ExportEffect(typeof(AndroidLongPressedEffect), "LongPressedEffect")] 
namespace AndroidAppNamespace.Effects 
{ 
    /// <summary> 
    /// Android long pressed effect. 
    /// </summary> 
    public class AndroidLongPressedEffect : PlatformEffect 
    { 
     private bool _attached; 

     /// <summary> 
     /// Initializer to avoid linking out 
     /// </summary> 
     public static void Initialize() { } 

     /// <summary> 
     /// Initializes a new instance of the 
     /// <see cref="T:Yukon.Application.AndroidComponents.Effects.AndroidLongPressedEffect"/> class. 
     /// Empty constructor required for the odd Xamarin.Forms reflection constructor search 
     /// </summary> 
     public AndroidLongPressedEffect() 
     { 
     } 

     /// <summary> 
     /// Apply the handler 
     /// </summary> 
     protected override void OnAttached() 
     { 
      //because an effect can be detached immediately after attached (happens in listview), only attach the handler one time. 
      if (!_attached) 
      { 
       if (Control != null) 
       { 
        Control.LongClickable = true; 
        Control.LongClick += Control_LongClick; 
       } 
       else 
       { 
        Container.LongClickable = true; 
        Container.LongClick += Control_LongClick; 
       } 
       _attached = true; 
      } 
     } 

     /// <summary> 
     /// Invoke the command if there is one 
     /// </summary> 
     /// <param name="sender">Sender.</param> 
     /// <param name="e">E.</param> 
     private void Control_LongClick(object sender, Android.Views.View.LongClickEventArgs e) 
     { 
      Console.WriteLine("Invoking long click command"); 
      var command = LongPressedEffect.GetCommand(Element); 
      command?.Execute(LongPressedEffect.GetCommandParameter(Element)); 
     } 

     /// <summary> 
     /// Clean the event handler on detach 
     /// </summary> 
     protected override void OnDetached() 
     { 
      if (_attached) 
      { 
       if (Control != null) 
       { 
        Control.LongClickable = true; 
        Control.LongClick -= Control_LongClick; 
       } 
       else 
       { 
        Container.LongClickable = true; 
        Container.LongClick -= Control_LongClick; 
       } 
       _attached = false; 
      } 
     } 
    } 
} 

w iOS:

[assembly: ResolutionGroupName("MyApp")] 
[assembly: ExportEffect(typeof(iOSLongPressedEffect), "LongPressedEffect")] 
namespace iOSNamespace.Effects 
{ 
    /// <summary> 
    /// iOS long pressed effect 
    /// </summary> 
    public class iOSLongPressedEffect : PlatformEffect 
    { 
     private bool _attached; 
     private readonly UILongPressGestureRecognizer _longPressRecognizer; 
     /// <summary> 
     /// Initializes a new instance of the 
     /// <see cref="T:Yukon.Application.iOSComponents.Effects.iOSLongPressedEffect"/> class. 
     /// </summary> 
     public iOSLongPressedEffect() 
     { 
      _longPressRecognizer = new UILongPressGestureRecognizer(HandleLongClick); 
     } 

     /// <summary> 
     /// Apply the handler 
     /// </summary> 
     protected override void OnAttached() 
     { 
      //because an effect can be detached immediately after attached (happens in listview), only attach the handler one time 
      if (!_attached) 
      { 
       Container.AddGestureRecognizer(_longPressRecognizer); 
       _attached = true; 
      } 
     } 

     /// <summary> 
     /// Invoke the command if there is one 
     /// </summary> 
     private void HandleLongClick() 
     { 
      var command = LongPressedEffect.GetCommand(Element); 
      command?.Execute(LongPressedEffect.GetCommandParameter(Element)); 
     } 

     /// <summary> 
     /// Clean the event handler on detach 
     /// </summary> 
     protected override void OnDetached() 
     { 
      if (_attached) 
      { 
       Container.RemoveGestureRecognizer(_longPressRecognizer); 
       _attached = false; 
      } 
     } 

    } 
} 

W XAML

<Label Text="Long Press Me!" effects:LongPressedEffect.Command="{Binding ShowAlertCommand}" effects:LongPressedEffect.CommandParameter="{Binding .}"> 
    <Label.Effects> 
     <effects:LongPressedEffect /> 
    </Label.Effects> 
</Label> 
Powiązane problemy