How to use SetAnimationListener()? - animation

I would like to know when my animation is finished, so I have to use an AnimationListener.
I cannot seem to find out how to do that in MonoDroid (C#).
Does anyone know how to do this ?

Here is a short one I wrote to get me a callback when the animation ends:
class AnimationListenerEndCallback : Java.Lang.Object, Animation.IAnimationListener
{
public delegate void Callback(Animation animation);
private Callback callback;
public AnimationListenerEndCallback(Callback callback)
{
this.callback = callback;
}
public void OnAnimationEnd(Android.Views.Animations.Animation animation)
{
callback(animation);
}
public void OnAnimationRepeat(Android.Views.Animations.Animation animation)
{
// do nothing
}
public void OnAnimationStart(Android.Views.Animations.Animation animation)
{
// do nothing
}
}
You use it like this:
Animation a = AnimationUtils.LoadAnimation(this, Resource.Animation.pull_up);
a.SetAnimationListener(new AnimationListenerEndCallback(delegate
{
// all your local variables are still in scope, so you
// can use them here
}));

Related

ICommand Xamarin Forms

I have a strange issue of getting null exception. I created class that implements ICommand interface, I have two methods.
public void Execute(object parameter)
{
NavigateAsync();
}
private async void NavigateAsync()
{
await App.MainNavigation.PushAsync(new Pages.SettingsPage());
}
When NavigateAsync() is exectude my MainNavigation is always null, even that I can see that parameter inside Execute is set.
In my App.xaml.cs file I have created public static INavigation MainNavigation { get; set; }
public partial class App : Application
{
public static ViewModels.MainViewModel ViewModel { get; set; }
public static INavigation MainNavigation { get; set; }
public App ()
{
InitializeComponent();
MainPage = new NavigationPage(new Paperboy.MainPage());
}
protected override void OnStart ()
{
// Handle when your app starts
}
protected override void OnSleep ()
{
// Handle when your app sleeps
}
protected override void OnResume ()
{
// Handle when your app resumes
}
}
Se when clicking icon i can se that command is executed but App.MainNavigation inside NavigateAsync() in null. So command is not executing PushAsync to SettingsPage.
You never instantiate your static MainNavigation property...
If I can give you 2 remarks:
instead of using a static property declared into your App.xaml.cs, maybe a better implementation could be to embed a Navigation getter into a specific 'service' class or directly into your Command definition:
public class MyCommand : ICommand
{
...
// Navigation getter
// There are better places for this prop but it's better
// than in app.xaml.cs
private INavigation MainNavigation
{
get => Application.Current?.MainPage?.Navigation;
}
public void Execute(object parameter)
{
NavigateAsync();
}
private async void NavigateAsync()
{
try
{
await MainNavigation?.PushAsync(new Pages.SettingsPage());
}
catch(){ ... }
}
}
Another point I would like to note, is that your Command looks like asynchronous. Maybe you already know, but here is a good implementation of async commands to avoid app crashes: Asynchronous commands
I hope it can help you. Happy coding !

Delegate in Xamarin.iOS

I have a problem in creating class for xamarin.ios delegate.
In iOS we use protocols to implement the delegate but here I can not implement Interface as a delegate.
Let me clear this concept.
I have an interface in one file like:
public interface SendBackDelegate
{
void sendBackData();
}
public class SelectList
{
}
In other file I have main class like this:
public class ShowList: SendBackDelegate
{
public ShowList()
{
SelectList obj = new SelectList();
obj.delegate = this;
}
void sendBackData()
{
Console.WriteLine("Send Back DATA");
}
}
Now Can you please tell me how this interface be implemented in SelectList class?
Thanks
you can use Interface like protocol, only you have to make reference object of interfaces it can own the class object which already implemented the Interface methods. it will be clear with your example as well.
public interface SendBackDelegate
{
void sendBackData();
}
public class SelectList
{
ShowList showListObj = new ShowList();
SendBackDelegate delegate = showListObj;
delegate.sendBackData();
//this will call the method sendBackData() of class ShowList.
}
public class ShowList: SendBackDelegate
{
public ShowList()
{
SelectList obj = new SelectList();
obj.delegate = this;
}
void sendBackData()
{
Console.WriteLine("Send Back DATA");
}
}
Please let me know if you still have questions.
I am not using delegates anymore on Xamarin.iOS. I prefer to use actions though.
class MainClass
{
public static void Main (string[] args)
{
var x = new ShowList ();
}
}
public interface SendBackDelegate
{
void sendBackData ();
}
public class ShowList : SendBackDelegate
{
public ShowList ()
{
SelectList obj = new SelectList (sendBackData);
}
public void sendBackData ()
{
Console.WriteLine ("Send Back DATA");
}
}
public class SelectList
{
Action _callback;
public SelectList (Action callback)
{
_callback = callback;
Ticker ();
}
private void Ticker ()
{
_callback ();
}
}

raising events in chaining classes

say I have three classes: class1, control1 and form1; form1 instantiate contorl. and control1 instantiate class1, the later produces some event that I need to 'bypass' to form1, to achieve that I have made an intermediate function as shown below:
public delegate void TestHandler(String^ str);
public ref Class class1
{
event TestHandler^ TestHappen;
void someFunction()
{
TestHappen("test string");
}
};
public ref Class control1
{
event TestHandler^ TestHappen;
class1^ class1Obj;
control1()
{
class1Obj= gcnew class1();
class1Obj->TestHappen+= gcnew TestHandler(this,&control1::onTest);
}
void onTest(String^ str)
{
TestHappen(str);
}
};
public ref Class form1
{
control1^ control1Obj;
form1()
{
control1Obj= gcenw control1();
control1Obj->TestHappen+= gcnew TestHandler(this,&form1::onTest);
}
void onTest(String^ str)
{
//do something with the string...
}
};
I don't want to use class1 in form1, are there a way to remove the intermediate onTest() function.
Yes, if you use a custom event, you can write its add-handler and remove-handler functions so that they add and remove the delegate directly from another object's event.
For example:
public ref class control1 // in "ref class", class is lowercase!
{
class1 class1Obj; // stack-semantics syntax, locks class1Obj lifetime to be same as the containing control1 instance
public:
event TestHandler^ TestHappen {
void add(TestHandler^ handler) { class1Obj.TestHappen += handler; }
void remove(TestHandler^ handler) { class1Obj.TestHappen -= handler; }
}
};

Should I Call RaiseCanExecuteChanged in Prism' DelegateCommand?

I have written a CanExecute method for the DelegateCommand. CanExecute is not being re-evaluated as other commands which inherites from a CommandBase, that looks like this.
public abstract class CommandBase : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
public virtual bool CanExecute(object parameter)
{
return true;
}
public abstract void Execute(object parameter);
}
Can I make the Prism DelegateCommand work like this, so CanExecute is automatically re-evaluated when appropriate or should I manually call RaiseCanExecuteChanged() when needed?
How should the command or the command manager know that it's execution state changed? To have them know about that you need to signal this via the RaiseCanExecuteChanged method.

Instant value change handler on a GWT textbox

I would like to update a text field instantly when typing in a GWT TextBox. My problem is that ValueChangeEvent and ChangeEvent handlers only fire when the TextBox loses focus. I thought about using the KeyPressEvent but then nothing would happen when performing a copy paste with the mouse.
What's the simplest way to do that ?
You could catch the ONPASTE event and manually fire a ValueChangeEvent. Something like this:
public void onModuleLoad() {
final Label text = new Label();
final ExtendedTextBox box = new ExtendedTextBox();
box.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
text.setText(event.getValue());
}
});
box.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent event) {
text.setText(box.getText());
}
});
RootPanel.get().add(box);
RootPanel.get().add(text);
}
private class ExtendedTextBox extends TextBox {
public ExtendedTextBox() {
super();
sinkEvents(Event.ONPASTE);
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (DOM.eventGetType(event)) {
case Event.ONPASTE:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
ValueChangeEvent.fire(ExtendedTextBox.this, getText());
}
});
break;
}
}
}
Tested on firefox 3.6.1.
As a general solution, what works for me (thx to gal-bracha comment):
Generally, GWT does not have classes to handle input event (described here
and here). So we need to implement it by ourselves:
Handler class:
import com.google.gwt.event.shared.EventHandler;
public interface InputHandler extends EventHandler {
void onInput(InputEvent event);
}
Event class:
import com.google.gwt.event.dom.client.DomEvent;
public class InputEvent extends DomEvent<InputHandler> {
private static final Type<InputHandler> TYPE = new Type<InputHandler>("input", new InputEvent());
public static Type<InputHandler> getType() {
return TYPE;
}
protected InputEvent() {
}
#Override
public final Type<InputHandler> getAssociatedType() {
return TYPE;
}
#Override
protected void dispatch(InputHandler handler) {
handler.onInput(this);
}
}
Usage:
box.addDomHandler(new InputHandler() {
#Override
public void onInput(InputEvent event) {
text.setText(box.getText());
}
},InputEvent.getType());
It works on every TextBox value change including pasting using context menu. It does not react on arrows, ctrl, shift etc...
This has been a major issue for me in the past. The keyupHandler wont work because the copy paste requires a second key press on the paste option which does not fire the event. the best i have been able to do is use the old changelistener not ideal but it does work.
I prefer use Elements than Widgets so this my way to handler.
Element input = Document.get().getElementById("my-input");
DOM.sinkBitlessEvent(input, "input");
DOM.setEventListener(input, event -> GWT.log("Event!"));
Why not use combination of both KeyUpHandler and a ChangeHandler on the TextBox?
Should take care of immediate feedback on each keystroke as well as copy paste case as well.
Just saw this question. Because I was facing the similar problem.
Did some hack and it worked for me.
You can use KeyUpHandler but use it with additional if block that checks
for length of textbox. If length of text box is > 0, do your thing.
Ex:
textBox.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent keyUpEvent) {
if (textBox.getText().length() > 0) {
//do your stuff`enter code here`
}
}

Resources