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
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;
}
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
}
});
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);
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
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)
}
});
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.
}
});
Essayez de l'appeler avec la méthode onViewCreated
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);
}
});
}
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.
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);
}
});
}
}
}