Android - remove View when its animation finished

2019-09-03 12:50发布

问题:

Hey I have a method which adds a TextView to my FrameLayout and starts the Animation. The method should be able to be called more often (for multiple Animations). That is working fine since I can run multiple Animations at one time, but i want to remove the animated view when its animation has finished.

public void showMoneyAnimation(int amoutAddedOrRemoved){
    //Adding Money
        float textSize = Math.round((global.getDisplaySize().y / scaleValue) * 34.0);
        final TextView temp = new TextView(context);
        temp.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
        temp.setText("+ " + amoutAddedOrRemoved + "$");
        temp.setTextAppearance(context, R.style.tsMoney1);
        temp.setTypeface(global.getFont("Grobold"));
        temp.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);

        sb_money.measure(0, 0);
        temp.measure(0,0);
        int xtemp = ((int) sb_money.getX() + sb_money.getMeasuredWidth()) - temp.getMeasuredWidth();
        temp.setX(xtemp);
        temp.setY(0);

        //Adding My Text to my FrameLayout
        bgFl.addView(temp);

        Animation atemp = AnimationUtils.loadAnimation(context, R.anim.addanim);
        temp.startAnimation(atemp);
        atemp.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // This is the problem's origin!
                bgFl.removeView(temp);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

But I'm getting a NullPointerException, maybe because the views have the same name? How can I work around that problem? Please help :)

Here the Exception:

01-27 22:52:25.633  25975-25975/de.cookedapps.needforweed E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: de.cookedapps.needforweed, PID: 25975
java.lang.NullPointerException
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3146)
        at android.view.View.getDisplayList(View.java:14283)
        at android.view.View.getDisplayList(View.java:14330)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3284)
        at android.view.View.getDisplayList(View.java:14225)
        at android.view.View.getDisplayList(View.java:14330)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3284)
        at android.view.View.getDisplayList(View.java:14225)
        at android.view.View.getDisplayList(View.java:14330)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3284)
        at android.view.View.getDisplayList(View.java:14225)
        at android.view.View.getDisplayList(View.java:14330)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3284)
        at android.view.View.getDisplayList(View.java:14225)
        at android.view.View.getDisplayList(View.java:14330)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3284)
        at android.view.View.getDisplayList(View.java:14225)
        at android.view.View.getDisplayList(View.java:14330)
        at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1588)
        at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1467)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2754)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2620)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2188)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1249)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6585)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
        at android.view.Choreographer.doCallbacks(Choreographer.java:603)
        at android.view.Choreographer.doFrame(Choreographer.java:573)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5586)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
        at dalvik.system.NativeStart.main(Native Method)

回答1:

It's likely that you will have issues removing the view in this way since you should only be attempting to touch any of your views from the UI thread (to avoid other threads trying to change your UI elements at the same time which will just cause problems). For this reason Android provides a method called runOnUiThread() that will instruct your code to perform an action in the correct thread.

Something like this should get you pointed in the right direction. Place this in your onAnimationEnd method.

//get the parentView...
parentView.post(new Runnable() {
    public void run () {
        // it works without the runOnUiThread, but all UI updates must 
        // be done on the UI thread
        activity.runOnUiThread(new Runnable() {
            public void run() {
                parentView.removeView(view);
            }
        });
    }
}


回答2:

Try this:

  1. Make sure bgFl is not null
  2. You can try: temp.setVisibility(View.GONE) instead of remove

Or

  1. Use handler to remove view safely in UI thread.