I need to create a button/image/whatever that changes image while pressed to create the button pressed effect. How can i get to the 'while pressed' state? Even if using custom renderers, i cant do it. Could some one give me some hints?
One option is to use an image and just animate it on Tap. I got this code of the forums, it works fine for images as buttons (until the button control becomes fit for purpose).
<br />using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace OrderFinder.CustomRenderers
{
public class ImageButton : Image
{
public static readonly BindableProperty CommandProperty = BindableProperty.Create<ImageButton, ICommand>(p => p.Command, null);
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create<ImageButton, object>(p => p.CommandParameter, null);
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
private ICommand TransitionCommand
{
get
{
return new Command(async () =>
{
this.AnchorX = 0.48;
this.AnchorY = 0.48;
await this.ScaleTo(0.8, 50, Easing.Linear);
await Task.Delay(100);
await this.ScaleTo(1, 50, Easing.Linear);
if (Command != null)
{
Command.Execute(CommandParameter);
}
});
}
}
public ImageButton()
{
Initialize();
}
public void Initialize()
{
GestureRecognizers.Add(new TapGestureRecognizer()
{
Command = TransitionCommand
});
}
}
}
Then in your page you can use it to bind to a command.
It's straight forward enough to change the image when you Tap it. I don't think there's any event like MouseUp currently (without implementing a custom renderer) to change the image back so you'd have to use a timer or something to check the Tapcount and change the image back. A custom renderer as @Momm suggested is your best bet probably or if it's just for Android you could use a drawable to do this kind of thing.
I need to do it for all three platforms. I'm open to use renderers, my problem is how to do it.
I'm also aware i could do it using xml in android, but i don't think i can associate it with an image programatically. So i guess my only chance is to get a pressed event or something, like @Momm said. But i don't know how do it...
With MR.Gestures you get the Down and Up events on Images (and all other controls). You can change the Source in those event handlers. No need to write any platform specific renderers.
Really? I asked help writing the custom renderers and all i got was you telling me to use a paid library? Are you their partner? Do you share their profit?
As a matter of curiosity, don't you think this is a very basic action to do in any programming platform for mobile? Is this as exotic as the need for workarounds may make it look?
@PedroNeves.7715 - Thanks for sharing the code snippet. This is exactly what i was looking for. I am also impressed with @MichaelRumpler work. Great Stuff!
@VinnieVivace
Yes. I call Control.CallOnClick() manually.
case MotionEventActions.Down: //Pressed //Set text color lighter when pressed Control.SetTextColor(Android.Graphics.Color.Argb(100, defaultTextColor.R, defaultTextColor.G, defaultTextColor.B)); break; case MotionEventActions.Up: //Released Control.SetTextColor(defaultTextColor); Control.CallOnClick(); break; default: break;
@PedroNeves.7715 said:
Really? I asked help writing the custom renderers and all i got was you telling me to use a paid library? Are you their partner? Do you share their profit?
Seems like for iOS at least, in the custom renderer you could leverage the built in button.setImage which takes a state. Has anyone attempted to do it this way instead of custom handling the touchdown and touchup events?
Here is a stackoverflow question with an example of what I mean:
/questions/10778694/how-to-change-custom-buttons-image-when-tapping-in-ios (it won't let me post a link)
I'll try this later and report back to see if this would work. Might be a little simpler and use some built in functionality. Still would need the custom renderer but you wouldn't have to handle the up/down yourself I believe.
Answers
You will need to create a CustomRenderer for the ImageRenderer and override:
These methods will have to call a EventHandler, which will change the image based on the press state.
@PedroNeves.7715
One option is to use an image and just animate it on Tap. I got this code of the forums, it works fine for images as buttons (until the button control becomes fit for purpose).
Then in your page you can use it to bind to a command.
No need for a custom renderer
@NMackay i have to use a specific image, it is not my choice, but thanks.
@Momm thanks, can you provide a quick example?
Not sure what you mean by a "specific image"
I mean that i do not want to animate it. I've been given a button.png and button_pressed.png
Ahhh okay.
It's straight forward enough to change the image when you Tap it. I don't think there's any event like MouseUp currently (without implementing a custom renderer) to change the image back so you'd have to use a timer or something to check the Tapcount and change the image back. A custom renderer as @Momm suggested is your best bet probably or if it's just for Android you could use a drawable to do this kind of thing.
I need to do it for all three platforms. I'm open to use renderers, my problem is how to do it.
I'm also aware i could do it using xml in android, but i don't think i can associate it with an image programatically. So i guess my only chance is to get a pressed event or something, like @Momm said. But i don't know how do it...
If you don't have the time to figure out the customer renderer approach you could use use MrGestures.
http://www.mrgestures.com/
That can detect the Up on the image and change the image back. The benefit is you can do it all in the PCL (I think).
Best asking @MichaelRumpler the author just to double check.
The gesture support out of the box in Forms is too basic and not really extendible.
That's correct.
With MR.Gestures you get the
Down
andUp
events onImage
s (and all other controls). You can change theSource
in those event handlers. No need to write any platform specific renderers.Yes but that is a paid library.
Really? I asked help writing the custom renderers and all i got was you telling me to use a paid library? Are you their partner? Do you share their profit?
Yes, MRGestures is owned/created by Michael Rumpler
Lol. I actually laughed. You are right. Still, i won't get the library because the project's budget won't allow it
Nice Budget. The library is 10€. I don't think the effort of writing something like this on your own will be cheaper than this.
If you still want to write this on your own, maybe this is a good way to start.
Thanks.
As a matter of curiosity, don't you think this is a very basic action to do in any programming platform for mobile? Is this as exotic as the need for workarounds may make it look?
Answering my own question, here it goes:
PCL:
public class FancyButton : Button { }
Android:
[assembly: ExportRenderer(typeof(App2.FancyButton), typeof(FancyButtonAndroid))] namespace App2.Droid { public class FancyButtonAndroid : ButtonRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e) { base.OnElementChanged(e); Android.Widget.Button thisButton = Control as Android.Widget.Button; thisButton.Touch += (object sender, Android.Views.View.TouchEventArgs e2) => { if (e2.Event.Action == MotionEventActions.Down) System.Diagnostics.Debug.WriteLine("TouchDownEvent"); else if (e2.Event.Action == MotionEventActions.Up) System.Diagnostics.Debug.WriteLine("TouchUpEvent"); }; } } }
iOS:
[assembly: ExportRenderer(typeof(App2.FancyButton), typeof(FancyButtoniOS))] namespace App2.iOS { public class FancyButtoniOS : ButtonRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Button> e) { base.OnElementChanged(e); UIButton thisButton = Control as UIButton; thisButton.TouchDown += delegate { System.Diagnostics.Debug.WriteLine("TouchDownEvent"); }; thisButton.TouchUpInside += delegate { System.Diagnostics.Debug.WriteLine("TouchUpEvent"); }; } } }
Windows Phone:
[assembly: ExportRenderer(typeof(App2.FancyButton), typeof(FancyButtonWP))] namespace App2.WinPhone { public class FancyButtonWP : ButtonRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e) { base.OnElementChanged(e); System.Windows.Controls.Button thisButton = Control as System.Windows.Controls.Button; thisButton.ManipulationStarted += delegate { System.Diagnostics.Debug.WriteLine("TouchDownEvent"); }; thisButton.ManipulationCompleted += delegate { System.Diagnostics.Debug.WriteLine("TouchUpEvent"); }; } } }
@PedroNeves.7715 - Thanks for sharing the code snippet. This is exactly what i was looking for. I am also impressed with @MichaelRumpler work. Great Stuff!
@PedroNeves.7715 You are awesome.
@PedroNeves.7715
Hi Pedro, if I implement this in the renderer in Android, the click event in Forms no longer working. Any solution?
@RayQu I also found the same issue as you above (Click event not firing for Android). Did you manage to resolve?
@VinnieVivace
Yes. I call Control.CallOnClick() manually.
case MotionEventActions.Down: //Pressed //Set text color lighter when pressed Control.SetTextColor(Android.Graphics.Color.Argb(100, defaultTextColor.R, defaultTextColor.G, defaultTextColor.B)); break; case MotionEventActions.Up: //Released Control.SetTextColor(defaultTextColor); Control.CallOnClick(); break; default: break;
@RayQu nice one, thanks very much
@NMackay can u help me to add same effect of your custom Image Button to StackLayOut or somthing like that.
I tried same code for stacklayout and it works..
no need to be upset . it was just a suggestion .
Seems like for iOS at least, in the custom renderer you could leverage the built in button.setImage which takes a state. Has anyone attempted to do it this way instead of custom handling the touchdown and touchup events?
Here is a stackoverflow question with an example of what I mean:
/questions/10778694/how-to-change-custom-buttons-image-when-tapping-in-ios (it won't let me post a link)
I'll try this later and report back to see if this would work. Might be a little simpler and use some built in functionality. Still would need the custom renderer but you wouldn't have to handle the up/down yourself I believe.
For the record, this library is no longer 10 Euros.
Such overkill,


It's probably better to use Paint.Net and just create a new image with adapted brightness
using some code like this:
What an irony
https://github.com/AndreiMisiukevich/TouchEffect
That's really what you look for https://github.com/AndreiMisiukevich/TouchEffect