I'm working on a card game where I'm using ScatterLayout as Board because I am interested on the zoom in/out functionality, then I have some cards I want to move around. I know how to move the cards, but when using the ScatterLayout I end up moving the Scatterlayout rather than the cards. I can block the move of the ScatterLayout, because when zoomed in it's good I can move the layout around
I understand the issue, I need to make a distinction on when move the layout and when to move the card. Similar as what ScrollView does.
I've been reviewing the code the ScrollView and it makes this difference based on time and distance moved during the first touch. Which makes sense, But I haven't figurate out how to implement it on the ScatterLayout and the cards, as it seems I have to modify the on_touch_down and on_touch_move.
Is there any suggestion on how to implement this? i hope I'm not the first one facing this situation ;).
This is a sample code of what I'm working on:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.widget import Widget
Builder.load_string("""
<Board>:
Card:
pos: 100, 100
size: 100, 100
Card:
pos: 300, 100
size: 50, 100
<Card>:
size_hint: None, None
canvas:
Color:
rgba: 0, 1, 0, 1
Rectangle:
pos: self.pos
size: self.size
""")
class Card(Widget):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
touch.grab(self)
return super().on_touch_down(touch)
def on_touch_move(self, touch):
if touch.grab_current is self:
self.center_x = touch.x
self.center_y = touch.y
return True
return super().on_touch_move(touch)
def on_touch_up(self, touch):
if touch.grab_current is self:
touch.ungrab(self)
return super().on_touch_up(touch)
class Board(ScatterLayout):
do_collide_after_children=False
class MoveApp(App):
def build(self):
return Board()
MoveApp().run()
Can you explain, in greater detail, how you want to user to interact with the UI?
You have a small number of cards on a board, you want to be able to zoom in on the cards as a group, you want to be able to move the cards individually?
If that is correct here are some ideas:
Control the card size: If a zoom gesture is detected on the board (the enclosing layout) change the size of the cards. This way you retain all of the attributes of the cards, and can move them independently. Assuming the card is an Image, set keep_ratio to True.
Make each card a Scatter. Use a scatter for each card, rather than having all of the cards in a scatter layout. Each object remains independent.
Change the layout dynamically, use the Scatter Layout out for the zoom, but when it is time to turn zoom off and do other actions, replace the ScatterLayout with a FloatLayout.
--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/b0e9bbfb-9625-44de-955f-2ee1457e62c8n%40googlegroups.com.
Here below is the current code and issues:
Current issues:
After zoom in/out, Scatter move out of place. I don't think this is due the interaction with the ScrollView. I think this is just how the Scatter works and honestly, it is annoying. I haven't see anywhere on the Scatter code how to avoid this.
Cards are getting on the way when I try to pinch the screen to zoom in/out. If first fingers touch a card (which is very likely), the touch grabs the card and I can't zoom anymore. I have avoided this issue happening with the second finger by counting the touches currently on the screen. But I'm unable to trigger an action with the 2nd touch to tell 1st touch to ungrab the card and grab the Scatter (or re-trigger the on_touch_down method, which would also solve the issue).
I have tried using Buttons, as alternative to grab and move cards, but same issue. on_press gets on the way for zoom it.
Here are a few more ideas:
Consider there are 2 modes Zoom and Play. You could try this with a toggle button on the bottom of the screen.
In zoom mode the cards are on a screen in a ScatterLayout out, when pressing the toggle button again, the screen changes to the cards on a different screen in a Grid Layout.
Perhaps you could smooth the transition by animating the ScatterLayout parmaters to get the ScatterLayout back to the original view prior to switching screens.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/e999d674-cdc4-4e96-8f8b-4156e46e7f94n%40googlegroups.com.
Here is an example of using a ScreenManager to change the layouts switching between a play and zoom mode.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import
Screen
kv = """
#:import NoTransition kivy.uix.screenmanager.NoTransition
<Box@Widget>:
canvas:
Color:
rgb: .5, .5, .5
Rectangle:
size: self.size
pos: self.pos
<GridScreen@Screen>:
GridLayout:
padding: 10
spacing: 10
cols: 2
rows: 2
Box:
Box:
Box:
Box:
<ScatterScreen>:
ScatterLayout:
id: sl
GridLayout:
padding: 10
spacing: 10
cols: 2
rows: 2
Box:
Box:
Box:
Box:
BoxLayout:
orientation: 'vertical'
ScreenManager:
id: sm
transition: NoTransition()
GridScreen:
name: 'grid'
ScatterScreen:
name: 'scatter'
ToggleButton:
size_hint_y: None
height: 48
text: {'normal': 'Play', 'down': 'Zoom'}[self.state]
on_state:
sm.current = {'normal': 'grid', 'down': 'scatter'}[self.state]
# root.ids.sm.get_screen('scatter').reset()
"""
class ScatterScreen(Screen):
def reset(self):
self.ids.sl.scale = 1
self.ids.sl.rotation = 0
self.ids.sl.pos = 0,0
class MoveApp(App):
def build(self):
return Builder.load_string(kv)
MoveApp().run()
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/625c1afa.1c69fb81.367ba.24bdSMTPIN_ADDED_MISSING%40gmr-mx.google.com.