问题描述
ViewPage2嵌套Fragment+SeekBar,拖动SeekBar的进度条时,触发ViewPage2的滑动。
解决方案:
方案一:通过事件总线+ViewPage2的isUserInputEnabled属性
子Fragment:
class SeekBarFragment : Fragment() {private SeekBar seekBar;private val eventBus = EventBus.getInstance()override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)seekBar= view.findViewById(R.id.seekBar);// 设置SeekBar的监听器seekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {}override fun onStartTrackingTouch(seekBar: SeekBar?) {eventBus.post(SeekBarEvent.Start)}override fun onStopTrackingTouch(seekBar: SeekBar?) {eventBus.post(SeekBarEvent.End)}})}
}
父Fragment:
class ParentFragment : Fragment() {private val eventBus = EventBus.getInstance()override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)// 订阅SeekBar的滑动事件eventBus.events.observe(viewLifecycleOwner) {when (it) {is SeekBarEvent.Start -> {//禁止ViewPager2滑动viewPager2.isUserInputEnabled = false}is SeekBarEvent.End -> {// 允许ViewPager2滑动viewPager2.isUserInputEnabled = true}}}}override fun onDestroyView() {super.onDestroyView()// 取消订阅以避免内存泄漏eventBus.events.removeObservers(viewLifecycleOwner)}
}
SeekBarEvent 类:
sealed class SeekBarEvent {object Start : SeekBarEvent()object End : SeekBarEvent()
}
方案二:接口回调的方式
OnSeekBarSlideListener
interface OnSeekBarSlideListener {fun onSlideStart()fun onSlideEnd()
}
子Fragment
class SeekBarFragment : Fragment() {private var seekBarSlideListener: OnSeekBarSlideListener? = nullfun setOnSeekBarSlideListener(listener: OnSeekBarSlideListener) {seekBarSlideListener = listener}private SeekBar seekBar;override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)seekBar= view.findViewById(R.id.seekBar);// 设置SeekBar的监听器seekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {}override fun onStartTrackingTouch(seekBar: SeekBar?) {seekBarSlideListener?.onSlideStart()}override fun onStopTrackingTouch(seekBar: SeekBar?) {seekBarSlideListener?.onSlideEnd()}})}
}
父Fragment
class ParentFragment : Fragment(), OnSeekBarSlideListener {private val fragments= ArrayList<Fragment>()private lateinit var viewPager: ViewPager2private lateinit var adapter: MyFragmentAdapterprivate var seekBarFragment : SeekBarFragment ? = nulloverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {val view = inflater.inflate(R.layout.fragment_parent, container, false)fragments.add(SeekBarFragment ())// 初始化适配器并设置给ViewPager2adapter = MyPagerAdapter(childFragmentManager, lifecycle, mFragments)viewPager.adapter = adapter// 设置页面变化监听viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {override fun onPageSelected(position: Int) {super.onPageSelected(position)// 获取当前子Fragment实例seekBarFragment = adapter.createFragment(position) as? SeekBarFragmentseekBarFragment?.let { it.setOnSeekBarSlideListener(this)}}})return view}// 实现OnSeekBarSlideListener的回调override fun onSlideStart() {// 禁用ViewPager2的滑动viewPager2.isUserInputEnabled = false}override fun onSlideEnd() {// 重新启用ViewPager2的滑动viewPager2.isUserInputEnabled = true}
}
MyPagerAdapter
class MyPagerAdapter(private val fragments: ArrayList<Fragment>) : FragmentStateAdapter {constructor(fragmentManager: FragmentManager, lifecycle: Lifecycle, fragments: ArrayList<Fragment>) : this(fragments) {super(fragmentManager, lifecycle)}override fun createFragment(position: Int): Fragment {return fragments[position]}override fun getItemCount(): Int {return fragments.size}
}