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:background
with 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
OnTouchListener
on that button from theActivity
and 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
OnTouchListener
I believe that two things may be happening: Or theDrawable
is changed before the callonTouch
and there just extending toView
. Or he’s switching later, but the fact of starting theAnimation
, it does after the next pass onlayout
, in thestartAnimation
it only configures and invalidates theView
(need to confirm the correct time). In the second case would have to make the change manually (returnsfalse
in 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