size_hint: 1, None
height: self.minimum_height # bind height to minimum_height
width: self.minimum_width # bind width to minimum_width
height: self.parent.height # match the button's height
width: 100 # set to whatever you would like
pos: self.parent.pos # match the button's position
for i in range(3):
btn = Factory.CustomButton(text=str(i), size_hint=(1, None),
from kivy.factory import Factory
Finally, a side note: you're creating new bindings on grid_l every time search_btn_pressed() is called. These bindings should only be created once. You could bind once in Python by moving those bindings to HomeScreen.__init__(), but again, this is easier in kv:
It's actually not displaying only for the last button - it's displaying for each button, but in the same position. The problem is that Button is not a layout, and as such, does not perform layout of its children. So the GridLayout for each button is rendered at 0, 0 with size 100, 100 relative to the origin of the nearest relative parent (in this case, the GridLayout grid_l because it is contained by the ScrollView).
Then, in your loop:
When you add widgets to a non-layout widget, it's up to you to layout those widgets by setting position and size. Note that you must set the actual pos (or x and y) and size (or width and height) - you cannot use pos_hint or size_hint, as those are only handled by layouts.