简体   繁体   中英

AppBarLayout overlap my custom view with layout_behavior

I have a custom header with a custom behavior that interacting with a coordinator layout. This header depends on an appBarLayout that contains a collapsingToolbarLayout and a Toolbar. When the toolbar layout collapses, the custom header adjust its properties and position the way I want, but the second I reach the min height of the layout, the appBarLayout overlaps the custom header and I can't see it until I begin expanding it.

在此输入图像描述

在此输入图像描述

This is the code for the layout:

<?xml version="1.0" encoding="utf-8"?><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">

<android.support.design.widget.AppBarLayout
    android:id="@+id/toolbar_layout"
    android:layout_width="match_parent"
    android:layout_height="@dimen/mk_appbar_height">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/toolbar_collapse"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:minHeight="@dimen/mt_toolbar_height"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        app:titleEnabled="false">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            style="@style/ToolbarStyle"
            android:layout_width="match_parent"
            android:layout_height="@dimen/mt_toolbar_height"
            app:layout_collapseMode="pin"
            />

    </android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

<!-- This is a layout intended for containing MonkeyChatFragment and/or MonkeyConversationsFragment
RelativeLayout has an issue that doesn't render the RecyclerView with the whole size of its
container linear layout.
The only viable solution is FrameLayout -->
<FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<FrameLayout
    android:id="@+id/viewStatus"
    android:layout_width="match_parent"
    android:layout_height="@dimen/status_height"
    android:layout_marginTop="@dimen/status_inverse_height"
    android:background="@color/mk_status_connected"/>

<com.criptext.monkeykitui.toolbar.HeaderView
    android:id="@+id/custom_toolbar"
    layout="@layout/custom_toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="56dp"
    app:layout_behavior="com.criptext.monkeykitui.toolbar.HeaderViewBehavior"
    app:behavior_overlapTop="64dp"
    /></android.support.design.widget.CoordinatorLayout>

and this is the code of the layout_behavior:

class HeaderViewBehavior(context: Context, attrs: AttributeSet? = null) : CoordinatorLayout.Behavior<HeaderView>(context, attrs){

private val MIN_AVATAR_PERCENTAGE_SIZE = 0.3f
private val EXTRA_FINAL_AVATAR_PADDING = 80

private val TAG = "behavior"
private val mContext: Context = context

private val mCustomFinalHeight: Float = 0.toFloat()

private var mStartToolbarPosition: Float = 0.toFloat()
private var mStartYPosition: Int = 0
private var mFinalYPosition: Int = 0
private var mStartHeight: Int = 0
private var mfontSize: Float = 20.toFloat()
private var mChangeBehaviorPoint: Float = 0.toFloat()

override fun layoutDependsOn(parent: CoordinatorLayout?, child: HeaderView?, dependency: View?): Boolean {
    var hello = (dependency is AppBarLayout)
    return hello
}

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

    val maxScrollDistance = - mContext.resources.getDimension(R.dimen.mk_header_scroll)
    val expandedPercentageFactor = dependency.y / maxScrollDistance
    Log.d("TEST", dependency.y.toString())
    Log.d("TEST", maxScrollDistance.toString())


    if (expandedPercentageFactor < mChangeBehaviorPoint) {
        val heightFactor = (mChangeBehaviorPoint - expandedPercentageFactor) / mChangeBehaviorPoint

        val distanceYToSubtract = (mStartYPosition - mFinalYPosition) * (1f - expandedPercentageFactor) + child.getHeight() / 2

        child.setY(mStartYPosition - distanceYToSubtract)

        val heightToSubtract = (mStartHeight - mCustomFinalHeight) * heightFactor

        val lp = child.layoutParams as CoordinatorLayout.LayoutParams

        child.layoutParams = lp
    } else {
        val distanceYToSubtract = (mStartYPosition - mFinalYPosition) * (1f - expandedPercentageFactor)

        child.setY(mStartYPosition - distanceYToSubtract)

        if(mStartYPosition - distanceYToSubtract < mStartYPosition){
            child.setY(mStartYPosition.toFloat())
        }else if(mStartYPosition - distanceYToSubtract > mFinalYPosition){
            child.setY(mFinalYPosition.toFloat())
        }

        child.title.textSize = mfontSize - (mfontSize - 25) * (1f - expandedPercentageFactor)
        child.subtitle.textSize = 15 - (15 - 20) * (1f - expandedPercentageFactor)

        child.imageView.layoutParams.height = (126 - (126 - 226) * (1f - expandedPercentageFactor)).toInt()
        child.imageView.layoutParams.width = (126 - (126 - 226) * (1f - expandedPercentageFactor)).toInt()

    }
    return true
}

private fun maybeInitProperties(child: HeaderView, dependency: View) {
    if (mStartYPosition === 0)
        mStartYPosition = 0

    if (mFinalYPosition === 0)
        mFinalYPosition = mContext.resources.getDimension(R.dimen.mk_header_scroll).toInt()

    if (mStartHeight === 0)
        mStartHeight = child.getHeight()

    if (mStartToolbarPosition === 0.toFloat())
        mStartToolbarPosition = dependency.y

    if (mChangeBehaviorPoint === 0.toFloat())
        mChangeBehaviorPoint = (child.height - mCustomFinalHeight) / (2f * (mStartYPosition - mFinalYPosition))
}
}

Just in case anyone else is looking for the same answer I can say I've found solution in another SO question after literally wasting 6 hours trying various solutions to no avail.

To make View visibly overlay AppBarLayout after the latter has been collapsed you need to add android:elevation="8dp" (or higher value) property to the overlaying View .

So, the part of the code in the question that needs to change is:

<com.criptext.monkeykitui.toolbar.HeaderView
    android:id="@+id/custom_toolbar"
    layout="@layout/custom_toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="56dp"
    app:layout_behavior="com.criptext.monkeykitui.toolbar.HeaderViewBehavior"
    app:behavior_overlapTop="64dp"
/>

to:

<com.criptext.monkeykitui.toolbar.HeaderView
    android:id="@+id/custom_toolbar"
    layout="@layout/custom_toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="56dp"
    app:layout_behavior="com.criptext.monkeykitui.toolbar.HeaderViewBehavior"
    app:behavior_overlapTop="64dp"
    android:elevation="8dp"
/>

All credits go to @kris larson 's answer here: CoordinatorLayout custom behavior with AppBarLayout

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM