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?
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
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.
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.
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);
}
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.
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.
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>