improved user fragment ui
This commit is contained in:
parent
0d05f50a7c
commit
763452e335
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -5,7 +5,7 @@ import android.support.v7.widget.Toolbar
|
|||
|
||||
interface IToolBarSupportFragment {
|
||||
|
||||
val toolbar: Toolbar
|
||||
val fragmentToolbar: Toolbar
|
||||
|
||||
var controlBarOffset: Float
|
||||
|
||||
|
|
|
@ -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?) {
|
||||
|
|
|
@ -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?) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -26,5 +26,6 @@ import org.mariotaku.chameleon.ChameleonView
|
|||
|
||||
class UserProfileCoordinatorLayout(context: Context, attrs: AttributeSet?) :
|
||||
CoordinatorLayout(context, attrs), ChameleonView.StatusBarThemeable {
|
||||
|
||||
override fun isStatusBarColorHandled() = true
|
||||
}
|
||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue