1
\$\begingroup\$

I have a question about my implementation of a "special" Next-Button.
First I want to show you my AfterEffects file:

GIF Button Animation


So This Animation has 3 parts

  • Green: Entry correct
  • Red: Entry incorrect
  • Blue: Button has been pressed (visual feedback)


As I could not work this out with AVD and states I decided to use the Lottie library and play the different segments.

Main Activity - Only TestMethod, nothing really to review actually

private void initButtonTwo(){
    mNext = findViewById(R.id.next);
    mNextButton = new CancelCheckButton(mNext, new NextButtonListener() {
        @Override
        public void onClick() {

            if(enableVibration){
                vibrateFeedback();
            }

            switch (mNextCounter){
                //This is just a Test-Method, i want Tick and Cross to alternate
                case 1:
                case 3:
                    mNextButton.showTick();
                    break;
                case 2:
                case 4:
                    mNextButton.showCross();
                    break;
                case 5:
                    mNextButton.showTickEnd();
                    break;
            }

            if(mNextCounter >= 5){
                mNextCounter = 1;
            }else{
                mNextCounter = mNextCounter + 1;
            }
        }
    });
}



Interface for Communication Main -> Custom Button C

public interface NextButtonListener {
    public void onClick();
}



Custom Class CancelCheckButton

public class CancelCheckButton implements View.OnTouchListener, Animator.AnimatorListener {

    private LottieAnimationView mAnimationView;
    private NextButtonListener mListener;
    private final String LOG_TAG = this.getClass().getSimpleName();



    public CancelCheckButton(LottieAnimationView mView, final NextButtonListener mListener){
        this.mAnimationView = mView;
        this.mListener = mListener;

        this.setTouchListener();
        this.setAnimatorListener();

        Log.d(LOG_TAG, "CancelCheckButton: called");

    }

    private void setAnimatorListener(){
        mAnimationView.addAnimatorListener(this);
        Log.d(LOG_TAG, "CancelCheckButton: AnimatorListener called");
    }

    private void setTouchListener(){
        mAnimationView.setOnTouchListener(this);
        Log.d(LOG_TAG, "CancelCheckButton: TouchListener called");
    }


    /*****TOUCH INTERACTION ANIMATION*****/

    public void showPressed(){
        mAnimationView.setMinAndMaxFrame(452,462);                                                  
        mAnimationView.setSpeed(1.8f);                                                              
        mAnimationView.playAnimation();
        Log.d(LOG_TAG, "CancelCheckButton: PressAnimation played");
    }

    public void showReleased(){
        mAnimationView.setMinAndMaxFrame(485,495);
        mAnimationView.setSpeed(1.8f);
        mAnimationView.playAnimation();
        Log.d(LOG_TAG, "CancelCheckButton: RelleaseAnimation played");
    }


    /*****FEDBACK CONTROL ANIMATION*****/

    public void showTick(){
        mAnimationView.setOnTouchListener(null);                                                    
        mAnimationView.setMinAndMaxFrame(58,181);
        mAnimationView.setSpeed(1.8f);
        mAnimationView.playAnimation();
        Log.d(LOG_TAG, "CancelCheckButton: TickAnimation played, Touchlistener deactivated");
    }

    public void showTickEnd(){
        mAnimationView.setOnTouchListener(null);
        mAnimationView.setMinAndMaxFrame(58,94);
        mAnimationView.setSpeed(1.8f);
        mAnimationView.playAnimation();
        Log.d(LOG_TAG, "CancelCheckButton: TickEndAnimation played, Touchlistener deactivated");
    }

    public void showCross(){
        mAnimationView.setOnTouchListener(null);
        mAnimationView.setMinAndMaxFrame(300,431);
        mAnimationView.setSpeed(2.0f);
        mAnimationView.playAnimation();
        Log.d(LOG_TAG, "CancelCheckButton: CrossAnimation played, Touchlistener deactivated");
    }


    /*****LISTENER*****/

    @Override
    public boolean onTouch(View v, MotionEvent event) {                                             
        if(v.getId() == mAnimationView.getId()){
            switch(event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    showPressed();

                    Log.d(LOG_TAG, "CancelCheckButton: View is touched");
                    break;
                case MotionEvent.ACTION_UP:
                    showReleased();

                    v.performClick();
                    mListener.onClick();                                                            


                    Log.d(LOG_TAG, "CancelCheckButton: View is relleased, OnClick is fired");
                    break;
            }
        }
        return true;
    }

    @Override
    public void onAnimationStart(Animator animation) {
        Log.d(LOG_TAG, "CancelCheckButton: Called Animation is STARTED and Touchlistener deactivated");
    }

    @Override
    public void onAnimationEnd(Animator animation) {
        setTouchListener();
        Log.d(LOG_TAG, "CancelCheckButton: Called Animation is FINISHED and Touchlistener reset");
    }

    @Override
    public void onAnimationCancel(Animator animation) {
        Log.d(LOG_TAG, "CancelCheckButton: Called Animation is CANCELED and Touchlistener reset");
    }

    @Override
    public void onAnimationRepeat(Animator animation) {

    }
}



Notes
When you click on the button I want the blue part to appear and disappear when the finger is released. As it is a very short animation I decided to not deactivate the OnTouchListener. No matter how fast I tipped I could not see a difference.

For the green or red part I deactivated the onTouchListener to avoid an accidental restart of the animation.

It actually works perfectly but even though I tried to keep the code clean I am not happy with it. Is there a more effective or at least a more common way to do it?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.