1 回答
TA贡献1815条经验 获得超10个赞
找到了在不添加散点小部件的情况下实现捏合缩放的方法,因为散点不会更新数据的宽度和高度,因此滚动尺寸也不会更新。下面是没有分散的实现。缩放适用于触摸锚点。这并不理想,因为动画不流畅。
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.recycleview import RecycleView
from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.metrics import sp, dp
from kivy.animation import Animation
from kivy.uix.widget import Widget
from PIL import Image as PILImage
from kivy.properties import NumericProperty
from kivy.graphics.transformation import Matrix
from kivy.vector import Vector
from kivy.graphics.context_instructions import PopMatrix, PushMatrix, Translate
MY_APP_KV_LANG = """
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
<RootLayout>:
size_hint: 1, 1
canvas.before:
Color:
rgba: (0, 0, 0, 1)
Rectangle:
size: self.size
pos: self.pos
DocumentWidget:
id: rv
viewclass: 'Image'
key_size: 'size'
effect_cls: ScrollEffect
scroll_type: ['content']
bar_width: 0
cols: 1
RecycleBoxLayout:
id: rvbox
spacing: dp(10)
padding: dp(10)
cols: rv.cols
orientation: 'vertical'
size_hint: None, None
height: self.minimum_height
width: self.minimum_width
default_size_hint: 1, None
"""
class RootLayout(FloatLayout):
pass
class DocumentWidget(RecycleView):
scale = NumericProperty(1.)
scroll_y1 = NumericProperty(0.)
scroll_y2 = NumericProperty(0.)
delta_scy = NumericProperty(0.)
def __init__(self, **kwargs):
super(DocumentWidget, self).__init__(**kwargs)
pil_image = PILImage.open('test3.jpg')
self.data = [{'source': 'test3.jpg', 'width': Window.size[0] - dp(20), 'height': (Window.size[0] - dp(20)) * pil_image.size[1] / pil_image.size[0], 'size_hint_x': None, 'size_hint_y': None, 'allow_stretch': True, 'keep_ratio': True} for x in range(3)]
self.data_initial = [{'width': Window.size[0] - dp(20), 'height': (Window.size[0] - dp(20)) * pil_image.size[1] / pil_image.size[0]} for x in range(3)]
self.bind(on_scale = self.on_scale)
def on_touch_up(self, touch):
if self.collide_point(*touch.pos):
if touch.is_double_tap:
if 1.0 >= self.scale >= 0.99:
self.scroll_y1 = self.scroll_y
self.delta_scy = Window.size[1] - touch.pos[1] - dp(10)
def _prg(*args):
self.scroll_x = (touch.pos[0] * self.scale) / (self.data[0]["width"] + dp(20))
self.scroll_y = self.scroll_y1 - self.scroll_y1 * self.delta_scy * (self.scale - 1) / (self.layout_manager.size[1] - Window.size[1])
self.scroll_y2 = self.scroll_y
anim = Animation(scale=2, duration=0.2, transition='in_quad')
anim.bind(on_progress=_prg)
anim.start(self)
else:
def _prg(*args):
self.scroll_y = (self.scroll_y2 - self.scroll_y1) * self.scale + 2 * self.scroll_y1 - self.scroll_y2
anim = Animation(scale=1, duration=0.2, transition='out_quad')
anim.bind(on_progress=_prg)
anim.start(self)
return super(DocumentWidget, self).on_touch_up(touch)
def on_scale(self, *args):
for x in range(3):
self.data[x]["height"] = self.data_initial[x]["height"] * self.scale
self.data[x]["width"] = self.data_initial[x]["width"] * self.scale
self.refresh_from_data()
class MyApp(App):
def build(self):
self.root = Builder.load_string(MY_APP_KV_LANG)
return RootLayout()
if __name__ == "__main__":
MyApp().run()
添加回答
举报