如何在缩放时更新Scatter中嵌入的RecycleView的数据值(即图像宽度,高度)?

找不到有关嵌入在 Scatter 小部件中的 RecycleView 的任何详细信息。尽管在 RecycleView(或一般的 ScrollView)嵌入 Scatter 的情况下有几个与触摸相关的问题,但在我的特定情况下,问题是在缩放图像时图像宽度/高度等属性没有改变(Scatter 的预期行为),因此 RecycleView 布局不会更新。因此,水平滚动是不可能的。请查看以下代码:


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.scatter import Scatter

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


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        

    DocLayoutScat:

        id: docscat

        DocumentWidget:

            id: rv

            viewclass: 'Image'

            key_size: 'size'

            effect_cls: ScrollEffect

            scroll_type: ['content']

            bar_width: 0

            cols: 1

            width: docscat.width

            height: docscat.height

            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

"""


我试图用比例值改变图像的宽度/高度,但这会使增加宽度/高度的效果加倍。有什么方法可以更新 RecycleView 的数据属性以及缩放,以便在缩放/缩放时可以水平滚动?


慕码人8056858
浏览 73回答 1
1回答

动漫人物

找到了在不添加散点小部件的情况下实现捏合缩放的方法,因为散点不会更新数据的宽度和高度,因此滚动尺寸也不会更新。下面是没有分散的实现。缩放适用于触摸锚点。这并不理想,因为动画不流畅。from kivy.app import Appfrom kivy.uix.image import Imagefrom kivy.uix.recycleview import RecycleViewfrom kivy.core.window import Windowfrom kivy.uix.floatlayout import FloatLayoutfrom kivy.lang import Builderfrom kivy.metrics import sp, dpfrom kivy.animation import Animationfrom kivy.uix.widget import Widgetfrom PIL import Image as PILImagefrom kivy.properties import NumericPropertyfrom kivy.graphics.transformation import Matrixfrom kivy.vector import Vectorfrom kivy.graphics.context_instructions import PopMatrix, PushMatrix, TranslateMY_APP_KV_LANG = """#:import ScrollEffect kivy.effects.scroll.ScrollEffect<RootLayout>:&nbsp; &nbsp; size_hint: 1, 1&nbsp; &nbsp; canvas.before:&nbsp; &nbsp; &nbsp; &nbsp; Color:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rgba: (0, 0, 0, 1)&nbsp; &nbsp; &nbsp; &nbsp; Rectangle:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; size: self.size&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pos: self.pos&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; DocumentWidget:&nbsp; &nbsp; &nbsp; &nbsp; id: rv&nbsp; &nbsp; &nbsp; &nbsp; viewclass: 'Image'&nbsp; &nbsp; &nbsp; &nbsp; key_size: 'size'&nbsp; &nbsp; &nbsp; &nbsp; effect_cls: ScrollEffect&nbsp; &nbsp; &nbsp; &nbsp; scroll_type: ['content']&nbsp; &nbsp; &nbsp; &nbsp; bar_width: 0&nbsp; &nbsp; &nbsp; &nbsp; cols: 1&nbsp; &nbsp; &nbsp; &nbsp; RecycleBoxLayout:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id: rvbox&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spacing: dp(10)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; padding: dp(10)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cols: rv.cols&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; orientation: 'vertical'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; size_hint: None, None&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: self.minimum_height&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width: self.minimum_width&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default_size_hint: 1, None"""class RootLayout(FloatLayout):&nbsp; &nbsp; passclass DocumentWidget(RecycleView):&nbsp; &nbsp; scale = NumericProperty(1.)&nbsp; &nbsp; scroll_y1 = NumericProperty(0.)&nbsp; &nbsp; scroll_y2 = NumericProperty(0.)&nbsp; &nbsp; delta_scy = NumericProperty(0.)&nbsp; &nbsp; def __init__(self, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp; super(DocumentWidget, self).__init__(**kwargs)&nbsp; &nbsp; &nbsp; &nbsp; pil_image = PILImage.open('test3.jpg')&nbsp; &nbsp; &nbsp; &nbsp; 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)]&nbsp; &nbsp; &nbsp; &nbsp; 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)]&nbsp; &nbsp; &nbsp; &nbsp; self.bind(on_scale = self.on_scale)&nbsp; &nbsp; def on_touch_up(self, touch):&nbsp; &nbsp; &nbsp; &nbsp; if self.collide_point(*touch.pos):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if touch.is_double_tap:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if 1.0 >= self.scale >= 0.99:&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.scroll_y1 = self.scroll_y&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.delta_scy = Window.size[1] - touch.pos[1] - dp(10)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def _prg(*args):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.scroll_x = (touch.pos[0] * self.scale) / (self.data[0]["width"] + dp(20))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.scroll_y = self.scroll_y1 - self.scroll_y1 * self.delta_scy * (self.scale - 1) / (self.layout_manager.size[1] - Window.size[1])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.scroll_y2 = self.scroll_y&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anim = Animation(scale=2, duration=0.2, transition='in_quad')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anim.bind(on_progress=_prg)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anim.start(self)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def _prg(*args):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.scroll_y = (self.scroll_y2 - self.scroll_y1) * self.scale + 2 * self.scroll_y1 - self.scroll_y2&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anim = Animation(scale=1, duration=0.2, transition='out_quad')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anim.bind(on_progress=_prg)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; anim.start(self)&nbsp; &nbsp; &nbsp; &nbsp; return super(DocumentWidget, self).on_touch_up(touch)&nbsp; &nbsp; def on_scale(self, *args):&nbsp; &nbsp; &nbsp; &nbsp; for x in range(3):&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.data[x]["height"] = self.data_initial[x]["height"] * self.scale&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.data[x]["width"] = self.data_initial[x]["width"] * self.scale&nbsp; &nbsp; &nbsp; &nbsp; self.refresh_from_data()class MyApp(App):&nbsp; &nbsp; def build(self):&nbsp; &nbsp; &nbsp; &nbsp; self.root = Builder.load_string(MY_APP_KV_LANG)&nbsp; &nbsp; &nbsp; &nbsp; return RootLayout()if __name__ == "__main__":&nbsp; &nbsp; MyApp().run()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python