Improve/change profile and post layouts

This commit is contained in:
Matthieu 2024-01-30 13:44:07 +01:00
parent 14dee5463e
commit ddf1b273de
11 changed files with 380 additions and 234 deletions

View File

@ -6,6 +6,7 @@ import android.view.View
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.pixeldroid.app.R import org.pixeldroid.app.R
@ -24,13 +25,16 @@ import org.pixeldroid.app.utils.displayDimensionsInPx
class PostActivity : BaseActivity() { class PostActivity : BaseActivity() {
private lateinit var binding: ActivityPostBinding private lateinit var binding: ActivityPostBinding
private var commentFragment = CommentFragment() private lateinit var commentFragment: CommentFragment
private lateinit var status: Status private lateinit var status: Status
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityPostBinding.inflate(layoutInflater) binding = ActivityPostBinding.inflate(layoutInflater)
commentFragment = CommentFragment(binding.swipeRefreshLayout)
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.topBar) setSupportActionBar(binding.topBar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
@ -105,6 +109,11 @@ class PostActivity : BaseActivity() {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(R.id.commentFragment, commentFragment).commit() .add(R.id.commentFragment, commentFragment).commit()
binding.swipeRefreshLayout.setOnRefreshListener {
commentFragment.adapter.refresh()
commentFragment.adapter.notifyDataSetChanged()
}
} }
private suspend fun postComment( private suspend fun postComment(

View File

@ -11,6 +11,7 @@ import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadState import androidx.paging.LoadState
import androidx.paging.PagingDataAdapter import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
@ -20,6 +21,7 @@ import org.pixeldroid.app.posts.feeds.initAdapter
import org.pixeldroid.app.posts.feeds.launch import org.pixeldroid.app.posts.feeds.launch
import org.pixeldroid.app.utils.BaseFragment import org.pixeldroid.app.utils.BaseFragment
import org.pixeldroid.app.utils.api.objects.FeedContent import org.pixeldroid.app.utils.api.objects.FeedContent
import org.pixeldroid.app.utils.limitedLengthSmoothScrollToPosition
/** /**
@ -30,8 +32,7 @@ open class UncachedFeedFragment<T: FeedContent> : BaseFragment() {
internal lateinit var viewModel: FeedViewModel<T> internal lateinit var viewModel: FeedViewModel<T>
internal lateinit var adapter: PagingDataAdapter<T, RecyclerView.ViewHolder> internal lateinit var adapter: PagingDataAdapter<T, RecyclerView.ViewHolder>
lateinit var binding: FragmentFeedBinding var binding: FragmentFeedBinding? = null
private var job: Job? = null private var job: Job? = null
@ -48,25 +49,35 @@ open class UncachedFeedFragment<T: FeedContent> : BaseFragment() {
.distinctUntilChangedBy { it.refresh } .distinctUntilChangedBy { it.refresh }
// Only react to cases where Remote REFRESH completes i.e., NotLoading. // Only react to cases where Remote REFRESH completes i.e., NotLoading.
.filter { it.refresh is LoadState.NotLoading } .filter { it.refresh is LoadState.NotLoading }
.collect { binding.list.scrollToPosition(0) } .collect { binding?.list?.scrollToPosition(0) }
} }
} }
override fun onCreateView( fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?, swipeRefreshLayout: SwipeRefreshLayout?
): View? { ): View {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
binding = FragmentFeedBinding.inflate(layoutInflater) binding = FragmentFeedBinding.inflate(layoutInflater)
initAdapter( binding!!.let {
binding.progressBar, binding.swipeRefreshLayout, binding.list, initAdapter(
binding.motionLayout, binding.errorLayout, adapter it.progressBar, swipeRefreshLayout ?: it.swipeRefreshLayout, it.list,
) it.motionLayout, it.errorLayout, adapter
)
return binding.root }
return binding!!.root
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return onCreateView(inflater, container, savedInstanceState, null)
}
fun onTabReClicked() {
binding?.list?.limitedLengthSmoothScrollToPosition(0)
} }
} }

View File

@ -5,12 +5,15 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.NestedScrollingChild
import androidx.core.view.NestedScrollingChildHelper
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.paging.ExperimentalPagingApi import androidx.paging.ExperimentalPagingApi
import androidx.paging.PagingDataAdapter import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.CommentBinding import org.pixeldroid.app.databinding.CommentBinding
import org.pixeldroid.app.posts.PostActivity import org.pixeldroid.app.posts.PostActivity
@ -25,7 +28,7 @@ import org.pixeldroid.app.utils.setProfileImageFromURL
/** /**
* Fragment to show a list of [Status]s, in form of comments * Fragment to show a list of [Status]s, in form of comments
*/ */
class CommentFragment : UncachedFeedFragment<Status>() { class CommentFragment(val swipeRefreshLayout: SwipeRefreshLayout): UncachedFeedFragment<Status>() {
private lateinit var id: String private lateinit var id: String
private lateinit var domain: String private lateinit var domain: String
@ -42,11 +45,11 @@ class CommentFragment : UncachedFeedFragment<Status>() {
@OptIn(ExperimentalPagingApi::class) @OptIn(ExperimentalPagingApi::class)
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View? { ): View? {
val view = super.onCreateView(inflater, container, savedInstanceState) val view = super.onCreateView(inflater, container, savedInstanceState, swipeRefreshLayout)
// Get the view model // Get the view model
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@ -62,6 +65,7 @@ class CommentFragment : UncachedFeedFragment<Status>() {
launch() launch()
initSearch() initSearch()
binding?.swipeRefreshLayout?.isEnabled = false
return view return view
} }
companion object { companion object {

View File

@ -7,16 +7,19 @@ import android.util.Log
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ActivityProfileBinding import org.pixeldroid.app.databinding.ActivityProfileBinding
import org.pixeldroid.app.posts.feeds.cachedFeeds.CachedFeedFragment
import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedFeedFragment import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedFeedFragment
import org.pixeldroid.app.posts.parseHTMLText import org.pixeldroid.app.posts.parseHTMLText
import org.pixeldroid.app.utils.BaseActivity import org.pixeldroid.app.utils.BaseActivity
@ -58,6 +61,29 @@ class ProfileActivity : BaseActivity() {
val tabs = createProfileTabs(account) val tabs = createProfileTabs(account)
setupTabs(tabs) setupTabs(tabs)
setContent(account) setContent(account)
binding.profileMotion.setTransitionListener(
object : MotionLayout.TransitionListener {
override fun onTransitionStarted(
motionLayout: MotionLayout?, startId: Int, endId: Int,
) {}
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {}
override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
if (currentId == R.id.hideProfile && motionLayout?.startState == R.id.start) {
// If the 1st transition has been made go to the second one
motionLayout.setTransition(R.id.second)
} else if(currentId == R.id.hideProfile && motionLayout?.startState == R.id.hideProfile){
motionLayout.setTransition(R.id.first)
}
}
override fun onTransitionTrigger(
motionLayout: MotionLayout?, triggerId: Int, positive: Boolean, progress: Float,
) {}
}
)
} }
private fun createProfileTabs(account: Account?): Array<UncachedFeedFragment<FeedContent>> { private fun createProfileTabs(account: Account?): Array<UncachedFeedFragment<FeedContent>> {
@ -104,7 +130,7 @@ class ProfileActivity : BaseActivity() {
} }
private fun setupTabs( private fun setupTabs(
tabs: Array<UncachedFeedFragment<FeedContent>> tabs: Array<UncachedFeedFragment<FeedContent>>,
){ ){
binding.viewPager.adapter = object : FragmentStateAdapter(this) { binding.viewPager.adapter = object : FragmentStateAdapter(this) {
override fun createFragment(position: Int): Fragment { override fun createFragment(position: Int): Fragment {
@ -136,6 +162,14 @@ class ProfileActivity : BaseActivity() {
} }
} }
}.attach() }.attach()
binding.profileTabs.addOnTabSelectedListener(object : OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {}
override fun onTabUnselected(tab: TabLayout.Tab) {}
override fun onTabReselected(tab: TabLayout.Tab) {
tabs[tab.position].onTabReClicked()
}
})
} }
private fun setContent(account: Account?) { private fun setContent(account: Account?) {

View File

@ -101,7 +101,7 @@ class ProfileFeedFragment : UncachedFeedFragment<FeedContent>() {
val view = super.onCreateView(inflater, container, savedInstanceState) val view = super.onCreateView(inflater, container, savedInstanceState)
if(grid || bookmarks || collections || addCollection) { if(grid || bookmarks || collections || addCollection) {
binding.list.layoutManager = GridLayoutManager(context, 3) binding?.list?.layoutManager = GridLayoutManager(context, 3)
} }
// Get the view model // Get the view model
@ -191,8 +191,11 @@ class ProfileFeedFragment : UncachedFeedFragment<FeedContent>() {
val url = "$domain/i/collections/create" val url = "$domain/i/collections/create"
if(domain.isNullOrEmpty() || !requireContext().openUrl(url)) { if(domain.isNullOrEmpty() || !requireContext().openUrl(url)) {
Snackbar.make(binding.root, getString(R.string.new_collection_link_failed), binding?.let { binding ->
Snackbar.LENGTH_LONG).show() Snackbar.make(
binding.root, getString(R.string.new_collection_link_failed),
Snackbar.LENGTH_LONG).show()
}
} }
} }

View File

@ -3,88 +3,104 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scrollview" android:id="@+id/scrollview"
android:fitsSystemWindows="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorSecondaryContainer"
android:fitsSystemWindows="true"
tools:context=".posts.PostActivity"> tools:context=".posts.PostActivity">
<com.google.android.material.appbar.AppBarLayout <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/app_bar_layout" android:id="@+id/swipeRefreshLayout"
android:background="?attr/colorSecondaryContainer" app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:fitsSystemWindows="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="match_parent">
<com.google.android.material.appbar.MaterialToolbar <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/top_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:minHeight="?attr/actionBarSize" android:background="?attr/colorSurface">
app:layout_scrollFlags="scroll|enterAlways"/>
<com.google.android.material.appbar.CollapsingToolbarLayout <androidx.core.widget.NestedScrollView
android:background="?attr/colorSurface"
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="match_parent"
android:fillViewport="true"
<include app:layout_constraintBottom_toTopOf="parent"
android:id="@+id/postFragmentSingle" app:layout_constraintBottom_toBottomOf="parent">
layout="@layout/post_fragment" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/commentIn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
app:layout_constraintTop_toBottomOf="@+id/postFragmentSingle"
tools:layout_editor_absoluteX="10dp">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/textInputLayout2" android:id="@+id/top_bar"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" android:background="?attr/colorSecondaryContainer"
app:layout_constraintEnd_toStartOf="@+id/submitComment" android:minHeight="?attr/actionBarSize"
app:layout_constraintStart_toStartOf="parent">
<EditText
android:id="@+id/editComment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/comment_noun"
android:importantForAutofill="no"
android:inputType="text|textCapSentences|textMultiLine" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/submitComment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:contentDescription="@string/submit_comment"
android:text="@string/comment_verb"
app:layout_constraintBottom_toBottomOf="@+id/textInputLayout2"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textInputLayout2" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/textInputLayout2" /> app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintPost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_bar">
<include
android:id="@+id/postFragmentSingle"
layout="@layout/post_fragment" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/commentIn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/constraintPost"
tools:layout_editor_absoluteX="10dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/submitComment"
app:layout_constraintStart_toStartOf="parent">
<EditText
android:id="@+id/editComment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/comment_noun"
android:importantForAutofill="no"
android:inputType="text|textCapSentences|textMultiLine" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/submitComment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:contentDescription="@string/submit_comment"
android:text="@string/comment_verb"
app:layout_constraintBottom_toBottomOf="@+id/textInputLayout2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textInputLayout2"
app:layout_constraintTop_toTopOf="@+id/textInputLayout2" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/commentFragment"
android:layout_width="match_parent"
android:layout_height="500dp"
android:fillViewport="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/commentIn" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/commentFragment"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -3,154 +3,155 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".profile.ProfileActivity"> tools:context=".profile.ProfileActivity">
<com.google.android.material.appbar.AppBarLayout <androidx.constraintlayout.motion.widget.MotionLayout
android:id="@+id/app_bar_layout" android:id="@+id/profileMotion"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="?attr/colorSecondaryContainer"
app:layoutDescription="@xml/collapsing_motion_layout_scene">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/top_bar"
android:background="?attr/colorSecondaryContainer" android:background="?attr/colorSecondaryContainer"
android:fitsSystemWindows="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:fitsSystemWindows="true"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.appbar.MaterialToolbar <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/top_bar" android:id="@+id/profile"
android:layout_width="match_parent" android:elevation="-1dp"
android:background="?attr/colorSurface"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_bar">
<ImageView
android:id="@+id/profilePictureImageView"
android:layout_width="88dp"
android:layout_height="88dp"
android:clickable="false"
android:layout_marginStart="20dp"
android:layout_marginTop="6dp"
android:contentDescription="@string/profile_picture"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/nbPostsTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize" android:layout_marginStart="20dp"
app:layout_scrollFlags="scroll|enterAlways"/> android:layout_marginTop="10dp"
android:gravity="center"
android:clickable="false"
android:text="@string/default_nposts"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/descriptionTextView" />
<com.google.android.material.appbar.CollapsingToolbarLayout <TextView
android:id="@+id/collapsing_toolbar_layout" android:id="@+id/nbFollowersTextView"
android:background="?attr/colorSurface" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:text="@string/default_nfollowers"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/nbPostsTextView"
app:layout_constraintEnd_toStartOf="@+id/nbFollowingTextView"
app:layout_constraintStart_toEndOf="@+id/nbPostsTextView"
app:layout_constraintTop_toTopOf="@+id/nbPostsTextView" />
<TextView
android:id="@+id/nbFollowingTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:text="@string/default_nfollowing"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/nbFollowersTextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/nbFollowersTextView" />
<TextView
android:id="@+id/accountNameTextView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:clickable="false"
app:layout_scrollFlags="scroll|exitUntilCollapsed"> android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="20dp"
android:text="@string/no_username"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/profilePictureImageView" />
<androidx.constraintlayout.widget.ConstraintLayout <TextView
android:layout_width="match_parent" android:id="@+id/descriptionTextView"
android:layout_height="match_parent" android:layout_width="match_parent"
android:layout_marginBottom="12dp" android:clickable="false"
android:visibility="visible" android:layout_height="wrap_content"
app:layout_collapseMode="parallax" android:layout_marginLeft="20dp"
app:layout_constraintTop_toBottomOf="@id/nbFollowersTextView" android:layout_marginTop="5dp"
tools:visibility="visible"> android:layout_marginRight="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/accountNameTextView" />
<ImageView <Button
android:id="@+id/profilePictureImageView" android:id="@+id/followButton"
android:layout_width="88dp" android:layout_width="wrap_content"
android:layout_height="88dp" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginEnd="20dp"
android:layout_marginTop="6dp" android:text="@string/follow"
android:contentDescription="@string/profile_picture" android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="@+id/profilePictureImageView"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent"
tools:srcCompat="@tools:sample/avatars" /> app:layout_constraintTop_toTopOf="@+id/profilePictureImageView" />
<TextView <Button
android:id="@+id/nbPostsTextView" android:id="@+id/editButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:text="@string/edit_profile"
android:layout_marginTop="10dp" android:visibility="gone"
android:gravity="center" app:layout_constraintBottom_toBottomOf="@+id/profilePictureImageView"
android:text="@string/default_nposts" app:layout_constraintEnd_toEndOf="parent"
android:textStyle="bold" app:layout_constraintStart_toEndOf="@+id/profilePictureImageView"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/profilePictureImageView" />
app:layout_constraintTop_toBottomOf="@+id/descriptionTextView" /> </androidx.constraintlayout.widget.ConstraintLayout>
<TextView <com.google.android.material.tabs.TabLayout
android:id="@+id/nbFollowersTextView" android:id="@+id/profileTabs"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent"
android:background="?attr/selectableItemBackgroundBorderless" app:layout_constraintStart_toStartOf="parent"
android:gravity="center" app:layout_constraintTop_toBottomOf="@id/profile"
android:text="@string/default_nfollowers" android:layout_height="wrap_content"
android:textStyle="bold" app:layout_scrollFlags="scroll|enterAlways" />
app:layout_constraintBottom_toBottomOf="@+id/nbPostsTextView"
app:layout_constraintEnd_toStartOf="@+id/nbFollowingTextView"
app:layout_constraintStart_toEndOf="@+id/nbPostsTextView"
app:layout_constraintTop_toTopOf="@+id/nbPostsTextView" />
<TextView
android:id="@+id/nbFollowingTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:text="@string/default_nfollowing"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/nbFollowersTextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/nbFollowersTextView" />
<TextView
android:id="@+id/accountNameTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="20dp"
android:text="@string/no_username"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/profilePictureImageView" />
<TextView
android:id="@+id/descriptionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="5dp"
android:layout_marginRight="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/accountNameTextView" />
<Button
android:id="@+id/followButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:text="@string/follow"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/profilePictureImageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/profilePictureImageView" />
<Button
android:id="@+id/editButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/edit_profile"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/profilePictureImageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/profilePictureImageView"
app:layout_constraintTop_toTopOf="@+id/profilePictureImageView" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/profileTabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/nbPostsTextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager" android:id="@+id/view_pager"
android:background="?attr/colorSurface"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="0dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> app:layout_constraintTop_toBottomOf="@id/profileTabs"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -16,6 +16,8 @@
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/top_bar" android:id="@+id/top_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
app:titleTextColor="?attr/colorOnSecondaryContainer"
android:background="?attr/colorSecondaryContainer"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize" android:minHeight="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -38,7 +40,6 @@
android:id="@+id/refreshLayout" android:id="@+id/refreshLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginTop="10dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -8,14 +8,6 @@
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
xmlns:sparkbutton="http://schemas.android.com/apk/res-auto"> xmlns:sparkbutton="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:clipChildren="false"
android:clipToPadding="false">
<ImageView <ImageView
android:id="@+id/profilePic" android:id="@+id/profilePic"
android:layout_width="50dp" android:layout_width="50dp"
@ -243,6 +235,4 @@
app:layout_constraintTop_toBottomOf="@+id/postDate" app:layout_constraintTop_toBottomOf="@+id/postDate"
tools:text="3 comments" /> tools:text="3 comments" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<Transition
android:id="@+id/first"
app:constraintSetStart="@id/start"
app:constraintSetEnd="@id/hideProfile">
<OnSwipe
app:touchAnchorId="@+id/profile"
app:touchAnchorSide="top"
app:dragDirection="dragUp" />
</Transition>
<Transition
android:id="@+id/second"
app:constraintSetStart="@id/hideProfile"
app:constraintSetEnd="@id/hideBars">
<OnSwipe
app:touchAnchorId="@+id/profileTabs"
app:touchAnchorSide="top"
app:dragDirection="dragUp" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint android:id="@id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/hideProfile">
<Constraint android:id="@id/profile"
android:layout_width="match_parent"
app:layout_constraintBottom_toBottomOf="@id/top_bar"
app:layout_constraintStart_toStartOf="parent">
</Constraint>
<Constraint android:id="@id/profileTabs"
android:layout_width="match_parent"
app:layout_constraintTop_toBottomOf="@id/top_bar"
app:layout_constraintStart_toStartOf="parent">
</Constraint>
<Constraint android:id="@id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/hideBars">
<Constraint android:id="@id/profile"
android:layout_width="match_parent"
app:layout_constraintBottom_toBottomOf="@id/top_bar"
app:layout_constraintStart_toStartOf="parent">
</Constraint>
<Constraint android:id="@id/profileTabs"
android:layout_width="match_parent"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent">
</Constraint>
<Constraint android:id="@id/top_bar"
android:layout_width="match_parent"
app:layout_constraintBottom_toTopOf="@id/profileTabs"
app:layout_constraintStart_toStartOf="parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent">
</Constraint>
</ConstraintSet>
</MotionScene>

View File

@ -26,3 +26,4 @@ kapt.incremental.apt=true
android.enableR8.fullMode=true android.enableR8.fullMode=true
android.nonTransitiveRClass=false android.nonTransitiveRClass=false
android.nonFinalResIds=false android.nonFinalResIds=false
org.gradle.configuration-cache=true