Поместите Snackbar на самом высоком уровне z, чтобы избежать блокировки выпадающим меню AutoCompleteTextView
У меня есть Snackbar
, который выглядит следующим образом:
Однако, если выпадающий список AutoCompleteTextView
слишком длинный, выпадающий список заблокирует Snackbar
.
Как вы можете видеть на приведенном выше изображении, Snackbar
на самом деле показывает. Однако его видимость блокируется длинным падением вниз. Вы можете видеть из приведенного выше изображения
Я стараюсь использовать следующее Snackbar code
. Добавление bringToFront()
не очень помогает.
private void showSnackbar(String message) {
Snackbar snackbar
= Snackbar.make(getActivity().findViewById(R.id.content), message, Snackbar.LENGTH_LONG);
snackbar.getView().bringToFront();
snackbar.show();
}
R.id.content
является CoordinatorLayout
:
<android.support.design.widget.CoordinatorLayout
android:id="@+id/content"
android:background="?attr/MyActivityBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?attr/headerShadow" />
Есть ли какой-нибудь хороший способ, чтобы избежать Snackbar
от того, чтобы быть покрытым падением AutoCompleteTextView
?
6 ответов:
Возможно, у меня есть решение для этого случая. Конечно, есть некоторые предположения, но, возможно, решение вас устроит.
Ключ здесь заключается в том, чтобы поместить
AutoCompleteTextView
внутрьCoordinatorLayout
и добавить к нему пользовательскийCoordinatorLayout.Behavior
.Конечно, это очень простое решение, которое, например, не анимирует высоту списка, но я думаю, что это хорошее начало. Вот полнаясуть .
Создайте соответствующий
Behavior
для вашего класса:public class AutoCompleteTextViewBehaviour extends CoordinatorLayout.Behavior<AutoCompleteTextView> { public AutoCompleteTextViewBehaviour(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, AutoCompleteTextView child, View dependency) { return dependency instanceof Snackbar.SnackbarLayout; } }
Переопределить метод
layoutDependsOn
:@Override public boolean layoutDependsOn(CoordinatorLayout parent, AutoCompleteTextView child, View dependency) { return dependency instanceof Snackbar.SnackbarLayout; }
Получить ссылку на
К сожалению, я не нашел для этого простого решения. Однако это можно сделать с помощью отражение.AutoCompleteTextView
всплывающее окно:@Nullable private View getPopupList(AutoCompleteTextView child) { try { Field popupField; Class clazz; if (child instanceof AppCompatAutoCompleteTextView) { clazz = child.getClass().getSuperclass(); } else { clazz = child.getClass(); } popupField = clazz.getDeclaredField("mPopup"); popupField.setAccessible(true); ListPopupWindow popup = (ListPopupWindow) popupField.get(child); Field popupListViewField = popup.getClass().getDeclaredField("mDropDownList"); popupListViewField.setAccessible(true); return (View) popupListViewField.get(popup); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }
Переопределение
onDependentViewChanged
метод:@Override public boolean onDependentViewChanged(CoordinatorLayout parent, final AutoCompleteTextView child, View dependency) { if (popupList == null) { popupList = getPopupList(child); if (popupList == null) { return super.onDependentViewChanged(parent, child, dependency); } } int dropdownBottom = child.getBottom() + child.getDropDownVerticalOffset() + popupList.getHeight(); int snackBarTop = dependency.getTop(); int difference = dropdownBottom - snackBarTop; if (difference > 0) { child.setDropDownHeight(popupList.getHeight() - difference); return true; } else { child.setDropDownHeight(ViewGroup.LayoutParams.WRAP_CONTENT); } return super.onDependentViewChanged(parent, child, dependency); }
Примените поведение к
AutocompleteTextView
в.xml
:app:layout_behavior="com.example.package.AutoCompleteTextViewBehaviour"/>
Вы можете рассчитать и настроить высоту всплывающего окна в качестве альтернативы. На следующем рисунке я устанавливаю высоту выпадающего списка следующим образом:
textView.viewTreeObserver.addOnGlobalLayoutListener { textView.dropDownHeight = snackbarView.top - textView.bottom }
Это вычисление для случая, когда высота списка предложений достаточно велика. Вместо этого вы можете установить для этого свойства значение
Насколько мне известно, изменить "z-порядок" невозможно, если вы не добавите закусочную непосредственно кWRAP_CONTENT
.WindowManager
.AutoCompleteTextView
внутренне используетListPopupWindow
, чтобы показать всплывающее окно предложений иListPopupWindow
имеет тип окнаWindowManager.LayoutParams.TYPE_APPLICATION_PANEL
= 1000, который выше, чем тип окна действия, который имеетWindowManager.LayoutParams.TYPE_APPLICATION
= 2.
Почему бы просто не установить
android:dropDownHeight
в фиксированноеdp
значение? Вы даже можете определить его динамически на основе размера экрана, обратившись к ресурсуdimension
. Это одна строка кода, она решает вашу проблему, проста в обслуживании и понимании (через полгода вы спросите себя, для чего используется весь материалBehavior
).
Я думаю, что вы должны принять во внимание много мыслей:
- должно быть место для всех. клавиатура, закусочная и автозаполнение Textview
- Вы не можете изменить высоту клавиатуры (с помощью вашего приложения), поэтому вы должны изменить высоту автозаполнения TextView, чтобы быть выше закусочной (которая находится над клавиатурой)
В моем случае я мог бы заставить его работать с
setZ
:Snackbar snackbar = Snackbar.make(container, text, Snackbar.LENGTH_LONG); snackbar.getView().setZ(200); snackbar.show();
Шаг 1. Реализовать новое поведение
Необходимо проверить, поддерживает ли операционное устройство snackbar.
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> { private static final boolean SNACKBAR_BEHAVIOR_ENABLED; @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight()); child.setTranslationY(translationY); return true; } static { SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= 11; } }
Шаг 2. Реализуйте пользовательский вид, чтобы мы могли применить к нему MoveUpwardBehavior.
В этом случае мы заставляем весь LinearLayout взаимодействовать с snackbar. Это очень просто, как здесь сказано, просто передайте класс в defaultbehavior аннотации.
Шаг 3. Почти Готово!@CoordinatorLayout.DefaultBehavior(MoveUpwardBehavior.class) public class CustomLinearLayout extends LinearLayout { public CustomLinearLayout(Context context) { super(context); } public CustomLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
Добавьте CustomLinearLayout в макет. Помните, что он должен быть включен Координаторлай!
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.alisondemo.musicgenre.CustomLinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> ... </com.example.alisondemo.musicgenre.CustomLinearLayout> </android.support.design.widget.CoordinatorLayout>
Но....почему нам даже не нужно реализовывать поведение для FAB?
Сформируйте исходный код android.поддержка.дизайн.штучка.Класс FloatingActionButton, как вы можете видеть:
@DefaultBehavior (FloatingActionButton.Поведение.класс) FloatingActionButton общественный класс расширяет графическое представление { ... Да, у него на самом деле реализовано собственное поведение.
Заключение
Мы можем реализовать любой тип поведения, который мы хотим, в любых представлениях. Это должно быть очень интересный. :)
Вы можете увидеть только демо: http://alisonhuang-blog.logdown.com/posts/290009-design-support-library-coordinator-layout-and-behavior
Полный исходный код теперь на GitHub https://github.com/Alishuang/MusicGenre