سؤال

I've got an activity in which several Views animate. The animations are triggered when a RelativeLayout containing a few images is clicked. It's set up in onCreate() like this:

mContainer.setOnClickListener(new ContainerClicked());

And the ContainerClicked() class looks like this:

private class ContainerClicked implements OnClickListener {

    @Override
    public void onClick(View arg0) {
        Log.i(TAG, "TEST!");
        mSomeButton.setOnClickListener(null);
        mSomeButton.setEnabled(false);

        mAnotherButton.setOnClickListener(null);
        mAnotherButton.setEnabled(false);

        mYetAnotherButton.setOnClickListener(null);
        mYetAnotherButton.setEnabled(false);

        mContainer.setOnClickListener(null);
        if (mLogo.getVisibility() == View.VISIBLE)
            new AnimateToParty().execute();
        else
            new AnimateFromParty().execute();
    }
}

This works, and animates everything just how I want it.

AnimateToParty() looks like this:

private class AnimateToParty extends AsyncTask<Void, Integer, Void> {

    @Override
    protected void onProgressUpdate(final Integer... values) {
        final View theView = findViewById(values[0]);
        if (!(values[0] == mBackgroundImage.getId() || values[0] == mContainer
                .getId())) {
            final Animation animation = AnimationUtils.loadAnimation(
                    DashboardActivity.this, values[1]);
            animation.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationStart(Animation arg0) {
                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                }

                @Override
                public void onAnimationEnd(Animation arg0) {
                    theView.setVisibility(View.INVISIBLE);
                }
            });
            theView.startAnimation(animation);
        } else if (values[0] == mBackgroundImage.getId()) {
            TransitionDrawable transition = (TransitionDrawable) theView
                    .getBackground();
            transition.startTransition(getResources().getInteger(
                    android.R.integer.config_mediumAnimTime));
        } else {
            TranslateAnimation animation = new TranslateAnimation(0, 0, 0,
                    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                            -60, getResources().getDisplayMetrics()));
            animation.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationStart(Animation arg0) {
                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                }

                @Override
                public void onAnimationEnd(Animation arg0) {
                    LayoutParams lp = (LayoutParams) mContainer
                            .getLayoutParams();
                    lp.bottomMargin = 0;
                    RelativeLayout parent = (RelativeLayout) mContainer
                            .getParent();
                    mSomeButton.setVisibility(View.GONE);
                    mAnotherButton.setVisibility(View.GONE);
                    mYetAnotherButton.setVisibility(View.GONE);
                    mLogo.setVisibility(View.GONE);
                    // mContainer.setLayoutParams(lp);
                    // This caused a visible flicker, so I went with the solution below.
                    parent.removeView(mContainer);
                    parent.addView(mContainer, lp);
                }
            });
            animation.setDuration(1000);
            mContainer.startAnimation(animation);
        }
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        try {
            publishProgress(mContainer.getId());
            publishProgress(mLogo.getId(), R.anim.slide_out_up);
            Thread.sleep(100);
            publishProgress(mSomeButton.getId(), R.anim.slide_out_left);
            Thread.sleep(110);
            publishProgress(mAnotherButton.getId(), R.anim.slide_out_left);
            Thread.sleep(120);
            publishProgress(mYetAnotherButton.getId(), R.anim.slide_out_left);
            Thread.sleep(130);
            publishProgress(mBackgroundImage.getId());
            Thread.sleep(550);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        mContainer.setOnClickListener(new LighterClicked());
    }
}

The class above animates some buttons and the logo out of the way, and then reveals the container. In order to keep it there, I change it's layoutparams. Just changing them produces a visible flicker where the container jumps 60 dip up for about one frame (the animation doesn't seem to be quite finished), before settling where I want it. I read somewhere to remove it from its parent and put it back in, and this does not produce the same flicker. However, now the rebinding of the onclicklistener does not work!

I've tried just about everything, and I just now noticed that every click that didn't "go through" fires if I press the home button and open the application again.

Is there a better way to avoid the "flicker"? A better way to do the animations? (I'm quite new at animating views) Why do the click-events fire when I reopen the application?

هل كانت مفيدة؟

المحلول

To avoid the flicker you are seeing, you have to call clearAnimation() at the start of onAnimationEnd

@Override
public void onAnimationEnd(Animation arg0) {
    theView.clearAnimation()
    ...
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top