ViewModel 实现Fragment中监听返回键

背景:做一个小窗口实现手机相机预览,可以全屏切换预览画面

实现是采用cameraX api实现摄像头预览,参考了谷歌的实现;CameraXBasic中是一个activity加多个fragment的方式,使用navigation管理页面跳转。

参考CameraXBasic自己的项目也是单activity加fragment,使用navigation管理页面跳转。采用MVVM架构。

问题:预览在一个fragment中在切换到全屏时,当点击返回键,期望变为小窗预览,实际直接退出预览界面了;在网上看了一些文章如https://www.jianshu.com/p/fff1ef649fc0等,感觉都有些麻烦。

项目中使用了ViewModel,就想通过activity和fragment中共用一个ViewModel实例,在ViewModel中保存一个全屏的属性,

val isFullScreen= MutableLiveData()

在activity 中重写onBackPresse()做全屏切换;


override fun onBackPressed() {

if (model.isFullScreen.value ==true) {

model.isFullScreen.value =false

    }else {

super.onBackPressed()

}

}

共用一个viewmodel参考官方文档

class MyActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

// Create a ViewModel the first time the system calls an activity's onCreate() method.

// Re-created activities receive the same MyViewModel instance created by the first activity.

// Use the 'by viewModels()' Kotlin property delegate

// from the activity-ktx artifact

 val model:MyViewModel by viewModels()

model.getUsers().observe(this, Observer>{ users ->// update UI})}}

class DetailFragment : Fragment() {

// Use the 'by activityViewModels()' Kotlin property delegate// from the fragment-ktx artifactprivate val model: SharedViewModel by activityViewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)

model.selected.observe(viewLifecycleOwner, Observer { item ->// Update the UI})}}

全屏和小窗切换通过在fragment中监听isFullScreen来切换


model.isFullScreen.observe(viewLifecycleOwner, Observer { it ->

if (it) {

mSecondConstraintSet.applyTo(binding.rootContainer)

}else {

mFirstConstraintSet.applyToWithoutCustom(binding.rootContainer)

}

})

其中布局切换使用ConstraintSet 实现,写好全屏和小窗的两个布局即可;


private val mFirstConstraintSet by lazy {

    ConstraintSet().apply {

        load(requireContext(), R.layout.camera_fragment)

}

}

private val mSecondConstraintSet by lazy {

    ConstraintSet().apply {

        load(requireContext(), R.layout.camera_fullscreen_fragment)

}

}

还可以添加切换动画


TransitionManager.beginDelayedTransition(binding.rootContainer)

备注:binding.rootContainer是采用了viewBinding,参考


buildFeatures{

    // for view binding :

    viewBinding =true

}

在没有添加相机预览画面时,全屏切换是从中间切换到全屏,再从全屏切换到正中的小窗

添加视频流后,模拟器上显示效果如下:真机上显示没有小窗后面的视频;

image

全屏时如下:左上角有一个原来小窗时的隐藏的视频画面

image

添加动画后,就是从左上角预览画面移动到正中;

不是全屏缩小到正中;摄像头预览使用的androidx.camera.view.PreviewView

具体还没研究什么原因,先把动画去掉了

你可能感兴趣的:(ViewModel 实现Fragment中监听返回键)