Quick search

Table Of Contents

Source code for kivy.uix.pagelayout

"""
PageLayout
==========

The :class:`PageLayout` class allow to create a simple multiple page
layout, in a way that allows easy flipping of one page to another using
borders.

:class:`PageLayout` doesn't honor size_hint or pos_hint in any way currently.

.. versionadded:: 1.8.0

example::

    PageLayout:
        Button:
            text: 'page1'

        Button:
            text: 'page2'

        Button:
            text: 'page3'
"""

__all__ = ('PageLayout', )

from kivy.uix.layout import Layout
from kivy.properties import NumericProperty
from kivy.animation import Animation


[docs]class PageLayout(Layout): '''PageLayout class. See module documentation for more information ''' '''Currently displayed page. :data:`page` is a :class:`~kivy.properties.NumericProperty`, default to 0. ''' page = NumericProperty(0) '''Width of the border used around current page to display previous/next page when needed. :data:`border` is a :class:`~kivy.properties.NumericProperty`, default to 0. ''' border = NumericProperty('50dp') '''Thresold to the swipe action triggering, as percentage of the widget size. :data:`swipe_threshold` is a :class:`~kivy.properties.NumericProperty`, default to .5. ''' swipe_threshold = NumericProperty(.5) def __init__(self, **kwargs): super(PageLayout, self).__init__(**kwargs) self.bind( border=self._trigger_layout, page=self._trigger_layout, parent=self._trigger_layout, children=self._trigger_layout, size=self._trigger_layout, pos=self._trigger_layout) def do_layout(self, *largs): l_children = len(self.children) for i, c in enumerate(reversed(self.children)): if i < l_children: width = self.width - self.border else: width = self.width - 2 * self.border if i == 0: x = self.x elif i < self.page: x = self.x elif i == self.page: x = self.x + self.border elif i == self.page + 1: x = self.right - self.border else: x = self.right c.height = self.height c.width = width Animation( x=x, y=self.y, d=.5, t='in_quad').start(c) def on_touch_down(self, touch): if self.y < touch.y < self.top: if self.page > 0 and self.x < touch.x < (self.x + self.border): touch.ud['page'] = 'previous' touch.grab(self) return True elif ( self.page < len(self.children) - 1 and self.right > touch.x > (self.right - self.border) ): touch.ud['page'] = 'next' touch.grab(self) return True return self.children[-self.page - 1].on_touch_down(touch) def on_touch_move(self, touch): if touch.grab_current == self: if touch.ud['page'] == 'previous': self.children[-self.page - 1].x = max(min( self.x + self.border + (touch.x - touch.ox), self.right - self.border), self.x + self.border) if self.page > 1: self.children[-self.page].x = min( self.x + self.border * (touch.sx - touch.osx), self.x + self.border) if self.page < len(self.children) - 1: self.children[-self.page + 1].x = min( self.right - self.border * (1 - (touch.sx - touch.osx)), self.right) elif touch.ud['page'] == 'next': self.children[-self.page + 1].x = min(max( self.right - self.border + (touch.x - touch.ox), self.x + self.border), self.right - self.border) if self.page >= 1: self.children[-self.page - 1].x = max( self.x + self.border * (1 - (touch.osx - touch.sx)), self.x) if self.page < len(self.children) - 2: self.children[-self.page].x = max( self.right + self.border * (touch.sx - touch.osx), self.right - self.border) return self.children[-self.page - 1].on_touch_move(touch) def on_touch_up(self, touch): if touch.grab_current == self: if ( touch.ud['page'] == 'previous' and abs(touch.sx - touch.osx) > self.swipe_threshold ): self.page -= 1 elif ( touch.ud['page'] == 'next' and abs(touch.sx - touch.osx) > self.swipe_threshold ): self.page += 1 else: self._trigger_layout() touch.ungrab(self) return self.children[-self.page + 1].on_touch_up(touch)
if __name__ == '__main__': from kivy.base import runTouchApp from kivy.uix.button import Button pl = PageLayout() for i in range(1, 4): b = Button(text='page%s' % i) pl.add_widget(b) runTouchApp(pl)