improved user fragment ui

This commit is contained in:
Mariotaku Lee 2017-10-29 00:01:24 +08:00
parent 0d05f50a7c
commit 763452e335
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
13 changed files with 124 additions and 52 deletions

View File

@ -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)

View File

@ -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)
}
}
}

View File

@ -61,7 +61,7 @@ abstract class AbsContentRecyclerViewFragment<A : LoadMoreSupportAdapter<Recycle
// Callbacks and listeners
lateinit var scrollListener: RecyclerViewScrollHandler<A>
// 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<A : LoadMoreSupportAdapter<Recycle
insets.right + extraPadding.right, insets.bottom + extraPadding.bottom)
errorContainer.setPadding(insets.left, insets.top, insets.right, insets.bottom)
progressContainer.setPadding(insets.left, insets.top, insets.right, insets.bottom)
systemWindowsInsets.set(insets)
systemWindowInsets.set(insets)
updateRefreshProgressOffset()
}
@ -280,7 +280,7 @@ abstract class AbsContentRecyclerViewFragment<A : LoadMoreSupportAdapter<Recycle
}
protected fun updateRefreshProgressOffset() {
val insets = this.systemWindowsInsets
val insets = this.systemWindowInsets
if (insets.top == 0 || swipeLayout == null || swipeLayout.isRefreshing) {
return
}

View File

@ -41,7 +41,7 @@ abstract class AbsToolbarTabPagesFragment : BaseFragment(), RefreshScrollTopInte
HideUiOnScroll, OnPageChangeListener, IToolBarSupportFragment, KeyboardShortcutCallback {
protected lateinit var pagerAdapter: SupportTabsAdapter
override val toolbar: Toolbar
override val fragmentToolbar: Toolbar
get() = toolbarContainer.toolbar
override fun onActivityCreated(savedInstanceState: Bundle?) {
@ -185,7 +185,7 @@ abstract class AbsToolbarTabPagesFragment : BaseFragment(), RefreshScrollTopInte
}
override val controlBarHeight: Int
get() = toolbar.measuredHeight
get() = fragmentToolbar.measuredHeight
override fun setupWindow(activity: FragmentActivity): Boolean {
return false

View File

@ -24,6 +24,7 @@ import android.content.SharedPreferences
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.text.BidiFormatter
import android.view.View
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.squareup.otto.Bus
@ -137,6 +138,16 @@ open class BaseFragment : Fragment(), IBaseFragment<BaseFragment> {
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()

View File

@ -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 {

View File

@ -5,7 +5,7 @@ import android.support.v7.widget.Toolbar
interface IToolBarSupportFragment {
val toolbar: Toolbar
val fragmentToolbar: Toolbar
var controlBarOffset: Float

View File

@ -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?) {

View File

@ -117,11 +117,11 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
get() = super.reachingEnd
override val controlBarHeight: Int
get() = toolbar.height
get() = fragmentToolbar.height
override var controlBarOffset: Float = 1f
override val toolbar: Toolbar
override val fragmentToolbar: Toolbar
get() = conversationContainer.toolbar
override fun onActivityCreated(savedInstanceState: Bundle?) {

View File

@ -0,0 +1,45 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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<View>(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
}
}

View File

@ -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
}

View File

@ -26,5 +26,6 @@ import org.mariotaku.chameleon.ChameleonView
class UserProfileCoordinatorLayout(context: Context, attrs: AttributeSet?) :
CoordinatorLayout(context, attrs), ChameleonView.StatusBarThemeable {
override fun isStatusBarColorHandled() = true
}

View File

@ -71,13 +71,12 @@
android:layout_height="wrap_content"/>
</FrameLayout>
<FrameLayout
<View
android:id="@+id/pagerWindowOverlay"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/layout_content_fragment_common"/>
</FrameLayout>
android:layout_height="@dimen/element_spacing_msmall"
android:background="@drawable/shadow_bottom"
app:layout_behavior="org.mariotaku.twidere.view.behavior.userprofile.HeaderShadowBehavior"/>
<FrameLayout
android:id="@+id/pagesErrorContainer"
@ -117,9 +116,16 @@
</FrameLayout>
<View
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/layout_content_fragment_common"/>
</FrameLayout>
<View
android:id="@+id/statusBarBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="org.mariotaku.twidere.view.behavior.userprofile.StatusBarBehavior"
tools:layout_height="25dp"/>
@ -138,10 +144,5 @@
tools:title="User"
tools:titleTextColor="?android:colorBackground"/>
<View
android:id="@+id/pagerWindowOverlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:windowContentOverlay"/>
</org.mariotaku.twidere.view.userprofile.UserProfileCoordinatorLayout>