Reputation: 21
I need to change orientation to vertical, but it does not work the same way as BoxLayout. There is also no information about this in the Kivy official documentation. In addition, is there any way to change the page by swiping from any place on the screen and not only the border?
Python:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class MainScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("final.kv")
class MainApp(App):
def build(self):
return presentation
if __name__ == "__main__":
MainApp().run()
Kivy:
ScreenManagement:
MainScreen:
<MainScreen>:
canvas:
Rectangle:
source: "nakedman.jpg"
pos: self.pos
size: self.size
name: "main"
PageLayout:
orientation: "vertical"
BoxLayout:
Button:
text: "Button1"
Button:
text: "Button2"
BoxLayout:
Button:
text: "Button3"
Button:
text: "Button4"
Upvotes: 1
Views: 697
Reputation: 244132
PageLayout does not have the orientation attribute, so you have to build everything, in this case use the source code of PageLayout to obtain this new code:
__all__ = ('PageLayoutVertical', )
from kivy.uix.layout import Layout
from kivy.properties import NumericProperty, DictProperty
from kivy.animation import Animation
class PageLayoutVertical(Layout):
'''PageLayout class. See module documentation for more information.
'''
page = NumericProperty(0)
'''The currently displayed page.
:data:`page` is a :class:`~kivy.properties.NumericProperty` and defaults
to 0.
'''
border = NumericProperty('50dp')
'''The width of the border around the current page used to display
the previous/next page swipe areas when needed.
:data:`border` is a :class:`~kivy.properties.NumericProperty` and
defaults to 50dp.
'''
swipe_threshold = NumericProperty(.5)
'''The thresold used to trigger swipes as percentage of the widget
size.
:data:`swipe_threshold` is a :class:`~kivy.properties.NumericProperty`
and defaults to .5.
'''
anim_kwargs = DictProperty({'d': .5, 't': 'in_quad'})
'''The animation kwargs used to construct the animation
:data:`anim_kwargs` is a :class:`~kivy.properties.DictProperty`
and defaults to {'d': .5, 't': 'in_quad'}.
.. versionadded:: 1.11.0
'''
def __init__(self, **kwargs):
super(PageLayoutVertical, self).__init__(**kwargs)
trigger = self._trigger_layout
fbind = self.fbind
fbind('border', trigger)
fbind('page', trigger)
fbind('parent', trigger)
fbind('children', trigger)
fbind('size', trigger)
fbind('pos', trigger)
def do_layout(self, *largs):
l_children = len(self.children) - 1
w = self.width
x_parent, y_parent = self.pos
p = self.page
border = self.border
half_border = border / 2.
top = self.top
height = self.height - border
for i, c in enumerate(reversed(self.children)):
if i < p:
y = y_parent
elif i == p:
if not p: # it's first page
y = y_parent
elif p != l_children: # not first, but there are post pages
y = y_parent + half_border
else: # not first and there are no post pages
y = y_parent + border
elif i == p + 1:
if not p: # second page - no left margin
y = top - border
else: # there's already a left margin
y = top - half_border
else:
y = top
c.width = w
c.height = height
Animation(
x=x_parent,
y=y,
**self.anim_kwargs).start(c)
def on_touch_down(self, touch):
if (
self.disabled or
not self.collide_point(*touch.pos) or
not self.children
):
return
page = self.children[-self.page - 1]
if self.y <= touch.y < page.y:
touch.ud['page'] = 'previous'
touch.grab(self)
return True
elif page.top <= touch.y < self.top:
touch.ud['page'] = 'next'
touch.grab(self)
return True
return page.on_touch_down(touch)
def on_touch_move(self, touch):
if touch.grab_current != self:
return
p = self.page
border = self.border
half_border = border / 2.
page = self.children[-p - 1]
if touch.ud['page'] == 'previous':
# move next page upto right edge
if p < len(self.children) - 1:
self.children[-p - 2].y = min(
self.top - self.border * (1 - (touch.sy - touch.osy)),
self.top)
# move current page until edge hits the right border
if p >= 1:
b_right = half_border if p > 1 else border
b_left = half_border if p < len(self.children) - 1 else border
self.children[-p - 1].y = max(min(
self.y + b_left + (touch.y - touch.oy),
self.top - b_right),
self.y + b_left)
# move previous page left edge upto left border
if p > 1:
self.children[-p].y = min(
self.y + half_border * (touch.sy - touch.osy),
self.y + half_border)
elif touch.ud['page'] == 'next':
# move current page upto left edge
if p >= 1:
self.children[-p - 1].y = max(
self.y + half_border * (1 - (touch.osy - touch.sy)),
self.y)
# move next page until its edge hit the left border
if p < len(self.children) - 1:
b_right = half_border if p >= 1 else border
b_left = half_border if p < len(self.children) - 2 else border
self.children[-p - 2].y = min(max(
self.top - b_right + (touch.y - touch.oy),
self.y + b_left),
self.top - b_right)
# move second next page upto right border
if p < len(self.children) - 2:
self.children[-p - 3].y = max(
self.top + half_border * (touch.sy - touch.osy),
self.top - half_border)
return page.on_touch_move(touch)
def on_touch_up(self, touch):
if touch.grab_current == self:
if (
touch.ud['page'] == 'previous' and
abs(touch.y - touch.oy) / self.height > self.swipe_threshold
):
self.page -= 1
elif (
touch.ud['page'] == 'next' and
abs(touch.y - touch.oy) / self.height > self.swipe_threshold
):
self.page += 1
else:
self._trigger_layout()
touch.ungrab(self)
if len(self.children) > 1:
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 = PageLayoutVertical()
for i in range(1, 10):
b = Button(text='page%s' % i)
pl.add_widget(b)
runTouchApp(pl)
Upvotes: 0