AppBarLayout与我的自定义行为重叠了一个自定义布局

时间:2018-11-12 11:29:34

标签: android material-design android-coordinatorlayout android-appbarlayout

我知道有很多关于SO重叠的问题。但以我为例,我不明白如何更改行为以删除重叠部分并使文本滚动。

Google的文档说,我们必须为coordinatorLayout的所有子项添加“ app:layout_behavior”,如果我添加了

  layout_behavior="@string/appbar_scrolling_view_behavior"

重叠被删除,但是如何使用我的自定义行为来估计重叠。我调试了onMeasureChild和onLayoutChild方法,并且每次使用自定义行为时都看到appBarLayout的高度等于0。

CoordinatorLayout

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|snap">

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

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

        <LinearLayout
            android:id="@+id/navigation_tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:background="@color/colorPrimary"/>

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

  <com.navigation.NavigationLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@android:color/white"
      android:layout_gravity="bottom"
      >

      <TextView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="@string/text"/>

  </com.navigation.NavigationLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>     

NavigationLayout

class NavigationLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
                      defStyleAttr: Int = 0):   FrameLayout(context, attrs, defStyleAttr),
                                                CoordinatorLayout.AttachedBehavior {

    override fun getBehavior(): CoordinatorLayout.Behavior<NavigationLayout> {
        return NavigationBehavior()
    }

    private val recyclerView: RecyclerView?
    private val progressBar: ProgressBar? = null

    init {
        val a = context.obtainStyledAttributes(attrs, R.styleable.NavigationLayout,defStyleAttr,0)
        val behavior = a.getBoolean(R.styleable.NavigationLayout_nav_layout_behavior, false)

        removeAllViews()

        a.recycle()
    }

}

我使用NavigationBehavior中的下一个代码解决了这个问题。我有与在XML app中使用时相同的行为:layout_behavior =“ @ string / appbar_scrolling_view_behavior

    class NavigationBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<NavigationLayout>(context, attrs) {

        override fun layoutDependsOn(parent: CoordinatorLayout, child: NavigationLayout, dependency: View): Boolean {
            return dependency is AppBarLayout
        }

        override fun onDependentViewChanged(parent: CoordinatorLayout, child: NavigationLayout, dependency: View): Boolean {

            child.top = dependency.measuredHeight + dependency.y.toInt()
            val childParams = child.layoutParams
            childParams.height = child.bottom - child.top
            child.layoutParams = childParams
            return true

        }

        override fun onLayoutChild(parent: CoordinatorLayout, child: NavigationLayout, layoutDirection: Int): Boolean {
            return super.onLayoutChild(parent, child, layoutDirection)
        }


        override fun onMeasureChild(parent: CoordinatorLayout, child: NavigationLayout, parentWidthMeasureSpec: Int, widthUsed: Int,
                                    parentHeightMeasureSpec: Int, heightUsed: Int): Boolean {

            val appBarLayout = findFirstAppBarLayout(parent.getDependencies(child))

            if (appBarLayout != null) {
                val availableHeight = View.MeasureSpec.getSize(parentHeightMeasureSpec) - appBarLayout.measuredHeight
                val newParentHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(availableHeight, View.MeasureSpec.AT_MOST)
                parent.onMeasureChild(child, parentWidthMeasureSpec, widthUsed, newParentHeightMeasureSpec, heightUsed)
                return true
            } else {
                return super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed)
            }

        }

        private fun findFirstAppBarLayout(views: List<View>): AppBarLayout? =
                views.firstOrNull { view -> view is AppBarLayout } as? AppBarLayout
}

0 个答案:

没有答案