Creating a custom and animated toggle

0

I'm creating an Android app where I'm using ToggleButton as one of the interface elements. I am trying to make it have images instead of the button itself and that there is a transition between them (when the button is turned on / off).

Given a search, I read that to use images in the button the best would be to use an xml file, which is here:

<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/btn_off" android:state_checked="false" />
    <item android:drawable="@drawable/btn_on" android:state_checked="true" />
</selector>

What I did not find out how to do is how to associate this file with the button and how to put a transition between on / off. What's the best way to do this? I had already been able to toggle background images by code, as follows:

// botão ligado
mToggle.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_on));

// botão desligado
mToggle.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_off));

But it seems to me an unorthodox way, with Android having more specific resources to do the same.

    
asked by anonymous 01.08.2014 / 05:12

1 answer

1

To do this, I made an auxiliary class to listen for events of Motion in ToggleButton , which in sequence:

  • Starts an alpha animation from 1 to 0, leaving ToggleButton transparent.
  • Using ToggleButton transparent modifies its state using setChecked
  • Then start an alpha animation from 0 to 1 to display the new status.
  • The helper 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 GestureDetector because working only on onTouch may have false positives of ACTION_UP . The ACTION_UP also occurs when he raises his finger off the button, and this is characterized as a cancellation. GestureDetector can do this treatment, so it's easier to use.

    To use:

    ToggleButton toggle = findViewById(...);
    
    toggle.setOnTouchListener(new DrawableTransition(getApplicationContext(), toggle));
    
        
    02.08.2014 / 01:31