带有kivy的android上的后退按钮功能

Posted

技术标签:

【中文标题】带有kivy的android上的后退按钮功能【英文标题】:back button functionality on android with kivy 【发布时间】:2013-12-04 03:16:23 【问题描述】:

在 Kivy 中,当我按下我的 android 设备上的后退按钮时,它会将我抛出应用程序。有没有办法使用 Kivy 语言而不是 python 返回到上一个屏幕?这是我用kivy写的:

<MyAppClass>:
AnchorLayout:
    anchor_x : 'center'
    anchor_y : 'top'
    ScreenManager:
        size_hint : 1, .9
        id: _screen_manager

        Screen:
            name:'screen1'
            StackLayout:
                # irrelevant code

        Screen:
            name:'screen2'
            StackLayout:
                # irrelevant code

我需要从 python 操作屏幕管理器及其屏幕...如果可以的话,我会用 python 没问题。

【问题讨论】:

【参考方案1】:

Android 上的 Kivy 将后退按钮绑定到 esc 按钮,因此在您的应用中绑定和监听 esc 按钮将帮助您处理按下后退按钮时应用的行为方式。

换句话说,在您的应用程序中,在您的桌面上测试它时,请听系统键盘上的退出键,这将自动转换为您的 Android 设备上的后退按钮。类似的东西::

def on_start():
    from kivy.base import EventLoop
    EventLoop.window.bind(on_keyboard=self.hook_keyboard)

def hook_keyboard(self, window, key, *largs):
    if key == 27:
       # do what you want, return True for stopping the propagation
       return True 

【讨论】:

我已经编辑了我的请求...也许它会更清楚,抱歉第一次是一个抽象的问题。【参考方案2】:

我想我已经解决了,但应该感谢@inclement 和@qua-non!你们的回答让我走上了正确的道路!所以在kv中我假设我给了我的屏幕管理器一个id(请参考我写kv代码的问题),在python中我应该做以下事情:

    from kivy.core.window import Window
    from kivy.properties import ObjectProperty

    class MyAppClass(FloatLayout):#its a FloatLayout in my case
        _screen_manager=ObjectProperty(None)
        def __init__(self,**kwargs):
            super(MyAppClass,self).__init__(**kwargs)
            #code goes here and add:
            Window.bind(on_keyboard=self.Android_back_click)

        def Android_back_click(self,window,key,*largs):
            if key == 27:
                self._scree_manager.current='screen1'#you can create a method here to cache in a list the number of screens and then pop the last visited screen.
                return True

    class MyApp(App):
        def build(self):
            return MyAppClass()

    if __name__=='__main__':
        MyApp().run()

【讨论】:

没有。您必须在类级别声明 ObjectProperty,而不是在 init 函数中。 我想你是对的,但在 init 和类级别工作。但正确的方法是你说的地方。再次感谢你...... 它在 init 中不起作用,只是你没有注意到,因为巧合你所做的其他一些东西复制了正确的行为。 我不能说我理解你的意思。对象属性应该在类级别,它们要么在 init 中,要么在它之上。它应该双向工作 “在班级级别”是指您当前在示例中的位置。这是使属性正常工作的唯一方法,如果您在 init 中执行此操作,它们将无法正确绑定为属性。我认为 kv 语言也隐式地创建属性,这就是为什么你的示例以任何方式工作的原因 - kv 语言 _screen_manager 声明覆盖了 init 函数所做的事情。【参考方案3】:

这当然是可能的。这是一个简短的示例应用程序,其中包含我用来执行此操作的方法:

from kivy.utils import platform
from kivy.core.window import Window

class ExampleApp(App):
    manager = ObjectProperty()

    def build(self):
        sm = MyScreenManager()
        self.manager = sm
        self.bind(on_start=self.post_build_init)
        return sm

    def post_build_init(self, *args):
        if platform() == 'android':
            import android
            android.map_key(android.KEYCODE_BACK, 1001)

        win = Window
        win.bind(on_keyboard=self.my_key_handler)

    def my_key_handler(self, window, keycode1, keycode2, text, modifiers):
        if keycode1 in [27, 1001]:
            self.manager.go_back()
            return True
        return False

这应该给出正确的基本概念,但有几点说明:

ScreenManager 不会跟踪以前的屏幕,您可以根据自己的喜好来实施。我的示例假设您使用 go_back 方法定义了一个 MyScreenManager 类。 可能不需要绑定到 on_start 并运行 post_build_init,这正是我最初使用的示例的方式(见下文)。但有时它可能很重要,可能是在运行 build() 时未初始化窗口,并且原始邮件列表帖子表明作者出于某种原因需要它。 该示例侦听键码 27 或 1001。正如 qua-non 在我写这篇文章时所说,前者侦听 esc,因此您可以在桌面上获得相同的行为。 我没有尝试不使用 android.map_key 行,但似乎没有必要。 你提到你想使用 kivy 语言而不是 python。你需要做一些 python 来得到这个结果,我看不出有什么办法(它不是真正的 kv 语言的领域)。我想你可以通过在某处定义一个“go_back”事件并在按下键时触发它来将一些东西转移到 kv,同时绑定你的屏幕管理器来观看该事件,但这似乎还有很长的路要走。

我的代码基于https://groups.google.com/forum/#!topic/kivy-users/7rOZGMMIFXI 的邮件列表线程。可能有更好的方法,但这很实用。

【讨论】:

我已经编辑了我的请求...也许它会更清楚,抱歉第一次是一个抽象的问题。 那么你真正的问题是什么?您不知道如何更改当前屏幕?你不知道如何在 python 中获取 screenmanager 的引用? 我的问题是如何在 python 中获取对 screenmanager 的引用:会不会像 _screen_manager=ObjectProperty(None)?那么 self._screen_manager.current = 'screen1' ? 是的,这是一个很好的方法。不过,不要忘记将对象属性设置为实际指向您的 kv 文件中的屏幕管理器,您可以使用 ids 来执行此操作。 我尝试了以下方法:_screen_manager=ObjectProperty(ScreenManager()),然后在更改按键 27 按下事件上的屏幕的功能中添加:self._screen_manager.current='screen1' when测试它我没有名为“screen1”的屏幕,很抱歉打扰你@inclement,但我很接近......【参考方案4】:

现在我一直在 2020 年使用:

Clock.schedule_once(lambda x: Window.bind(on_keyboard=self.hook_keyboard))

结合与其他答案类似的 hook_keyboard 方法,以延迟我的构建方法中的绑定。工作正常,但这些其他方式似乎都不适合我了。

【讨论】:

以上是关于带有kivy的android上的后退按钮功能的主要内容,如果未能解决你的问题,请参考以下文章

如何为Android应用程序统一访问手机后退按钮

新手关于移动网站上的android后退按钮

在工作灯中使用带有 Dojomobile 和 phonegap 的 android 后退按钮

如何使用 appium 自动化 android 手机后退按钮

kivy 按钮按下以转到多个屏幕之一

如何在nativescript vue中处理webview上的android后退按钮