kivy scroll layout issue - python

class Template_Screen (Screen):
pass
Above is the class which i have added into a App class as follows
class MAKE_HTML(App):
"""
Still i need to write it fully.... Thanks for patience.....
"""
def build(self):
sm = ScreenManager()
sm.add_widget(Template_Screen(name='Select Template'))
I am using the kv file which is as follows
#the below screen gives the template
<Template_Screen>
ScrollView:
do_scroll_y:True
do_scroll_x: False
GridLayout:
size_hint_y:None
cols:1
height:self.minimum_height
BoxLayout:
Image:
source: "Images/Templates Pictures/Temp-1.png"
Label:
text:"Some sort of text\n Some text"
Problems:
When I scroll, the scroll first scrolls and then goes up even if i do not scroll up. i.e, After scrolling down-> Automatically goes up.
The image is not visible. I want the image to be 1/2 the size of screen.
I want to scroll with above like o/p.

The default value for effect_cls of a ScrollView is DampedScrollEffect, which the documentation describes as:
DampedScrollEffect: The current default. Allows the user to scroll
beyond the normal boundaries, but has the content spring back once the
touch/click is released.
So that is the automatic scrolling effect that you see. You can eliminate that behavior by using ScrollEffect as the effect_cls, but that will also prevent you from scrolling when the contents do not fill the ScrollView
When you use height:self.minimum_height for a GridLayout, you must provide a height for each child. Since you want the Image to be half the size of the Screen, you can use a kv like this:
#the below screen gives the template
<Template_Screen>
ScrollView:
do_scroll_y:True
do_scroll_x: False
effect_cls: 'ScrollEffect'
GridLayout:
size_hint_y:None
cols:1
height:self.minimum_height
BoxLayout:
size_hint: None, None
size: root.width/2, root.height/2
Image:
source: "mages/Templates Pictures/Temp-1.png"
allow_stretch: True
keep_ratio: True
Label:
text:"Some sort of text\\n Some text"
size_hint: None, None
size: self.texture_size

Related

How can I align my Label text on the left and still have X-axis scroll in Kivy?

I am making a weather app in which text results are displayed in a scrollview. I have been testing my app and have decided I need to add in x-axis scrolling. In previous times I was making use of just y-axis scrolling but have found that some of the weather results include longer lines that end up not fitting in the screen width and as a result, are being moved down a line which makes the formatting look bad.
I have found that not having anything set in text_size: allows the words to run off the screen without having them forced onto the next line. That is what I needed in regards to that.
Now I am stuck trying to figure out how to have my text results start out being aligned on the left margin of the screen and then allowing the user to scroll across to view entire line(s) if necessary. I am planning on having the run on iPad and iPhone so the screen widths will obviously differ, and I don't want to make the font size any smaller because the user wont be able to read it.
I have tried a whole bunch of different combinations with the layouts in the scrollview, with the parent and child but can't seem to get it right.
I have made a very minimalistic reproducible version that seems to behave the same as my actual app. The scrollview in my homescreen is the culprit. If someone could please help me out with this, that would be so good, thank you.
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
class HomeScreen(Screen):
pass
class Results1Screen(Screen):
pass
class TestApp(App):
def build(self):
return Builder.load_file("main.kv")
def on_start(self):
brief_res_1 = self.root.ids["home_screen"].ids["brief_res_1"]
brief_res_1.text = (open("text.txt", "r")).read()
TestApp().run()
main.kv
#:include kv/homescreen.kv
GridLayout:
cols: 1
FloatLayout:
ScreenManager:
size_hint: 1, .95
pos_hint: {"top": .95, "left": 1}
id: screen_manager
HomeScreen:
name: "home_screen"
id: home_screen
homescreen.kv
<HomeScreen>:
BoxLayout:
pos_hint: {"top": .7, "left": 1}
size_hint: 1, 1
size_hint_y: None
ScrollView:
Label:
id: brief_res_1
font_size: '9sp' # need to keep this at '9sp'
do_scroll_x: True
size_hint_y: None
size_hint_x: None
height: self.texture_size[1]
halign: "left" # not too sure if this should be "left"
valign: "center"
text:
text.txt
LINE 1 TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT
LINE 2 TEXT TEXT TEXT TEXT TEXT TEXT
LINE 3 TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT
You can just replace:
height: self.texture_size[1]
with:
size: self.texture_size
If you do not set the width of the Label, it will take the default width of 100, and your x-scrolling will not happen until the width of your HomeScreen gets less than 100 pixels wide.

Insert a widget to the beginning of a layout. Kivy

I am trying to understand how StackLayout works within ScrollView in Kivy. And i have got a problem. I do not know how to insert a widget to the beginning of the layout. If i use .add_widget() method, it adds the widget to the end(in the bottom) of the layout. And if i change the orientation of the layout(it
has stacking id) to 'lr-bt' and then add the widget(with "Title" and "Print" labels), then it causes some padding from the top of the ScrollView. So here is what i get:
May we could use other layouts. If anyone could help me fix that top padding or insert widget to the beginning, that would be great. Thanks.
Here is some code from .py file:
pln = Plan(text_label="Title", text="Print")
self.root.ids.stacking.add_widget(pln)
And here is my ScrollView with the StackLayout from .kv file:
BoxLayout:
id: stack_box
size_hint_y: 1
pos: 2, root.height-1057
RecycleView:
scroll_y: 1
do_scroll_x: False
do_scroll_y: True
size_hint: 1, None
height: 1000
id: scroll_plans
StackLayout:
spacing: 10
padding: 10
id: stacking
orientation: 'lr-bt'
size_hint_y: None
height: 9000

Problem with Kivy when trying to scrolldown vertical ScrollView with an horizontal ScrollView inside

Ok, so I'm building something with Kivy(1.11.1) and summarizing I have a ScrollView that scrolls vertically and inside it there are some others ScrollViews but these ones only scroll horizontally, the problem is that whenever I scroll the outer ScrollView down and the mouse position gets into the inner Horizontal ScrollViews the outer Scrollview stops scrolling down, it looks like once the mouse position collides with the horizontal scrollview the scroll behavior stops being sent to the outer ScrollView (vertical) so it stops scrolling down. What I want is something like the Netflix page, in which there are some scrollviews horizontally (My List, Series, Horror Movies, etc) that you can scroll to see more options but they're all inside an outer scrollview that scrolls vertically, of course that in Netflix when you scrolldown even if your mouse position get inside one of the horizontal scrollviews it still continue scrolling the outer ScrollView down.
I've tried setting the horizontall scrollview do_scroll_y to False but the problem goes on. Besides that. Scrolling up works just fine
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
Builder.load_string(
'''
<ScrollApp>:
ScrollView:
bar_width: 10
scroll_type: ['bars', 'content']
BoxLayout:
id: content
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
padding: 22, 0, 22, 50
spacing: 50
canvas:
Color:
rgba: .15, .15, .15, .9
Rectangle:
size: self.size
pos: self.pos
Button:
size_hint: None, None
width: 100
height: 100
on_press: print('pressed')
# "ScrollViews containers"
Custom
Custom
Custom
Custom
<Custom#BoxLayout>:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
Label:
size_hint: None, None
size: self.texture_size
id: label
font_size: 20
ScrollView:
size_hint: 1, None
height: 150
do_scroll: True, False
on_scroll_start: print('scrolling. but why?')
GridLayout:
id: grid
size_hint: None, None
size: self.minimum_width, 150
spacing: 5
cols: 3
Button:
size_hint: None, None
size: 400, 150
Button:
size_hint: None, None
size: 400, 150
Button:
size_hint: None, None
size: 400, 150
''' )
class ScrollApp(BoxLayout):
pass
class Test(App):
def build(self):
return ScrollApp()
Test().run()
I can't claim to understand this situation completely, but it seems that vertical ScrollView inside another vertical ScrollView works. So, a work around is to make the ScrollView inside your Custom class to allow vertical scrolling (along with the horizontal scrolling). To do this, change the kv for the ScrollView inside Custom to:
ScrollView:
size_hint: 1, None
height: 150
do_scroll: True, True # allow vertical scrolling also
on_scroll_start: print('scrolling. but why?')
GridLayout:
id: grid
size_hint: None, 1.01 # height must be slightly greater than ScrollView height
width: self.minimum_width
In order for the vertical scrolling to work in the above, the height of the GridLayout must be larger than the height of the ScrollView, thus the 1.01 size hint.

Scroll contents of GridLayout in ScrollView - Kivy

I will say first off I have tried every single example on the web involving kv lang. Not once have I had any success.
The idea is pretty simple: As I swipe up/down/scroll the contents of GridLayout() within ScrollView() are scrolled up or down.
The best I have been able to do is have the scroll bar fade into view when running the program. Not able to scroll unfortunately.
<Root>
grid_layout: grid_layout
ScreenManager:
...
Screen:
...
ScrollView:
GridLayout:
id: grid_layout
size_hint_y: None
cols: 1
height: self.minimum_height
<list of buttons>
Binding minimum_heightin the __init__ method of the root class (RelativeLayout):
grid_layout = ObjectProperty(None)
self.grid_layout.bind(minimum_height=self.grid_layout.setter('height'))
I have followed https://github.com/kivy/kivy/blob/master/examples/widgets/scrollview.py converting it to kv lang - scroll bar visible, unable to scroll. Also tried every example on Google Groups and here related to using kv lang. Still no scroll :\
Compiling using buildozer and running on Android fails for an unknown reason.
I would appreciate any assistance that can be given.. I am completely clueless at this point
This:
height: self.minimum_height
should be:
minimum_height: self.height
This is unnecessary:
grid_layout = ObjectProperty(None)
self.grid_layout.bind(minimum_height=self.grid_layout.setter('height'))
It also won't scroll unless the contents are larger than the scrollview's height:
Full code:
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
Builder.load_string('''
<Root>:
ScrollView:
size_hint: 1, .1
# setting the width of the scrollbar to 50pixels
bar_width: 50
# setting the color of the active bar using rgba
bar_color: 5, 10, 15, .8
# setting the color of the inactive bar using rgba
bar_inactive_color: 5, 20, 10, .5
# setting the content only to scroll via bar, not content
scroll_type: ['bars']
GridLayout:
size_hint_y: None
cols: 1
minimum_height: self.height
Button
text: 'one'
Button:
text: 'two'
Button:
text: 'three'
Button:
text: 'four'
''')
class Root(FloatLayout):
pass
class DemoApp(App):
def build(self):
return Root()
if __name__ == '__main__':
DemoApp().run()
Being unable to scroll was due to a misunderstanding of Kivy's touch handlers. Completely unrelated to the code mentioned in my question.
The key is to have GridLayout be larger than ScrollView, so GridLayout can be panned within ScrollView.
For those wanting to use ScrollView inside ScreenManager using kvlang only:
ScreenManager:
id: screen_manager
Screen:
manager: screen_manager
id: main_screen
name: 'main'
ScrollView:
bar_width: 4
# pos_hint defaults to 1,1 so no need to declare it
GridLayout:
size_hint_y: None
cols: 1
# you do not need to manually bind to setter('height') in
# python - perfectly possible with kv lang
# this allows for height to update depending on the
# collective heights of its child widgets
height: self.minimum_height
<----- widgets here ----->
# for scroll to show/work there must be more widgets
# then can fit root.height. If not there is no need
# for scrollview :)

Kivy behavior of drawing in canvas, to change it's background

I'm trying to set the background of my layout with the following kv language:
<RootWidget>:
Menu:
orientation: 'vertical'
Button:
text: 'btn1'
on_release: print('btn1')
Button:
text: 'btn'
on_release: print('btn2')
BoxLayout:
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'main_background.png'
ToggleMenuButton:
on_release: root.toggle_state()
size_hint: None, None
size: 60, 60
background_color: 0, 0, 0, 0
Image:
size: self.parent.size
pos: self.parent.pos
allow_stretch: True
source: './data/images/white_menu.png'
And this is my code:
from kivy.app import App
from kivy.garden.navigationdrawer import NavigationDrawer
from layouts.menu import Menu
from layouts.menu import ToggleMenuButton
from layouts.content import Content
class RootWidget(NavigationDrawer):
pass
class MainApp(App):
def build(self):
self.root = RootWidget()
return self.root
if __name__ == '__main__':
MainApp().run()
The Menu and Content classes are Kivy BoxLayout, the ToggleMenuButton is a Kivy Button.
When I run this code I get the following screen:
The background should be my image, not black. If I but the white_menu.png as my background, I also get a black braground. But, if put the following code:
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'main_background.png'
I get the following:
Like you can notice on the bottom, the image is transparent, with 3 white rectangles, but on the main layout the image is red. I kwnow that it is red, because the rgba code, but why the image changes it's color?
If I put the background on canvas.after it works correctly, I can see my background, but I can't see the widgets.
Summing up, I want to understand what is happening? Why I cant see the changes on canvas.before? Why/How putting a color on my canvas changes my image?
If I change, the RootWidget to be a BoxLayout instead of a NavigationDrawer, it works correctaly. Why? Why changing the canvas of a child of a child of a NavigationDrawer does not work?

Categories