如何从 GestureListener onX 处理程序访问 ViewModel 对象

How to reach ViewModel object from GestureListener onX handlers

提问人:Javier Vilarroig 提问时间:12/27/2019 最后编辑:Javier Vilarroig 更新时间:8/5/2020 访问量:212

问:

我正在编写一个简单的 Kotlin Android 应用程序,它必须在屏幕上显示图像并使用手势滚动列表,具体来说是 Fling。我是 Android 开发和 Kotlin 的新手。

我正在使用 ViewModel 派生类来存储应用程序信息。

我已经能够使用按钮显示图像并滚动列表。按下该按钮时,将显示 ViewModel 中的图像位置在图像列表中的计数器。为此,我使用了数据绑定。

但是,当我实现手势检测逻辑时,我意识到从 onFling 方法内部我无权访问 ViewModel 数据,因此我无法更新计数器,因此我无法与应用状态进行交互。onFling 方法被正确调用,我有足够的信息来实现逻辑,但无权修改 ViewModel 中的数据。

我相信一定有办法做到这一点,但我一直找不到办法。

如果没有可能到达修改 ViewModel 数据,所有 Gestures 框架似乎都毫无用处。

我不认为我的代码会澄清这个问题,但如果需要,我可以发布它。(感谢@Andy)

这是 Activity 类代码:

class MainActivity : AppCompatActivity() {
    private val _data: AppData by viewModels()
    private lateinit var _binding: ActivityMainBinding
    private lateinit var _detector: GestureDetectorCompat

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        // Binding app data to the View
        _binding.lifecycleOwner = this
        _binding.data = _data

        // Check permissions
        .
        . Irrelevant code
        .

        // Initialize gesture Listener
        _detector = GestureDetectorCompat(this, MyGestureListener())
        val focusImage: ImageView = findViewById(R.id.photo_focus)
        focusImage.setOnTouchListener {_ , event -> _detector.onTouchEvent(event) }

        // Load the available photos
        .
        . Irrelevant code
        .
    }

    private class MyGestureListener: GestureDetector.SimpleOnGestureListener()           {
         override fun onDown(event: MotionEvent): Boolean {
            Log.d("Gesture", "onDown: $event")
            return true
        }

        override fun onFling(
            event1: MotionEvent,
            event2: MotionEvent,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            Log.d("Gesture", "onFling: $event1 $event2 $velocityX $velocityY")

            // NO ACCESS TO ViewModel!!!
            // I will like to do something like
            val data = some_way_get_ViewModel()

            if (velocityX > 1000)
                data.moveNext()

            if (velocityZ < -1000)
                data.movePrev()

            return true
        }
    }
}

提前感谢您的帮助。

Android Kotlin ViewModel 手势

评论

0赞 Andy 12/27/2019
欢迎来到 stackoverflow。你可能会因为没有显示你的代码,或者至少没有显示一个概述你的问题的示例项目而受到打击。在这一点上,在他们看到源代码之前,没有人能够真正提供帮助。

答:

0赞 Praanto 8/5/2020 #1

这个问题还悬而未决吗?如果是这样,我只是遇到了类似的问题,自己找到了解决方案。

您可以向 MyGestureListener 类添加 viewModel 构造函数,如下所示:

private class MyGestureListener(private val viewModel: MainActivityVM?):
 GestureDetector.SimpleOnGestureListener() {
        
        override fun onDoubleTap(e: MotionEvent?): Boolean {
            viewModel?.yourMutableLiveData?.value = true
            return true
        }
// You can call other override methods too.
}

然后像这样在MainActivity中传递你的viewModel:

        // Initialize gesture Listener
        _detector = GestureDetectorCompat(this, MyGestureListener(_binding.data))

viewModel 本身无法扩展 GestureDetector 类,因为 viewModel 无法接受触摸输入。这是由您的活动完成的。

评论

0赞 Javier Vilarroig 8/6/2020
多谢!!我会尝试你回答并提供反馈。