To do this effect, I made an auxiliary class to listen for events of Motion in the ToggleButton, that in sequence:
- Starts an alpha animation from 1 to 0, leaving the
ToggleButton transparent.
- With the
ToggleButton transparent modifies its state using the setChecked
- Then start an alpha animation from 0 to 1 to display the new state.
The auxiliary class is:
public class DrawableTransition extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener, Animation.AnimationListener {
WeakReference<ToggleButton> mToggle;
GestureDetector mGestureDetector;
AlphaAnimation mAlphaTo0, mAlphaTo1;
public DrawableTransition(Context context, ToggleButton toggle) {
mToggle = new WeakReference<ToggleButton>(toggle);
mGestureDetector = new GestureDetector(context, this);
mAlphaTo1 = new AlphaAnimation(0f, 1f);
mAlphaTo1.setDuration(1000l);
mAlphaTo0 = new AlphaAnimation(1f, 0f);
mAlphaTo0.setDuration(1000l);
mAlphaTo0.setAnimationListener(this);
}
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
// Animacao de alpha para 0 terminou, vamos mostrar o botao
show();
}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public boolean onTouch(View v, MotionEvent event) {
// Delega para o GestureDetector
mGestureDetector.onTouchEvent(event);
return true;
}
// Single tap foi confirmado
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return hide();
}
// Troca o estado, com isso alterando o background
// depois iniciando uma animacao de alpha para 1, exibindo o botao novamente
boolean show() {
ToggleButton toggle = mToggle.get();
if(toggle == null) {
return false;
}
toggle.setChecked(! toggle.isChecked());
toggle.startAnimation(mAlphaTo1);
return true;
}
// Faz a animacao de alpha para 0, escondendo o botao
boolean hide() {
ToggleButton toggle = mToggle.get();
if(toggle == null) {
return false;
}
toggle.startAnimation(mAlphaTo0);
return true;
}
/**
* Limpar recursos, a fim de evitar memory leak
* Chamar no onDestroy ou onDestroyView
*/
public void clean() {
mGestureDetector = null;
mToggle.clear();
mToggle = null;
mAlphaTo0 = mAlphaTo1 = null;
}
}
I ended up using the GestureDetector, why work only on onTouch there may be false positives of ACTION_UP. The ACTION_UP also occurs when he lifts his finger off the button, and this is characterized as a cancellation. The GestureDetector can do this treatment, so it is easier to use it.
To use:
ToggleButton toggle = findViewById(...);
toggle.setOnTouchListener(new DrawableTransition(getApplicationContext(), toggle));
Renan, just use the attribute
android:backgroundwith this drawable state list. It didn’t work?– Wakim
Thanks @Wakim, it worked! The article I found added 3 steps after creating this XML to achieve something similar. Now I have only one question: how do I encourage this change of images?
– Renan Lazarotto
Would it be applying an animation of transition between these two states? I think only programmatically, making a component that extends the Togglebutton and inside the onTouch or some more specific method that makes the backgroundDrawable change and make an animation (could use an Alphaanimation (1 to 0), swap the background and execute another Alphaanimation (0 to 1)). There is also Drawableanimation, but it is as if it transitions between "frames" (http://developer.android.com/guide/topics/graphics/drawable-animation.html) and still needs to be started programmatically.
– Wakim
Exactly, it would apply a transition between the two states. It is not possible to do without creating a new class?
– Renan Lazarotto
You can set a
OnTouchListeneron that button from theActivityand do the animation on it.– Wakim
Thank you, it worked perfectly. Only one thing is not right: when the animation starts, the state image disappears (for example: if it is off, the off state image disappears) to then begin the transition animation. How can I make the image remain Teriror? (something like 'off' image > fade > 'on' image, not 'off' image > some > fade > 'on image')
– Renan Lazarotto
Using the
OnTouchListenerI believe that two things may be happening: Or theDrawableis changed before the callonTouchand there just extending toView. Or he’s switching later, but the fact of starting theAnimation, it does after the next pass onlayout, in thestartAnimationit only configures and invalidates theView(need to confirm the correct time). In the second case would have to make the change manually (returnsfalsein theonTouch, starts alpha animation for 0 change thebackground, starts another alpha to 1).– Wakim
Let’s go continue this discussão in chat.
– Renan Lazarotto