diff --git a/twidere/src/main/kotlin/android/support/design/widget/AccessorHeaderScrollingViewBehavior.kt b/twidere/src/main/kotlin/android/support/design/widget/AccessorHeaderScrollingViewBehavior.kt index ee5b15d60..6f6e565aa 100644 --- a/twidere/src/main/kotlin/android/support/design/widget/AccessorHeaderScrollingViewBehavior.kt +++ b/twidere/src/main/kotlin/android/support/design/widget/AccessorHeaderScrollingViewBehavior.kt @@ -26,8 +26,7 @@ import android.view.View internal abstract class AccessorHeaderScrollingViewBehavior(context: Context, attrs: AttributeSet? = null) : HeaderScrollingViewBehavior(context, attrs) { internal val tempRect1 = mTempRect1 - - internal val verticalLayoutGapAccessor = verticalLayoutGap + internal val tempRect2 = mTempRect2 internal override fun getOverlapRatioForOffset(header: View): Float { return super.getOverlapRatioForOffset(header) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/LinkHandlerActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/LinkHandlerActivity.kt index e065e7873..f0a91b37c 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/LinkHandlerActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/LinkHandlerActivity.kt @@ -114,7 +114,7 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowInsetsCallback, IControl fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() { override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedState: Bundle?) { if (f is IToolBarSupportFragment) { - setSupportActionBar(f.toolbar) + setSupportActionBar(f.fragmentToolbar) } } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentRecyclerViewFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentRecyclerViewFragment.kt index 906e3ce69..94cbf6952 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentRecyclerViewFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentRecyclerViewFragment.kt @@ -61,7 +61,7 @@ abstract class AbsContentRecyclerViewFragment // Data fields - private val systemWindowsInsets = Rect() + private val systemWindowInsets = Rect() private val refreshCompleteListener: RefreshCompleteListener? get() = parentFragment as? RefreshCompleteListener @@ -232,7 +232,7 @@ abstract class AbsContentRecyclerViewFragment { GeneralComponent.get(context).inject(this) } + override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + view?.addOnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom -> + if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) { + requestApplyInsets() + } + } + } + override fun onViewStateRestored(savedInstanceState: Bundle?) { super.onViewStateRestored(savedInstanceState) requestApplyInsets() diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt index 91f413c13..7a77db1bc 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt @@ -67,7 +67,6 @@ import android.widget.TextView import android.widget.Toast import com.squareup.otto.Subscribe import kotlinx.android.synthetic.main.fragment_user.* -import kotlinx.android.synthetic.main.fragment_user.view.* import kotlinx.android.synthetic.main.header_user.* import kotlinx.android.synthetic.main.header_user.view.* import kotlinx.android.synthetic.main.layout_content_fragment_common.* @@ -137,18 +136,16 @@ import org.mariotaku.twidere.util.support.ViewSupport import org.mariotaku.twidere.util.support.WindowSupport import org.mariotaku.twidere.util.support.view.ViewOutlineProviderCompat import org.mariotaku.twidere.view.TabPagerIndicator -import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener -import java.lang.ref.WeakReference import java.util.* class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, - OnSizeChangedListener, OnTouchListener, SupportFragmentCallback, + OnTouchListener, SupportFragmentCallback, SystemWindowInsetsCallback, RefreshScrollTopInterface, OnPageChangeListener, KeyboardShortcutCallback, UserColorChangedListener, UserNicknameChangedListener, IToolBarSupportFragment, AbsContentRecyclerViewFragment.RefreshCompleteListener { - override val toolbar: Toolbar - get() = coordinatorLayout.toolbar + override val fragmentToolbar: Toolbar + get() = toolbar private lateinit var profileBirthdayBanner: View private lateinit var pagerAdapter: SupportTabsAdapter @@ -159,7 +156,6 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, private var account: AccountDetails? = null private var relationship: ParcelableRelationship? = null - private var systemWindowsInsets: Rect = Rect() private var userInfoLoaderInitialized: Boolean = false private var friendShipLoaderInitialized: Boolean = false private var bannerWidth: Int = 0 @@ -495,7 +491,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, override fun getSystemWindowInsets(caller: Fragment, insets: Rect): Boolean { insetsCallback?.getSystemWindowInsets(this, insets) if (caller.parentFragment === this) { - insets.top = toolbar.bottom + toolbarTabs.height + insets.top = toolbar.height + toolbarTabs.height } return true } @@ -626,7 +622,6 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, followersCount.setOnClickListener(this) friendsCount.setOnClickListener(this) url.setOnClickListener(this) - profileBanner.onSizeChangedListener = this profileBannerSpace.setOnTouchListener(this) profileHeaderBackground.setBackgroundColor(cardBackgroundColor) @@ -1207,13 +1202,6 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, displayUser(user, account) } - override fun onSizeChanged(view: View, w: Int, h: Int, oldw: Int, oldh: Int) { - bannerWidth = w - if (w != oldw || h != oldh) { - requestApplyInsets() - } - } - @SuppressLint("ClickableViewAccessibility") override fun onTouch(v: View, event: MotionEvent): Boolean { if (profileBirthdayStub == null && profileBirthdayBanner.visibility == View.VISIBLE) { @@ -1389,7 +1377,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, private fun showAddToListDialog(user: ParcelableUser) { val accountKey = user.account_key ?: return - val weakThis = WeakReference(this) + val weakThis = toWeak() executeAfterFragmentResumed { ProgressDialogFragment.show(it.childFragmentManager, "get_list_progress") }.then { @@ -1535,7 +1523,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, d.applyTheme() d.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener { val checkedPositions = d.listView.checkedItemPositions - val weakActivity = WeakReference(activity) + val weakActivity = activity.toWeak() (activity as IBaseActivity<*>).executeAfterFragmentResumed { ProgressDialogFragment.show(it.supportFragmentManager, "update_lists_progress") }.then { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/iface/IToolBarSupportFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/iface/IToolBarSupportFragment.kt index 7b4aa9915..95e18fb49 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/iface/IToolBarSupportFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/iface/IToolBarSupportFragment.kt @@ -5,7 +5,7 @@ import android.support.v7.widget.Toolbar interface IToolBarSupportFragment { - val toolbar: Toolbar + val fragmentToolbar: Toolbar var controlBarOffset: Float diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt index 8708ea743..e280133af 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt @@ -113,10 +113,10 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment, private lateinit var adapter: ConversationInfoAdapter private lateinit var itemDecoration: ConversationInfoDecoration - override val controlBarHeight: Int get() = toolbar.measuredHeight + override val controlBarHeight: Int get() = fragmentToolbar.measuredHeight override var controlBarOffset: Float = 0f - override val toolbar: Toolbar + override val fragmentToolbar: Toolbar get() = toolbarLayout.toolbar override fun onActivityCreated(savedInstanceState: Bundle?) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt index e70fd8808..974ff4c37 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt @@ -117,11 +117,11 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.view.behavior.userprofile + +import android.content.Context +import android.support.design.widget.CoordinatorLayout +import android.support.v4.view.ViewCompat +import android.util.AttributeSet +import android.view.View +import org.mariotaku.twidere.R + + +class HeaderShadowBehavior(context: Context, attrs: AttributeSet?) : CoordinatorLayout.Behavior(context, attrs) { + override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + return dependency.id == R.id.profileHeader + } + + override fun onLayoutChild(parent: CoordinatorLayout, child: View, layoutDirection: Int): Boolean { + val dependency = parent.getDependencies(child).first() + child.layout(0, dependency.bottom, child.measuredWidth, dependency.bottom + child.measuredHeight) + return true + } + + override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + ViewCompat.offsetTopAndBottom(child, dependency.bottom - child.top) + return true + } +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/view/behavior/userprofile/PagerBehavior.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/view/behavior/userprofile/PagerBehavior.kt index 1b60d7c6e..02fec6f6f 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/view/behavior/userprofile/PagerBehavior.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/view/behavior/userprofile/PagerBehavior.kt @@ -23,26 +23,53 @@ import android.content.Context import android.graphics.Rect import android.support.design.widget.AccessorHeaderScrollingViewBehavior import android.support.design.widget.CoordinatorLayout +import android.support.design.widget.lastWindowInsetsCompat import android.support.v4.view.ViewCompat import android.util.AttributeSet import android.view.View +import kotlinx.android.synthetic.main.fragment_user.view.* import kotlinx.android.synthetic.main.header_user.view.* import org.mariotaku.twidere.R import org.mariotaku.twidere.extension.view.measureChildIgnoringInsets internal class PagerBehavior(context: Context, attrs: AttributeSet? = null) : AccessorHeaderScrollingViewBehavior(context, attrs) { - override fun onMeasureChild(parent: CoordinatorLayout, child: View, - parentWidthMeasureSpec: Int, widthUsed: Int, parentHeightMeasureSpec: Int, - heightUsed: Int): Boolean { - return parent.measureChildIgnoringInsets(child, parentWidthMeasureSpec, widthUsed, - parentHeightMeasureSpec, heightUsed) - } - override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean { return dependency.id == R.id.profileHeader } + override fun onMeasureChild(parent: CoordinatorLayout, child: View, + parentWidthMeasureSpec: Int, widthUsed: Int, parentHeightMeasureSpec: Int, + heightUsed: Int): Boolean { + val topInset = parent.lastWindowInsetsCompat?.systemWindowInsetTop ?: 0 + return parent.measureChildIgnoringInsets(child, parentWidthMeasureSpec, widthUsed, + parentHeightMeasureSpec - topInset, heightUsed) + } + + override fun layoutChild(parent: CoordinatorLayout, child: View, layoutDirection: Int) { + val header = parent.getDependencies(child).first() + val lp = child.layoutParams as CoordinatorLayout.LayoutParams + val rect = tempRect1 + rect.set(parent.paddingLeft + lp.leftMargin, + header.contentBottom + lp.topMargin, + parent.width - parent.paddingRight - lp.rightMargin, + parent.height + header.contentBottom + - parent.paddingBottom - lp.bottomMargin) + + val parentInsets = parent.lastWindowInsetsCompat + if ((parentInsets != null && ViewCompat.getFitsSystemWindows(parent) + && !ViewCompat.getFitsSystemWindows(child))) { + // If we're set to handle insets but this child isn't, then it has been measured as + // if there are no insets. We need to lay it out to match horizontally. + // Top and bottom and already handled in the logic above + rect.left += parentInsets.systemWindowInsetLeft + rect.right -= parentInsets.systemWindowInsetRight + } + + val overlap = getOverlapPixelsForOffsetAccessor(header) + + child.layout(rect.left, rect.top - overlap, rect.right, rect.bottom - overlap) + } override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean { offsetChildAsNeeded(parent, child, dependency) @@ -73,7 +100,7 @@ internal class PagerBehavior(context: Context, attrs: AttributeSet? = null) : Ac // any vertical gap and overlap ViewCompat.offsetTopAndBottom(child, (dependency.contentBottom - child.top - + behavior.offsetDelta + verticalLayoutGapAccessor) + + behavior.offsetDelta) - getOverlapPixelsForOffsetAccessor(dependency)) } @@ -111,5 +138,5 @@ internal class PagerBehavior(context: Context, attrs: AttributeSet? = null) : Ac } private val View.contentBottom - get() = top + toolbarTabs.bottom + get() = bottom - toolbarTabs.height - (parent as View).toolbar.height } \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/view/userprofile/UserProfileCoordinatorLayout.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/view/userprofile/UserProfileCoordinatorLayout.kt index 9bb827553..cea797723 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/view/userprofile/UserProfileCoordinatorLayout.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/view/userprofile/UserProfileCoordinatorLayout.kt @@ -26,5 +26,6 @@ import org.mariotaku.chameleon.ChameleonView class UserProfileCoordinatorLayout(context: Context, attrs: AttributeSet?) : CoordinatorLayout(context, attrs), ChameleonView.StatusBarThemeable { + override fun isStatusBarColorHandled() = true } diff --git a/twidere/src/main/res/layout/fragment_user.xml b/twidere/src/main/res/layout/fragment_user.xml index f50c7431e..96a8bdb06 100644 --- a/twidere/src/main/res/layout/fragment_user.xml +++ b/twidere/src/main/res/layout/fragment_user.xml @@ -71,13 +71,12 @@ android:layout_height="wrap_content"/> - - - - - + android:layout_height="@dimen/element_spacing_msmall" + android:background="@drawable/shadow_bottom" + app:layout_behavior="org.mariotaku.twidere.view.behavior.userprofile.HeaderShadowBehavior"/> - + + + + + @@ -138,10 +144,5 @@ tools:title="User" tools:titleTextColor="?android:colorBackground"/> - \ No newline at end of file