Comment déplacer une vue au-dessus de Snackbar tout comme FloatingButton

j'ai une disposition linéaire que je veux déplacer quand un Snackbar apparaît.

j'ai vu beaucoup d'exemples comment faire avec FloatingButton, mais qu'en est-il d'une vue régulière?

30
demandé sur Jonik 2015-10-19 17:37:23

7 réponses

vous devez ajouter un comportement à votre LinearLayout et l'intégrer dans un CoordinatorLayout. Vous pourriez vouloir lire ceci: http://alisonhuang-blog.logdown.com/posts/290009-design-support-library-coordinator-layout-and-behavior

12
répondu ligi 2015-10-19 14:44:22

je vais développer la réponse approuvée parce que je pense qu'il y a une mise en œuvre légèrement plus simple que cet article fournit.

Je n'ai pas été en mesure de trouver un comportement intégré qui gère un déplacement générique de vues, mais celui-ci est une bonne option à usage général (de http://alisonhuang-blog.logdown.com/posts/290009-design-support-library-coordinator-layout-and-behavior linked in another comment):

import android.content.Context;
import android.support.annotation.Keep;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

@Keep
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> {

    public MoveUpwardBehavior() {
        super();
    }

    public MoveUpwardBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof Snackbar.SnackbarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());
        ViewCompat.setTranslationY(child, translationY);
        return true;
    }

    //you need this when you swipe the snackbar(thanx to ubuntudroid's comment)
    @Override
    public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {
        ViewCompat.animate(child).translationY(0).start();
    }
}

puis, dans votre fichier de mise en page Ajouter un layout_behavior comme ci-dessous:

<LinearLayout
    android:id="@+id/main_content"
    android:orientation="vertical"
    app:layout_behavior="com.example.MoveUpwardBehavior"/>

où layout_behavior est le chemin complet vers votre comportement personnalisé. Il n'y a pas besoin de sous-classe LinearLayout sauf si vous avez un besoin spécifique d'avoir un comportement par défaut, ce qui semble peu commun.

59
répondu Travis Castillo 2017-07-26 22:17:59

basé sur la réponse de @Travis Castillo. Problèmes résolus tels que:

Moving entire layout up and cause the objects on top of view disappear.
Doesnt push the layout up when showing SnackBars immediately after eachother.

voici donc le code fixe pour la classe MoveUpwardBehavior:

import android.content.Context;
import android.support.annotation.Keep;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

@Keep
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> {

    public MoveUpwardBehavior() {

        super();

    }

    public MoveUpwardBehavior(Context context, AttributeSet attrs) {

        super(context, attrs);

    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {

        return dependency instanceof Snackbar.SnackbarLayout;

    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {

        float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());

        //Dismiss last SnackBar immediately to prevent from conflict when showing SnackBars immediately after eachother
        ViewCompat.animate(child).cancel();

        //Move entire child layout up that causes objects on top disappear
        ViewCompat.setTranslationY(child, translationY);

        //Set top padding to child layout to reappear missing objects
        //If you had set padding to child in xml, then you have to set them here by <child.getPaddingLeft(), ...>
        child.setPadding(0, -Math.round(translationY), 0, 0);

        return true;
    }

    @Override
    public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {

        //Reset paddings and translationY to its default
        child.setPadding(0, 0, 0, 0);
        ViewCompat.animate(child).translationY(0).start();

    }
}

ce code repousse ce que l'utilisateur voit à l'écran et en plus l'Utilisateur a accès à tous les objets de votre mise en page pendant que SnackBar montre.

si vous voulez que le SnackBar couvre les objets au lieu de pousser et en plus l'Utilisateur a accès à tous les objets, alors vous devez méthode de changement onDependentViewChanged:

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {

    float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());

    //Dismiss last SnackBar immediately to prevent from conflict when showing SnackBars immediately after eachother
    ViewCompat.animate(child).cancel();

    //Padding from bottom instead pushing top and padding from top.
    //If you had set padding to child in xml, then you have to set them here by <child.getPaddingLeft(), ...>
    child.setPadding(0, 0, 0, -Math.round(translationY));

    return true;
}

et méthode onDependentViewRemoved :

@Override
public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {

    //Reset paddings and translationY to its default
    child.setPadding(0, 0, 0, 0);

}

malheureusement, vous perdrez l'animation lorsque l'utilisateur passe pour supprimer SnackBar. Et vous devez utiliser la classe ValueAnimator pour faire de l'animation pour les changements de rembourrage qui font un certain conflit ici et vous devez les déboguer.

https://developer.android.com/reference/android/animation/ValueAnimator.html

tout commentaire sur l'animation pour glisser pour supprimer SnackBar apprécié.

si vous pouvez sauter cette animation alors vous pouvez l'utiliser.

de toute façon, je recommande le premier type.

10
répondu IR AGCOM 2017-07-26 16:05:20

j'ai implémenté ceci et j'ai trouvé que lorsque le snackbar a disparu la vue est restée en haut avec de l'espace blanc dans la place snackbars, apparemment ceci est connu si les animations ont été désactivées sur l'appareil.

pour corriger ceci j'ai changé la méthode onDependentViewChanged pour stocker la position initiale Y de la vue à laquelle ce comportement est attaché. Puis, en enlevant le snackbar réinitialiser la position de cette vue à la position y stockée

private static float initialPositionY;

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
    initialPositionY = child.getY();
    float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
    child.setTranslationY(translationY);
    return true;
}

@Override
public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {
    super.onDependentViewRemoved(parent, child, dependency);
    child.setTranslationY(initialPositionY);
}
3
répondu Charles Barter 2016-10-07 06:34:22

en plus de la réponse de Travis Castillo: Pour permettre le déclenchement de SnackBars consécutifs, dans onDependentViewChanged() , vous devez annuler toute animation éventuellement en cours commencé par onDependentViewRemoved() :

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
    float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());
    ViewCompat.animate(child).cancel(); //cancel potential animation started in onDependentViewRemoved()
    ViewCompat.setTranslationY(child, translationY);
    return true;
}

sans annulation, Le Saut en ligne va sauter au-dessous du 2e SnackBar quand un SnackBar est remplacé par un autre SnackBar.

1
répondu Tromse 2017-03-15 09:00:29

j'ai écrit une bibliothèque que des vues supplémentaires peuvent être ajoutées pour animer avec la barre Snackprogress. Il comprend également progressBar et d'autres choses. Essayez https://github.com/tingyik90/snackprogressbar

supposons que vous ayez les vues suivantes à animer.

View[] views = {view1, view2, view3};

créer une instance de SnackProgressBarManager dans votre activité et inclut la vue d'animer.

SnackProgressBarManager snackProgressBarManager = new SnackProgressBarManager(rootView)
        .setViewsToMove(views)

Quand une barre de Snackprogress est montrée ou rejetée, ces vues seront animées en conséquence.

0
répondu tingyik90 2017-09-04 08:00:17

pas besoin de coordinateur layout en utilisant une vue régulière alignez la barre de collation vers le bas de la vue, et placez le bouton sur le dessus de celui-ci, sur le clic du bouton de quelque soit votre logique montre snackbar ou la disposition linéaire.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
/*snackbar code

 <LinearLayout
            android:id="@+id/linear_snack bar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/margin_45"
            android:layout_alignParentBottom="true"
            android:layout_marginTop="@dimen/margin_0"
            android:background="@color/dark_grey">

            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@color/orange"
                android:gravity="center"
                android:textColor="@color/white"
                android:textSize="@dimen/text_size_h7" />

            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:textSize="@dimen/text_size_h7" />
        </LinearLayout>

<View  android:layout_above="@+id/linear_snack bar"



</RelativeLayout>
-4
répondu war_Hero 2015-10-19 14:49:53