I have a problem. I want hiding TopLayout when view pager scrolling. I had been successfully this but recycler views heights are wrong when NestedScrollView scrolling.
HomeFragment.kt
Main fragment is here
private var fragments = mutableListOf(FirstFragment(), SecondFragment())
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
tabLayout = view.findViewById(R.id.tabs)
val viewPager2 = view.findViewById<ViewPager2>(R.id.view_pager)
nsd = view.findViewById(R.id.nested_id)
val adapter = ViewPagerAdapter(context as FragmentActivity, fragments)
viewPager2.adapter = adapter
TabLayoutMediator(
tabLayout, viewPager2
) { tab, position ->
tab.text = "Tab " (position 1)
}.attach()
}
home_fragment.xml
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.core.widget.NestedScrollView
android:id="@ id/nested_id"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@ id/image"
android:layout_width="match_parent"
android:layout_height="150d"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@ id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/image" />
<androidx.viewpager2.widget.ViewPager2
android:id="@ id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tabs" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
FirstFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lateinit var recyclerAdapter: MainRecyclerAdapter
val cities = arrayListOf("cities1", "cities2","...","cities81")
var recyclerView: RecyclerView = view.findViewById(R.id.fr_recyclerView)
val gr = GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false)
recyclerView.layoutManager = gr
recyclerAdapter = MainRecyclerAdapter(cities)
recyclerView.adapter = recyclerAdapter
}
fragment_first.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@ id/fr_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
SecondFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lateinit var recyclerAdapter: MainRecyclerAdapter
val cities = arrayListOf("cities1", "cities2","...","cities10")
var recyclerView: RecyclerView = view.findViewById(R.id.fr_recyclerView)
val gr = GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false)
recyclerView.layoutManager = gr
recyclerAdapter = MainRecyclerAdapter(cities)
recyclerView.adapter = recyclerAdapter
}
fragment_second.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1F4A8A"
tools:context=".SecondFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@ id/second_fr_recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>
RecyclerViewAdapter.kt
class MainRecyclerAdapter(private val list: ArrayList<String>) :
RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder>() {
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var city: TextView
init {
city = itemView.findViewById(R.id.text)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.recycler_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.city.text = list[position]
}
override fun getItemCount(): Int {
return list.size
}
CodePudding user response:
The solution is to register a PageChangeCallback and adjust the LayoutParams of the ViewPager2 after asking the child to re-measure itself.
pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val view = // fragment view
view.post {
val wMeasureSpec = MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY)
val hMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
view.measure(wMeasureSpec, hMeasureSpec)
if (pager.layoutParams.height != view.measuredHeight) {
pager.layoutParams = (pager.layoutParams as ConstraintLayout.LayoutParams)
.also { lp -> lp.height = view.measuredHeight }
}
}
}
})