web-dev-qa-db-fra.com

Impossible de démarrer cet animateur sur une vue séparée! révéler l'effet

J'essaie de créer l'effet de révélation dans mon application, mais sans succès. Ce que je veux, c'est révéler un cardview quand j'ouvre un fragment. Ce que j'ai essayé jusqu'à présent c'est:

private void toggleInformationView(View view) {
        infoContainer = view.findViewById(R.id.contact_card);

        int cx = (view.getLeft() + view.getRight()) / 2;
        int cy = (view.getTop() + view.getBottom()) / 2;
        float radius = Math.max(infoContainer.getWidth(), infoContainer.getHeight()) * 2.0f;

        if (infoContainer.getVisibility() == View.INVISIBLE) {
            infoContainer.setVisibility(View.VISIBLE);
            ViewAnimationUtils.createCircularReveal(infoContainer, cx, cy, 0, radius).start();
        } else {
            Animator reveal = ViewAnimationUtils.createCircularReveal(
                    infoContainer, cx, cy, radius, 0);
            reveal.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    infoContainer.setVisibility(View.INVISIBLE);
                }
            });
            reveal.start();
        }
    }

et dans la onCreateView j'ai commencé la méthode:

toggleInformationView(view);

c'est la vue carte:

<Android.support.v7.widget.CardView
        xmlns:card_view="http://schemas.Android.com/apk/res-auto"
        Android:layout_width="match_parent"
        Android:id="@+id/contact_card"
        Android:visibility="invisible"
        Android:layout_height="wrap_content"
        Android:layout_margin="5dp"
        Android:elevation="4dp"
        Android:foreground="?android:attr/selectableItemBackground"
        Android:orientation="vertical"
        Android:padding="10dp"
        card_view:cardCornerRadius="2dp" >

        <LinearLayout   
            Android:orientation="vertical"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            >
            <ImageView
                Android:id="@+id/bg_contact"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_centerHorizontal="true"
                Android:layout_weight="0"
                Android:adjustViewBounds="true"
                Android:scaleType="centerCrop"
                Android:src="@drawable/banner" />

        </LinearLayout>
    </Android.support.v7.widget.CardView>

et le logcat:

11-08 17:25:48.541: E/AndroidRuntime(26925): Java.lang.IllegalStateException: Cannot start this animator on a detached view!
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.view.RenderNode.addAnimator(RenderNode.Java:817)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.view.RenderNodeAnimator.setTarget(RenderNodeAnimator.Java:277)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.view.RenderNodeAnimator.setTarget(RenderNodeAnimator.Java:261)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.animation.RevealAnimator.<init>(RevealAnimator.Java:37)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.view.ViewAnimationUtils.createCircularReveal(ViewAnimationUtils.Java:48)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at com.as.asapp.TFragment.toggleInformationView(TFragment.Java:64)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at com.as.asapp.TFragmentshowInformation(TFragment.Java:52)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at com.as.asapp.TFragment.onCreateView(TFragment.Java:37)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.support.v4.app.Fragment.performCreateView(Fragment.Java:1786)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:947)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1126)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.support.v4.app.BackStackRecord.run(BackStackRecord.Java:739)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.Java:1489)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.Java:454)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.os.Handler.handleCallback(Handler.Java:739)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.os.Handler.dispatchMessage(Handler.Java:95)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.os.Looper.loop(Looper.Java:135)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Android.app.ActivityThread.main(ActivityThread.Java:5221)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Java.lang.reflect.Method.invoke(Native Method)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at Java.lang.reflect.Method.invoke(Method.Java:372)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:899)
11-08 17:25:48.541: E/AndroidRuntime(26925):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:694)

En vérifiant, il semble que getWidth() et getHeight() retournent 0. Mais je ne sais pas si c'est le vrai problème. Merci

59
End.Game

Voici comment j'ai résolu le problème: j'ai ajouté un écouteur onLayoutChange à la vue dans le rappel onCreateView.

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        // Inflate the layout for this fragment
        final View view = inflater.inflate(R.layout.fragment_map_list, container, false);
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
            view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                @TargetApi(Build.VERSION_CODES.Lollipop)
                @Override
                public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                    v.removeOnLayoutChangeListener(this);
                    toggleInformationView(view);
                }
            });
        }
        return view;
    }
70
Fernando Gallego

Vous pouvez utiliser runnable pour faire l'animal. Ce runnable s'exécutera après la création de la vue.

view.post(new Runnable() {
            @Override
            public void run() {
                //create your anim here
            }
        });
34
BennyKok

Petit ajout à Hitesh answer . Il vaut mieux utiliser https://developer.Android.com/reference/Android/support/v4/view/ViewCompat.html#isAttachedToWindow(Android. view.View)

Android.support.v4.view.ViewCompat

boolean isAttachedToWindow (View view)

Exemple:

LinearLayout rootView = null;
rootView = (LinearLayout) findViewById(R.id.rootView);
boolean isAttachedToWindow = ViewCompat.isAttachedToWindow(rootView);
12
Alexander

Pourquoi ne pas simplement placer la méthode dans la méthode onViewCreated ():

@Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        toggleInformationView(view);
    }

Ça marche 

6
Ziv Kesten

simplifié en dehors du champ de la question

private void startAnimation(@NonNull final View view, @NonNull final Runnable onAttachedToWindow) {
    if (view.isAttachedToWindow()) {
        onAttachedToWindow.run();
    } else {
        view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View view) {
                onAttachedToWindow.run();
                view.removeOnAttachStateChangeListener(this)
            }

            @Override
            public void onViewDetachedFromWindow(View view) {

            }
        });
    }
}

appelez startAnimation pour une ou plusieurs animations en tête

startAnimation(view, new Runnable() {
        @Override
        public void run() {
          //the code inside toggleInformationView(view)
        }
    });
2
Juan Mendez

ah !!!, alors enfin voici la solution à cette erreur. En réalité, le problème est que nous attribuons une vue à une animation avec sa hauteur et sa largeur, et tout à coup nous n’avons pas remarqué qu’il pouvait y avoir un cas, cette vue ne se chargerait pas correctement cette fois-ci lorsque nous l’assignons à une animation. Donc, pour cela, nous devons attendre que la vue soit correctement chargée.

LayoutInflater inflater = this.getLayoutInflater();
View rowView = inflater.inflate( R.layout.fileselecttype,null, true );

rowView   or [Your View]

[Your View].post(new Runnable() {
            @Override
            public void run() {
                //Do your animation work here.
            }
        });
2
Sohaib Aslam

Essayez de l'appeler avec la méthode onViewCreated

1
Fernando Gallego

Utilisez un ViewTreeObserver.

 ViewTreeObserver viewTreeObserver = rootLayout.getViewTreeObserver();
    if (viewTreeObserver.isAlive()) {
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                revealActivity(revealX, revealY);
                rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });
    }
1
josedlujan

J'utilisais une vue personnalisée. J'ai donc utilisé la méthode isAttachedToWindow() pour vérifier si la vue est attachée et éviter de révéler si la vue n'est pas attachée.

0
Hitesh Sahu

Vérifiez que votre mise en page est attachée à la fenêtre ou non en utilisant la méthode rootLayout.isAttachedToWindow().

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        if (rootLayout!= null) {

            if(rootLayout.isAttachedToWindow()) {
                ViewTreeObserver viewTreeObserver = drawerLayout.getViewTreeObserver();
                if (viewTreeObserver.isAlive()) {
                    viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                        @Override
                        public void onGlobalLayout() {
                            startRevealAnimation(rootLayout);
                            rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        }
                    });
                }
            }
        }
0
Rehan Sarwar