I have Python code:
class Screen3(Screen):
def __init__(self, **kwargs):
self.scv = ScrollView()
self.bl_main = BoxLayout()
self.bl_main.padding = [20, 20, 20, 20]
self.bl_main.spacing = 50
self.bl_main.orientation = 'vertical'
super(Screen, self).__init__(**kwargs)
def on_enter(self, *args):
for i in [f'Button {i+1}' for i in range(20)]:
b = Button()
b.size_hint = None, None
b.size = 350, 350
b.text = i
anch = AnchorLayout()
anch.anchor_x = 'right'
anch.add_widget(b)
self.bl_main.add_widget(anch)
self.scv.add_widget(self.bl_main)
self.add_widget(self.scv)
And I have kivy
code:
Screen3:
name: 'screen3'
BoxLayout:
orientation: vertical
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
MDToolbar:
title: "History"
left_action_items: [['menu', lambda x: nav_drawer.set_state()], ['skip-backward', lambda x: app.change_screen('main screen', screen_manager)]]
elevation: 12
Here you can see my app.
https://pasteboard.co/J7KTdeR.jpg
How do I correct both of these points?
Please, help me.
Your icon-Buttons don't work because the ScrollView
that you add in on_enter()
has the default size_hint
of (1,1), and thus fills the entire Screen3
(even though parts of the ScrollView
are transparent). The ScrollView
is grabbing the mouse clicks, so the icon-Buttons never see the mouse clicks.
In a similar way, the BoxLayout
(bl_main) also has the default size_hint
, so its height will be the height of the ScrollView
, and it will try to fit the 20 Buttons
in that height
. Each Button
gets its share of the height, which is not enough, so they overlap.
The fix is to build the ScrollView
and BoxLayout
in the kv
to take advantage of the automatic bindings, and to set their sizes. Here is a version of your code that does that:
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.app import MDApp
class Screen3(Screen):
def on_enter(self, *args):
for i in [f'Button {i+1}' for i in range(20)]:
b = Button()
b.size_hint = None, None
b.size = 350, 350
b.text = i
# anch = AnchorLayout()
# anch.anchor_x = 'right'
# anch.add_widget(b)
# self.ids.bl_main.add_widget(anch)
self.ids.bl_main.add_widget(b)
kv = '''
Screen3:
name: 'screen3'
BoxLayout:
orientation: 'vertical'
size_hint_y: None
height: toolbar.height
pos_hint: {'center_x':0.5, 'top':1}
# AnchorLayout:
# anchor_x: 'center'
# anchor_y: 'top'
MDToolbar:
id: toolbar
title: "History"
left_action_items: [['menu', lambda x: nav_drawer.set_state()], ['skip-backward', lambda x: app.change_screen('main screen', screen_manager)]]
elevation: 12
ScrollView:
size_hint: (None, None)
height: root.height - toolbar.height
width: 390 # Button width plus BoxLayout padding
pos_hint: {'right':1}
BoxLayout:
id: bl_main
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
padding: [20, 20, 20, 20]
spacing: 50
'''
class TestApp(MDApp):
def build(self):
sm = ScreenManager()
sm.add_widget(Builder.load_string(kv))
return sm
TestApp().run()
Note the setting of sizes, positions, and the use of height: self.minimum_height
for the BoxLayout
. Refer to the ScrollView documentation for the reasoning behind this.
I have also commented out your use of AnchorLayout
, as it is superfluous.