Scaler for Retina screen

winstonwolff edited this page Oct 19, 2013 · 2 revisions


  • author: Mathieu Virbel
  • kivy: >= 1.3.0

On Retina screen (iOS / iPad 3), the resolution is high (> 2000px) with an high DPI. Kivy currently don't support DPI, and then, all the text will look very tiny etc. We don't have anything for properly handling DPI and the moment, so you could use that Scaler class. You might do some change in order to use it.



# Put in your method
from kivy.utils import platform
from scaler import Scaler

class MyApp(App):
    def build(self):
        # construct your app here
        self.root = MyRootWidget()

        # special case for retina display, high dpi is not well handled
        # in kivy. use scatter to "zoom in"
        from kivy.core.window import Window
        self._scaler = None
        if platform() == 'ios' and (
            Window.width > 2000 or Window.height > 2000):
            self._scaler = Scaler(
                size=Window.size, scale=2)

        # add the widget to Window or scaler
        parent = self._scaler or Window


from kivy.uix.widget import Widget
from import NumericProperty, ObjectProperty
from kivy.base import EventLoop
from kivy.lang import Builder

class Scaler(Widget):
    scale = NumericProperty(2)
    container = ObjectProperty(None)

    def __init__(self, **kwargs):
        from kivy.base import EventLoop
        from kivy.lang import Builder
    container: container
            scale: root.scale


        id: container
        size: root.width / root.scale, root.height / root.scale

        super(Scaler, self).__init__(**kwargs)

    def get_parent_window(self):
        return self.container

    def add_widget(self, widget):
        if self.container is not None:
            return self.container.add_widget(widget)
        return super(Scaler, self).add_widget(widget)

    def remove_widget(self, widget):
        if self.container is not None:
            return self.container.remove_widget(widget)
        return super(Scaler, self).remove_widget(widget)

    def process_to_local(self, x, y, relative=False):
        if x is None:
            return None, None
        s = float(self.scale)
        return x / s, y / s

    def process(self, events):
        transform = self.process_to_local
        transformed = []
        for etype, event in events:

            # you might have a move and up event in the same process
            # then avoid the double-transformation
            if event in transformed:

  , = transform(,
            if etype == 'begin':
                event.osx, event.osy = transform(event.osx, event.osy)
                # update the delta
                event.dsx = - event.psx
                event.dsy = - event.psy

        return events

##Comments Add your comments here ...

Is this relevant anymore now that kivy includes kivy.metrics? - Winston Oct 2013

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.