主頁 > 移動端開發 > Flutter影片:將小部件從flex布局移動到另一個flex布局

Flutter影片:將小部件從flex布局移動到另一個flex布局

2022-05-24 10:13:14 移動端開發

我想將一個小部件從 flex 布局(在本例中為 Wrap)移動到另一個 flex 布局(再次為 Wrap)。這有點像以編程方式拖放。

我已經撰寫了一個作業概念證明:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

// To get the position of a widget
extension GlobalKeyExtension on GlobalKey {
  Rect? get globalPaintBounds {
    final renderObject = currentContext?.findRenderObject();
    final matrix = renderObject?.getTransformTo(null);

    if (matrix != null && renderObject?.paintBounds != null) {
      final rect = MatrixUtils.transformRect(matrix, renderObject!.paintBounds);
      return rect;
    } else {
      return null;
    }
  }
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: MyHomePage());
  }
}

// A simple square
class Square extends StatelessWidget {
  final Color color;

  const Square({this.color = Colors.blue, Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: color,
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final parentKey = GlobalKey();
  final sourceKey = GlobalKey();
  final targetKey = GlobalKey();
  Rect? sourceRect;
  Rect? targetRect;
  bool moved = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Move test')),
      body: Stack(
        key: parentKey,
        children: [
          Padding(
            padding: const EdgeInsets.all(32),
            child: Column(
              children: [
                // The top Wrap is the target of the movement
                Wrap(
                  spacing: 16,
                  runSpacing: 16,
                  children: [
                    const Square(),
                    const Square(),
                    // Display the target
                    if (moved)
                      const Square(color: Colors.yellow)
                    else if (sourceRect != null && targetRect != null)
                      const Opacity(opacity: 0, child: Square())
                    else
                      Square(key: targetKey),
                    const Square(),
                    const Square(),
                  ],
                ),
                const Spacer(),
                Wrap(
                  spacing: 16,
                  runSpacing: 16,
                  children: [
                    const Square(color: Colors.red),
                    const Square(color: Colors.red),
                    // Display the source
                    if (sourceRect == null && targetRect == null && !moved)
                      InkWell(
                        onTap: () {
                          print('Tapped');
                          setState(() {
                            final parentRect = parentKey.globalPaintBounds;
                            if (parentRect != null) {
                              sourceRect = sourceKey.globalPaintBounds;
                              sourceRect = sourceRect?.translate(
                                -parentRect.left,
                                -parentRect.top,
                              );
                              targetRect = targetKey.globalPaintBounds;
                              targetRect = targetRect?.translate(
                                -parentRect.left,
                                -parentRect.top,
                              );
                            }
                          });
                          WidgetsBinding.instance
                              .addPostFrameCallback((timeStamp) {
                            setState(() {
                              sourceRect = targetRect;
                              print('START animation!');
                            });
                          });
                        },
                        child: Square(key: sourceKey, color: Colors.red),
                      ),
                    const Square(color: Colors.red),
                    const Square(color: Colors.red),
                  ],
                ),
              ],
            ),
          ),
          // This part is within Stack and moves the square
          if (sourceRect != null && targetRect != null)
            AnimatedPositioned(
              left: sourceRect!.left,
              top: sourceRect!.top,
              duration: const Duration(seconds: 1),
              onEnd: () {
                print('STOP animation!');
                setState(() {
                  sourceRect = null;
                  targetRect = null;
                  moved = true;
                });
              },
              child: const Square(color: Colors.yellow),
            ),
        ],
      ),
    );
  }
}

結果是這樣的:一個移動的小部件影片(gif)

所以,我的問題是:有沒有更好的方法在框架內或使用庫中做到這一點?

uj5u.com熱心網友回復:

我不確定你所說的“更好的方式”是什么意思,但是有一個(不是庫)被呼叫,它適用于你在兩個頁面之間但在同一個頁面內使用小部件local_hero獲得的相同影片,也許你可以試試看Hero看看它是否是你想要的:

https://pub.dev/packages/local_hero

萬一你不知道,https://pub.dev是 flutter/dart 包正式發布的地方。

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/480656.html

標籤: 动画片

上一篇:如何使用ObjectAnimator正確縮放ImageView并將其移動到絕對位置

下一篇:返回列表

標籤雲
其他(140642) Python(33561) JavaScript(21279) Java(15659) C(13887) 區塊鏈(8222) AI(7469) C#(6618) 基礎類(6313) 爪哇(6257) MySQL(6174) html(5706) 熊猫(5292) sql(5241) PHP(5148) 腳本語言(PerlPython)(5129) 非技術區(4971) Linux(4835) 数组(4750) R(4612) Android(4340) 反应(4265) 数据框(3701) css(3641) 节点.js(3351) C語言(3288) C++語言(3117) json(2804) Java相關(2746) 疑難問題(2699) 列表(2698) 扑(2598) 安卓(2585) VBA(2511) 單片機工控(2479) 打字稿(2471) 细绳(2178) ASP.NET(2129) iOS(2087) MongoDB(1976) Web開發(1951) 字典(1928) 麻木的(1901) 正则表达式(1890) 循环(1880) 擅长(1824) 镖(1818) 網絡通信(1793) 迅速(1781) 蟒蛇-3.x(1774) 數據庫相關(1767) VB基礎類(1755) .NETCore(1740) Unity3D(1689) C++(1660) 功能(1654) 開發(1646) .NET技术(1638) 系統維護與使用區(1617) HtmlCss(1594)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布