Подтвердить что ты не робот

Как перемещать представление выше Закусочной, как FloatingButton

У меня есть линейный макет, который я хочу переместить, когда появляется Snackbar.

Я видел много примеров, как это сделать с помощью FloatingButton, но как насчет регулярного представления?

4b9b3361

Ответ 2

Я собираюсь рассказать об утверждённом ответе, потому что я думаю, что есть несколько более простая реализация, чем в этой статье.

Мне не удалось найти встроенное поведение, которое обрабатывает общее перемещение представлений, но это хороший вариант общего назначения (из 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, если у вас нет конкретной необходимости иметь поведение по умолчанию, которое кажется необычным.

Ответ 3

На основании ответа @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 оценены.

Если вы можете пропустить эту анимацию, вы можете ее использовать.

Во всяком случае, я рекомендую первый тип.

Ответ 4

Я реализовал это и обнаружил, что когда закусочная исчезла, вид остался белым пространством в месте закусочных, очевидно, это известно, если анимация отключена на устройстве.

Чтобы исправить это, я изменил метод 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);
}

Ответ 5

В дополнение к Тревису Кастильо ответ: Чтобы разрешить запуск последовательных 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.

Ответ 6

Я написал библиотеку, в которую можно добавить дополнительные представления для анимации с помощью SnackProgressBar. Он также включает progressBar и другие вещи. Попробуйте https://github.com/tingyik90/snackprogressbar

Предположим, у вас есть следующие виды для анимации.

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

Создайте экземпляр SnackProgressBarManager в своей деятельности и включите представление для анимации.

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

Когда SnackProgressBar отображается или отклоняется, эти представления будут соответственно анимированы.

Ответ 7

НЕТ необходимости в компоновке координатора, используя обычный вид, выровняйте снэк-панель в нижней части представления и поместите кнопку поверх нее, нажав кнопку любой вашей логики показать закуски или линейную компоновку.

<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>