You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Activity中监听ViewPager2子Fragment滚动并控制按钮显示?

实现子Fragment滚动控制主Activity控件可见性

核心思路

通过Activity级别的ViewModel实现跨组件通信,子Fragment监听滚动事件并将状态传递给ViewModel,主Activity监听ViewModel的状态变化来控制控件可见性,避免组件间强耦合。


步骤1:创建共享ViewModel

用于传递滚动方向事件:

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class ScrollEventViewModel : ViewModel() {
    private val _scrollUpEvent = MutableLiveData<Boolean>()
    val scrollUpEvent: LiveData<Boolean> = _scrollUpEvent

    // 发送滚动方向事件:true=向上滚动,false=向下滚动
    fun sendScrollUpEvent(isScrollingUp: Boolean) {
        _scrollUpEvent.value = isScrollingUp
    }
}

步骤2:子Fragment监听滚动事件

针对NestedScrollView的实现:

class PickupFragment : Fragment() {
    private lateinit var scrollEventViewModel: ScrollEventViewModel
    private var lastScrollY = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 获取Activity级别的ViewModel实例
        scrollEventViewModel = ViewModelProvider(requireActivity())[ScrollEventViewModel::class.java]
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val scrollView = view.findViewById<NestedScrollView>(R.id.scrollView)
        
        scrollView.setOnScrollChangeListener { _, _, scrollY, _, _ ->
            val isScrollingUp = scrollY < lastScrollY
            // 仅当状态变化时发送事件,减少冗余更新
            if (isScrollingUp != scrollEventViewModel.scrollUpEvent.value) {
                scrollEventViewModel.sendScrollUpEvent(isScrollingUp)
            }
            lastScrollY = scrollY
        }
    }
}

针对RecyclerView的实现:

class ListFragment : Fragment() {
    private lateinit var scrollEventViewModel: ScrollEventViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        scrollEventViewModel = ViewModelProvider(requireActivity())[ScrollEventViewModel::class.java]
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerView)
        
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                val isScrollingUp = dy < 0
                if (isScrollingUp != scrollEventViewModel.scrollUpEvent.value) {
                    scrollEventViewModel.sendScrollUpEvent(isScrollingUp)
                }
            }
        })
    }
}

步骤3:主Activity监听状态并控制控件

class MainActivity : AppCompatActivity() {
    private lateinit var scrollEventViewModel: ScrollEventViewModel
    private lateinit var bottomNav: BottomNavigationView
    private lateinit var fab: FloatingActionButton

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        bottomNav = findViewById(R.id.bottom_nav)
        fab = findViewById(R.id.fab)
        scrollEventViewModel = ViewModelProvider(this)[ScrollEventViewModel::class.java]

        // 监听滚动事件,更新控件可见性
        scrollEventViewModel.scrollUpEvent.observe(this) { isScrollingUp ->
            if (isScrollingUp) {
                bottomNav.visibility = View.VISIBLE
                fab.show()
            } else {
                bottomNav.visibility = View.GONE
                fab.hide()
            }
        }
    }
}

步骤4:处理ViewPager2页面切换(可选)

切换页面时恢复默认控件状态,避免残留之前的滚动状态:

class HomeFragment : Fragment() {
    private lateinit var scrollEventViewModel: ScrollEventViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        scrollEventViewModel = ViewModelProvider(requireActivity())[ScrollEventViewModel::class.java]
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val viewPager = view.findViewById<ViewPager2>(R.id.viewpager)
        
        viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)
                // 切换页面后默认显示控件
                scrollEventViewModel.sendScrollUpEvent(true)
            }
        })
    }
}

内容的提问来源于stack exchange,提问作者mskim96

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 02:24:57