@@ -80,6 +80,32 @@ class MainActivity : AppCompatActivity() {
8080 adapter = MainPagerAdapter (this )
8181 binding.viewPager.adapter = adapter
8282 binding.viewPager.offscreenPageLimit = 4
83+
84+ // FIX: giảm độ nhạy cạnh (edge sensitivity) giúp cử chỉ vuốt được ViewPager2
85+ // nhận diện dứt khoát hơn, tránh xung đột với vuốt back gesture / RecyclerView con
86+ reduceViewPagerTouchSlop(binding.viewPager)
87+ }
88+ }
89+
90+ /* *
91+ * FIX: ViewPager2 dùng RecyclerView bên trong, mặc định touchSlop khá lớn khiến
92+ * cử chỉ vuốt đôi khi bị "trễ"/giật lúc bắt đầu kéo. Giảm touchSlop giúp
93+ * ViewPager2 phản hồi ngay từ pixel di chuyển đầu tiên, cảm giác mượt hơn.
94+ */
95+ private fun reduceViewPagerTouchSlop (viewPager : androidx.viewpager2.widget.ViewPager2 ) {
96+ try {
97+ val recyclerViewField = androidx.viewpager2.widget.ViewPager2 ::class .java
98+ .getDeclaredField(" mRecyclerView" )
99+ recyclerViewField.isAccessible = true
100+ val recyclerView = recyclerViewField.get(viewPager)
101+
102+ val touchSlopField = androidx.recyclerview.widget.RecyclerView ::class .java
103+ .getDeclaredField(" mTouchSlop" )
104+ touchSlopField.isAccessible = true
105+ val currentTouchSlop = touchSlopField.get(recyclerView) as Int
106+ touchSlopField.set(recyclerView, (currentTouchSlop * 0.6 ).toInt())
107+ } catch (e: Exception ) {
108+ // Reflection có thể fail trên một số phiên bản AndroidX -> bỏ qua, không critical
83109 }
84110 }
85111
@@ -163,16 +189,28 @@ class MainActivity : AppCompatActivity() {
163189 if (binding.viewPager.currentItem != tab.position) {
164190 binding.viewPager.setCurrentItem(tab.position, true )
165191 }
166-
192+
167193 // Cập nhật hiệu ứng hiển thị (màu sắc/scale) của tab
168194 tabHelper.updateHighlight(binding.tabLayout, tab.position)
169-
170- isFavoritesTab = (tab.position == 0 )
171- invalidateOptionsMenu()
195+
196+ // FIX: chỉ invalidate menu khi trạng thái favorites thật sự đổi,
197+ // tránh rebuild toàn bộ Toolbar menu mỗi lần vuốt/settle tab
198+ // (đây là nguyên nhân chính gây giật khi vuốt chuyển tab, vì
199+ // invalidateOptionsMenu() chạy đồng bộ trên main thread đúng lúc
200+ // animation settle của ViewPager2 vừa kết thúc)
201+ val nowFavorites = (tab.position == 0 )
202+ if (isFavoritesTab != nowFavorites) {
203+ isFavoritesTab = nowFavorites
204+ invalidateOptionsMenu()
205+ }
172206 }
173207 override fun onTabUnselected (tab : TabLayout .Tab ) {}
174208 override fun onTabReselected (tab : TabLayout .Tab ) {}
175209 })
210+
211+ // FIX: tắt hiệu ứng "over-scroll glow" ở rìa để cảm giác vuốt liền mạch hơn,
212+ // đặc biệt khi vuốt tới tab đầu/cuối
213+ binding.viewPager.getChildAt(0 )?.overScrollMode = android.view.View .OVER_SCROLL_NEVER
176214 }
177215
178216 private fun getItems (pageNode : PageNode ): ArrayList <NodeInfoBase >? {
0 commit comments