Как приложение контактов Android L свернуть свою панель инструментов?
Я пытаюсь воспроизвести способ, которым приложение "Контакты" версии 5.0 сворачивает панель инструментов при прокрутке списка.
Галерея скриншотов, демонстрирующих желаемое взаимодействие
Обратите внимание на крах панели инструментов поэтапно, где он отображает поиск + последний контакт, исчезает последний контакт, сворачивает последний контакт, сворачивает поиск, оставляя только вкладки.
До сих пор у меня есть панель инструментов, расположенная над recyclerview в LinearLayout, и панель инструментов используется как панель действий, а не отдельная.
Я не могу понять, как перехватить событие touch на recyclerview и заставить его сжимать панель инструментов, а затем вернуть событие прокрутки в recyclerview. Я попытался поместить все это в scrollview, но затем recyclerview не смог правильно рассчитать высоту и не отобразить содержимое. Я попробовал переопределить onscroll на recyclerview и обнаружил, что он только уведомит меня о начале прокрутки и предоставит мне первый видимый идентификатор карты.
Как это выглядит правильно, но я не могу работать для жизни меня, это:
getSupportActionBar().setHideOnContentScrollEnabled(true);
Что возвращает:
Caused by: java.lang.UnsupportedOperationException: Hide on content scroll is not supported in this action bar configuration.
Использование традиционной панели действий, установка под ней панели инструментов и установка hideoncontentscrollenabled также не работали, прокрутка никогда не вызывала метод hide на панели действий.
- изменить -
Мне удалось заставить hideOnContentScrollEnabled работать с списком с помощью традиционного экрана действий, но поведение не совпадает с поведением контактов. Это явно не метод, который они использовали - он просто запускает .hide() на панели действий, когда событие перелета происходит в списке, что заметно отличается от приложения-контакта, которое перетаскивает панель инструментов вместе со случаем прокрутки.
-/edit -
Итак, я отказался от этого маршрута и поместил fill_parent на высоту карты и анимировал крах на панели инструментов. Но как я могу вызвать его так, чтобы он следовал за событием touch, а затем возвратил событие touch в recyclerview?
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/actionBarSize"
android:background="@color/colorPrimary"
/>
<fragment android:name="me.myapplication.FragmentTab"
android:id="@+id/tab_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="8dp"
android:background="#eeeeee"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
styles.xml
...
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
MainActivity.java
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
// Disable the logo in the actionbar, as per material guidelines
toolbar.getMenu().clear();
toolbar.setTitle("My toolbar");
setSupportActionBar(toolbar);
Ответы
Ответ 1
Я еще не исследовал исходный код, но этот парень, похоже, сделал жизнь легкой, но просветительной.
https://github.com/ksoichiro/Android-ObservableScrollView
ИЗМЕНИТЬ
Google только что выпустила Android Design Library. Посмотрите, как он содержит все эффекты обрушения панелей инструментов и многое другое.
Ответ 2
Ну, я понятия не имею, как они это делают, но... почему бы вам не взглянуть на исходный код? К счастью для нас, приложение "Контакты" по-прежнему является открытым исходным кодом на Android L (другим не так повезло, как "Контакты", например "Почта", которые больше не работают на L или "Клавиатура", которые они перестали обновлять с момента запуска их проприетарной Google Keyboard).
В любом случае, здесь исходный код, на который я думаю, вам следует посмотреть:
https://github.com/android/platform_packages_apps_contacts/blob/master/src%2Fcom%2Fandroid%2Fcontacts%2Factivities%2FActionBarAdapter.java
Обратите внимание на метод update(boolean skipAnimation)
в строке 311, который вызывает animateTabHeightChange(int start, int end)
(строка 437).
Мое предположение - все, что там происходит, -)
Ответ 3
По состоянию на июнь 2015 года желаемый эффект можно выполнить с помощью так называемой CollapsingToolbarLayout новой библиотеки поддержки дизайна.
На основе примера кода здесь, я полагаю, что:
- Карточка поиска является дочерней на панели инструментов
- карта пропущенного вызова принадлежит к collapsingtoolbar с атрибутом
collapseMode
, установленным для вывода
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="112dp"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="?attr/actionBarSize"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed|enterAlways">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="false"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways">
<!-- Search layout -->
<android.support.v7.widget.CardView
</android.support.v7.widget.CardView>
</android.support.v7.widget.Toolbar>
<!-- Last call card view-->
<android.support.v7.widget.CardView
app:layout_collapseMode="pin">
</android.support.v7.widget.CardView>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/primary_color"
app:layout_scrollFlags="scroll"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Ответ 4
Не требуется сторонняя библиотека! Android официально предоставляет библиотеку. Вы можете свернуть панель инструментов и сделать много других настроек.
Отметьте это блог разработчика Android
И не забудьте добавить эту зависимость в ваш файл build.gradle
.
compile 'com.android.support:design:22.2.0'
Ответ 5
Я нашел эту библиотеку, которая, кажется, делает то, что вы ищете: https://github.com/kmshack/Android-ParallaxHeaderViewPager и https://github.com/flavienlaurent/NotBoringActionBar
Вы можете воспроизвести видео, чтобы увидеть поведение: https://www.youtube.com/watch?v=sCP-b0a1x5Y
Это может быть не "новый" стандартный способ сделать это с помощью ToolBar, но он может дать вам представление, проверив код. Кажется, он присоединяет OnScrollListener к прокручиваемому контенту и затем запускает изменения в размере панели.
Ответ 6
Для меня https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling%28part3%29/ помогло. Исходный код можно найти здесь: https://github.com/mzgreen/HideOnScrollExample/tree/master/app/src/main.
RecycleView в вашем макете должен выглядеть так:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Обратите внимание, что после запуска приложения появляются две панели инструментов (панель действий и панель инструментов). Поэтому в вашей деятельности .java вы должны написать так:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide ActionBar.
supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
getSupportActionBar().hide();
setContentView(R.layout.your_activity_layout);
...
Панель инструментов настроена так, как показано ниже: fooobar.com/questions/28770/.... Я имею в виду, он появляется без названия и любых других элементов, поэтому вы можете добавить их в макет.
Ответ 7
Приложение Android Contact не имеет простого решения plug-and-play, которое вы можете использовать для своего приложения.
Он выполняет полную реализацию, в основном делая это так же, как и вы, если бы вы реализовали его с нуля. Для контекста, прежде чем смотреть на код, имейте в виду, как выглядят представления:
https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/res/layout/quickcontact_activity.xml
MultiShrinkScroller - это FrameLayout, который интермедирует поведение прокрутки, но основной материал находится в LinearLayout, поэтому уменьшение высоты высших видов будет "прокручивать" нижние виды вверх.
Ключевым файлом для реализации является следующий:
https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/src/com/android/contacts/widget/MultiShrinkScroller.java
public void scrollTo(int x, int y) {
final int delta = y - getScroll();
boolean wasFullscreen = getScrollNeededToBeFullScreen() <= 0;
if (delta > 0) {
scrollUp(delta);
} else {
scrollDown(delta);
}
updatePhotoTintAndDropShadow();
updateHeaderTextSizeAndMargin();
//... other stuff
}
private void scrollUp(int delta) {
// Collapse higher views first
if (getTransparentViewHeight() != 0) {
final int originalValue = getTransparentViewHeight();
setTransparentViewHeight(getTransparentViewHeight() - delta);
setTransparentViewHeight(Math.max(0, getTransparentViewHeight()));
delta -= originalValue - getTransparentViewHeight();
}
// Shrink toolbar as needed
final ViewGroup.LayoutParams toolbarLayoutParams
= mToolbar.getLayoutParams();
if (toolbarLayoutParams.height > getFullyCompressedHeaderHeight()) {
final int originalValue = toolbarLayoutParams.height;
toolbarLayoutParams.height -= delta;
toolbarLayoutParams.height = Math.max(toolbarLayoutParams.height,
getFullyCompressedHeaderHeight());
mToolbar.setLayoutParams(toolbarLayoutParams);
delta -= originalValue - toolbarLayoutParams.height;
}
// Finally, scroll content if nothing left to shrink
mScrollView.scrollBy(0, delta);
}
updatePhotoTintAndDropShadow();
и updateHeaderTextSizeAndMargin();
обрабатывают изменение оттенка и текста по мере его свертывания, так что он превращается в внешний вид регулярного ActionBar/ToolBar.
Вы можете захватить сам файл MultiShrinkScroller и адаптировать его для собственного использования, но в настоящее время, вероятно, есть более простые реализации (в том числе и из библиотеки дизайна Android).