У меня есть линейный макет, который я хочу переместить, когда появляется Snackbar.
Я видел много примеров, как это сделать с помощью FloatingButton, но как насчет регулярного представления?
У меня есть линейный макет, который я хочу переместить, когда появляется Snackbar.
Я видел много примеров, как это сделать с помощью FloatingButton, но как насчет регулярного представления?
Вам нужно добавить поведение к вашему LinearLayout и вставить его в CoordinatorLayout. Вы можете прочитать следующее: http://alisonhuang-blog.logdown.com/posts/290009-design-support-library-coordinator-layout-and-behavior
Я собираюсь рассказать об утверждённом ответе, потому что я думаю, что есть несколько более простая реализация, чем в этой статье.
Мне не удалось найти встроенное поведение, которое обрабатывает общее перемещение представлений, но это хороший вариант общего назначения (из http://alisonhuang-blog.logdown.com/posts/290009-design-support-library-coordinator-layout-and-behavior, связанный в другом комментарии):
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 comment)
@Override
public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {
ViewCompat.animate(child).translationY(0).start();
}
}
то в вашем файле макета добавьте layout_behavior, как показано ниже:
<LinearLayout
android:id="@+id/main_content"
android:orientation="vertical"
app:layout_behavior="com.example.MoveUpwardBehavior"/>
где layout_behavior - это полный путь к вашему пользовательскому поведению. Там нет необходимости подкласса LinearLayout, если у вас нет конкретной необходимости иметь поведение по умолчанию, которое кажется необычным.
На основании ответа @Travis Castillo. Исправлены такие проблемы, как:
Moving entire layout up and cause the objects on top of view disappear.
Doesnt push the layout up when showing SnackBars immediately after eachother.
Итак, здесь фиксированный код для MoveUpwardBehavior Class:
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();
}
}
Эти коды подталкивают то, что видит пользователь на экране, и, кроме того, пользователь имеет доступ ко всем объектам в вашем макете, пока отображается SnackBar.
Если вы хотите, чтобы SnackBar закрывал объекты, а не нажал, и, кроме того, у пользователя есть доступ ко всем объектам, вам нужно изменить метод 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;
}
и метод onDependentViewRemoved:
@Override
public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {
//Reset paddings and translationY to its default
child.setPadding(0, 0, 0, 0);
}
К сожалению, вы потеряете анимацию при удалении пользователя, чтобы удалить SnackBar. И вы должны использовать класс ValueAnimator, чтобы сделать анимацию для изменений дополнений, что делает некоторые конфликты здесь, и вы должны их отлаживать.
https://developer.android.com/reference/android/animation/ValueAnimator.html
Любые комментарии об анимации для салфетки для удаления SnackBar оценены.
Если вы можете пропустить эту анимацию, вы можете ее использовать.
Во всяком случае, я рекомендую первый тип.
Я реализовал это и обнаружил, что когда закусочная исчезла, вид остался белым пространством в месте закусочных, очевидно, это известно, если анимация отключена на устройстве.
Чтобы исправить это, я изменил метод onDependentViewChanged, чтобы сохранить начальную позицию Y вида, к которой привязано это поведение. Затем при удалении закусочной reset положение этого вида в сохраненное положение Y
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);
}
В дополнение к Тревису Кастильо ответ:
Чтобы разрешить запуск последовательных SnackBars, в пределах onDependentViewChanged()
вам нужно отменить любую возможную текущую анимацию, начатую 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;
}
Без отмены LinearLayout спрыгнет ниже второго SnackBar, когда SnackBar будет заменен другим SnackBar.
Я написал библиотеку, в которую можно добавить дополнительные представления для анимации с помощью SnackProgressBar. Он также включает progressBar и другие вещи. Попробуйте https://github.com/tingyik90/snackprogressbar
Предположим, у вас есть следующие виды для анимации.
View[] views = {view1, view2, view3};
Создайте экземпляр SnackProgressBarManager в своей деятельности и включите представление для анимации.
SnackProgressBarManager snackProgressBarManager = new SnackProgressBarManager(rootView)
.setViewsToMove(views)
Когда SnackProgressBar отображается или отклоняется, эти представления будут соответственно анимированы.
НЕТ необходимости в компоновке координатора, используя обычный вид, выровняйте снэк-панель в нижней части представления и поместите кнопку поверх нее, нажав кнопку любой вашей логики показать закуски или линейную компоновку.
<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>