Часть содержимого CollapsingToolbarLayout становится липкой сверху, когда используется с viewpager и recyclerview - PullRequest
11 голосов
/ 06 мая 2020

Я пытаюсь реализовать такой макет:

enter image description here

Проблема в том, что при прокрутке вверх карта касается панели инструментов, а она не go больше не так:

enter image description here

Я хочу, чтобы он прокручивался вверх, пока окно просмотра не заполнит экран ie, по крайней мере, прямоугольник card, должен прокручиваться вверх за пределы панели инструментов (даже tabLayout также может прокручиваться вверх). Но я не хочу, чтобы он оставался липким вверху.

Основной макет находится здесь:

 <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:showIn="@layout/activity_main">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/background_dark"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/toolbarCollapse"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="190dp"
                android:minHeight="190dp"
                android:src="@drawable/ic_launcher_foreground"
                app:layout_collapseMode="parallax" />


            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                app:layout_collapseMode="pin" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>


    </com.google.android.material.appbar.AppBarLayout>


    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:behavior_overlapTop="90dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:id="@+id/lin"
            android:nestedScrollingEnabled="false"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <include layout="@layout/debit_card_item" />


            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabLayout"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                android:layout_marginTop="40dp"
                android:background="?attr/colorPrimary" />


            <androidx.viewpager.widget.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

        </LinearLayout>
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Фрагменты пейджера находятся внутри NestedScrollView, например:

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rcView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>

Вещи, которые я пробовал:

  1. Я попытался удалить NestedScrollView над линейным макетом и добавил app:behavior_overlapTop="90dp" app:layout_behavior="@string/appbar_scrolling_view_behavior" в линейный макет. но он по-прежнему дает мне тот же результат.
  2. Установить высоту пейджера вида статически (дал тот же результат).

- >>> EDIT <<< 3. Я подумал об обходном пути и пытаюсь добавить настраиваемое поведение в свой LinearLayout в моем mainActivity. так, чтобы уменьшить нижнее поле и высоту карточки rect angular. Когда я открываю и закрываю сворачивающуюся панель инструментов, это дает хорошие результаты. Но когда я удерживаю и прокручиваю, экран мерцает, как показано ниже: </p>

enter image description here

Мое настраиваемое поведение

class CustomHeaderBehavior : AppBarLayout.ScrollingViewBehavior {
    private var mContext: Context

    var height = 0
    var width = 0
    var marginBottom = 0
    var firstTime = true

    constructor(
        context: Context,
        attrs: AttributeSet?
    ) : super(context, attrs) {
        mContext = context
    }

    constructor(
        context: Context?,
        attrs: AttributeSet?,
        mContext: Context
    ) : super(context, attrs) {
        this.mContext = mContext
    }

    override fun layoutDependsOn(
        parent: CoordinatorLayout,
        child: View,
        dependency: View
    ): Boolean {
        return super.layoutDependsOn(parent, child, dependency)
    }

    override fun onDependentViewChanged(
        parent: CoordinatorLayout,
        childP: View,
        dependency: View
    ): Boolean {
        val child = childP.findViewById<RelativeLayout>(R.id.cardParent)
        val maxScroll: Int = (dependency as AppBarLayout).totalScrollRange
        val percentage =
            abs(dependency.y) / maxScroll.toFloat()
        Log.d("Behavx","D.y "+abs(dependency.y)+ " m s "+maxScroll+ " p "+percentage)
        val lp: LinearLayout.LayoutParams =
            child.layoutParams as LinearLayout.LayoutParams
        if(firstTime){
            height = child.height
            width = child.width
            marginBottom = lp.bottomMargin
            firstTime = false
        }
        Log.d("Behaviour", "P "+ ((1-(percentage))*100).toString() +" H " +height+ " U H " +(height*(((1-(percentage))*100))/100) )
//        lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100) - ((height*((((percentage))*100))/100))).toInt()
        lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100)).toInt() //updating margin bottom
        lp.height = ((height*(((1-(percentage))*100))/100)).toInt() //updating height

        child.layoutParams = lp
        child.alpha = 1 - (percentage * 4)
        return super.onDependentViewChanged(parent, childP, dependency)

    }


    companion object {
        fun getToolbarHeight(context: Context): Int {
            var result = 0
            val tv = TypedValue()
            if (context.theme.resolveAttribute(R.attr.actionBarSize, tv, true)) {
                result = TypedValue.complexToDimensionPixelSize(
                    tv.data,
                    context.resources.displayMetrics
                )
            }
            return result
        }
    }
}

Кажется, что мерцание происходит из-за того, что dependency.y случайно становится неправильным, в то время как я удерживаю, прокручиваю и обновляю высоту карты (если я только обновляю поля, мерцания не происходит). Почему-то управление шириной происходит плавно. Но, к сожалению, это мне здесь не помогает.

Я также попытался сделать что-то подобное, добавив offsetChangedListener на панель приложения следующим образом:

appBar.addOnOffsetChangedListener (OnOffsetChangedListener {appBarLayout, verticalOffset -> if (abs (verticalOffset) = = appBarLayout.totalScrollRange) {// Свернутая cardParent.visibility = View.GONE} else {// Расширенная картаParent.visibility = View.VISIBLE}})

Но я все еще получаю мерцание

Я добавил сюда образец проекта: ссылка на github Пользовательское поведение перенесено в новую ветку custom_behaviour

Ответы [ 2 ]

5 голосов
/ 11 мая 2020

Наконец-то решена моя проблема. Я добавил карту внутри сворачивающегося макета, например, Kalyans answer , и добавил фиктивный вид и поле -ve к карте, чтобы иметь эффект перекрытия, например

<com.google.android.material.appbar.CollapsingToolbarLayout
        android:id="@+id/toolbarCollapse"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            app:layout_collapseMode="pin" />

        <View
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="#000" />

        <include
            layout="@layout/debit_card_item"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="-90dp"
            app:layout_collapseMode="parallax" />
    </LinearLayout>

</com.google.android.material.appbar.CollapsingToolbarLayout>

Я также нажал мой код в github.

2 голосов
/ 07 мая 2020

Для достижения этого эффекта макет карточки должен находиться внутри сворачивающейся панели инструментов.

Попробуйте заменить это:

<ImageView
            android:layout_width="match_parent"
            android:layout_height="190dp"
            android:minHeight="190dp"
            android:src="@drawable/ic_launcher_foreground"
            app:layout_collapseMode="parallax" />

на:

<include layout="@layout/debit_card_item"
            android:layout_width="match_parent"
            android:layout_height="190dp"
            android:minHeight="190dp"
            android:layout_marginTop="32dp"
            android:layout_marginBottom="72dp"
            app:layout_collapseMode="parallax"/>

и удалите <include layout="@layout/debit_card_item" /> в NestedScrollView.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...