The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .github
    ├── FUNDING.yml
    └── workflows
    │   └── ci.yml
├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
    ├── .gitignore
    ├── app
    │   ├── build.gradle
    │   ├── build.gradle.kts
    │   └── src
    │   │   ├── debug
    │   │       └── AndroidManifest.xml
    │   │   ├── main
    │   │       ├── AndroidManifest.xml
    │   │       ├── kotlin
    │   │       │   └── com
    │   │       │   │   └── gsy
    │   │       │   │       └── shuyu
    │   │       │   │           └── gsy_flutter_demo
    │   │       │   │               └── MainActivity.kt
    │   │       └── res
    │   │       │   ├── drawable-v21
    │   │       │       └── launch_background.xml
    │   │       │   ├── drawable
    │   │       │       └── launch_background.xml
    │   │       │   ├── mipmap-hdpi
    │   │       │       └── ic_launcher.png
    │   │       │   ├── mipmap-mdpi
    │   │       │       └── ic_launcher.png
    │   │       │   ├── mipmap-xhdpi
    │   │       │       └── ic_launcher.png
    │   │       │   ├── mipmap-xxhdpi
    │   │       │       └── ic_launcher.png
    │   │       │   ├── mipmap-xxxhdpi
    │   │       │       └── ic_launcher.png
    │   │       │   ├── values-night
    │   │       │       └── styles.xml
    │   │       │   └── values
    │   │       │       └── styles.xml
    │   │   └── profile
    │   │       └── AndroidManifest.xml
    ├── build.gradle
    ├── build.gradle.kts
    ├── gradle.properties
    ├── gradle
    │   └── wrapper
    │   │   └── gradle-wrapper.properties
    ├── settings.gradle
    └── settings.gradle.kts
├── assets
    ├── Agne.otf
    ├── Bobbers.ttf
    ├── Canterbury.ttf
    ├── HelloStockholm.otf
    ├── Horizon.otf
    ├── background.png
    └── bglbt.ttf
├── demo.jpg
├── ios
    ├── .gitignore
    ├── Flutter
    │   ├── AppFrameworkInfo.plist
    │   ├── Debug.xcconfig
    │   ├── Release.xcconfig
    │   └── ephemeral
    │   │   ├── flutter_lldb_helper.py
    │   │   └── flutter_lldbinit
    ├── Runner.xcodeproj
    │   ├── project.pbxproj
    │   ├── project.xcworkspace
    │   │   ├── contents.xcworkspacedata
    │   │   └── xcshareddata
    │   │   │   ├── IDEWorkspaceChecks.plist
    │   │   │   └── WorkspaceSettings.xcsettings
    │   └── xcshareddata
    │   │   └── xcschemes
    │   │       └── Runner.xcscheme
    ├── Runner.xcworkspace
    │   ├── contents.xcworkspacedata
    │   └── xcshareddata
    │   │   ├── IDEWorkspaceChecks.plist
    │   │   └── WorkspaceSettings.xcsettings
    ├── Runner
    │   ├── AppDelegate.swift
    │   ├── Assets.xcassets
    │   │   ├── AppIcon.appiconset
    │   │   │   ├── Contents.json
    │   │   │   ├── Icon-App-1024x1024@1x.png
    │   │   │   ├── Icon-App-20x20@1x.png
    │   │   │   ├── Icon-App-20x20@2x.png
    │   │   │   ├── Icon-App-20x20@3x.png
    │   │   │   ├── Icon-App-29x29@1x.png
    │   │   │   ├── Icon-App-29x29@2x.png
    │   │   │   ├── Icon-App-29x29@3x.png
    │   │   │   ├── Icon-App-40x40@1x.png
    │   │   │   ├── Icon-App-40x40@2x.png
    │   │   │   ├── Icon-App-40x40@3x.png
    │   │   │   ├── Icon-App-60x60@2x.png
    │   │   │   ├── Icon-App-60x60@3x.png
    │   │   │   ├── Icon-App-76x76@1x.png
    │   │   │   ├── Icon-App-76x76@2x.png
    │   │   │   └── Icon-App-83.5x83.5@2x.png
    │   │   └── LaunchImage.imageset
    │   │   │   ├── Contents.json
    │   │   │   ├── LaunchImage.png
    │   │   │   ├── LaunchImage@2x.png
    │   │   │   ├── LaunchImage@3x.png
    │   │   │   └── README.md
    │   ├── Base.lproj
    │   │   ├── LaunchScreen.storyboard
    │   │   └── Main.storyboard
    │   ├── Info.plist
    │   └── Runner-Bridging-Header.h
    └── RunnerTests
    │   └── RunnerTests.swift
├── lib
    ├── main.dart
    └── widget
    │   ├── align_demo_page.dart
    │   ├── anim_bg_demo_page.dart
    │   ├── anim_bubble_gum.dart
    │   ├── anim_button
    │       ├── anim_button_demo_page.dart
    │       ├── loading_anim_button.dart
    │       └── play_anim_button.dart
    │   ├── anim_juejin_logo_demo_page.dart
    │   ├── anim_progress_img_demo_page.dart
    │   ├── anim_scan_demo_page.dart
    │   ├── anim_switch_layout_demo_page.dart
    │   ├── anim_text_demo_page.dart
    │   ├── anim_tip_demo_page.dart
    │   ├── anima_demo_page.dart
    │   ├── anima_demo_page2.dart
    │   ├── anima_demo_page4.dart
    │   ├── anima_demo_page5.dart
    │   ├── animation_container_demo_page.dart
    │   ├── arc_seek_bar_demo_page.dart
    │   ├── async_to_sync_call_page.dart
    │   ├── blur_demo_page.dart
    │   ├── book_page
    │       ├── book_page.dart
    │       ├── book_painter.dart
    │       ├── book_text_clip.dart
    │       └── cal_point.dart
    │   ├── bottom_anim_nav_page.dart
    │   ├── bubble
    │       ├── bubble_demo_page.dart
    │       ├── bubble_painter.dart
    │       └── bubble_tip_widget.dart
    │   ├── canvas_click_demo_page.dart
    │   ├── card_3d_demo_page.dart
    │   ├── card_item_page.dart
    │   ├── card_perspective_demo_page.dart
    │   ├── card_real_3d_demo_page.dart
    │   ├── chat_list_scroll_demo_page.dart
    │   ├── chat_list_scroll_demo_page_2.dart
    │   ├── clip_demo_page.dart
    │   ├── cloud
    │       ├── cloud_demo_page.dart
    │       ├── cloud_render.dart
    │       └── cloud_widget.dart
    │   ├── color_progress_demo_page.dart
    │   ├── controller_demo_page.dart
    │   ├── custom_multi_render_demo_page.dart
    │   ├── custom_pull
    │       ├── gsy_refresh_sliver.dart
    │       └── refrsh_demo_page3.dart
    │   ├── custom_shader_path_demo_page.dart
    │   ├── custom_sliver
    │       ├── custom_sliver.dart
    │       └── scroll_header_demo_page.dart
    │   ├── custom_viewport
    │       ├── custom_viewport.dart
    │       ├── custom_viewport_page.dart
    │       ├── first_tab_bar.dart
    │       ├── first_tab_bar_render_sliver.dart
    │       ├── first_tab_bar_sliver_widget.dart
    │       ├── secondary_tab_bar.dart
    │       ├── secondary_tab_bar_render_sliver.dart
    │       └── secondary_tab_bar_sliver_widget.dart
    │   ├── dash_3d_demo_page.dart
    │   ├── demo_draggable_sheet_stick_page.dart
    │   ├── demo_navigator_new.dart
    │   ├── drag_img_demo_page.dart
    │   ├── drop_select_menu
    │       ├── drop_rect_tween.dart
    │       ├── drop_select_controller.dart
    │       ├── drop_select_demo_data.dart
    │       ├── drop_select_demo_page.dart
    │       ├── drop_select_expanded_menu.dart
    │       ├── drop_select_grid_menu.dart
    │       ├── drop_select_header.dart
    │       ├── drop_select_list_menu.dart
    │       ├── drop_select_menu.dart
    │       ├── drop_select_object.dart
    │       └── drop_select_widget.dart
    │   ├── expand
    │       └── expand_widget.dart
    │   ├── floating_touch_demo_page.dart
    │   ├── gesture_password
    │       ├── gesture_password_demo_page.dart
    │       ├── gesture_password_view.dart
    │       └── src
    │       │   ├── gesture_view_controller.dart
    │       │   ├── gesture_view_model.dart
    │       │   ├── gesture_view_path.dart
    │       │   └── gesture_view_point.dart
    │   ├── glass_demo_page.dart
    │   ├── gradient_text_demo_page.dart
    │   ├── honor_demo_page.dart
    │   ├── index_stack_drag_card_demo_page.dart
    │   ├── index_stack_drag_card_demo_page2.dart
    │   ├── input_bottom_demo_page.dart
    │   ├── juejin_3d_box_logo_demo_page.dart
    │   ├── juejin_3d_logo_demo_page.dart
    │   ├── keyboard_demo_page.dart
    │   ├── link_scroll_page.dart
    │   ├── link_sliver
    │       ├── link_flexible_space_bar.dart
    │       ├── link_sliver_demo_page.dart
    │       └── link_sliver_header.dart
    │   ├── liquid_glass_demo.dart
    │   ├── liquid_glass_demo2.dart
    │   ├── list_anim
    │       ├── header_appbar.dart
    │       └── list_anim_demo_page.dart
    │   ├── list_anim_2
    │       ├── header_appbar.dart
    │       └── list_anim_demo_page.dart
    │   ├── list_link_bottomsheet_demo_page.dart
    │   ├── matrix_custom_painter_page.dart
    │   ├── overflow_image_page.dart
    │   ├── pageview_in_pageview_demo_page.dart
    │   ├── particle
    │       ├── particle_model.dart
    │       ├── particle_page.dart
    │       ├── particle_painter.dart
    │       └── particle_widget.dart
    │   ├── photo_gallery_demo_page.dart
    │   ├── png_shadow_demo_page.dart
    │   ├── positioned_demo_page.dart
    │   ├── refrsh_demo_page.dart
    │   ├── refrsh_demo_page2.dart
    │   ├── rich
    │       └── real_rich_text.dart
    │   ├── rich_text_demo_page.dart
    │   ├── rich_text_demo_page2.dart
    │   ├── route_demo_page.dart
    │   ├── scroll_inner_content_demo_page.dart
    │   ├── scroll_listener_demo_page.dart
    │   ├── scroll_to_index_demo_page.dart
    │   ├── scroll_to_index_demo_page2.dart
    │   ├── shader_canvas_demo_page.dart
    │   ├── silder_verify_page.dart
    │   ├── sliver_list_demo_page.dart
    │   ├── sliver_stick_demo_page.dart
    │   ├── sliver_tab
    │       ├── sliver_tab_child_page.dart
    │       ├── sliver_tab_demo_page3.dart
    │       └── sliver_tab_sliver.dart
    │   ├── sliver_tab_demo_page.dart
    │   ├── sliver_tab_demo_page2.dart
    │   ├── star_bomb_button_page.dart
    │   ├── statusbar_demo_page.dart
    │   ├── stick
    │       ├── stick_demo_page.dart
    │       ├── stick_demo_page2.dart
    │       ├── stick_render.dart
    │       └── stick_widget.dart
    │   ├── stick_sliver_list_demo_page.dart
    │   ├── tag_demo_page.dart
    │   ├── tear_text_demo_page.dart
    │   ├── test_center_sliver
    │       ├── test_center_sliver.dart
    │       └── test_center_sliver_page.dart
    │   ├── text_line_height_demo_page.dart
    │   ├── text_size_demo_page.dart
    │   ├── tick_click_demo_page.dart
    │   ├── transform_canvas_demo_page.dart
    │   ├── transform_demo_page.dart
    │   ├── un_bounded_listview.dart
    │   ├── verification_code_input_demo_page.dart
    │   ├── verification_code_input_demo_page2.dart
    │   ├── viewpager_demo_page.dart
    │   ├── vp_list_demo_page.dart
    │   └── wrap_content_page.dart
├── linux
    ├── .gitignore
    ├── CMakeLists.txt
    ├── flutter
    │   ├── CMakeLists.txt
    │   ├── generated_plugin_registrant.cc
    │   ├── generated_plugin_registrant.h
    │   └── generated_plugins.cmake
    └── runner
    │   ├── CMakeLists.txt
    │   ├── main.cc
    │   ├── my_application.cc
    │   └── my_application.h
├── macos
    ├── .gitignore
    ├── Flutter
    │   ├── Flutter-Debug.xcconfig
    │   ├── Flutter-Release.xcconfig
    │   └── GeneratedPluginRegistrant.swift
    ├── Runner.xcodeproj
    │   ├── project.pbxproj
    │   ├── project.xcworkspace
    │   │   └── xcshareddata
    │   │   │   └── IDEWorkspaceChecks.plist
    │   └── xcshareddata
    │   │   └── xcschemes
    │   │       └── Runner.xcscheme
    ├── Runner.xcworkspace
    │   ├── contents.xcworkspacedata
    │   └── xcshareddata
    │   │   └── IDEWorkspaceChecks.plist
    ├── Runner
    │   ├── AppDelegate.swift
    │   ├── Assets.xcassets
    │   │   └── AppIcon.appiconset
    │   │   │   ├── Contents.json
    │   │   │   ├── app_icon_1024.png
    │   │   │   ├── app_icon_128.png
    │   │   │   ├── app_icon_16.png
    │   │   │   ├── app_icon_256.png
    │   │   │   ├── app_icon_32.png
    │   │   │   ├── app_icon_512.png
    │   │   │   └── app_icon_64.png
    │   ├── Base.lproj
    │   │   └── MainMenu.xib
    │   ├── Configs
    │   │   ├── AppInfo.xcconfig
    │   │   ├── Debug.xcconfig
    │   │   ├── Release.xcconfig
    │   │   └── Warnings.xcconfig
    │   ├── DebugProfile.entitlements
    │   ├── Info.plist
    │   ├── MainFlutterWindow.swift
    │   └── Release.entitlements
    └── RunnerTests
    │   └── RunnerTests.swift
├── privacy.html
├── pubspec.lock
├── pubspec.yaml
├── shaders
    ├── liquid_glass.frag
    └── liquid_glass2.frag
├── static
    ├── card_down.png
    ├── card_down_2.png
    ├── card_up.png
    ├── card_up_2.png
    ├── gsy_cat.png
    ├── iOS26.png
    ├── juejin.riv
    ├── person.jpg
    ├── test.jpeg
    └── test_logo.png
├── test
    └── widget_test.dart
├── thanks.jpg
├── web.jpg
├── web
    ├── favicon.png
    ├── icons
    │   ├── Icon-192.png
    │   ├── Icon-512.png
    │   ├── Icon-maskable-192.png
    │   └── Icon-maskable-512.png
    ├── index.html
    └── manifest.json
└── windows
    ├── .gitignore
    ├── CMakeLists.txt
    ├── flutter
        ├── CMakeLists.txt
        ├── generated_plugin_registrant.cc
        ├── generated_plugin_registrant.h
        └── generated_plugins.cmake
    └── runner
        ├── CMakeLists.txt
        ├── Runner.rc
        ├── flutter_window.cpp
        ├── flutter_window.h
        ├── main.cpp
        ├── resource.h
        ├── resources
            └── app_icon.ico
        ├── runner.exe.manifest
        ├── utils.cpp
        ├── utils.h
        ├── win32_window.cpp
        └── win32_window.h


/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 | 
3 | custom: http://img.cdn.guoshuyu.cn/thanks.jpg
4 | 


--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
 1 | name: CI
 2 | 
 3 | on:
 4 |   push:
 5 |     branches:
 6 |       - master
 7 |     tags:
 8 |       - 'v*'
 9 |   pull_request:
10 |     paths-ignore:
11 |       - '**/*.md'
12 |       - '**/*.txt'
13 |       - '**/*.png'
14 |       - '**/*.jpg'
15 | 
16 | jobs:
17 |   build:
18 |     name: Build
19 |     runs-on: ubuntu-latest
20 |     steps:
21 |       - uses: actions/checkout@v2
22 |       - uses: actions/setup-java@v2
23 |         with:
24 |           distribution: 'zulu'
25 |           java-version: 21
26 |       - uses: subosito/flutter-action@v1
27 |         with:
28 |           flutter-version: '3.29.2'
29 |       - run: flutter pub get
30 |       - run: flutter build apk
31 | 
32 |   apk:
33 |     name: Generate APK
34 |     if: startsWith(github.ref, 'refs/tags/v')
35 |     runs-on: ubuntu-latest
36 |     steps:
37 |       - name: Checkout
38 |         uses: actions/checkout@v2
39 |       - name: Setup JDK
40 |         uses: actions/setup-java@v2
41 |         with:
42 |           distribution: 'zulu'
43 |           java-version: 21
44 |       - uses: subosito/flutter-action@v1
45 |         with:
46 |           flutter-version: '3.29.2'
47 |       - run: flutter pub get
48 |       - run: flutter build apk --target-platform android-arm64
49 |       - name: Upload APK
50 |         uses: actions/upload-artifact@v4
51 |         with:
52 |           name: apk
53 |           path: build/app/outputs/apk/release/app-release.apk
54 |   release:
55 |     name: Release APK
56 |     needs: apk
57 |     if: startsWith(github.ref, 'refs/tags/v')
58 |     runs-on: ubuntu-latest
59 |     steps:
60 |       - name: Download APK from build
61 |         uses: actions/download-artifact@v4
62 |         with:
63 |           name: apk
64 |       - name: Display structure of downloaded files
65 |         run: ls -R
66 | 
67 |       - name: Create Release
68 |         id: create_release
69 |         uses: actions/create-release@v1.1.4
70 |         env:
71 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
72 |         with:
73 |           tag_name: ${{ github.ref }}
74 |           release_name: Release ${{ github.ref }}
75 |       - name: Upload Release APK
76 |         id: upload_release_asset
77 |         uses: actions/upload-release-asset@v1.0.1
78 |         env:
79 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80 |         with:
81 |           upload_url: ${{ steps.create_release.outputs.upload_url }}
82 |           asset_path: ./app-release.apk
83 |           asset_name: app-release.apk
84 |           asset_content_type: application/zip
85 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | # Miscellaneous
 2 | *.class
 3 | *.log
 4 | *.pyc
 5 | *.swp
 6 | .DS_Store
 7 | .atom/
 8 | .buildlog/
 9 | .history
10 | .svn/
11 | 
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 | 
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 | 
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .packages
28 | .pub-cache/
29 | .pub/
30 | /build/
31 | .gradle
32 | .cxx/
33 | 
34 | # Android related
35 | **/android/**/gradle-wrapper.jar
36 | **/android/.gradle
37 | **/android/captures/
38 | **/android/gradlew
39 | **/android/gradlew.bat
40 | **/android/local.properties
41 | **/android/**/GeneratedPluginRegistrant.java
42 | 
43 | # iOS/XCode related
44 | **/ios/**/*.mode1v3
45 | **/ios/**/*.mode2v3
46 | **/ios/**/*.moved-aside
47 | **/ios/**/*.pbxuser
48 | **/ios/**/*.perspectivev3
49 | **/ios/**/*sync/
50 | **/ios/**/.sconsign.dblite
51 | **/ios/**/.tags*
52 | **/ios/**/.vagrant/
53 | **/ios/**/DerivedData/
54 | **/ios/**/Icon?
55 | **/ios/**/Pods/
56 | **/ios/**/.symlinks/
57 | **/ios/**/profile
58 | **/ios/**/xcuserdata
59 | **/ios/.generated/
60 | **/ios/Flutter/App.framework
61 | **/ios/Flutter/Flutter.framework
62 | **/ios/Flutter/Generated.xcconfig
63 | **/ios/Flutter/app.flx
64 | **/ios/Flutter/app.zip
65 | **/ios/Flutter/flutter_assets/
66 | **/ios/ServiceDefinitions.json
67 | **/ios/Runner/GeneratedPluginRegistrant.*
68 | 
69 | # Exceptions to above rules.
70 | !**/ios/**/default.mode1v3
71 | !**/ios/**/default.mode2v3
72 | !**/ios/**/default.pbxuser
73 | !**/ios/**/default.perspectivev3
74 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
75 | ios/Flutter/flutter_export_environment.sh
76 | 
77 | ios/Flutter/.last_build_id
78 | ios/Flutter/Flutter.podspec
79 | 
80 | .flutter-plugins-dependencies


--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
 1 | # This file tracks properties of this Flutter project.
 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
 3 | #
 4 | # This file should be version controlled and should not be manually edited.
 5 | 
 6 | version:
 7 |   revision: "8defaa71a77c16e8547abdbfad2053ce3a6e2d5b"
 8 |   channel: "[user-branch]"
 9 | 
10 | project_type: app
11 | 
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 |   platforms:
15 |     - platform: root
16 |       create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
17 |       base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
18 |     - platform: android
19 |       create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
20 |       base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
21 |     - platform: ios
22 |       create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
23 |       base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
24 |     - platform: linux
25 |       create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
26 |       base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
27 |     - platform: macos
28 |       create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
29 |       base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
30 |     - platform: web
31 |       create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
32 |       base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
33 |     - platform: windows
34 |       create_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
35 |       base_revision: 8defaa71a77c16e8547abdbfad2053ce3a6e2d5b
36 | 
37 |   # User provided section
38 | 
39 |   # List of Local paths (relative to this file) that should be
40 |   # ignored by the migrate tool.
41 |   #
42 |   # Files that are not part of the templates will be ignored by default.
43 |   unmanaged_files:
44 |     - 'lib/main.dart'
45 |     - 'ios/Runner.xcodeproj/project.pbxproj'
46 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2019 Shuyu Guo
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
 1 | include: package:flutter_lints/flutter.yaml
 2 | 
 3 | analyzer:
 4 |   errors:
 5 |     mixin_inherits_from_not_object: ignore
 6 | 
 7 | linter:
 8 |   rules:
 9 |     library_private_types_in_public_api: false
10 |     constant_identifier_names: false
11 |     library_prefixes: false


--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
 1 | gradle-wrapper.jar
 2 | /.gradle
 3 | /captures/
 4 | /gradlew
 5 | /gradlew.bat
 6 | /local.properties
 7 | GeneratedPluginRegistrant.java
 8 | .cxx/
 9 | 
10 | # Remember to never publicly share your keystore.
11 | # See https://flutter.dev/to/reference-keystore
12 | key.properties
13 | **/*.keystore
14 | **/*.jks
15 | 


--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
 1 | plugins {
 2 |     id "com.android.application"
 3 |     id "kotlin-android"
 4 |     id "dev.flutter.flutter-gradle-plugin"
 5 | }
 6 | 
 7 | def localProperties = new Properties()
 8 | def localPropertiesFile = rootProject.file('local.properties')
 9 | if (localPropertiesFile.exists()) {
10 |     localPropertiesFile.withReader('UTF-8') { reader ->
11 |         localProperties.load(reader)
12 |     }
13 | }
14 | 
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 |     flutterVersionCode = '1'
18 | }
19 | 
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 |     flutterVersionName = '1.0'
23 | }
24 | 
25 | android {
26 |     compileSdkVersion 34
27 | 
28 |     namespace "com.gsy.shuyu.gsy_flutter_demo"
29 | 
30 |     sourceSets {
31 |         main.java.srcDirs += 'src/main/kotlin'
32 |     }
33 | 
34 |     lintOptions {
35 |         disable 'InvalidPackage'
36 |         checkReleaseBuilds false
37 |         // Or, if you prefer, you can continue to check for errors in release builds,
38 |         // but continue the build even when errors are found:
39 |         abortOnError false
40 |     }
41 | 
42 |     defaultConfig {
43 |         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
44 |         applicationId "com.gsy.shuyu.gsy_flutter_demo"
45 |         minSdkVersion flutter.minSdkVersion
46 |         targetSdkVersion 33
47 |         versionCode flutterVersionCode.toInteger()
48 |         versionName flutterVersionName
49 |     }
50 | 
51 |     buildTypes {
52 |         release {
53 |             // TODO: Add your own signing config for the release build.
54 |             // Signing with the debug keys for now, so `flutter run --release` works.
55 |             signingConfig signingConfigs.debug
56 |             minifyEnabled false
57 |             shrinkResources false
58 |         }
59 |     }
60 |     compileOptions {
61 |         sourceCompatibility JavaVersion.VERSION_17
62 |         targetCompatibility JavaVersion.VERSION_17
63 |     }
64 |     kotlinOptions {
65 |         jvmTarget = '17'
66 |     }
67 | }
68 | 
69 | flutter {
70 |     source '../..'
71 | }
72 | 
73 | dependencies {}
74 | 


--------------------------------------------------------------------------------
/android/app/build.gradle.kts:
--------------------------------------------------------------------------------
 1 | plugins {
 2 |     id("com.android.application")
 3 |     id("kotlin-android")
 4 |     // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
 5 |     id("dev.flutter.flutter-gradle-plugin")
 6 | }
 7 | 
 8 | android {
 9 |     namespace = "com.gsy.shuyu.gsy_flutter_demo"
10 |     compileSdk = flutter.compileSdkVersion
11 |     ndkVersion = flutter.ndkVersion
12 | 
13 |     compileOptions {
14 |         sourceCompatibility = JavaVersion.VERSION_11
15 |         targetCompatibility = JavaVersion.VERSION_11
16 |     }
17 | 
18 |     kotlinOptions {
19 |         jvmTarget = JavaVersion.VERSION_11.toString()
20 |     }
21 | 
22 |     defaultConfig {
23 |         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24 |         applicationId = "com.gsy.shuyu.gsy_flutter_demo"
25 |         // You can update the following values to match your application needs.
26 |         // For more information, see: https://flutter.dev/to/review-gradle-config.
27 |         minSdk = flutter.minSdkVersion
28 |         targetSdk = flutter.targetSdkVersion
29 |         versionCode = flutter.versionCode
30 |         versionName = flutter.versionName
31 |     }
32 | 
33 |     buildTypes {
34 |         release {
35 |             // TODO: Add your own signing config for the release build.
36 |             // Signing with the debug keys for now, so `flutter run --release` works.
37 |             signingConfig = signingConfigs.getByName("debug")
38 |         }
39 |     }
40 | }
41 | 
42 | flutter {
43 |     source = "../.."
44 | }
45 | 


--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 | <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 |     package="com.gsy.shuyu.gsy_flutter_demo">
3 |     <!-- Flutter needs it to communicate with the running application
4 |          to allow setting breakpoints, to provide hot reload, etc.
5 |     -->
6 |     <uses-permission android:name="android.permission.INTERNET"/>
7 | </manifest>
8 | 


--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
 1 | <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 2 |     package="com.gsy.shuyu.gsy_flutter_demo">
 3 | 
 4 |     <!-- io.flutter.app.FlutterApplication is an android.app.Application that
 5 |          calls FlutterMain.startInitialization(this); in its onCreate method.
 6 |          In most cases you can leave this as-is, but you if you want to provide
 7 |          additional functionality it is fine to subclass or reimplement
 8 |          FlutterApplication and put your custom class here. -->
 9 | 
10 |     <uses-permission android:name="android.permission.INTERNET"/>
11 |     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
12 |     <uses-permission android:name="android.permission.WAKE_LOCK" />
13 | 
14 |     <application
15 |         android:label="gsy_flutter_demo"
16 |         android:icon="@mipmap/ic_launcher">
17 |         <activity
18 |             android:name=".MainActivity"
19 |             android:launchMode="singleTop"
20 |             android:theme="@style/LaunchTheme"
21 |             android:exported="true"
22 |             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
23 |             android:hardwareAccelerated="true"
24 |             android:windowSoftInputMode="adjustResize">
25 |             <!-- This keeps the window background of the activity showing
26 |                  until Flutter renders its first frame. It can be removed if
27 |                  there is no splash screen (such as the default splash screen
28 |                  defined in @style/LaunchTheme). -->
29 |             <meta-data
30 |                 android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
31 |                 android:value="true" />
32 |             <intent-filter>
33 |                 <action android:name="android.intent.action.MAIN"/>
34 |                 <category android:name="android.intent.category.LAUNCHER"/>
35 |             </intent-filter>
36 |         </activity>
37 |         <!-- Don't delete the meta-data below.
38 |         This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
39 |         <meta-data
40 |                 android:name="flutterEmbedding"
41 |                 android:value="2" />
42 |     </application>
43 | </manifest>
44 | 


--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/gsy/shuyu/gsy_flutter_demo/MainActivity.kt:
--------------------------------------------------------------------------------
 1 | package com.gsy.shuyu.gsy_flutter_demo
 2 | 
 3 | import android.os.Bundle
 4 | import io.flutter.embedding.android.FlutterActivity
 5 | import io.flutter.embedding.engine.FlutterEngine
 6 | import io.flutter.plugins.GeneratedPluginRegistrant
 7 | 
 8 | class MainActivity: FlutterActivity() {
 9 | }
10 | 


--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <!-- Modify this file to customize your launch splash screen -->
 3 | <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 4 |     <item android:drawable="?android:colorBackground" />
 5 | 
 6 |     <!-- You can insert your own image assets here -->
 7 |     <!-- <item>
 8 |         <bitmap
 9 |             android:gravity="center"
10 |             android:src="@mipmap/launch_image" />
11 |     </item> -->
12 | </layer-list>
13 | 


--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <!-- Modify this file to customize your launch splash screen -->
 3 | <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 4 |     <item android:drawable="@android:color/white" />
 5 | 
 6 |     <!-- You can insert your own image assets here -->
 7 |     <!-- <item>
 8 |         <bitmap
 9 |             android:gravity="center"
10 |             android:src="@mipmap/launch_image" />
11 |     </item> -->
12 | </layer-list>
13 | 


--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png


--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png


--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png


--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png


--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <resources>
 3 |     <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
 4 |     <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
 5 |         <!-- Show a splash screen on the activity. Automatically removed when
 6 |              the Flutter engine draws its first frame -->
 7 |         <item name="android:windowBackground">@drawable/launch_background</item>
 8 |     </style>
 9 |     <!-- Theme applied to the Android Window as soon as the process has started.
10 |          This theme determines the color of the Android Window while your
11 |          Flutter UI initializes, as well as behind your Flutter UI while its
12 |          running.
13 | 
14 |          This Theme is only used starting with V2 of Flutter's Android embedding. -->
15 |     <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
16 |         <item name="android:windowBackground">?android:colorBackground</item>
17 |     </style>
18 | </resources>
19 | 


--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="utf-8"?>
2 | <resources>
3 |     <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
4 |         <!-- Show a splash screen on the activity. Automatically removed when
5 |              Flutter draws its first frame -->
6 |         <item name="android:windowBackground">@drawable/launch_background</item>
7 |     </style>
8 | </resources>
9 | 


--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 | <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 |     package="com.gsy.shuyu.gsy_flutter_demo">
3 |     <!-- Flutter needs it to communicate with the running application
4 |          to allow setting breakpoints, to provide hot reload, etc.
5 |     -->
6 |     <uses-permission android:name="android.permission.INTERNET"/>
7 | </manifest>
8 | 


--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
 1 | allprojects {
 2 |     repositories {
 3 |         google()
 4 |         jcenter()
 5 |     }
 6 | }
 7 | 
 8 | rootProject.buildDir = '../build'
 9 | subprojects {
10 |     project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 |     project.evaluationDependsOn(':app')
14 | }
15 | 
16 | tasks.register("clean", Delete) {
17 |     delete rootProject.buildDir
18 | }
19 | 


--------------------------------------------------------------------------------
/android/build.gradle.kts:
--------------------------------------------------------------------------------
 1 | allprojects {
 2 |     repositories {
 3 |         google()
 4 |         mavenCentral()
 5 |     }
 6 | }
 7 | 
 8 | val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
 9 | rootProject.layout.buildDirectory.value(newBuildDir)
10 | 
11 | subprojects {
12 |     val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
13 |     project.layout.buildDirectory.value(newSubprojectBuildDir)
14 | }
15 | subprojects {
16 |     project.evaluationDependsOn(":app")
17 | }
18 | 
19 | tasks.register<Delete>("clean") {
20 |     delete(rootProject.layout.buildDirectory)
21 | }
22 | 


--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
3 | android.useAndroidX=true
4 | # Automatically convert third-party libraries to use AndroidX
5 | android.enableJetifier=true


--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
7 | 


--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
 1 | pluginManagement {
 2 |     def flutterSdkPath = {
 3 |         def properties = new Properties()
 4 |         file("local.properties").withInputStream { properties.load(it) }
 5 |         def flutterSdkPath = properties.getProperty("flutter.sdk")
 6 |         assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
 7 |         return flutterSdkPath
 8 |     }()
 9 | 
10 |     includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 | 
12 |     repositories {
13 |         google()
14 |         mavenCentral()
15 |         gradlePluginPortal()
16 |     }
17 | }
18 | 
19 | plugins {
20 |     id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 |     id "com.android.application" version "8.6.1" apply false
22 |     id "org.jetbrains.kotlin.android" version "1.7.10" apply false
23 | }
24 | 
25 | include ":app"


--------------------------------------------------------------------------------
/android/settings.gradle.kts:
--------------------------------------------------------------------------------
 1 | pluginManagement {
 2 |     val flutterSdkPath = run {
 3 |         val properties = java.util.Properties()
 4 |         file("local.properties").inputStream().use { properties.load(it) }
 5 |         val flutterSdkPath = properties.getProperty("flutter.sdk")
 6 |         require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
 7 |         flutterSdkPath
 8 |     }
 9 | 
10 |     includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 | 
12 |     repositories {
13 |         google()
14 |         mavenCentral()
15 |         gradlePluginPortal()
16 |     }
17 | }
18 | 
19 | plugins {
20 |     id("dev.flutter.flutter-plugin-loader") version "1.0.0"
21 |     id("com.android.application") version "8.7.3" apply false
22 |     id("org.jetbrains.kotlin.android") version "2.1.0" apply false
23 | }
24 | 
25 | include(":app")
26 | 


--------------------------------------------------------------------------------
/assets/Agne.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/assets/Agne.otf


--------------------------------------------------------------------------------
/assets/Bobbers.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/assets/Bobbers.ttf


--------------------------------------------------------------------------------
/assets/Canterbury.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/assets/Canterbury.ttf


--------------------------------------------------------------------------------
/assets/HelloStockholm.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/assets/HelloStockholm.otf


--------------------------------------------------------------------------------
/assets/Horizon.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/assets/Horizon.otf


--------------------------------------------------------------------------------
/assets/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/assets/background.png


--------------------------------------------------------------------------------
/assets/bglbt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/assets/bglbt.ttf


--------------------------------------------------------------------------------
/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/demo.jpg


--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
 1 | **/dgph
 2 | *.mode1v3
 3 | *.mode2v3
 4 | *.moved-aside
 5 | *.pbxuser
 6 | *.perspectivev3
 7 | **/*sync/
 8 | .sconsign.dblite
 9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 | 
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 | 


--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 |   <key>CFBundleDevelopmentRegion</key>
 6 |   <string>en</string>
 7 |   <key>CFBundleExecutable</key>
 8 |   <string>App</string>
 9 |   <key>CFBundleIdentifier</key>
10 |   <string>io.flutter.flutter.app</string>
11 |   <key>CFBundleInfoDictionaryVersion</key>
12 |   <string>6.0</string>
13 |   <key>CFBundleName</key>
14 |   <string>App</string>
15 |   <key>CFBundlePackageType</key>
16 |   <string>FMWK</string>
17 |   <key>CFBundleShortVersionString</key>
18 |   <string>1.0</string>
19 |   <key>CFBundleSignature</key>
20 |   <string>????</string>
21 |   <key>CFBundleVersion</key>
22 |   <string>1.0</string>
23 |   <key>MinimumOSVersion</key>
24 |   <string>12.0</string>
25 | </dict>
26 | </plist>
27 | 


--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 | 


--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 | 


--------------------------------------------------------------------------------
/ios/Flutter/ephemeral/flutter_lldb_helper.py:
--------------------------------------------------------------------------------
 1 | #
 2 | # Generated file, do not edit.
 3 | #
 4 | 
 5 | import lldb
 6 | 
 7 | def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
 8 |     """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
 9 |     base = frame.register["x0"].GetValueAsAddress()
10 |     page_len = frame.register["x1"].GetValueAsUnsigned()
11 | 
12 |     # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
13 |     # first page to see if handled it correctly. This makes diagnosing
14 |     # misconfiguration (e.g. missing breakpoint) easier.
15 |     data = bytearray(page_len)
16 |     data[0:8] = b'IHELPED!'
17 | 
18 |     error = lldb.SBError()
19 |     frame.GetThread().GetProcess().WriteMemory(base, data, error)
20 |     if not error.Success():
21 |         print(f'Failed to write into {base}[+{page_len}]', error)
22 |         return
23 | 
24 | def __lldb_init_module(debugger: lldb.SBDebugger, _):
25 |     target = debugger.GetDummyTarget()
26 |     # Caveat: must use BreakpointCreateByRegEx here and not
27 |     # BreakpointCreateByName. For some reasons callback function does not
28 |     # get carried over from dummy target for the later.
29 |     bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES
quot;)
30 |     bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
31 |     bp.SetAutoContinue(True)
32 |     print("-- LLDB integration loaded --")
33 | 


--------------------------------------------------------------------------------
/ios/Flutter/ephemeral/flutter_lldbinit:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 | 
5 | command script import --relative-to-command-file flutter_lldb_helper.py
6 | 


--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Workspace
3 |    version = "1.0">
4 |    <FileRef
5 |       location = "self:">
6 |    </FileRef>
7 | </Workspace>
8 | 


--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>IDEDidComputeMac32BitWarning</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>PreviewsEnabled</key>
6 | 	<false/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Workspace
3 |    version = "1.0">
4 |    <FileRef
5 |       location = "group:Runner.xcodeproj">
6 |    </FileRef>
7 | </Workspace>
8 | 


--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>IDEDidComputeMac32BitWarning</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>PreviewsEnabled</key>
6 | 	<false/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
 1 | import UIKit
 2 | import Flutter
 3 | 
 4 | @main
 5 | @objc class AppDelegate: FlutterAppDelegate {
 6 |   override func application(
 7 |     _ application: UIApplication,
 8 |     didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
 9 |   ) -> Bool {
10 |     GeneratedPluginRegistrant.register(with: self)
11 |     return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 |   }
13 | }
14 | 


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
  1 | {
  2 |   "images" : [
  3 |     {
  4 |       "size" : "20x20",
  5 |       "idiom" : "iphone",
  6 |       "filename" : "Icon-App-20x20@2x.png",
  7 |       "scale" : "2x"
  8 |     },
  9 |     {
 10 |       "size" : "20x20",
 11 |       "idiom" : "iphone",
 12 |       "filename" : "Icon-App-20x20@3x.png",
 13 |       "scale" : "3x"
 14 |     },
 15 |     {
 16 |       "size" : "29x29",
 17 |       "idiom" : "iphone",
 18 |       "filename" : "Icon-App-29x29@1x.png",
 19 |       "scale" : "1x"
 20 |     },
 21 |     {
 22 |       "size" : "29x29",
 23 |       "idiom" : "iphone",
 24 |       "filename" : "Icon-App-29x29@2x.png",
 25 |       "scale" : "2x"
 26 |     },
 27 |     {
 28 |       "size" : "29x29",
 29 |       "idiom" : "iphone",
 30 |       "filename" : "Icon-App-29x29@3x.png",
 31 |       "scale" : "3x"
 32 |     },
 33 |     {
 34 |       "size" : "40x40",
 35 |       "idiom" : "iphone",
 36 |       "filename" : "Icon-App-40x40@2x.png",
 37 |       "scale" : "2x"
 38 |     },
 39 |     {
 40 |       "size" : "40x40",
 41 |       "idiom" : "iphone",
 42 |       "filename" : "Icon-App-40x40@3x.png",
 43 |       "scale" : "3x"
 44 |     },
 45 |     {
 46 |       "size" : "60x60",
 47 |       "idiom" : "iphone",
 48 |       "filename" : "Icon-App-60x60@2x.png",
 49 |       "scale" : "2x"
 50 |     },
 51 |     {
 52 |       "size" : "60x60",
 53 |       "idiom" : "iphone",
 54 |       "filename" : "Icon-App-60x60@3x.png",
 55 |       "scale" : "3x"
 56 |     },
 57 |     {
 58 |       "size" : "20x20",
 59 |       "idiom" : "ipad",
 60 |       "filename" : "Icon-App-20x20@1x.png",
 61 |       "scale" : "1x"
 62 |     },
 63 |     {
 64 |       "size" : "20x20",
 65 |       "idiom" : "ipad",
 66 |       "filename" : "Icon-App-20x20@2x.png",
 67 |       "scale" : "2x"
 68 |     },
 69 |     {
 70 |       "size" : "29x29",
 71 |       "idiom" : "ipad",
 72 |       "filename" : "Icon-App-29x29@1x.png",
 73 |       "scale" : "1x"
 74 |     },
 75 |     {
 76 |       "size" : "29x29",
 77 |       "idiom" : "ipad",
 78 |       "filename" : "Icon-App-29x29@2x.png",
 79 |       "scale" : "2x"
 80 |     },
 81 |     {
 82 |       "size" : "40x40",
 83 |       "idiom" : "ipad",
 84 |       "filename" : "Icon-App-40x40@1x.png",
 85 |       "scale" : "1x"
 86 |     },
 87 |     {
 88 |       "size" : "40x40",
 89 |       "idiom" : "ipad",
 90 |       "filename" : "Icon-App-40x40@2x.png",
 91 |       "scale" : "2x"
 92 |     },
 93 |     {
 94 |       "size" : "76x76",
 95 |       "idiom" : "ipad",
 96 |       "filename" : "Icon-App-76x76@1x.png",
 97 |       "scale" : "1x"
 98 |     },
 99 |     {
100 |       "size" : "76x76",
101 |       "idiom" : "ipad",
102 |       "filename" : "Icon-App-76x76@2x.png",
103 |       "scale" : "2x"
104 |     },
105 |     {
106 |       "size" : "83.5x83.5",
107 |       "idiom" : "ipad",
108 |       "filename" : "Icon-App-83.5x83.5@2x.png",
109 |       "scale" : "2x"
110 |     },
111 |     {
112 |       "size" : "1024x1024",
113 |       "idiom" : "ios-marketing",
114 |       "filename" : "Icon-App-1024x1024@1x.png",
115 |       "scale" : "1x"
116 |     }
117 |   ],
118 |   "info" : {
119 |     "version" : 1,
120 |     "author" : "xcode"
121 |   }
122 | }
123 | 


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "universal",
 5 |       "filename" : "LaunchImage.png",
 6 |       "scale" : "1x"
 7 |     },
 8 |     {
 9 |       "idiom" : "universal",
10 |       "filename" : "LaunchImage@2x.png",
11 |       "scale" : "2x"
12 |     },
13 |     {
14 |       "idiom" : "universal",
15 |       "filename" : "LaunchImage@3x.png",
16 |       "scale" : "3x"
17 |     }
18 |   ],
19 |   "info" : {
20 |     "version" : 1,
21 |     "author" : "xcode"
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png


--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 | 
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 | 
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.


--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
 3 |     <dependencies>
 4 |         <deployment identifier="iOS"/>
 5 |         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
 6 |     </dependencies>
 7 |     <scenes>
 8 |         <!--View Controller-->
 9 |         <scene sceneID="EHf-IW-A2E">
10 |             <objects>
11 |                 <viewController id="01J-lp-oVM" sceneMemberID="viewController">
12 |                     <layoutGuides>
13 |                         <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
14 |                         <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
15 |                     </layoutGuides>
16 |                     <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
17 |                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
18 |                         <subviews>
19 |                             <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
20 |                             </imageView>
21 |                         </subviews>
22 |                         <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
23 |                         <constraints>
24 |                             <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
25 |                             <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
26 |                         </constraints>
27 |                     </view>
28 |                 </viewController>
29 |                 <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
30 |             </objects>
31 |             <point key="canvasLocation" x="53" y="375"/>
32 |         </scene>
33 |     </scenes>
34 |     <resources>
35 |         <image name="LaunchImage" width="168" height="185"/>
36 |     </resources>
37 | </document>
38 | 


--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
 3 |     <dependencies>
 4 |         <deployment identifier="iOS"/>
 5 |         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
 6 |     </dependencies>
 7 |     <scenes>
 8 |         <!--Flutter View Controller-->
 9 |         <scene sceneID="tne-QT-ifu">
10 |             <objects>
11 |                 <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
12 |                     <layoutGuides>
13 |                         <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
14 |                         <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
15 |                     </layoutGuides>
16 |                     <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
17 |                         <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
18 |                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19 |                         <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
20 |                     </view>
21 |                 </viewController>
22 |                 <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
23 |             </objects>
24 |         </scene>
25 |     </scenes>
26 | </document>
27 | 


--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 | 	<key>CFBundleDevelopmentRegion</key>
 6 | 	<string>en</string>
 7 | 	<key>CFBundleExecutable</key>
 8 | 	<string>$(EXECUTABLE_NAME)</string>
 9 | 	<key>CFBundleIdentifier</key>
10 | 	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11 | 	<key>CFBundleInfoDictionaryVersion</key>
12 | 	<string>6.0</string>
13 | 	<key>CFBundleName</key>
14 | 	<string>gsy_flutter_demo</string>
15 | 	<key>CFBundlePackageType</key>
16 | 	<string>APPL</string>
17 | 	<key>CFBundleShortVersionString</key>
18 | 	<string>$(FLUTTER_BUILD_NAME)</string>
19 | 	<key>CFBundleSignature</key>
20 | 	<string>????</string>
21 | 	<key>CFBundleVersion</key>
22 | 	<string>$(FLUTTER_BUILD_NUMBER)</string>
23 | 	<key>LSRequiresIPhoneOS</key>
24 | 	<true/>
25 | 	<key>UILaunchStoryboardName</key>
26 | 	<string>LaunchScreen</string>
27 | 	<key>UIMainStoryboardFile</key>
28 | 	<string>Main</string>
29 | 	<key>UISupportedInterfaceOrientations</key>
30 | 	<array>
31 | 		<string>UIInterfaceOrientationPortrait</string>
32 | 		<string>UIInterfaceOrientationLandscapeLeft</string>
33 | 		<string>UIInterfaceOrientationLandscapeRight</string>
34 | 	</array>
35 | 	<key>UISupportedInterfaceOrientations~ipad</key>
36 | 	<array>
37 | 		<string>UIInterfaceOrientationPortrait</string>
38 | 		<string>UIInterfaceOrientationPortraitUpsideDown</string>
39 | 		<string>UIInterfaceOrientationLandscapeLeft</string>
40 | 		<string>UIInterfaceOrientationLandscapeRight</string>
41 | 	</array>
42 | 	<key>UIViewControllerBasedStatusBarAppearance</key>
43 | 	<false/>
44 | 	<key>CADisableMinimumFrameDurationOnPhone</key>
45 | 	<true/>
46 | 	<key>UIApplicationSupportsIndirectInputEvents</key>
47 | 	<true/>
48 | </dict>
49 | </plist>
50 | 


--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"


--------------------------------------------------------------------------------
/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
 1 | import Flutter
 2 | import UIKit
 3 | import XCTest
 4 | 
 5 | class RunnerTests: XCTestCase {
 6 | 
 7 |   func testExample() {
 8 |     // If you add code to the Runner application, consider adding tests here.
 9 |     // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 |   }
11 | 
12 | }
13 | 


--------------------------------------------------------------------------------
/lib/widget/align_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:math' as math;
 2 | import 'package:flutter/material.dart';
 3 | 
 4 | class AlignDemoPage extends StatefulWidget {
 5 |   const AlignDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   AlignDemoPageState createState() => AlignDemoPageState();
 9 | }
10 | 
11 | class AlignDemoPageState extends State<AlignDemoPage>
12 |     with SingleTickerProviderStateMixin {
13 |   getAlign(x) {
14 |     return Align(
15 |       alignment: Alignment(math.cos(x * math.pi), math.sin(x * math.pi)),
16 |       child: Container(
17 |         height: 20,
18 |         width: 20,
19 |         decoration: const BoxDecoration(
20 |             color: Colors.green,
21 |             borderRadius: BorderRadius.all(Radius.circular(10))),
22 |       ),
23 |     );
24 |   }
25 | 
26 |   @override
27 |   Widget build(BuildContext context) {
28 |     int size = 20;
29 |     return Scaffold(
30 |       appBar: AppBar(
31 |         title: const Text("AlignDemoPage"),
32 |       ),
33 |       body: Container(
34 |         alignment: const Alignment(0, 0),
35 |         child: SizedBox(
36 |           height: MediaQuery.sizeOf(context).width,
37 |           width: MediaQuery.sizeOf(context).width,
38 |           child: Stack(
39 |             children: List.generate(size, (index) {
40 |               return getAlign(index.toDouble() / size / 2);
41 |             }),
42 |           ),
43 |         ),
44 |       ),
45 |     );
46 |   }
47 | }
48 | 


--------------------------------------------------------------------------------
/lib/widget/anim_button/anim_button_demo_page.dart:
--------------------------------------------------------------------------------
  1 | import 'dart:io';
  2 | 
  3 | import 'package:flutter/material.dart';
  4 | import 'package:gsy_flutter_demo/widget/anim_button/play_anim_button.dart';
  5 | 
  6 | import 'loading_anim_button.dart';
  7 | 
  8 | class AnimButtonDemoPage extends StatefulWidget {
  9 |   const AnimButtonDemoPage({super.key});
 10 | 
 11 |   @override
 12 |   AnimButtonDemoPageState createState() => AnimButtonDemoPageState();
 13 | }
 14 | 
 15 | class AnimButtonDemoPageState extends State<AnimButtonDemoPage> {
 16 |   LoadingState? loadingState = LoadingState.STATE_PRE;
 17 | 
 18 |   updateState() {
 19 |     setState(() {});
 20 |   }
 21 | 
 22 |   @override
 23 |   Widget build(BuildContext context) {
 24 |     Widget playButton;
 25 |     try {
 26 |       if (Platform.isAndroid == true || Platform.isIOS == true) {
 27 |         playButton = const SizedBox(
 28 |           height: 50,
 29 |           width: 50,
 30 |           child: PlayAnimButton(),
 31 |         );
 32 |       } else {
 33 |         playButton = const Text(
 34 |           "该控件效果暂不支持 Web,已隐藏",
 35 |           style: TextStyle(color: Colors.white, fontSize: 16),
 36 |         );
 37 |       }
 38 |     } catch (e) {
 39 |       playButton = const Text(
 40 |         "该效果暂不支持 Web",
 41 |         style: TextStyle(color: Colors.white, fontSize: 16),
 42 |       );
 43 |     }
 44 |     return Scaffold(
 45 |       appBar: AppBar(
 46 |         title: const Text("AnimButtonDemoPage"),
 47 |       ),
 48 |       body: Container(
 49 |         color: Colors.blueAccent,
 50 |         child: Center(
 51 |             child: Column(
 52 |           mainAxisAlignment: MainAxisAlignment.center,
 53 |           children: <Widget>[
 54 |             const Text(
 55 |               "点击下方按键切换动画效果",
 56 |               style: TextStyle(color: Colors.white, fontSize: 16),
 57 |             ),
 58 |             const SizedBox(
 59 |               height: 50,
 60 |             ),
 61 |             playButton,
 62 |             const SizedBox(
 63 |               height: 50,
 64 |             ),
 65 |             SizedBox(
 66 |               height: 50,
 67 |               width: 50,
 68 |               child: InkWell(
 69 |                 onTap: () {
 70 |                   LoadingState nextState;
 71 |                   switch (loadingState) {
 72 |                     case LoadingState.STATE_PRE:
 73 |                       nextState = LoadingState.STATE_COMPLETE;
 74 |                       break;
 75 |                     case LoadingState.STATE_END:
 76 |                       nextState = LoadingState.STATE_DOWNLOADING;
 77 |                       break;
 78 |                     case LoadingState.STATE_DOWNLOADING:
 79 |                       nextState = LoadingState.STATE_PRE;
 80 |                       break;
 81 |                     case LoadingState.STATE_COMPLETE:
 82 |                     default:
 83 |                       nextState = LoadingState.STATE_END;
 84 |                       break;
 85 |                   }
 86 |                   setState(() {
 87 |                     loadingState = nextState;
 88 |                   });
 89 |                 },
 90 |                 child: LoadingAnimButton(
 91 |                   loadingState: loadingState,
 92 |                   loadingSpeed: 1,
 93 |                 ),
 94 |               ),
 95 |             ),
 96 |           ],
 97 |         )),
 98 |       ),
 99 |     );
100 |   }
101 | }
102 | 


--------------------------------------------------------------------------------
/lib/widget/anim_juejin_logo_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:rive/rive.dart';
 3 | 
 4 | class AnimJueJinLogoDemoPage extends StatefulWidget {
 5 |   const AnimJueJinLogoDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   State<AnimJueJinLogoDemoPage> createState() => _AnimJueJinLogoDemoPageState();
 9 | }
10 | 
11 | class _AnimJueJinLogoDemoPageState extends State<AnimJueJinLogoDemoPage> {
12 |   @override
13 |   Widget build(BuildContext context) {
14 |     return Scaffold(
15 |       appBar: AppBar(
16 |         title: const Text("AnimJueJinLogoDemoPage"),
17 |       ),
18 |       body: const RiveAnimation.asset(
19 |         'static/juejin.riv',
20 |       ),
21 |     );
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/lib/widget/anim_tip_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class AnimTipDemoPage extends StatefulWidget {
 4 |   const AnimTipDemoPage({super.key});
 5 | 
 6 |   @override
 7 |   _AnimTipDemoPageState createState() => _AnimTipDemoPageState();
 8 | }
 9 | 
10 | class _AnimTipDemoPageState extends State<AnimTipDemoPage> {
11 |   bool showTipItem = false;
12 | 
13 |   @override
14 |   Widget build(BuildContext context) {
15 |     return Scaffold(
16 |       appBar: AppBar(
17 |         title: const Text("AnimTipDemoPage"),
18 |       ),
19 |       body: Column(children: [
20 |         AnimatedSwitcher(
21 |           switchInCurve: const Cubic(0.4, 0.0, 0.2, 1.0),
22 |           switchOutCurve: const Cubic(1.0, 0.1, 1.0, 0.1),
23 |           transitionBuilder: (child, anim) {
24 |             return SlideTransition(
25 |                 position: Tween<Offset>(
26 |                   begin: const Offset(0.0, -1.0),
27 |                   end: const Offset(0.0, 0.0),
28 |                 ).animate(anim),
29 |                 child: child);
30 |           },
31 |           duration: const Duration(milliseconds: 500),
32 |           child: showTipItem
33 |               ? Container(
34 |                   alignment: Alignment.centerLeft,
35 |                   width: MediaQuery.sizeOf(context).width,
36 |                   height: 70,
37 |                   key: const ValueKey("TipItem"),
38 |                   color: Colors.amber,
39 |                   child: const Row(
40 |                     children: <Widget>[
41 |                       Icon(Icons.ac_unit,
42 |                           color: Colors.white, size: 13),
43 |                       SizedBox(
44 |                         width: 10,
45 |                       ),
46 |                       Text(
47 |                         "StickText",
48 |                         style: TextStyle(color: Colors.white),
49 |                       ),
50 |                     ],
51 |                   ),
52 |                 )
53 |               : Container(
54 |                   key: const ValueKey("hideItem"),
55 |                 ),
56 |         ),
57 |         Expanded(
58 |           child: Center(
59 |             child: TextButton(
60 |               onPressed: () {
61 |                 setState(() {
62 |                   showTipItem = true;
63 |                 });
64 |                 Future.delayed(const Duration(seconds: 1), () {
65 |                   setState(() {
66 |                     showTipItem = false;
67 |                   });
68 |                 });
69 |               },
70 |               child: const Text("Click Me"),
71 |             ),
72 |           ),
73 |         )
74 |       ]),
75 |     );
76 |   }
77 | }
78 | 


--------------------------------------------------------------------------------
/lib/widget/anima_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class AnimaDemoPage extends StatefulWidget {
 4 |   const AnimaDemoPage({super.key});
 5 | 
 6 |   @override
 7 |   _AnimaDemoPageState createState() => _AnimaDemoPageState();
 8 | }
 9 | 
10 | class _AnimaDemoPageState extends State<AnimaDemoPage>
11 |     with SingleTickerProviderStateMixin {
12 |   late AnimationController controller1;
13 | 
14 |   Animation? animation1;
15 | 
16 |   late Animation animation2;
17 | 
18 |   @override
19 |   void initState() {
20 |     super.initState();
21 |     controller1 =
22 |         AnimationController(vsync: this, duration: const Duration(seconds: 3));
23 | 
24 |     animation1 = Tween(begin: 0.0, end: 200.0).animate(controller1)
25 |       ..addListener(() {
26 |         setState(() {});
27 |       });
28 | 
29 |     animation2 = Tween(begin: 0.0, end: 1.0).animate(controller1);
30 | 
31 |     controller1.repeat();
32 |   }
33 | 
34 |   @override
35 |   void dispose() {
36 |     controller1.dispose();
37 |     super.dispose();
38 |   }
39 | 
40 |   @override
41 |   Widget build(BuildContext context) {
42 |     return Scaffold(
43 |       appBar: AppBar(
44 |         title: const Text("AnimaDemoPage"),
45 |       ),
46 | 
47 |       ///用封装好的 Transition 做动画
48 |       body: RotationTransition(
49 |         turns: animation2 as Animation<double>,
50 |         child: Center(
51 |           child: Container(
52 |             height: 200,
53 |             width: 200,
54 |             color: Colors.greenAccent,
55 |             child: CustomPaint(
56 |               ///直接使用值做动画
57 |               foregroundPainter: _AnimationPainter(animation1),
58 |             ),
59 |           ),
60 |         ),
61 |       ),
62 |     );
63 |   }
64 | }
65 | 
66 | class _AnimationPainter extends CustomPainter {
67 |   final Paint _paint = Paint();
68 | 
69 |   Animation? animation;
70 | 
71 |   _AnimationPainter(this.animation);
72 | 
73 |   @override
74 |   void paint(Canvas canvas, Size size) {
75 |     _paint
76 |       ..color = Colors.redAccent
77 |       ..strokeWidth = 4
78 |       ..style = PaintingStyle.stroke;
79 |     canvas.drawCircle(const Offset(100, 100), animation!.value * 1.5, _paint);
80 |   }
81 | 
82 |   @override
83 |   bool shouldRepaint(CustomPainter oldDelegate) => true;
84 | }
85 | 


--------------------------------------------------------------------------------
/lib/widget/anima_demo_page4.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class AnimaDemoPage4 extends StatefulWidget {
 4 |   const AnimaDemoPage4({super.key});
 5 | 
 6 |   @override
 7 |   _AnimaDemoPageState createState() => _AnimaDemoPageState();
 8 | }
 9 | 
10 | class _AnimaDemoPageState extends State<AnimaDemoPage4> {
11 |   IconData iconData = Icons.clear;
12 | 
13 |   @override
14 |   Widget build(BuildContext context) {
15 |     return Scaffold(
16 |       appBar: AppBar(
17 |         title: const Text('AnimaDemoPage4'),
18 |         actions: <Widget>[
19 |           AnimatedSwitcher(
20 |             transitionBuilder: (child, anim) {
21 |               return ScaleTransition(scale: anim, child: child);
22 |             },
23 |             duration: const Duration(milliseconds: 300),
24 |             child: IconButton(
25 |                 key: ValueKey(iconData),
26 |                 icon: Icon(iconData),
27 |                 onPressed: () {
28 |                   setState(() {
29 |                     if (iconData == Icons.clear) {
30 |                       iconData = Icons.add;
31 |                     } else {
32 |                       iconData = Icons.clear;
33 |                     }
34 |                   });
35 |                 }),
36 |           )
37 |         ],
38 |       ),
39 |       body: Container(),
40 |       floatingActionButton: FloatingActionButton(
41 |         onPressed: () {
42 |           setState(() {
43 |             if (iconData == Icons.clear) {
44 |               iconData = Icons.add;
45 |             } else {
46 |               iconData = Icons.clear;
47 |             }
48 |           });
49 |         },
50 |         child: AnimatedSwitcher(
51 |           transitionBuilder: (child, anim) {
52 |             return ScaleTransition(scale: anim, child: child);
53 |           },
54 |           duration: const Duration(milliseconds: 300),
55 |           child: IconButton(
56 |               key: ValueKey(iconData),
57 |               icon: Icon(iconData),
58 |               onPressed: () {
59 |                 setState(() {
60 |                   if (iconData == Icons.clear) {
61 |                     iconData = Icons.add;
62 |                   } else {
63 |                     iconData = Icons.clear;
64 |                   }
65 |                 });
66 |               }),
67 |         ),
68 |       ),
69 |     );
70 |   }
71 | }
72 | 


--------------------------------------------------------------------------------
/lib/widget/animation_container_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:math' as math;
 2 | 
 3 | import 'package:flutter/material.dart';
 4 | 
 5 | ///来着 [Flutter 社区 公众号] 的动画例子
 6 | class AnimationContainerDemoPage extends StatefulWidget {
 7 |   const AnimationContainerDemoPage({super.key});
 8 | 
 9 |   @override
10 |   _AnimationContainerDemoPageState createState() => _AnimationContainerDemoPageState();
11 | }
12 | 
13 | class _AnimationContainerDemoPageState extends State<AnimationContainerDemoPage> {
14 | 
15 |   ///定义需要执行的滑动效果数值
16 |   double _width = 50;
17 |   double _height = 50;
18 |   Color _color = Colors.green;
19 |   BorderRadiusGeometry _borderRadius = BorderRadius.circular(8);
20 | 
21 | 
22 |   @override
23 |   Widget build(BuildContext context) {
24 |     return  Scaffold(
25 |       appBar: AppBar(
26 |         title: const Text('AnimationContainerDemoPage Demo'),
27 |       ),
28 |       body: Center(
29 |         child: AnimatedContainer(
30 |           // Use the properties stored in the State class.
31 |           width: _width,
32 |           height: _height,
33 |           decoration: BoxDecoration(
34 |             color: _color,
35 |             borderRadius: _borderRadius,
36 |           ),
37 |           // Define how long the animation should take.
38 |           duration: const Duration(seconds: 1),
39 |           // Provide an optional curve to make the animation feel smoother.
40 |           curve: Curves.fastOutSlowIn,
41 |         ),
42 |       ),
43 |       floatingActionButton: FloatingActionButton(
44 |         child: const Icon(Icons.play_arrow),
45 |         // When the user taps the button
46 |         onPressed: () {
47 |           // Use setState to rebuild the widget with new values.
48 |           setState(() {
49 |             // Create a random number generator.
50 |             final random = math.Random();
51 | 
52 |             // Generate a random width and height.
53 |             _width = random.nextInt(300).toDouble();
54 |             _height = random.nextInt(300).toDouble();
55 | 
56 |             // Generate a random color.
57 |             _color = Color.fromRGBO(
58 |               random.nextInt(256),
59 |               random.nextInt(256),
60 |               random.nextInt(256),
61 |               1,
62 |             );
63 | 
64 |             // Generate a random border radius.
65 |             _borderRadius =
66 |                 BorderRadius.circular(random.nextInt(100).toDouble());
67 |           });
68 |         },
69 |       ),
70 |     );
71 |   }
72 | }
73 | 


--------------------------------------------------------------------------------
/lib/widget/async_to_sync_call_page.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:async';
 2 | 
 3 | import 'package:flutter/foundation.dart';
 4 | import 'package:flutter/material.dart';
 5 | 
 6 | class AsyncToSyncCallPage extends StatefulWidget {
 7 |   const AsyncToSyncCallPage({super.key});
 8 | 
 9 |   @override
10 |   State<AsyncToSyncCallPage> createState() => _AsyncToSyncCallPageState();
11 | }
12 | 
13 | class _AsyncToSyncCallPageState extends State<AsyncToSyncCallPage> {
14 |   Completer<void>? _syncCompleter;
15 | 
16 |   Future<void> _syncWait(Future Function() fn) async {
17 |     var currentAsync = _syncCompleter;
18 |     final completer = Completer<void>();
19 |     _syncCompleter = completer;
20 | 
21 |     ///第一次是 null
22 |     await currentAsync?.future;
23 |     await fn.call();
24 |     completer.complete();
25 |   }
26 | 
27 |   ///因为 setState 不是同步的,只是内部把标记位标志为脏数据
28 |   ///所以如果需要等待 setState 执行结束,需要做一个等待
29 |   waitSetStateComplete(Future Function() fn) async {
30 |     await fn();
31 |     if (mounted) {
32 |       setState(() {});
33 |     }
34 |     final completer = Completer<void>();
35 | 
36 |     ///下一帧结束
37 |     WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
38 |       completer.complete();
39 |     });
40 |     return completer.future;
41 |   }
42 | 
43 |   @override
44 |   Widget build(BuildContext context) {
45 |     return Scaffold(
46 |       appBar: AppBar(
47 |         title: const Text("AsyncToSyncCallPage"),
48 |       ),
49 |       floatingActionButton: FloatingActionButton(
50 |         onPressed: () {
51 |           if (kDebugMode) {
52 |             print("Start······Waiting");
53 |           }
54 |           _syncWait(() async {
55 |             await Future.delayed(const Duration(seconds: 4));
56 |             if (kDebugMode) {
57 |               print("Finish First");
58 |             }
59 |           });
60 | 
61 |           _syncWait(() async {
62 |             await Future.delayed(const Duration(seconds: 2));
63 |             if (kDebugMode) {
64 |               print("Finish Tow");
65 |             }
66 |           });
67 | 
68 |           _syncWait(() async {
69 |             await Future.delayed(const Duration(seconds: 1));
70 |             if (kDebugMode) {
71 |               print("Finish Three");
72 |             }
73 |           });
74 |         },
75 |       ),
76 |     );
77 |   }
78 | }
79 | 


--------------------------------------------------------------------------------
/lib/widget/blur_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:ui';
 2 | 
 3 | import 'package:flutter/material.dart';
 4 | 
 5 | class BlurDemoPage extends StatelessWidget {
 6 |   const BlurDemoPage({super.key});
 7 | 
 8 |   @override
 9 |   Widget build(BuildContext context) {
10 |     return Scaffold(
11 |       appBar: AppBar(
12 |         title: const Text("BlurDemoPage"),
13 |       ),
14 |       body: Stack(
15 |         children: <Widget>[
16 |           Positioned(
17 |             top: 0,
18 |             bottom: 0,
19 |             left: 0,
20 |             right: 0,
21 |             child: Image.asset(
22 |               "static/gsy_cat.png",
23 |               fit: BoxFit.cover,
24 |               width: MediaQuery.sizeOf(context).width,
25 |               height: MediaQuery.sizeOf(context).height,
26 |             ),
27 |           ),
28 |           Center(
29 |             child: SizedBox(
30 |               width: 200,
31 |               height: 200,
32 |               child: ClipRRect(
33 |                 borderRadius: BorderRadius.circular(15.0),
34 |                 child: BackdropFilter(
35 |                   filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
36 |                   child: const Row(
37 |                     mainAxisSize: MainAxisSize.max,
38 |                     crossAxisAlignment: CrossAxisAlignment.center,
39 |                     mainAxisAlignment: MainAxisAlignment.center,
40 |                     children: <Widget>[
41 |                       Icon(Icons.ac_unit),
42 |                       Text("哇!!")
43 |                     ],
44 |                   ),
45 |                 ),
46 |               ),
47 |             ),
48 |           )
49 |         ],
50 |       ),
51 |     );
52 |   }
53 | }
54 | 


--------------------------------------------------------------------------------
/lib/widget/book_page/book_text_clip.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class BookTextClip extends CustomClipper<Path> {
 4 |   final Path path;
 5 | 
 6 |   BookTextClip(this.path);
 7 | 
 8 |   @override
 9 |   Path getClip(Size size) {
10 |     return path;
11 |   }
12 | 
13 |   @override
14 |   bool shouldReclip(CustomClipper<Path> oldClipper) {
15 |     return true;
16 |   }
17 | }
18 | 


--------------------------------------------------------------------------------
/lib/widget/book_page/cal_point.dart:
--------------------------------------------------------------------------------
1 | class CalPoint {
2 | 
3 |   CalPoint();
4 | 
5 |   CalPoint.data(this.x, this.y);
6 | 
7 |   double? x = -1;
8 |   double? y = -1;
9 | }


--------------------------------------------------------------------------------
/lib/widget/clip_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | /// 圆角效果处理实现
 4 | class ClipDemoPage extends StatelessWidget {
 5 |   const ClipDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   Widget build(BuildContext context) {
 9 |     return Scaffold(
10 |       appBar: AppBar(
11 |         title: const Text("ClipDemoPage"),
12 |       ),
13 |       body: Container(
14 |         alignment: Alignment.center,
15 |         margin: const EdgeInsets.all(10),
16 |         child: Column(
17 |           crossAxisAlignment: CrossAxisAlignment.center,
18 |           mainAxisAlignment: MainAxisAlignment.center,
19 |           children: <Widget>[
20 |             const Text("BoxDecoration 圆角"),
21 |             Container(
22 |               width: 100,
23 |               height: 100,
24 |               decoration: const BoxDecoration(
25 |                   color: Colors.red,
26 |                   image: DecorationImage(
27 |                     fit: BoxFit.cover,
28 |                     image: AssetImage("static/gsy_cat.png"),
29 |                   ),
30 |                   borderRadius: BorderRadius.all(Radius.circular(5.0))),
31 |             ),
32 |             const SizedBox(
33 |               height: 10,
34 |             ),
35 |             const Text("BoxDecoration 圆角对 child"),
36 |             Container(
37 |               width: 100,
38 |               height: 100,
39 |               decoration: const BoxDecoration(
40 |                   color: Colors.red,
41 |                   borderRadius: BorderRadius.all(Radius.circular(5.0))),
42 |               child: Image.asset(
43 |                 "static/gsy_cat.png",
44 |                 fit: BoxFit.cover,
45 |                 width: 100,
46 |                 height: 100,
47 |               ),
48 |             ),
49 |             const SizedBox(
50 |               height: 10,
51 |             ),
52 |             const Text("ClipRRect 圆角对 child"),
53 |             ClipRRect(
54 |               borderRadius: const BorderRadius.all(Radius.circular(5.0)),
55 |               child: Image.asset(
56 |                 "static/gsy_cat.png",
57 |                 fit: BoxFit.cover,
58 |                 width: 100,
59 |                 height: 100,
60 |               ),
61 |             )
62 |           ],
63 |         ),
64 |       ),
65 |     );
66 |   }
67 | }
68 | 


--------------------------------------------------------------------------------
/lib/widget/cloud/cloud_widget.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | import 'cloud_render.dart';
 4 | 
 5 | class CloudWidget extends MultiChildRenderObjectWidget {
 6 |   final Clip overflow;
 7 |   final double ratio;
 8 | 
 9 |   const CloudWidget({
10 |     super.key,
11 |     this.ratio = 1,
12 |     this.overflow = Clip.none,
13 |     super.children,
14 |   });
15 | 
16 |   @override
17 |   RenderObject createRenderObject(BuildContext context) {
18 |     return RenderCloudWidget(
19 |       ratio: ratio,
20 |       overflow: overflow,
21 |     );
22 |   }
23 | 
24 |   @override
25 |   void updateRenderObject(
26 |       BuildContext context, RenderCloudWidget renderObject) {
27 |     renderObject
28 |       ..ratio = ratio
29 |       ..overflow = overflow;
30 |   }
31 | }


--------------------------------------------------------------------------------
/lib/widget/controller_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/foundation.dart';
 2 | import 'package:flutter/material.dart';
 3 | 
 4 | /// 在 Flutter 中有很多内置的 Controller
 5 | /// 大部分内置控件都可以通过 Controller 设置和获取控件参数
 6 | /// 比如 TextField 的 TextEditingController
 7 | /// 比如 ListView  的 ScrollController
 8 | /// 一般想对控件做 OOXX 的事情,先找个 Controller 就对了。
 9 | class ControllerDemoPage extends StatelessWidget {
10 |   const ControllerDemoPage({super.key});
11 | 
12 |   @override
13 |   Widget build(BuildContext context) {
14 |     if (kDebugMode) {
15 |       print("######### MyHomePage ${MediaQuery.of(context).size}");
16 |     }
17 |     return Scaffold(
18 |       appBar: AppBar(),
19 |       body: const DefaultTabController(
20 |           length: 3,
21 |           child: TabBarView(
22 |             //physics: const BouncingScrollPhysics(),
23 |             children: [
24 |               EditPage(),
25 |               EditPage(),
26 |               EditPage(),
27 |             ],
28 |           )),
29 |     );
30 |   }
31 | }
32 | 
33 | class EditPage extends StatelessWidget {
34 |   const EditPage({super.key});
35 | 
36 |   @override
37 |   Widget build(BuildContext context) {
38 |     return ListView(
39 |       children: [
40 |         const ListTile(
41 |           title: Text("Title"),
42 |           subtitle: Text("Subtitle"),
43 |           trailing: Icon(Icons.arrow_forward_ios),
44 |         ),
45 |         Container(
46 |           color: Colors.red,
47 |           alignment: Alignment.center,
48 |           height: 40,
49 |           child: const Text("FFFF"),
50 |         ),
51 |         Container(
52 |           color: Colors.red,
53 |           alignment: Alignment.center,
54 |           height: 40,
55 |           child: const Text("FFFF"),
56 |         )
57 |       ],
58 |     );
59 |   }
60 | }
61 | 


--------------------------------------------------------------------------------
/lib/widget/custom_shader_path_demo_page.dart:
--------------------------------------------------------------------------------
  1 | import 'dart:async';
  2 | import 'dart:math';
  3 | import 'dart:ui' as ui;
  4 | import 'package:flutter/material.dart';
  5 | 
  6 | class CustomShaderPathDemoPage extends StatefulWidget {
  7 |   const CustomShaderPathDemoPage({super.key});
  8 | 
  9 |   @override
 10 |   State<CustomShaderPathDemoPage> createState() =>
 11 |       _CustomShaderPathDemoPageState();
 12 | }
 13 | 
 14 | class _CustomShaderPathDemoPageState extends State<CustomShaderPathDemoPage> {
 15 |   Future<ui.Image> _loadAssetImage() {
 16 |     Completer<ui.Image> completer = Completer<ui.Image>();
 17 | 
 18 |     const AssetImage("static/gsy_cat.png")
 19 |         .resolve(const ImageConfiguration())
 20 |         .addListener(
 21 |             ImageStreamListener((ImageInfo image, bool synchronousCall) {
 22 |       ui.Image img;
 23 |       img = image.image;
 24 |       completer.complete(img);
 25 |     }));
 26 | 
 27 |     return completer.future;
 28 |   }
 29 | 
 30 |   @override
 31 |   Widget build(BuildContext context) {
 32 |     return Scaffold(
 33 |         appBar: AppBar(
 34 |           title: const Text("CustomShaderPathDemoPage"),
 35 |         ),
 36 |         body: Center(
 37 |           child: FutureBuilder<ui.Image>(
 38 |             future: _loadAssetImage(),
 39 |             builder: (c, s) {
 40 |               if (s.data == null) {
 41 |                 return Container();
 42 |               }
 43 |               return Container(
 44 |                 height: 200,
 45 |                 width: 200,
 46 |                 color: Colors.greenAccent,
 47 |                 child: CustomPaint(
 48 |                   ///直接使用值做动画
 49 |                   foregroundPainter: _AnimationPainter(s.data!),
 50 |                 ),
 51 |               );
 52 |             },
 53 |           ),
 54 |         ));
 55 |   }
 56 | }
 57 | 
 58 | class _AnimationPainter extends CustomPainter {
 59 |   final Paint _paint = Paint();
 60 | 
 61 |   final ui.Image img;
 62 | 
 63 |   _AnimationPainter(this.img);
 64 | 
 65 |   @override
 66 |   void paint(Canvas canvas, Size size) {
 67 | 
 68 |     var y1 = sin(50);
 69 |     var y2 = sin(50 + pi / 2);
 70 |     var y3 = sin(50 + pi);
 71 | 
 72 |     final startPointY = size.height * (0.5 + 0.4 * y1);
 73 |     final controlPointY = size.height * (0.5 + 0.4 * y2);
 74 |     final endPointY = size.height * (0.5 + 0.4 * y3);
 75 |     var path = Path();
 76 |     path.moveTo(size.width * 0, startPointY);
 77 |     path.quadraticBezierTo(
 78 |         size.width * 0.5, controlPointY, size.width, endPointY);
 79 |     path.lineTo(size.width, size.height);
 80 |     path.lineTo(0, size.height);
 81 |     path.close();
 82 |     canvas.drawPath(
 83 |         path,
 84 |         _paint
 85 |           ..shader = ImageShader(img, TileMode.repeated, TileMode.repeated,
 86 |               Matrix4.identity().scaled(0.2).storage)
 87 |           ..strokeWidth = 20
 88 |           ..style = PaintingStyle.stroke);
 89 | 
 90 | 
 91 | 
 92 |     ///网格
 93 |     var step = 1;
 94 |     var b = path.getBounds();
 95 |     canvas.save();
 96 |     canvas.clipPath(path);
 97 |     for (int i = step; i < b.width; i = i + step) {
 98 |       canvas.drawLine(
 99 |           Offset(b.left + i, b.top), Offset(b.left + i, b.bottom), Paint());
100 |     }
101 | 
102 |     for (int i = step; i < b.height; i = i + step) {
103 |       canvas.drawLine(
104 |           Offset(b.left, b.top + i), Offset(b.right, b.top + i), Paint());
105 |     }
106 | 
107 |     canvas.restore();
108 |   }
109 | 
110 |   @override
111 |   bool shouldRepaint(CustomPainter oldDelegate) => true;
112 | }
113 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/custom_viewport.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/cupertino.dart';
 2 | import 'package:flutter/foundation.dart';
 3 | import 'package:flutter/rendering.dart';
 4 | import 'package:flutter/widgets.dart';
 5 | 
 6 | class CustomViewport extends Viewport {
 7 |   /// 需要最后渲染的widget的RenderObject类列表
 8 |   final List<Type> highestChildInPaintOrderClassList;
 9 | 
10 |   CustomViewport({
11 |     super.key,
12 |     super.axisDirection,
13 |     super.crossAxisDirection,
14 |     super.anchor,
15 |     required super.offset,
16 |     super.center,
17 |     super.cacheExtent,
18 |     super.slivers,
19 |     this.highestChildInPaintOrderClassList = const <Type>[],
20 |   });
21 | 
22 |   @override
23 |   RenderViewport createRenderObject(BuildContext context) {
24 |     return _RenderExpandedViewport(
25 |       axisDirection: axisDirection,
26 |       crossAxisDirection: crossAxisDirection ??
27 |           Viewport.getDefaultCrossAxisDirection(context, axisDirection),
28 |       anchor: anchor,
29 |       offset: offset,
30 |       cacheExtent: cacheExtent,
31 |       highestChildInPaintOrderClassList: highestChildInPaintOrderClassList,
32 |     );
33 |   }
34 | }
35 | 
36 | class _RenderExpandedViewport extends RenderViewport {
37 |   final List<Type> highestChildInPaintOrderClassList;
38 | 
39 |   _RenderExpandedViewport({
40 |     super.axisDirection,
41 |     required super.crossAxisDirection,
42 |     required super.offset,
43 |     super.anchor,
44 |     super.cacheExtent,
45 |     this.highestChildInPaintOrderClassList = const <Type>[],
46 |   });
47 | 
48 |   @override
49 |   Iterable<RenderSliver> get childrenInPaintOrder {
50 |     if (firstChild == null) return [];
51 |     final children = _getChildrenPaintOrder();
52 |     return children;
53 |   }
54 | 
55 |   @override
56 |   Iterable<RenderSliver> get childrenInHitTestOrder {
57 |     if (firstChild == null) return [];
58 |     final children = _getChildrenPaintOrder();
59 |     return children.reversed.toList();
60 |   }
61 | 
62 |   List<RenderSliver> _getChildrenPaintOrder() {
63 |     final List<RenderSliver> children = [];
64 |     var child = firstChild;
65 |     while (child != null) {
66 |       children.add(child);
67 |       child = childAfter(child);
68 |     }
69 |     if (highestChildInPaintOrderClassList.isNotEmpty) {
70 |       for (var clazz in highestChildInPaintOrderClassList) {
71 |         try {
72 |           final renderSliver =
73 |               children.firstWhere((child) => child.runtimeType == clazz);
74 |           children.remove(renderSliver);
75 |           children.add(renderSliver);
76 |         } catch (e) {
77 |           if (kDebugMode) {
78 |             print(e);
79 |           }
80 |         }
81 |       }
82 |       return children;
83 |     } else {
84 |       return children.reversed.toList();
85 |     }
86 |   }
87 | }
88 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/custom_viewport_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:flutter/rendering.dart';
 3 | import 'package:gsy_flutter_demo/widget/custom_viewport/custom_viewport.dart';
 4 | import 'package:gsy_flutter_demo/widget/custom_viewport/first_tab_bar.dart';
 5 | import 'package:gsy_flutter_demo/widget/custom_viewport/first_tab_bar_render_sliver.dart';
 6 | import 'package:gsy_flutter_demo/widget/custom_viewport/secondary_tab_bar.dart';
 7 | import 'package:gsy_flutter_demo/widget/custom_viewport/secondary_tab_bar_render_sliver.dart';
 8 | 
 9 | class CustomViewportPage extends StatelessWidget {
10 |   const CustomViewportPage({super.key});
11 | 
12 |   @override
13 |   Widget build(BuildContext context) {
14 |     return Scaffold(
15 |       appBar: AppBar(),
16 |       body: Scrollable(
17 |         viewportBuilder: (BuildContext context, ViewportOffset position) {
18 |           return CustomViewport(
19 |             offset: position,
20 |             highestChildInPaintOrderClassList: const [
21 |               FirstTabBarRenderSliver,
22 |               SecondaryTabBarRenderSliver,
23 |             ],
24 |             slivers: <Widget>[
25 |               const FirstTabBar(),
26 |               SliverGrid(
27 |                 gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
28 |                   maxCrossAxisExtent: 200.0,
29 |                   mainAxisSpacing: 10.0,
30 |                   crossAxisSpacing: 10.0,
31 |                   childAspectRatio: 4.0,
32 |                 ),
33 |                 delegate: SliverChildBuilderDelegate(
34 |                   (BuildContext context, int index) {
35 |                     return Container(
36 |                       alignment: Alignment.center,
37 |                       color: Colors.teal[100 * (index % 9)],
38 |                       child: Text('Grid Item $index'),
39 |                     );
40 |                   },
41 |                   childCount: 20,
42 |                 ),
43 |               ),
44 |               const SecondaryTabBar(),
45 |               SliverFixedExtentList(
46 |                 itemExtent: 50.0,
47 |                 delegate: SliverChildBuilderDelegate(
48 |                   (BuildContext context, int index) {
49 |                     return Container(
50 |                       alignment: Alignment.center,
51 |                       color: Colors.lightBlue[100 * (index % 9)],
52 |                       child: Text('List Item $index'),
53 |                     );
54 |                   },
55 |                 ),
56 |               ),
57 |             ],
58 |           );
59 |         },
60 |       ),
61 |     );
62 |   }
63 | }
64 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/first_tab_bar.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/custom_viewport/first_tab_bar_sliver_widget.dart';
 3 | 
 4 | class FirstTabBar extends StatelessWidget {
 5 |   const FirstTabBar({
 6 |     super.key,
 7 |   });
 8 | 
 9 |   @override
10 |   Widget build(BuildContext context) {
11 |     return FirstTabBarSliverWidget(
12 |       child: _buildChild(),
13 |     );
14 |   }
15 | 
16 |   Widget _buildChild() {
17 |     return Container(
18 |       height: 66,
19 |       color: Colors.deepPurpleAccent,
20 |       child: const Center(
21 |         child: Text('一级tab'),
22 |       ),
23 |     );
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/first_tab_bar_render_sliver.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:math';
 2 | 
 3 | import 'package:flutter/rendering.dart';
 4 | 
 5 | class FirstTabBarRenderSliver extends RenderSliverSingleBoxAdapter {
 6 |   @override
 7 |   void performLayout() {
 8 |     if (child == null) {
 9 |       geometry = SliverGeometry.zero;
10 |       return;
11 |     }
12 |     child!.layout(constraints.asBoxConstraints(), parentUsesSize: true);
13 |     double childExtent;
14 |     switch (constraints.axis) {
15 |       case Axis.horizontal:
16 |         childExtent = child!.size.width;
17 |         break;
18 |       case Axis.vertical:
19 |         childExtent = child!.size.height;
20 |         break;
21 |     }
22 |     final paintedChildExtent = min(
23 |       childExtent,
24 |       constraints.remainingPaintExtent - constraints.overlap,
25 |     );
26 |     double paintOrigin = constraints.overlap;
27 |     paintOrigin = paintOrigin < 0 ? 0 : paintOrigin;
28 |     geometry = SliverGeometry(
29 |       paintExtent: paintedChildExtent,
30 |       maxPaintExtent: childExtent,
31 |       maxScrollObstructionExtent: childExtent,
32 |       paintOrigin: paintOrigin,
33 |       scrollExtent: childExtent,
34 |       layoutExtent: max(0.0, paintedChildExtent - constraints.scrollOffset),
35 |       hasVisualOverflow: paintedChildExtent < childExtent,
36 |     );
37 |   }
38 | 
39 |   @override
40 |   double childMainAxisPosition(RenderBox child) {
41 |     return 0;
42 |   }
43 | }
44 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/first_tab_bar_sliver_widget.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/custom_viewport/first_tab_bar_render_sliver.dart';
 3 | 
 4 | class FirstTabBarSliverWidget extends SingleChildRenderObjectWidget {
 5 |   const FirstTabBarSliverWidget({super.child, super.key});
 6 | 
 7 |   @override
 8 |   RenderObject createRenderObject(BuildContext context) {
 9 |     return FirstTabBarRenderSliver();
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/secondary_tab_bar.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/custom_viewport/secondary_tab_bar_sliver_widget.dart';
 3 | 
 4 | class SecondaryTabBar extends StatelessWidget {
 5 |   const SecondaryTabBar({
 6 |     super.key,
 7 |   });
 8 | 
 9 |   @override
10 |   Widget build(BuildContext context) {
11 |     return SecondaryTabBarSliverWidget(
12 |       child: _buildChild(),
13 |     );
14 |   }
15 | 
16 |   Widget _buildChild() {
17 |     return Container(
18 |       height: 66,
19 |       color: Colors.red.withValues(alpha: 0.8),
20 |       child: const Center(child: Text('二级tab')),
21 |     );
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/secondary_tab_bar_render_sliver.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:math';
 2 | 
 3 | import 'package:flutter/rendering.dart';
 4 | 
 5 | class SecondaryTabBarRenderSliver extends RenderSliverSingleBoxAdapter {
 6 |   @override
 7 |   void performLayout() {
 8 |     if (child == null) {
 9 |       geometry = SliverGeometry.zero;
10 |       return;
11 |     }
12 |     child!.layout(constraints.asBoxConstraints(), parentUsesSize: true);
13 |     double childExtent;
14 |     switch (constraints.axis) {
15 |       case Axis.horizontal:
16 |         childExtent = child!.size.width;
17 |         break;
18 |       case Axis.vertical:
19 |         childExtent = child!.size.height;
20 |         break;
21 |     }
22 |     final paintedChildExtent = min(
23 |       childExtent,
24 |       constraints.remainingPaintExtent - constraints.overlap,
25 |     );
26 |     double paintOrigin = constraints.overlap - 44;
27 |     paintOrigin = paintOrigin < 0 ? 0 : paintOrigin;
28 |     geometry = SliverGeometry(
29 |       paintExtent: paintedChildExtent,
30 |       maxPaintExtent: childExtent,
31 |       maxScrollObstructionExtent: childExtent,
32 |       paintOrigin: paintOrigin,
33 |       scrollExtent: childExtent,
34 |       layoutExtent: max(0.0, paintedChildExtent - constraints.scrollOffset),
35 |       hasVisualOverflow: paintedChildExtent < childExtent,
36 |     );
37 |   }
38 | 
39 |   @override
40 |   double childMainAxisPosition(RenderBox child) {
41 |     return 0;
42 |   }
43 | }
44 | 


--------------------------------------------------------------------------------
/lib/widget/custom_viewport/secondary_tab_bar_sliver_widget.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | import 'secondary_tab_bar_render_sliver.dart';
 4 | 
 5 | class SecondaryTabBarSliverWidget extends SingleChildRenderObjectWidget {
 6 |   const SecondaryTabBarSliverWidget({super.child, super.key});
 7 | 
 8 |   @override
 9 |   RenderObject createRenderObject(BuildContext context) {
10 |     return SecondaryTabBarRenderSliver();
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/lib/widget/drag_img_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:matrix_gesture_detector/matrix_gesture_detector.dart';
 3 | 
 4 | class DragImgDemoPage extends StatefulWidget {
 5 |   const DragImgDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   _DragImgDemoPageState createState() => _DragImgDemoPageState();
 9 | }
10 | 
11 | class _DragImgDemoPageState extends State<DragImgDemoPage> {
12 | 
13 |   Matrix4 transform = Matrix4.diagonal3Values(1, 1, 1.0);
14 | 
15 |   @override
16 |   Widget build(BuildContext context) {
17 |     return Scaffold(
18 |       appBar: AppBar(
19 |         title: const Text("DragImgDemoPage"),
20 |       ),
21 |       body: MatrixGestureDetector(
22 |         onMatrixUpdate: (m, tm, sm, rm) {
23 |           setState(() {
24 |             transform = m;
25 |           });
26 |         },
27 |         child: Transform(
28 |             transform: transform,
29 |             child: Image.asset(
30 |               "static/gsy_cat.png",
31 |               fit: BoxFit.fitWidth,
32 |               width: MediaQuery
33 |                   .of(context)
34 |                   .size
35 |                   .width,
36 |               height: MediaQuery
37 |                   .of(context)
38 |                   .size
39 |                   .height,
40 |             )
41 |         ),
42 |       ),
43 |     );
44 |   }
45 | }
46 | 


--------------------------------------------------------------------------------
/lib/widget/drop_select_menu/drop_rect_tween.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class DropRectTween extends Tween<Rect> {
 4 |   /// Creates a [Rect] tween.
 5 |   ///
 6 |   /// The [begin] and [end] properties may be null; the null value
 7 |   /// is treated as an empty rect at the top left corner.
 8 |   DropRectTween({required Rect begin, required Rect end})
 9 |       : super(begin: begin, end: end);
10 | 
11 |   /// Returns the value this variable has at the given animation clock value.
12 |   @override
13 |   Rect lerp(double t) => Rect.lerp(begin, end, t)!;
14 | }
15 | 


--------------------------------------------------------------------------------
/lib/widget/drop_select_menu/drop_select_controller.dart:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | import 'package:flutter/material.dart';
 4 | 
 5 | class DropSelectController extends ChangeNotifier {
 6 | 
 7 |   DropSelectEvent? event;
 8 | 
 9 |   int? menuIndex;
10 | 
11 |   int? index;
12 | 
13 |   dynamic data;
14 | 
15 |   void hide() {
16 |     event = DropSelectEvent.HIDE;
17 |     notifyListeners();
18 |   }
19 | 
20 |   void show(int index) {
21 |     event = DropSelectEvent.ACTIVE;
22 |     menuIndex = index;
23 |     notifyListeners();
24 |   }
25 | 
26 |   void select(dynamic data, {int? index}) {
27 |     event = DropSelectEvent.SELECT;
28 |     this.data = data;
29 |     this.index = index;
30 |     notifyListeners();
31 |   }
32 | }
33 | 
34 | 
35 | enum DropSelectEvent {
36 |   SELECT,
37 |   // ignore: constant_identifier_names
38 |   ACTIVE,
39 |   HIDE,
40 | }
41 | 


--------------------------------------------------------------------------------
/lib/widget/drop_select_menu/drop_select_demo_data.dart:
--------------------------------------------------------------------------------
 1 | import 'package:gsy_flutter_demo/widget/drop_select_menu/drop_select_object.dart';
 2 | 
 3 | final selectNormal = getSelectList();
 4 | final selectExpand = getSelectChildExpandList();
 5 | final selectChildGrid = getSelectChildList();
 6 | 
 7 | getSelectList() {
 8 |   return [
 9 |     DropSelectObject(title: "全部", selectedCleanOther: true, selected: true),
10 |     DropSelectObject(title: "选择2"),
11 |     DropSelectObject(title: "选择3"),
12 |     DropSelectObject(title: "选择4"),
13 |     DropSelectObject(title: "选择5"),
14 |     DropSelectObject(title: "选择6"),
15 |     DropSelectObject(title: "选择7"),
16 |     DropSelectObject(title: "选择7"),
17 |   ];
18 | }
19 | 
20 | getSelectChildList() {
21 |   List<DropSelectObject> children1 = [
22 |     DropSelectObject(title: "全部", selectedCleanOther: true, selected: true),
23 |     DropSelectObject(title: "问题1"),
24 |     DropSelectObject(title: "问题2"),
25 |     DropSelectObject(title: "问题3"),
26 |     DropSelectObject(title: "问题4"),
27 |     DropSelectObject(title: "问题5"),
28 |     DropSelectObject(title: "问题6"),
29 |     DropSelectObject(title: "问题7"),
30 |     DropSelectObject(title: "问题8"),
31 |   ];
32 | 
33 |   List<DropSelectObject> children2 = [
34 |     DropSelectObject(title: "全部", selectedCleanOther: true, selected: true),
35 |     DropSelectObject(title: "测试1"),
36 |     DropSelectObject(title: "测试2"),
37 |     DropSelectObject(title: "测试3"),
38 |     DropSelectObject(title: "测试4"),
39 |     DropSelectObject(title: "测试5"),
40 |     DropSelectObject(title: "测试6"),
41 |   ];
42 | 
43 |   return [
44 |     DropSelectObject(title: "选择1", children: children1),
45 |     DropSelectObject(title: "选择2", children: children2),
46 |   ];
47 | }
48 | 
49 | getSelectChildExpandList() {
50 |   List<DropSelectObject> children1 = [
51 |     DropSelectObject(title: "全部", selectedCleanOther: true, selected: true),
52 |     DropSelectObject(title: "距离1"),
53 |     DropSelectObject(title: "距离2"),
54 |     DropSelectObject(title: "距离3"),
55 |     DropSelectObject(title: "距离4"),
56 |     DropSelectObject(title: "距离5"),
57 |     DropSelectObject(title: "距离6"),
58 |     DropSelectObject(title: "距离7"),
59 |   ];
60 | 
61 |   List<DropSelectObject> children2 = [
62 |     DropSelectObject(title: "全部", selectedCleanOther: true, selected: true),
63 |     DropSelectObject(title: "范围1"),
64 |     DropSelectObject(title: "范围2"),
65 |     DropSelectObject(title: "范围3"),
66 |     DropSelectObject(title: "范围4"),
67 |     DropSelectObject(title: "范围5"),
68 |     DropSelectObject(title: "范围6"),
69 |     DropSelectObject(title: "范围7"),
70 |     DropSelectObject(title: "范围8"),
71 |   ];
72 | 
73 |   List<DropSelectObject> children3 = [
74 |     DropSelectObject(title: "全部", selectedCleanOther: true, selected: true),
75 |     DropSelectObject(title: "路径1"),
76 |     DropSelectObject(title: "路径2"),
77 |     DropSelectObject(title: "路径3"),
78 |     DropSelectObject(title: "路径4"),
79 |     DropSelectObject(title: "路径5"),
80 |   ];
81 | 
82 |   List<DropSelectObject> children4 = [
83 |     DropSelectObject(title: "全部", selectedCleanOther: true, selected: true),
84 |     DropSelectObject(title: "回家1"),
85 |     DropSelectObject(title: "回家2"),
86 |     DropSelectObject(title: "回家3"),
87 |   ];
88 | 
89 |   return [
90 |     DropSelectObject(title: "距离", children: children1),
91 |     DropSelectObject(title: "范围", children: children2),
92 |     DropSelectObject(title: "路径", children: children3),
93 |     DropSelectObject(title: "回家", children: children4),
94 |   ];
95 | }
96 | 


--------------------------------------------------------------------------------
/lib/widget/drop_select_menu/drop_select_list_menu.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:flutter/widgets.dart';
 3 | import 'package:gsy_flutter_demo/widget/drop_select_menu/drop_select_object.dart';
 4 | 
 5 | import 'drop_select_controller.dart';
 6 | import 'drop_select_widget.dart';
 7 | 
 8 | typedef MenuItemBuilder<T extends DropSelectObject> = Widget Function(
 9 |     BuildContext context, T data);
10 | 
11 | const double kDropSelectMenuItemHeight = 45.0;
12 | 
13 | class DropSelectListMenu<T extends DropSelectObject> extends DropSelectWidget {
14 |   final List<T>? data;
15 |   final MenuItemBuilder? itemBuilder;
16 |   final bool singleSelected;
17 |   final double itemExtent;
18 | 
19 |   const DropSelectListMenu(
20 |       {super.key, this.data,
21 |       this.singleSelected = false,
22 |       this.itemBuilder,
23 |       this.itemExtent = kDropSelectMenuItemHeight});
24 | 
25 |   @override
26 |   DropSelectState<DropSelectWidget> createState() {
27 |     return _MenuListState<T>();
28 |   }
29 | }
30 | 
31 | class _MenuListState<T extends DropSelectObject>
32 |     extends DropSelectState<DropSelectListMenu<T>> {
33 |   @override
34 |   void initState() {
35 |     super.initState();
36 |   }
37 | 
38 |   Widget buildItem(BuildContext context, int index) {
39 |     final List<T> list = widget.data!;
40 | 
41 |     final T data = list[index];
42 |     return GestureDetector(
43 |       behavior: HitTestBehavior.opaque,
44 |       child: widget.itemBuilder!(context, data),
45 |       onTap: () {
46 |         if (widget.singleSelected) {
47 |           for (var item in widget.data!) {
48 |             item.selected = false;
49 |           }
50 |         }
51 |         if(data.selectedCleanOther) {
52 |           for (var item in widget.data!) {
53 |             item.selected = false;
54 |           }
55 |         }
56 |         setState(() {
57 |           data.selected = !data.selected;
58 |         });
59 |         controller?.select(data, index: index);
60 |       },
61 |     );
62 |   }
63 | 
64 |   @override
65 |   Widget build(BuildContext context) {
66 |     return ListView.builder(
67 |       itemExtent: widget.itemExtent,
68 |       itemBuilder: buildItem,
69 |       itemCount: widget.data!.length,
70 |     );
71 |   }
72 | 
73 |   @override
74 |   void onEvent(DropSelectEvent? event) {
75 |     switch (event) {
76 |       case DropSelectEvent.SELECT:
77 |       case DropSelectEvent.HIDE:
78 |         {}
79 |         break;
80 |       case DropSelectEvent.ACTIVE:
81 |       default:
82 |         {}
83 |         break;
84 |     }
85 |   }
86 | }
87 | 


--------------------------------------------------------------------------------
/lib/widget/drop_select_menu/drop_select_object.dart:
--------------------------------------------------------------------------------
 1 | class DropSelectObject {
 2 |   String? title;
 3 |   List<DropSelectObject>? children;
 4 |   bool selected;
 5 |   bool selectedCleanOther;
 6 | 
 7 |   DropSelectObject(
 8 |       {this.title,
 9 |       this.children,
10 |       this.selected = false,
11 |       this.selectedCleanOther = false});
12 | 
13 |   DropSelectObject clone() {
14 |     DropSelectObject newData = DropSelectObject();
15 |     newData.title = title;
16 |     newData.children =  [];
17 |     children?.forEach((item) {
18 |       newData.children!.add(item.clone());
19 |     });
20 | 
21 |     newData.selected = selected;
22 |     newData.selectedCleanOther = selectedCleanOther;
23 |     return newData;
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/lib/widget/floating_touch_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | ///全局悬浮按键
 4 | class FloatingTouchDemoPage extends StatefulWidget {
 5 |   const FloatingTouchDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   _FloatingTouchDemoPageState createState() => _FloatingTouchDemoPageState();
 9 | }
10 | 
11 | class _FloatingTouchDemoPageState extends State<FloatingTouchDemoPage> {
12 |   Offset offset = const Offset(200, 200);
13 | 
14 |   final double height = 80;
15 | 
16 |   ///显示悬浮控件
17 |   _showFloating() {
18 |     var overlayState = Overlay.of(context);
19 |     OverlayEntry? overlayEntry;
20 |     overlayEntry = OverlayEntry(builder: (context) {
21 |       return Stack(
22 |         children: <Widget>[
23 |           Positioned(
24 |             left: offset.dx,
25 |             top: offset.dy,
26 |             child: _buildFloating(overlayEntry),
27 |           ),
28 |         ],
29 |       );
30 |     });
31 | 
32 |     ///插入全局悬浮控件
33 |     overlayState.insert(overlayEntry);
34 |   }
35 | 
36 |   ///绘制悬浮控件
37 |   _buildFloating(OverlayEntry? overlayEntry) {
38 |     return GestureDetector(
39 |       behavior: HitTestBehavior.deferToChild,
40 |       onPanDown: (details) {
41 |         offset = details.globalPosition - Offset(height / 2, height / 2);
42 |         overlayEntry!.markNeedsBuild();
43 |       },
44 |       onPanUpdate: (DragUpdateDetails details) {
45 |         ///根据触摸修改悬浮控件偏移
46 |         offset = offset + details.delta;
47 |         overlayEntry!.markNeedsBuild();
48 |       },
49 |       onLongPress: () {
50 |         overlayEntry!.remove();
51 |       },
52 |       child: Material(
53 |         color: Colors.transparent,
54 |         child: Container(
55 |           height: height,
56 |           width: height,
57 |           alignment: Alignment.center,
58 |           decoration: BoxDecoration(
59 |               color: Colors.redAccent,
60 |               borderRadius: BorderRadius.all(Radius.circular(height / 2))),
61 |           child: const Text(
62 |             "长按\n移除",
63 |             style: TextStyle(color: Colors.white),
64 |           ),
65 |         ),
66 |       ),
67 |     );
68 |   }
69 | 
70 |   @override
71 |   Widget build(BuildContext context) {
72 |     return Scaffold(
73 |       appBar: AppBar(
74 |         title: const Text("FloatingTouchDemoPage"),
75 |       ),
76 |       body: Center(
77 |         child: TextButton(
78 |             onPressed: () {
79 |               _showFloating();
80 |             },
81 |             child: const Text("显示悬浮")),
82 |       ),
83 |     );
84 |   }
85 | }
86 | 


--------------------------------------------------------------------------------
/lib/widget/gesture_password/gesture_password_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/gesture_password/gesture_password_view.dart';
 3 | 
 4 | class GesturePasswordDemoPage extends StatefulWidget {
 5 |   const GesturePasswordDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   _GesturePasswordDemoState createState() => _GesturePasswordDemoState();
 9 | }
10 | 
11 | class _GesturePasswordDemoState extends State<GesturePasswordDemoPage> {
12 |   String _pwd = '';
13 | 
14 |   @override
15 |   Widget build(BuildContext context) {
16 |     return Scaffold(
17 |       appBar: AppBar(
18 |         title: const Text("手势密码"),
19 |       ),
20 |       body: Center(
21 |         child: Column(
22 |           mainAxisAlignment: MainAxisAlignment.center,
23 |           children: [
24 |             SizedBox(
25 |               width: 300,
26 |               height: 300,
27 |               child: GesturePasswordView(
28 |                 pathWidth: 6,
29 |                 frameRadius: 30,
30 |                 onDone: (value) {
31 |                   setState(() {
32 |                     _pwd = value.join();
33 |                   });
34 |                 },
35 |               ),
36 |             ),
37 |             Text("当前密码: $_pwd"),
38 |           ],
39 |         ),
40 |       ),
41 |     );
42 |   }
43 | }
44 | 


--------------------------------------------------------------------------------
/lib/widget/gesture_password/gesture_password_view.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | import 'src/gesture_view_controller.dart';
 4 | import 'src/gesture_view_path.dart';
 5 | import 'src/gesture_view_point.dart';
 6 | 
 7 | class GesturePasswordView extends StatefulWidget {
 8 | 
 9 |   /// 圆圈半径
10 |   final double frameRadius;
11 | 
12 |   /// 圆圈中心点半径
13 |   final double pointRadius;
14 | 
15 |   /// 圆圈普通状态下颜色
16 |   final Color color;
17 | 
18 |   /// 圆圈选中颜色
19 |   final Color highlightColor;
20 | 
21 |   /// 连线颜色
22 |   final Color pathColor;
23 | 
24 |   /// 连线半径
25 |   final double pathWidth;
26 | 
27 |   /// 手势结果
28 |   final Function(List<int>)? onDone;
29 | 
30 |   const GesturePasswordView({
31 |     super.key,
32 |     this.pointRadius = 10,
33 |     this.frameRadius = 40,
34 |     this.color = Colors.grey,
35 |     this.highlightColor = Colors.blue,
36 |     this.pathColor = Colors.blue,
37 |     this.onDone,
38 |     this.pathWidth = 5,
39 |   });
40 | 
41 |   @override
42 |   State<StatefulWidget> createState() => _GesturePasswordState();
43 | }
44 | 
45 | class _GesturePasswordState extends State<GesturePasswordView> {
46 |   final GestureViewController controller = GestureViewController();
47 | 
48 |   @override
49 |   void initState() {
50 |     controller.initParameters(
51 |       pointRadius: widget.pointRadius,
52 |       frameRadius: widget.frameRadius,
53 |       color: widget.color,
54 |       highlightColor: widget.highlightColor,
55 |       pathColor: widget.pathColor,
56 |       onFinishGesture: widget.onDone,
57 |       pathWidth: widget.pathWidth,
58 |       updateView: (){
59 |         setState(() {});
60 |       }
61 |     );
62 |     WidgetsBinding.instance.addPostFrameCallback((_) => controller.setPointValues());
63 |     super.initState();
64 |   }
65 | 
66 |   @override
67 |   Widget build(BuildContext context) {
68 |     return SizedBox(
69 |       key: controller.globalKey,
70 |       width: double.infinity,
71 |       height: double.infinity,
72 |       child: Stack(
73 |         children: [
74 |           GestureDotsPanelWidget(points: controller.point),
75 |           GestureViewPathWidget(
76 |             points: controller.pathPoint,
77 |             pathWidth: controller.pathWidth,
78 |             color: controller.pathColor,
79 |             onPanDown: controller.onPanDown,
80 |             onPanEnd: controller.onPanEnd,
81 |             onPanUpdate: controller.onPanUpdate,
82 |           ),
83 |         ],
84 |       ),
85 |     );
86 |   }
87 | }
88 | 


--------------------------------------------------------------------------------
/lib/widget/gesture_password/src/gesture_view_model.dart:
--------------------------------------------------------------------------------
 1 | 
 2 | import 'dart:math';
 3 | import 'package:flutter/material.dart';
 4 | 
 5 | class GesturePasswordPointModel {
 6 |   Offset centerPoint = Offset.zero;
 7 |   bool selected = false;
 8 |   double frameRadius;
 9 |   double pointRadius;
10 |   Color color = Colors.grey;
11 |   Color highlightColor = Colors.blue;
12 |   Color pathColor = Colors.blue;
13 |   int index = 0;
14 | 
15 |   GesturePasswordPointModel({
16 |     this.index = 0,
17 |     this.centerPoint = Offset.zero,
18 |     this.frameRadius = 0.0,
19 |     this.pointRadius = 0.0,
20 |     this.selected = false,
21 |     this.color = Colors.grey,
22 |     this.highlightColor = Colors.blue,
23 |     this.pathColor = Colors.blue,
24 |   });
25 | 
26 | 
27 |   Color get pointColor{
28 |     return selected ? highlightColor : color;
29 |   }
30 |   Color get frameColor => selected ?  highlightColor : color;
31 | 
32 |   bool containPoint(Offset offset){
33 |     return distanceTo(offset, centerPoint) <= frameRadius;
34 |   }
35 | 
36 | 
37 |   double distanceTo(Offset f1, Offset f2){
38 |     var dx= f1.dx - f2.dx;
39 |     var dy= f1.dy - f2.dy;
40 |     return sqrt(dx * dx + dy * dy);
41 |   }
42 | 
43 | }
44 | 


--------------------------------------------------------------------------------
/lib/widget/gesture_password/src/gesture_view_path.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | 
 4 | class GestureViewPathWidget extends StatelessWidget {
 5 |   final Function(DragDownDetails)? onPanDown;
 6 |   final Function(DragUpdateDetails)? onPanUpdate;
 7 |   final Function(DragEndDetails)? onPanEnd;
 8 |   final List<Offset> points;
 9 |   final Color color;
10 |   final double pathWidth;
11 | 
12 |   const GestureViewPathWidget({
13 |     super.key,
14 |     required this.points,
15 |     this.onPanDown,
16 |     this.onPanUpdate,
17 |     this.onPanEnd,
18 |     this.color = Colors.blue,
19 |     this.pathWidth = 4,
20 |   });
21 | 
22 |   @override
23 |   Widget build(BuildContext context) {
24 |     return GestureDetector(
25 |       behavior: HitTestBehavior.opaque,
26 |       onPanDown: _onPanDown,
27 |       onPanUpdate: _onPanUpdate,
28 |       onPanEnd: _onPanEnd,
29 |       child: CustomPaint(
30 |         size: const Size(double.infinity, double.infinity),
31 |         painter: _PathPainter(points, color: color, pathWidth: pathWidth),
32 |       ),
33 |     );
34 |   }
35 | 
36 |   _onPanDown(DragDownDetails e) {
37 |     onPanDown?.call(e);
38 |   }
39 | 
40 |   _onPanUpdate(DragUpdateDetails e) {
41 |     onPanUpdate?.call(e);
42 |   }
43 | 
44 |   _onPanEnd(DragEndDetails e) {
45 |     onPanEnd?.call(e);
46 |   }
47 | }
48 | 
49 | class _PathPainter extends CustomPainter {
50 |   final List<Offset> points;
51 |   final Color color;
52 |   final double pathWidth;
53 | 
54 |   final pathPainter = Paint()
55 |     ..style = PaintingStyle.stroke
56 |     ..strokeCap = StrokeCap.round;
57 | 
58 |   _PathPainter(
59 |     this.points, {
60 |     this.color = Colors.blue,
61 |         this.pathWidth = 4,
62 |   }){
63 |     pathPainter.color = color;
64 |     pathPainter.strokeWidth = pathWidth;
65 |   }
66 | 
67 |   @override
68 |   void paint(Canvas canvas, Size size) {
69 |     if (points.length > 1) {
70 |       for (int index = 0; index < points.length - 1; index++) {
71 |         Offset p1 = points[index];
72 |         Offset p2 = points[index + 1];
73 |         canvas.drawLine(p1, p2, pathPainter);
74 |       }
75 |     }
76 |   }
77 | 
78 |   @override
79 |   bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
80 | }
81 | 


--------------------------------------------------------------------------------
/lib/widget/gesture_password/src/gesture_view_point.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'gesture_view_model.dart';
 3 | 
 4 | class GestureDotsPanelWidget extends StatelessWidget {
 5 |   final List<GesturePasswordPointModel> points;
 6 | 
 7 |   const GestureDotsPanelWidget({super.key, required this.points});
 8 | 
 9 |   @override
10 |   Widget build(BuildContext context) {
11 |     return GridView.builder(
12 |       gridDelegate:
13 |           const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
14 |       itemCount: points.length,
15 |       physics: const NeverScrollableScrollPhysics(),
16 |       itemBuilder: (context, index) {
17 |         return GestureViewPoint(
18 |           data: points[index],
19 |         );
20 |       },
21 |     );
22 |   }
23 | }
24 | 
25 | class GestureViewPoint extends StatelessWidget {
26 |   final GesturePasswordPointModel data;
27 | 
28 |   const GestureViewPoint({super.key, required this.data});
29 | 
30 |   @override
31 |   Widget build(BuildContext context) {
32 |     return Container(
33 |       width: double.infinity,
34 |       height: double.infinity,
35 |       // color: random,
36 |       alignment: Alignment.center,
37 |       child: Stack(
38 |         children: [
39 |           CustomPaint(
40 |             painter: LinePainter(
41 |               radius: data.frameRadius,
42 |               style: PaintingStyle.stroke,
43 |               color: data.frameColor,
44 |             ),
45 |           ),
46 |           CustomPaint(
47 |             painter: LinePainter(
48 |               radius: data.pointRadius,
49 |               color: data.pointColor,
50 |             ),
51 |           ),
52 |         ],
53 |       ),
54 |     );
55 |   }
56 | }
57 | 
58 | class LinePainter extends CustomPainter {
59 |   final double radius;
60 |   final PaintingStyle style;
61 |   final Color color;
62 | 
63 |   LinePainter({
64 |     required this.radius,
65 |     this.style = PaintingStyle.fill,
66 |     this.color = Colors.grey,
67 |   });
68 | 
69 |   final Paint _paint = Paint()
70 |     ..color = Colors.grey
71 |     ..strokeCap = StrokeCap.square
72 |     ..isAntiAlias = true
73 |     ..strokeWidth = 3.0;
74 | 
75 |   @override
76 |   void paint(Canvas canvas, Size size) {
77 |     _paint.style = style;
78 |     _paint.color = color;
79 |     canvas.drawCircle(Offset.zero, radius, _paint);
80 |   }
81 | 
82 |   @override
83 |   bool shouldRepaint(CustomPainter oldDelegate) => true;
84 | }
85 | 
86 | 


--------------------------------------------------------------------------------
/lib/widget/gradient_text_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/foundation.dart';
 2 | import 'package:flutter/material.dart';
 3 | 
 4 | class GradientTextDemoPage extends StatelessWidget {
 5 |   const GradientTextDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   Widget build(BuildContext context) {
 9 |     return Scaffold(
10 |       appBar: AppBar(
11 |         title: const Text("GradientTextDemoPage"),
12 |       ),
13 |       body: Center(
14 |         child: Stack(
15 |           alignment: Alignment.center,
16 |           children: [
17 |             if (kIsWeb)
18 |               const Align(
19 |                 alignment: Alignment.topCenter,
20 |                 child: Padding(
21 |                   padding: EdgeInsets.only(top: 30),
22 |                   child: Text("当前效果不支持 Web ,请在 App 查看"),
23 |                 ),
24 |               ),
25 |             Text(
26 |               '8',
27 |               style: TextStyle(
28 |                   fontSize: 100,
29 | 
30 |                   /// 2.10 下因为有 shader (Gradient) , web 下会用 canvas
31 |                   ///编译文本,此时会有  _applySpanStyleToCanvas 时 setUpPaint 的 Rect 为 nul 的问题
32 |                   ///所以添加   fontFeatures 可以在底层渲染时切换回 p+span 标签
33 |                   ///但是目前 p+span 不支持 foreground 的 Paint
34 |                   fontFeatures:
35 |                       kIsWeb ? [const FontFeature.enable("tnum")] : null,
36 |                   foreground: Paint()
37 |                     ..style = PaintingStyle.fill
38 |                     ..strokeWidth = 3
39 |                     ..shader = const LinearGradient(
40 |                             begin: Alignment.bottomLeft,
41 |                             end: Alignment.topRight,
42 |                             colors: [Colors.yellow, Colors.black])
43 |                         .createShader(const Rect.fromLTWH(0, 0, 200, 100))),
44 |             ),
45 |             Text(
46 |               '8',
47 |               style: TextStyle(
48 |                   fontSize: 100,
49 | 
50 |                   /// 2.10 下因为有 shader (Gradient) , web 下会用 canvas
51 |                   ///编译文本,此时会有  _applySpanStyleToCanvas 时 setUpPaint 的 Rect 为 nul 的问题
52 |                   ///所以添加   fontFeatures 可以在底层渲染时切换回 p+span 标签
53 |                   ///但是目前 p+span 不支持 foreground 的 Paint
54 |                   fontFeatures:
55 |                       kIsWeb ? [const FontFeature.enable("tnum")] : null,
56 |                   foreground: Paint()
57 |                     ..style = PaintingStyle.stroke
58 |                     ..strokeWidth = 2
59 |                     ..shader = const LinearGradient(
60 |                             begin: Alignment.bottomLeft,
61 |                             end: Alignment.topRight,
62 |                             colors: [Colors.limeAccent, Colors.cyanAccent])
63 |                         .createShader(const Rect.fromLTWH(0, 0, 200, 100))),
64 |             ),
65 |           ],
66 |         ),
67 |       ),
68 |     );
69 |   }
70 | }
71 | 


--------------------------------------------------------------------------------
/lib/widget/honor_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | ///共性元素动画
 4 | class HonorDemoPage extends StatelessWidget {
 5 |   const HonorDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   Widget build(BuildContext context) {
 9 |     return Scaffold(
10 |       appBar: AppBar(
11 |         title: const Text("HonorDemoPage"),
12 |       ),
13 |       body: Center(
14 |         child: InkWell(
15 |           onTap: () {
16 |             Navigator.of(context).push(MaterialPageRoute(
17 |                 builder: (context) {
18 |                   return const HonorPage();
19 |                 },
20 |                 fullscreenDialog: true));
21 |           },
22 | 
23 |           /// Hero  tag 共享
24 |           child: Hero(
25 |             tag: "image",
26 |             child: Image.asset(
27 |               "static/gsy_cat.png",
28 |               fit: BoxFit.cover,
29 |               width: 100,
30 |               height: 100,
31 |             ),
32 |           ),
33 |         ),
34 |       ),
35 |     );
36 |   }
37 | }
38 | 
39 | class HonorPage extends StatelessWidget {
40 |   const HonorPage({super.key});
41 | 
42 |   @override
43 |   Widget build(BuildContext context) {
44 |     return Scaffold(
45 |       backgroundColor: Colors.transparent,
46 |       body: InkWell(
47 |         onTap: () {
48 |           Navigator.of(context).pop();
49 |         },
50 |         child: Container(
51 |           alignment: Alignment.center,
52 |           child: Hero(
53 |             tag: "image",
54 |             child: Image.asset(
55 |               "static/gsy_cat.png",
56 |               fit: BoxFit.cover,
57 |               width: MediaQuery.sizeOf(context).width,
58 |               height: MediaQuery.sizeOf(context).width,
59 |             ),
60 |           ),
61 |         ),
62 |       ),
63 |     );
64 |   }
65 | }
66 | 


--------------------------------------------------------------------------------
/lib/widget/overflow_image_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | /// 圆角效果处理实现
 4 | class OverflowImagePage extends StatelessWidget {
 5 |   const OverflowImagePage({super.key});
 6 | 
 7 |   @override
 8 |   Widget build(BuildContext context) {
 9 |     return Scaffold(
10 |       appBar: AppBar(
11 |         title: const Text("OverflowImagePage"),
12 |       ),
13 |       body: ListView.builder(
14 |         physics: const ClampingScrollPhysics(),
15 |         itemBuilder: (context, index) {
16 |           ///第二个Item
17 |           if (index == 1) {
18 |             return Container(
19 |               color: Colors.blue,
20 |               height: MediaQuery.sizeOf(context).height,
21 |             );
22 |           }
23 | 
24 |           ///广告图 Item
25 |           return SizedBox(
26 |             height: 100,
27 |             child: OverflowBox(
28 |                 alignment: Alignment.center,
29 |                 maxHeight: MediaQuery.sizeOf(context).height,
30 |                 child: Image(
31 |                   width: MediaQuery.sizeOf(context).width,
32 |                   height: MediaQuery.sizeOf(context).width * 220 / 247,
33 |                   image: const AssetImage("static/gsy_cat.png"),
34 |                   fit: BoxFit.fill,
35 |                 )),
36 |           );
37 |         },
38 |         itemCount: 2,
39 |       ),
40 |     );
41 |   }
42 | }
43 | 


--------------------------------------------------------------------------------
/lib/widget/particle/particle_model.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:math';
 2 | 
 3 | import 'package:flutter/material.dart';
 4 | import 'package:simple_animations/simple_animations.dart';
 5 | import 'package:supercharged/supercharged.dart';
 6 | 
 7 | enum ParticleOffsetProps { x, y }
 8 | 
 9 | class ParticleModel {
10 |   late MovieTween tween;
11 |   late double size;
12 |   late Duration duration;
13 |   late Duration startTime;
14 |   Random random;
15 | 
16 |   ParticleModel(this.random) {
17 |     _restart();
18 |     _shuffle();
19 |   }
20 | 
21 |   _restart() {
22 |     final startPosition = Offset(-0.2 + 1.4 * random.nextDouble(), 1.2);
23 |     final endPosition = Offset(-0.2 + 1.4 * random.nextDouble(), -0.2);
24 | 
25 |     tween = MovieTween()
26 |       ..tween(ParticleOffsetProps.x, startPosition.dx.tweenTo(endPosition.dx),
27 |           duration: const Duration(milliseconds: 20))
28 |       ..tween(ParticleOffsetProps.y, startPosition.dy.tweenTo(endPosition.dy),
29 |           duration: const Duration(milliseconds: 20));
30 | 
31 |     duration = 3000.milliseconds + random.nextInt(6000).milliseconds;
32 |     startTime = DateTime.now().duration();
33 |     size = 0.2 + random.nextDouble() * 0.4;
34 |   }
35 | 
36 |   void _shuffle() {
37 |     startTime -= (random.nextDouble() * duration.inMilliseconds)
38 |         .round()
39 |         .milliseconds;
40 |   }
41 | 
42 |   checkIfParticleNeedsToBeRestarted() {
43 |     if (progress() == 1.0) {
44 |       _restart();
45 |     }
46 |   }
47 | 
48 |   double progress() {
49 |     return ((DateTime.now().duration() - startTime) / duration)
50 |         .clamp(0.0, 1.0)
51 |         .toDouble();
52 |   }
53 | }
54 | 


--------------------------------------------------------------------------------
/lib/widget/particle/particle_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/particle/particle_widget.dart';
 3 | import 'package:simple_animations/simple_animations.dart';
 4 | import 'package:supercharged/supercharged.dart';
 5 | 
 6 | enum _ColorTween { color1, color2 }
 7 | 
 8 | class ParticlePage extends StatelessWidget {
 9 |   const ParticlePage({super.key});
10 | 
11 |   @override
12 |   Widget build(BuildContext context) {
13 |     return Scaffold(
14 |       appBar: AppBar(
15 |         title: const Text("ParticlePage"),
16 |       ),
17 |       backgroundColor: Colors.black,
18 |       body: const Stack(children: <Widget>[
19 |         Positioned.fill(child: AnimatedBackground()),
20 |         Positioned.fill(child: ParticlesWidget(30)),
21 |         Positioned.fill(
22 |           child: Center(
23 |             child: Text(
24 |               "GSY Flutter Demo",
25 |               style: TextStyle(
26 |                   fontSize: 30,
27 |                   fontWeight: FontWeight.bold,
28 |                   color: Colors.white),
29 |             ),
30 |           ),
31 |         ),
32 |       ]),
33 |     );
34 |   }
35 | }
36 | 
37 | class AnimatedBackground extends StatelessWidget {
38 |   const AnimatedBackground({super.key});
39 | 
40 |   @override
41 |   Widget build(BuildContext context) {
42 |     final tween = MovieTween()
43 |       ..tween(
44 |         _ColorTween.color1,
45 |         const Color(0xffD38312).tweenTo(Colors.lightBlue.shade900),
46 |         duration: 3.seconds,
47 |       )
48 |       ..tween(
49 |         _ColorTween.color2,
50 |         const Color(0xffA83279).tweenTo(Colors.blue.shade600),
51 |         duration: 3.seconds,
52 |       );
53 | 
54 |     return MirrorAnimationBuilder<Movie>(
55 |       tween: tween,
56 |       duration: tween.duration,
57 |       builder: (context, value, child) {
58 |         return Container(
59 |           decoration: BoxDecoration(
60 |               gradient: LinearGradient(
61 |                   begin: Alignment.topCenter,
62 |                   end: Alignment.bottomCenter,
63 |                   colors: [
64 |                     value.get<Color>(_ColorTween.color1),
65 |                     value.get<Color>(_ColorTween.color2)
66 |                   ])),
67 |         );
68 |       },
69 |     );
70 |   }
71 | }


--------------------------------------------------------------------------------
/lib/widget/particle/particle_painter.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/particle/particle_model.dart';
 3 | import 'package:simple_animations/simple_animations.dart';
 4 | 
 5 | class ParticlePainter extends CustomPainter {
 6 |   List<ParticleModel> particles;
 7 | 
 8 |   ParticlePainter(this.particles);
 9 | 
10 |   @override
11 |   void paint(Canvas canvas, Size size) {
12 |     final paint = Paint()..color = Colors.white.withAlpha(50);
13 | 
14 |     for (var particle in particles) {
15 |       final progress = particle.progress();
16 |       final Movie animation =
17 |       particle.tween.transform(progress);
18 |       final position = Offset(
19 |         animation.get<double>(ParticleOffsetProps.x) * size.width,
20 |         animation.get<double>(ParticleOffsetProps.y) * size.height,
21 |       );
22 |       canvas.drawCircle(position, size.width * 0.2 * particle.size, paint);
23 |     }
24 |   }
25 | 
26 |   @override
27 |   bool shouldRepaint(CustomPainter oldDelegate) => true;
28 | }


--------------------------------------------------------------------------------
/lib/widget/particle/particle_widget.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:math';
 2 | 
 3 | import 'package:flutter/material.dart';
 4 | import 'package:gsy_flutter_demo/widget/particle/particle_model.dart';
 5 | import 'package:gsy_flutter_demo/widget/particle/particle_painter.dart';
 6 | import 'package:simple_animations/simple_animations.dart';
 7 | import 'package:supercharged/supercharged.dart';
 8 | 
 9 | class ParticlesWidget extends StatefulWidget {
10 |   final int numberOfParticles;
11 | 
12 |   const ParticlesWidget(this.numberOfParticles, {super.key});
13 | 
14 |   @override
15 |   _ParticlesWidgetState createState() => _ParticlesWidgetState();
16 | }
17 | 
18 | class _ParticlesWidgetState extends State<ParticlesWidget> {
19 |   final Random random = Random();
20 | 
21 |   final List<ParticleModel> particles = [];
22 | 
23 |   @override
24 |   void initState() {
25 |     widget.numberOfParticles.times(() => particles.add(ParticleModel(random)));
26 |     super.initState();
27 |   }
28 | 
29 |   @override
30 |   Widget build(BuildContext context) {
31 |     return LoopAnimationBuilder(
32 |       duration: const Duration(seconds: 1),
33 |       tween: ConstantTween(1),
34 |       builder: (context, child, dynamic _) {
35 |         _simulateParticles();
36 |         return CustomPaint(
37 |           painter: ParticlePainter(particles),
38 |         );
39 |       },
40 |     );
41 |   }
42 | 
43 |   _simulateParticles() {
44 |     for (var particle in particles) {
45 |       particle.checkIfParticleNeedsToBeRestarted();
46 |     }
47 |   }
48 | 
49 | }
50 | 


--------------------------------------------------------------------------------
/lib/widget/png_shadow_demo_page.dart:
--------------------------------------------------------------------------------
  1 | import 'dart:ui';
  2 | 
  3 | import 'package:flutter/material.dart';
  4 | 
  5 | ///from https://pub.flutter-io.cn/packages/drop_shadow
  6 | class PngShadowDemoPage extends StatefulWidget {
  7 |   const PngShadowDemoPage({super.key});
  8 | 
  9 |   @override
 10 |   State<PngShadowDemoPage> createState() => _PngShadowDemoPageState();
 11 | }
 12 | 
 13 | class _PngShadowDemoPageState extends State<PngShadowDemoPage> {
 14 |   @override
 15 |   Widget build(BuildContext context) {
 16 |     return Scaffold(
 17 |       appBar: AppBar(
 18 |         title: const Text("PngShadowDemoPage"),
 19 |       ),
 20 |       body: Container(
 21 |         alignment: Alignment.center,
 22 |         child: DropShadow(
 23 |           child: Image.asset(
 24 |             'static/test_logo.png',
 25 |             width: 250,
 26 |           ),
 27 |         ),
 28 |       ),
 29 |     );
 30 |   }
 31 | }
 32 | 
 33 | class DropShadow extends StatelessWidget {
 34 |   final Widget child;
 35 |   final double blurRadius;
 36 |   final double borderRadius;
 37 |   final Offset offset;
 38 |   final double opacity;
 39 |   final double spread;
 40 | 
 41 |   const DropShadow({
 42 |     super.key,
 43 |     required this.child,
 44 |     this.blurRadius = 10.0,
 45 |     this.borderRadius = 0.0,
 46 |     this.offset = const Offset(0.0, 8.0),
 47 |     this.opacity = 1.0,
 48 |     this.spread = 1.0,
 49 |   });
 50 | 
 51 |   @override
 52 |   Widget build(BuildContext context) {
 53 |     double left = 0;
 54 |     double right = 0;
 55 |     double top = 0;
 56 |     double bottom = 0;
 57 | 
 58 |     left = (offset.dx.abs() + (blurRadius * 2)) * spread;
 59 |     right = (offset.dx + (blurRadius * 2)) * spread;
 60 |     top = (offset.dy.abs() + (blurRadius * 2)) * spread;
 61 |     bottom = (offset.dy + (blurRadius * 2)) * spread;
 62 | 
 63 |     /// [ClipRRect] to isolate [BackDropFilter] from other widgets
 64 |     return ClipRRect(
 65 |       child: Padding(
 66 |         /// Calculate Shadow's effect field
 67 |         padding: EdgeInsets.fromLTRB(left, top, right, bottom),
 68 |         child: Stack(
 69 |           children: [
 70 |             /// Arrange shadow position
 71 |             Transform.translate(
 72 |               offset: offset,
 73 | 
 74 |               /// Apply [BorderRadius] to the shadow
 75 |               child: ClipRRect(
 76 |                 borderRadius: BorderRadius.circular(borderRadius),
 77 | 
 78 |                 /// Apply [Opacity] to the shadow
 79 |                 child: Opacity(
 80 |                   opacity: opacity,
 81 |                   child: child,
 82 |                 ),
 83 |               ),
 84 |             ),
 85 | 
 86 |             /// Apply filter the whole [Stack] space
 87 |             Positioned.fill(
 88 |               /// Apply blur effect to the layer
 89 |               child: BackdropFilter(
 90 |                 filter: ImageFilter.blur(
 91 |                   sigmaX: blurRadius,
 92 |                   sigmaY: blurRadius,
 93 |                 ),
 94 | 
 95 |                 /// Filter effect field
 96 |                 child: Container(color: Colors.transparent),
 97 |               ),
 98 |             ),
 99 | 
100 |             /// [Widget] itself with given [BorderRadius]
101 |             ClipRRect(
102 |               borderRadius: BorderRadius.circular(borderRadius),
103 |               child: child,
104 |             ),
105 |           ],
106 |         ),
107 |       ),
108 |     );
109 |   }
110 | }
111 | 


--------------------------------------------------------------------------------
/lib/widget/positioned_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | ///Stack + Positioned例子
 4 | class PositionedDemoPage extends StatelessWidget {
 5 |   const PositionedDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   Widget build(BuildContext context) {
 9 |     return Scaffold(
10 |       appBar: AppBar(
11 |         title: const Text("PositionedDemoPage"),
12 |       ),
13 |       body: Container(
14 |         width: MediaQuery.sizeOf(context).width,
15 |         height: MediaQuery.sizeOf(context).height,
16 |         margin: const EdgeInsets.all(15),
17 |         child: Stack(
18 |           children: <Widget>[
19 |             MaterialButton(
20 |               onPressed: () {},
21 |               color: Colors.blue,
22 |             ),
23 |             Positioned(
24 |                 left: MediaQuery.sizeOf(context).width / 2,
25 |                 child: MaterialButton(
26 |                   onPressed: () {},
27 |                   color: Colors.greenAccent,
28 |                 )),
29 |             Positioned(
30 |               left: MediaQuery.sizeOf(context).width / 5,
31 |               top: MediaQuery.sizeOf(context).height / 4 * 3,
32 |               child: MaterialButton(
33 |                 onPressed: () {},
34 |                 color: Colors.yellow,
35 |               ),
36 |             ),
37 |             Positioned(
38 |               left: MediaQuery.sizeOf(context).width / 2 - Theme.of(context).buttonTheme.minWidth / 2,
39 |               top: MediaQuery.sizeOf(context).height / 2 -
40 |                   MediaQuery.paddingOf(context).top -
41 |                   kToolbarHeight,
42 |               child: MaterialButton(
43 |                 onPressed: () {},
44 |                 color: Colors.redAccent,
45 |               ),
46 |             ),
47 |           ],
48 |         ),
49 |       ),
50 |     );
51 |   }
52 | }
53 | 


--------------------------------------------------------------------------------
/lib/widget/refrsh_demo_page.dart:
--------------------------------------------------------------------------------
  1 | import 'package:flutter/material.dart';
  2 | 
  3 | ///刷新演示
  4 | ///比较粗略,没有做互斥等
  5 | ///详细使用还请查看 https://github.com/CarGuo/GSYGithubAppFlutter
  6 | class RefreshDemoPage extends StatefulWidget {
  7 |   const RefreshDemoPage({super.key});
  8 | 
  9 |   @override
 10 |   _RefreshDemoPageState createState() => _RefreshDemoPageState();
 11 | }
 12 | 
 13 | class _RefreshDemoPageState extends State<RefreshDemoPage> {
 14 |   final int pageSize = 30;
 15 | 
 16 |   bool disposed = false;
 17 | 
 18 |   List<String> dataList = [];
 19 | 
 20 |   final ScrollController _scrollController = ScrollController();
 21 | 
 22 |   final GlobalKey<RefreshIndicatorState> refreshKey = GlobalKey();
 23 | 
 24 |   Future<void> onRefresh() async {
 25 |     await Future.delayed(const Duration(seconds: 2));
 26 |     dataList.clear();
 27 |     for (int i = 0; i < pageSize; i++) {
 28 |       dataList.add("refresh");
 29 |     }
 30 |     if(disposed) {
 31 |       return;
 32 |     }
 33 |     setState(() {});
 34 |   }
 35 | 
 36 |   Future<void> loadMore() async {
 37 |     await Future.delayed(const Duration(seconds: 2));
 38 |     for (int i = 0; i < pageSize; i++) {
 39 |       dataList.add("loadmore");
 40 |     }
 41 |     if(disposed) {
 42 |       return;
 43 |     }
 44 |     setState(() {});
 45 |   }
 46 | 
 47 |   @override
 48 |   void initState() {
 49 |     super.initState();
 50 |     _scrollController.addListener(() {
 51 |       ///判断当前滑动位置是不是到达底部,触发加载更多回调
 52 |       if (_scrollController.position.pixels ==
 53 |           _scrollController.position.maxScrollExtent) {
 54 |         loadMore();
 55 |       }
 56 |     });
 57 |     Future.delayed(const Duration(seconds: 0), (){
 58 |       refreshKey.currentState!.show();
 59 |     });
 60 |   }
 61 | 
 62 |   @override
 63 |   void dispose() {
 64 |     disposed = true;
 65 |     super.dispose();
 66 |   }
 67 | 
 68 |   @override
 69 |   Widget build(BuildContext context) {
 70 |     return Scaffold(
 71 |       appBar: AppBar(
 72 |         title: const Text("RefreshDemoPage"),
 73 |       ),
 74 |       body: RefreshIndicator(
 75 |         ///GlobalKey,用户外部获取RefreshIndicator的State,做显示刷新
 76 |         key: refreshKey,
 77 | 
 78 |         ///下拉刷新触发,返回的是一个Future
 79 |         onRefresh: onRefresh,
 80 |         child: ListView.builder(
 81 |           ///保持ListView任何情况都能滚动,解决在RefreshIndicator的兼容问题。
 82 |           physics: const AlwaysScrollableScrollPhysics(),
 83 | 
 84 |           ///根据状态返回
 85 |           itemBuilder: (context, index) {
 86 |             if (index == dataList.length) {
 87 |               return Container(
 88 |                 margin: const EdgeInsets.all(10),
 89 |                 child: const Align(
 90 |                   child: CircularProgressIndicator(),
 91 |                 ),
 92 |               );
 93 |             }
 94 |             return Card(
 95 |               child: Container(
 96 |                 height: 60,
 97 |                 alignment: Alignment.centerLeft,
 98 |                 child: Text("Item ${dataList[index]} $index"),
 99 |               ),
100 |             );
101 |           },
102 | 
103 |           ///根据状态返回数量
104 |           itemCount: (dataList.length >= pageSize)
105 |               ? dataList.length + 1
106 |               : dataList.length,
107 | 
108 |           ///滑动监听
109 |           controller: _scrollController,
110 |         ),
111 |       ),
112 |     );
113 |   }
114 | }
115 | 


--------------------------------------------------------------------------------
/lib/widget/rich_text_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/gestures.dart';
 2 | import 'package:flutter/material.dart';
 3 | import 'package:gsy_flutter_demo/widget/rich/real_rich_text.dart';
 4 | 
 5 | class RichTextDemoPage extends StatefulWidget {
 6 |   const RichTextDemoPage({super.key});
 7 | 
 8 |   @override
 9 |   _RichTextDemoState createState() => _RichTextDemoState();
10 | }
11 | 
12 | class _RichTextDemoState extends State<RichTextDemoPage> {
13 |   @override
14 |   Widget build(BuildContext mainContext) {
15 |     return Scaffold(
16 |       appBar: AppBar(
17 |         title: const Text("RichTextDemoPage"),
18 |       ),
19 |       body: Container(
20 |         margin: const EdgeInsets.all(10),
21 |         child: Builder(builder: (context) {
22 |           return Center(
23 |             child: RealRichText([
24 |               TextSpan(
25 |                 text: "A Text Link",
26 |                 style: const TextStyle(color: Colors.red, fontSize: 14),
27 |                 recognizer: TapGestureRecognizer()
28 |                   ..onTap = () {
29 |                     show(context, "Link Clicked.");
30 |                   },
31 |               ),
32 |               ImageSpan(
33 |                 const AssetImage("static/gsy_cat.png"),
34 |                 imageWidth: 24,
35 |                 imageHeight: 24,
36 |               ),
37 |               ImageSpan(const AssetImage("static/gsy_cat.png"),
38 |                   imageWidth: 24,
39 |                   imageHeight: 24,
40 |                   margin: const EdgeInsets.symmetric(horizontal: 10)),
41 |               const TextSpan(
42 |                 text: "哈哈哈",
43 |                 style: TextStyle(color: Colors.yellow, fontSize: 14),
44 |               ),
45 |               TextSpan(
46 |                 text: "@Somebody",
47 |                 style: const TextStyle(
48 |                     color: Colors.black,
49 |                     fontSize: 14,
50 |                     fontWeight: FontWeight.bold),
51 |                 recognizer: TapGestureRecognizer()
52 |                   ..onTap = () {
53 |                     show(context, "Link Clicked.");
54 |                   },
55 |               ),
56 |               TextSpan(
57 |                 text: " #RealRichText# ",
58 |                 style: const TextStyle(color: Colors.blue, fontSize: 14),
59 |                 recognizer: TapGestureRecognizer()
60 |                   ..onTap = () {
61 |                     show(context, "Link Clicked.");
62 |                   },
63 |               ),
64 |               const TextSpan(
65 |                 text: "showing a bigger image",
66 |                 style: TextStyle(color: Colors.black, fontSize: 14),
67 |               ),
68 |               ImageSpan(const AssetImage("static/gsy_cat.png"),
69 |                   imageWidth: 24,
70 |                   imageHeight: 24,
71 |                   margin: const EdgeInsets.symmetric(horizontal: 5)),
72 |               const TextSpan(
73 |                 text: "and seems working perfect……",
74 |                 style: TextStyle(color: Colors.black, fontSize: 14),
75 |               ),
76 |             ]),
77 |           );
78 |         }),
79 |       ),
80 |     );
81 |   }
82 | 
83 |   show(context, text) {
84 |     ScaffoldMessenger.of(context).showSnackBar(SnackBar(
85 |       content: Text(text),
86 |       action: SnackBarAction(
87 |         label: 'ACTION',
88 |         onPressed: () {
89 |           ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
90 |             content: Text('You pressed snackbar\'s action.'),
91 |           ));
92 |         },
93 |       ),
94 |     ));
95 |   }
96 | }
97 | 


--------------------------------------------------------------------------------
/lib/widget/rich_text_demo_page2.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class RichTextDemoPage2 extends StatefulWidget {
 4 |   const RichTextDemoPage2({super.key});
 5 | 
 6 |   @override
 7 |   _RichTextDemoState2 createState() => _RichTextDemoState2();
 8 | }
 9 | 
10 | class _RichTextDemoState2 extends State<RichTextDemoPage2> {
11 |   double size = 50;
12 | 
13 |   @override
14 |   Widget build(BuildContext mainContext) {
15 |     return Scaffold(
16 |       appBar: AppBar(
17 |         title: const Text("RichTextDemoPage"),
18 |         actions: <Widget>[
19 |           IconButton(
20 |             onPressed: () {
21 |               setState(() {
22 |                 size += 10;
23 |               });
24 |             },
25 |             icon: const Icon(Icons.add_circle_outline),
26 |           ),
27 |           IconButton(
28 |             onPressed: () {
29 |               setState(() {
30 |                 size -= 10;
31 |               });
32 |             },
33 |             icon: const Icon(Icons.remove_circle_outline),
34 |           )
35 |         ],
36 |       ),
37 |       body: SelectionArea(
38 |         child: Container(
39 |           margin: const EdgeInsets.all(10),
40 |           child: Builder(builder: (context) {
41 |             return Center(
42 |               child: Text.rich(TextSpan(
43 |                 children: <InlineSpan>[
44 |                   const TextSpan(text: 'Flutter is'),
45 |                   const WidgetSpan(
46 |                       child: SizedBox(
47 |                     width: 120,
48 |                     height: 50,
49 |                     child: Card(
50 |                         color: Colors.blue,
51 |                         child: Center(child: Text('Hello World!'))),
52 |                   )),
53 |                   WidgetSpan(
54 |                       child: SizedBox(
55 |                     width: size > 0 ? size : 0,
56 |                     height: size > 0 ? size : 0,
57 |                     child: Image.asset(
58 |                       "static/gsy_cat.png",
59 |                       fit: BoxFit.cover,
60 |                     ),
61 |                   )),
62 |                   const TextSpan(text: 'the best!'),
63 |                   const WidgetSpan(
64 |                     child: SelectionContainer.disabled(
65 |                       child: Text(' not copy'),
66 |                     ),
67 |                   ),
68 |                 ],
69 |               )),
70 |             );
71 |           }),
72 |         ),
73 |       ),
74 |     );
75 |   }
76 | 
77 |   show(context, text) {
78 |     ScaffoldMessenger.of(context).showSnackBar(SnackBar(
79 |       content: Text(text),
80 |       action: SnackBarAction(
81 |         label: 'ACTION',
82 |         onPressed: () {
83 |           ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
84 |             content: Text('You pressed snackbar\'s action.'),
85 |           ));
86 |         },
87 |       ),
88 |     ));
89 |   }
90 | }
91 | 


--------------------------------------------------------------------------------
/lib/widget/route_demo_page.dart:
--------------------------------------------------------------------------------
  1 | import 'package:flutter/cupertino.dart';
  2 | import 'package:flutter/material.dart';
  3 | 
  4 | class RouteDemoPage extends StatefulWidget {
  5 |   const RouteDemoPage({super.key});
  6 | 
  7 |   @override
  8 |   State<RouteDemoPage> createState() => _RouteDemoPageState();
  9 | }
 10 | 
 11 | class _RouteDemoPageState extends State<RouteDemoPage> {
 12 |   final GlobalKey<NavigatorState> _navigator = GlobalKey();
 13 | 
 14 |   getRouter(index) {
 15 |     return CupertinoPageRoute(
 16 |         builder: (context) {
 17 |           return RoutePage(index);
 18 |         },
 19 |         maintainState: false,
 20 |         fullscreenDialog: true);
 21 |   }
 22 | 
 23 |   @override
 24 |   Widget build(BuildContext context) {
 25 |     return Scaffold(
 26 |       appBar: AppBar(
 27 |         title: const Text("RouteDemoPage"),
 28 |       ),
 29 |       body: Row(
 30 |         children: [
 31 |           Expanded(
 32 |             flex: 1,
 33 |             child: Container(
 34 |               color: Colors.blue,
 35 |               child: Column(
 36 |                 children: List.generate(10, (index) {
 37 |                   return InkWell(
 38 |                       onTap: () {
 39 |                         _navigator.currentState!.push(getRouter(index));
 40 |                       },
 41 |                       child: Container(
 42 |                           height: 30,
 43 |                           margin: const EdgeInsets.symmetric(vertical: 10),
 44 |                           color: Colors.amberAccent,
 45 |                           alignment: Alignment.center,
 46 |                           child: Text("click  $index")));
 47 |                 }),
 48 |               ),
 49 |             ),
 50 |           ),
 51 |           const Divider(
 52 |             color: Colors.grey,
 53 |           ),
 54 |           const SizedBox(
 55 |             width: 30,
 56 |           ),
 57 |           Expanded(
 58 |             flex: 3,
 59 |             child: Container(
 60 |               color: Colors.grey,
 61 |               child: Navigator(
 62 |                 restorationScopeId: 'nav2',
 63 |                 key: _navigator,
 64 |                 onGenerateInitialRoutes:
 65 |                     (NavigatorState navigator, String initialRoute) {
 66 |                   return [
 67 |                     getRouter(0),
 68 |                   ];
 69 |                 },
 70 |                 reportsRouteUpdateToEngine: true,
 71 |               ),
 72 |             ),
 73 |           ),
 74 |         ],
 75 |       ),
 76 |     );
 77 |   }
 78 | }
 79 | 
 80 | class RoutePage extends StatefulWidget {
 81 |   final int index;
 82 | 
 83 |   const RoutePage(this.index, {super.key});
 84 | 
 85 |   @override
 86 |   State<RoutePage> createState() => _RoutePageState();
 87 | }
 88 | 
 89 | class _RoutePageState extends State<RoutePage> {
 90 |   @override
 91 |   Widget build(BuildContext context) {
 92 |     return Container(
 93 |       alignment: Alignment.center,
 94 |       color: Colors.white,
 95 |       child: InkWell(
 96 |         onTap: () {
 97 |           if (Navigator.of(context).canPop()) Navigator.of(context).pop();
 98 |         },
 99 |         child: Container(
100 |           width: 200,
101 |           height: 200,
102 |           alignment: Alignment.center,
103 |           color: Colors.amber,
104 |           child: Text(
105 |             "${widget.index}",
106 |             style: const TextStyle(fontSize: 100, color: Colors.red),
107 |           ),
108 |         ),
109 |       ),
110 |     );
111 |   }
112 | }
113 | 


--------------------------------------------------------------------------------
/lib/widget/scroll_listener_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | ///滑动监听
 4 | class ScrollListenerDemoPage extends StatefulWidget {
 5 |   const ScrollListenerDemoPage({super.key});
 6 | 
 7 |   @override
 8 |   _ScrollListenerDemoPageState createState() => _ScrollListenerDemoPageState();
 9 | }
10 | 
11 | class _ScrollListenerDemoPageState extends State<ScrollListenerDemoPage> {
12 |   final ScrollController _scrollController = ScrollController();
13 | 
14 |   bool isEnd = false;
15 | 
16 |   double offset = 0;
17 | 
18 |   String notify = "";
19 | 
20 |   @override
21 |   void initState() {
22 |     super.initState();
23 |     _scrollController.addListener(() {
24 |       setState(() {
25 |         offset = _scrollController.offset;
26 |         isEnd = _scrollController.position.pixels ==
27 |             _scrollController.position.maxScrollExtent;
28 |       });
29 |     });
30 |   }
31 | 
32 |   @override
33 |   Widget build(BuildContext context) {
34 |     return Scaffold(
35 |       appBar: AppBar(
36 |         title: const Text("ScrollListenerDemoPage"),
37 |       ),
38 |       body: NotificationListener(
39 |         onNotification: (dynamic notification) {
40 |           String notify = "";
41 |           if (notification is ScrollEndNotification) {
42 |             notify = "ScrollEnd";
43 |           } else if (notification is ScrollStartNotification) {
44 |             notify = "ScrollStart";
45 |           } else if (notification is UserScrollNotification) {
46 |             notify = " UserScroll";
47 |           } else if (notification is ScrollUpdateNotification) {
48 |             notify = "ScrollUpdate";
49 |           }
50 |           setState(() {
51 |             this.notify = notify;
52 |           });
53 |           return false;
54 |         },
55 |         child: ListView.builder(
56 |           controller: _scrollController,
57 |           itemBuilder: (context, index) {
58 |             return Card(
59 |               child: Container(
60 |                 height: 60,
61 |                 alignment: Alignment.centerLeft,
62 |                 child: Text("Item $index"),
63 |               ),
64 |             );
65 |           },
66 |           itemCount: 100,
67 |         ),
68 |       ),
69 |       persistentFooterButtons: <Widget>[
70 |         TextButton(
71 |           onPressed: () {
72 |             _scrollController.animateTo(0,
73 |                 duration: const Duration(seconds: 1), curve: Curves.bounceInOut);
74 |           },
75 |           child: Text("position: ${offset.floor()}"),
76 |         ),
77 |         const SizedBox(width: 0.3, height: 30.0),
78 |         TextButton(
79 |           onPressed: () {},
80 |           child: Text(notify),
81 |         ),
82 |         Visibility(
83 |           visible: isEnd,
84 |           child: TextButton(
85 |             onPressed: () {},
86 |             child: const Text("到达底部"),
87 |           ),
88 |         )
89 |       ],
90 |     );
91 |   }
92 | }
93 | 


--------------------------------------------------------------------------------
/lib/widget/scroll_to_index_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'dart:math' as math;
 2 | 
 3 | import 'package:flutter/material.dart';
 4 | import 'package:scroll_to_index/scroll_to_index.dart';
 5 | 
 6 | /// 滑动到指定位置
 7 | /// 因为官方一直未支持滑动都执行 item
 8 | /// 所有有第三方库另辟蹊径
 9 | class ScrollToIndexDemoPage extends StatefulWidget {
10 |   const ScrollToIndexDemoPage({super.key});
11 | 
12 |   @override
13 |   _ScrollToIndexDemoPageState createState() => _ScrollToIndexDemoPageState();
14 | }
15 | 
16 | class _ScrollToIndexDemoPageState extends State<ScrollToIndexDemoPage> {
17 | 
18 |   static const maxCount = 100;
19 | 
20 |   /// pub  scroll_to_index 项目的 controller
21 |   AutoScrollController? controller;
22 | 
23 |   final random = math.Random();
24 | 
25 |   final scrollDirection = Axis.vertical;
26 | 
27 |   late List<List<int>> randomList;
28 | 
29 |   @override
30 |   void initState() {
31 |     super.initState();
32 |     controller = AutoScrollController(
33 |         viewportBoundaryGetter: () =>
34 |             Rect.fromLTRB(0, 0, 0, MediaQuery.paddingOf(context).bottom),
35 |         axis: scrollDirection);
36 |     ///一个 index 和 item 高度的数组
37 |     randomList = List.generate(maxCount,
38 |         (index) => <int>[index, (1000 * random.nextDouble()).toInt()]);
39 |   }
40 | 
41 |   Widget _getRow(int index, double height) {
42 |     return _wrapScrollTag(
43 |         index: index,
44 |         child: Container(
45 |           padding: const EdgeInsets.all(8),
46 |           alignment: Alignment.topCenter,
47 |           height: height,
48 |           decoration: BoxDecoration(
49 |               border: Border.all(color: Colors.lightBlue, width: 4),
50 |               borderRadius: BorderRadius.circular(12)),
51 |           child: Text('index: $index, height: $height'),
52 |         ));
53 |   }
54 | 
55 |   Widget _wrapScrollTag({required int index, required Widget child}) => AutoScrollTag(
56 |         key: ValueKey(index),
57 |         controller: controller!,
58 |         index: index,
59 |         highlightColor: Colors.black..withValues(alpha: 0.1),
60 |         child: child,
61 |       );
62 | 
63 |   @override
64 |   Widget build(BuildContext context) {
65 |     return Scaffold(
66 |       appBar: AppBar(
67 |         title: const Text("ScrollToIndexDemoPage"),
68 |       ),
69 |       body: ListView(
70 |         scrollDirection: scrollDirection,
71 |         controller: controller,
72 |         children: randomList.map<Widget>((data) {
73 |           return Padding(
74 |             padding: const EdgeInsets.all(8),
75 |             child: _getRow(data[0], math.max(data[1].toDouble(), 50.0)),
76 |           );
77 |         }).toList(),
78 |       ),
79 |       persistentFooterButtons: <Widget>[
80 |         TextButton(
81 |           onPressed: () async {
82 |             ///滑动到第13个的位置
83 |             await controller!.scrollToIndex(13,
84 |                 preferPosition: AutoScrollPosition.begin);
85 |             controller!.highlight(13);
86 |           },
87 |           child: const Text("Scroll to 13"),
88 |         ),
89 |       ],
90 |     );
91 |   }
92 | }
93 | 


--------------------------------------------------------------------------------
/lib/widget/scroll_to_index_demo_page2.dart:
--------------------------------------------------------------------------------
  1 | import 'dart:math' as math;
  2 | 
  3 | import 'package:flutter/foundation.dart';
  4 | import 'package:flutter/material.dart';
  5 | 
  6 | /// 滑动到指定位置 GlobalKey 版本
  7 | /// 基于 SingleChildScrollView 和 Column
  8 | class ScrollToIndexDemoPage2 extends StatefulWidget {
  9 |   const ScrollToIndexDemoPage2({super.key});
 10 | 
 11 |   @override
 12 |   _ScrollToIndexDemoPageState2 createState() => _ScrollToIndexDemoPageState2();
 13 | }
 14 | 
 15 | class _ScrollToIndexDemoPageState2 extends State<ScrollToIndexDemoPage2> {
 16 |   GlobalKey scrollKey = GlobalKey();
 17 | 
 18 |   ScrollController controller = ScrollController();
 19 | 
 20 |   List<ItemModel> dataList = [];
 21 | 
 22 |   @override
 23 |   void initState() {
 24 |     dataList.clear();
 25 |     for (int i = 0; i < 100; i++) {
 26 |       dataList.add(ItemModel(i));
 27 |     }
 28 |     super.initState();
 29 |   }
 30 | 
 31 |   _scrollToIndex() {
 32 |     var key = dataList[12];
 33 | 
 34 |     ///获取 renderBox
 35 |     RenderBox renderBox =
 36 |         key.globalKey.currentContext!.findRenderObject() as RenderBox;
 37 | 
 38 |     ///获取位置偏移,基于 ancestor: SingleChildScrollView 的 RenderObject()
 39 |     double dy = renderBox
 40 |         .localToGlobal(Offset.zero,
 41 |             ancestor: scrollKey.currentContext!.findRenderObject())
 42 |         .dy;
 43 | 
 44 |     ///计算真实位移
 45 |     var offset = dy + controller.offset;
 46 | 
 47 |     if (kDebugMode) {
 48 |       print("*******$offset");
 49 |     }
 50 | 
 51 |     controller.animateTo(offset,
 52 |         duration: const Duration(milliseconds: 500), curve: Curves.linear);
 53 |   }
 54 | 
 55 |   @override
 56 |   Widget build(BuildContext context) {
 57 |     return Scaffold(
 58 |       appBar: AppBar(
 59 |         title: const Text("ScrollToIndexDemoPage2"),
 60 |       ),
 61 |       body: SingleChildScrollView(
 62 |         key: scrollKey,
 63 |         controller: controller,
 64 |         child: Column(
 65 |           children: dataList.map<Widget>((data) {
 66 |             return CardItem(data, key: dataList[data.index].globalKey);
 67 |           }).toList(),
 68 |         ),
 69 |       ),
 70 |       persistentFooterButtons: <Widget>[
 71 |         TextButton(
 72 |           onPressed: () async {
 73 |             _scrollToIndex();
 74 |           },
 75 |           child: const Text("Scroll to 12"),
 76 |         ),
 77 |       ],
 78 |     );
 79 |   }
 80 | }
 81 | 
 82 | class CardItem extends StatelessWidget {
 83 |   final random = math.Random();
 84 | 
 85 |   final ItemModel data;
 86 | 
 87 |   CardItem(this.data, {super.key});
 88 | 
 89 |   @override
 90 |   Widget build(BuildContext context) {
 91 |     return Card(
 92 |       child: Container(
 93 |         height: (300 * random.nextDouble()),
 94 |         alignment: Alignment.centerLeft,
 95 |         child: Container(
 96 |           margin: const EdgeInsets.all(5),
 97 |           child: Text("Item ${data.index}"),
 98 |         ),
 99 |       ),
100 |     );
101 |   }
102 | }
103 | 
104 | class ItemModel {
105 |   ///这个key是关键
106 |   GlobalKey globalKey = GlobalKey();
107 | 
108 |   ///可以添加你的代码
109 |   final int index;
110 | 
111 |   ItemModel(this.index);
112 | }
113 | 


--------------------------------------------------------------------------------
/lib/widget/sliver_tab/sliver_tab_child_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/custom_sliver/custom_sliver.dart';
 3 | import 'package:gsy_flutter_demo/widget/sliver_tab/sliver_tab_sliver.dart';
 4 | 
 5 | class SliverTabChildPage extends StatefulWidget {
 6 |   final List pageList;
 7 |   final int tabIndex;
 8 | 
 9 |   const SliverTabChildPage(this.tabIndex, this.pageList, {super.key});
10 | 
11 |   @override
12 |   SliverTabChildPageState createState() => SliverTabChildPageState();
13 | }
14 | 
15 | class SliverTabChildPageState extends State<SliverTabChildPage>
16 |     with AutomaticKeepAliveClientMixin {
17 |   GlobalKey<CustomSliverState> globalKey = GlobalKey();
18 | 
19 |   double initLayoutExtent = 100;
20 |   double showPullDistance = 150;
21 |   final double indicatorExtent = 200;
22 |   final double triggerPullDistance = 300;
23 |   final ScrollController scrollController =
24 |       ScrollController(initialScrollOffset: -100);
25 | 
26 |   renderListByIndex(tabIndex, pageList) {
27 |     return CustomScrollView(
28 |       controller: scrollController,
29 |       physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
30 |       slivers: <Widget>[
31 |         SliverTabSliver(
32 |           key: globalKey,
33 |           initLayoutExtent: initLayoutExtent,
34 |           containerExtent: indicatorExtent,
35 |           triggerPullDistance: triggerPullDistance,
36 |           pinned: false,
37 |         ),
38 |         SliverPadding(
39 |           padding: const EdgeInsets.all(10.0),
40 |           sliver: SliverFixedExtentList(
41 |             itemExtent: 50.0, //item高度或宽度,取决于滑动方向
42 |             delegate: SliverChildBuilderDelegate(
43 |               (BuildContext context, int index) {
44 |                 return ListTile(
45 |                   title: Text('Tab $tabIndex Item $index'),
46 |                 );
47 |               },
48 |               childCount: pageList.length,
49 |             ),
50 |           ),
51 |         ),
52 |       ],
53 |     );
54 |   }
55 | 
56 |   @override
57 |   bool get wantKeepAlive => false;
58 | 
59 |   @override
60 |   Widget build(BuildContext context) {
61 |     super.build(context);
62 |     return renderListByIndex(widget.tabIndex, widget.pageList);
63 |   }
64 | }
65 | 


--------------------------------------------------------------------------------
/lib/widget/statusbar_demo_page.dart:
--------------------------------------------------------------------------------
  1 | import 'package:flutter/material.dart';
  2 | import 'package:flutter/services.dart';
  3 | 
  4 | ///状态栏颜色
  5 | class StatusBarDemoPage extends StatefulWidget {
  6 |   const StatusBarDemoPage({super.key});
  7 | 
  8 |   @override
  9 |   _StatusBarDemoPageState createState() => _StatusBarDemoPageState();
 10 | }
 11 | 
 12 | class _StatusBarDemoPageState extends State<StatusBarDemoPage> {
 13 |   bool customSystemUIOverlayStyle = false;
 14 | 
 15 |   @override
 16 |   Widget build(BuildContext context) {
 17 |     var body = getBody();
 18 |     ///如果手动设置过状态栏,就不可以用 AnnotatedRegion ,会影响
 19 |     if (customSystemUIOverlayStyle) {
 20 |       return body;
 21 |     }
 22 |     ///如果没有手动设置过状态栏,就可以用 AnnotatedRegion 直接嵌套显示
 23 |     return AnnotatedRegion<SystemUiOverlayStyle>(
 24 |       value: SystemUiOverlayStyle.dark,
 25 |       child: body,
 26 |     );
 27 |   }
 28 | 
 29 |   getBody() {
 30 |     return Scaffold(
 31 |       appBar: const ImageAppBar(),
 32 |       body: Center(
 33 |         child: Row(
 34 |           mainAxisAlignment: MainAxisAlignment.center,
 35 |           crossAxisAlignment: CrossAxisAlignment.center,
 36 |           children: <Widget>[
 37 |             TextButton(
 38 |               onPressed: () {
 39 |                 ///手动修改
 40 |                 setState(() {
 41 |                   customSystemUIOverlayStyle = true;
 42 |                 });
 43 |                 SystemChrome.setSystemUIOverlayStyle(
 44 |                     SystemUiOverlayStyle.light);
 45 |               },
 46 |               style: ButtonStyle(
 47 |                 backgroundColor: ButtonStyleButton.allOrNull<Color>(
 48 |                   Colors.yellowAccent,
 49 |                 ),
 50 |               ),
 51 |               child: const Text("Light"),
 52 |             ),
 53 |             const SizedBox(
 54 |               width: 10,
 55 |             ),
 56 |             TextButton(
 57 |               onPressed: () {
 58 |                 setState(() {
 59 |                   customSystemUIOverlayStyle = true;
 60 |                 });
 61 |                 SystemChrome.setSystemUIOverlayStyle(
 62 |                     SystemUiOverlayStyle.dark);
 63 |               },
 64 |               style: ButtonStyle(
 65 |                 backgroundColor: ButtonStyleButton.allOrNull<Color>(
 66 |                   Colors.greenAccent,
 67 |                 ),
 68 |               ),
 69 |               child: const Text("Dart"),
 70 |             ),
 71 |           ],
 72 |         ),
 73 |       ),
 74 |     );
 75 |   }
 76 | }
 77 | 
 78 | ///自定义 PreferredSizeWidget 做 AppBar
 79 | class ImageAppBar extends StatelessWidget implements PreferredSizeWidget {
 80 |   const ImageAppBar({super.key});
 81 | 
 82 |   @override
 83 |   Widget build(BuildContext context) {
 84 |     return Stack(
 85 |       children: <Widget>[
 86 |         Image.asset(
 87 |           "static/gsy_cat.png",
 88 |           fit: BoxFit.cover,
 89 |           width: MediaQuery.sizeOf(context).width,
 90 |           height: kToolbarHeight * 3,
 91 |         ),
 92 |         SafeArea(
 93 |           child: IconButton(
 94 |               color: Colors.white,
 95 |               icon: const Icon(Icons.arrow_back_ios),
 96 |               onPressed: () {
 97 |                 Navigator.of(context).pop();
 98 |               }),
 99 |         )
100 |       ],
101 |     );
102 |   }
103 | 
104 |   @override
105 |   Size get preferredSize => const Size.fromHeight(kToolbarHeight * 3);
106 | }
107 | 


--------------------------------------------------------------------------------
/lib/widget/stick/stick_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/foundation.dart';
 2 | import 'package:flutter/material.dart';
 3 | import 'package:gsy_flutter_demo/widget/stick/stick_widget.dart';
 4 | 
 5 | class StickDemoPage extends StatefulWidget {
 6 |   const StickDemoPage({super.key});
 7 | 
 8 |   @override
 9 |   _StickDemoPageState createState() => _StickDemoPageState();
10 | }
11 | 
12 | class _StickDemoPageState extends State<StickDemoPage> {
13 |   @override
14 |   Widget build(_) {
15 |     return Scaffold(
16 |       appBar: AppBar(
17 |         title: const Text("StickDemoPage"),
18 |       ),
19 |       body: ListView.builder(
20 |           physics: const AlwaysScrollableScrollPhysics(),
21 |           itemCount: 100,
22 |           itemBuilder: (context, index) {
23 |             return Container(
24 |               height: 200,
25 |               color: Colors.deepOrange,
26 |               child: StickWidget(
27 |                 ///header
28 |                 stickHeader: Container(
29 |                   height: 50.0,
30 |                   color: Colors.deepPurple,
31 |                   padding: const EdgeInsets.only(left: 10.0),
32 |                   alignment: Alignment.centerLeft,
33 |                   child: InkWell(
34 |                     onTap: () {
35 |                       if (kDebugMode) {
36 |                         print("header");
37 |                       }
38 |                     },
39 |                     child: Text(
40 |                       '我的 $index 头啊',
41 |                       style: const TextStyle(color: Colors.white),
42 |                     ),
43 |                   ),
44 |                 ),
45 | 
46 |                 ///content
47 |                 stickContent: InkWell(
48 |                   onTap: () {
49 |                     if (kDebugMode) {
50 |                       print("content");
51 |                     }
52 |                   },
53 |                   child: Container(
54 |                     margin: const EdgeInsets.only(left: 10),
55 |                     color: Colors.pinkAccent,
56 |                     height: 150,
57 |                     child: Center(
58 |                       child: Text(
59 |                         '我的$index 内容 啊',
60 |                         style: const TextStyle(color: Colors.white),
61 |                       ),
62 |                     ),
63 |                   ),
64 |                 ),
65 |               ),
66 |             );
67 |           }),
68 |     );
69 |   }
70 | }
71 | 


--------------------------------------------------------------------------------
/lib/widget/stick/stick_widget.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/stick/stick_render.dart';
 3 | 
 4 | class StickWidget extends MultiChildRenderObjectWidget {
 5 |   ///顺序添加 stickHeader 和 stickContent
 6 |   StickWidget({super.key, 
 7 |     required stickHeader,
 8 |     required stickContent,
 9 |   }) : super(
10 |           ///如果反过来,会有意想不到的效果哦
11 |           children: [stickContent, stickHeader],
12 |         );
13 | 
14 |   @override
15 |   StickRender createRenderObject(BuildContext context) {
16 |     ///传入 ScrollableState
17 |     return StickRender(scrollable: Scrollable.of(context));
18 |   }
19 | 
20 |   @override
21 |   void updateRenderObject(BuildContext context, StickRender renderObject) {
22 |     renderObject.scrollable = Scrollable.of(context);
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/lib/widget/tag_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class TagDemoPage extends StatelessWidget {
 4 |   const TagDemoPage({super.key});
 5 | 
 6 |   @override
 7 |   Widget build(BuildContext context) {
 8 |     return Scaffold(
 9 |       appBar: AppBar(
10 |         title: const Text("TagDemoPage"),
11 |       ),
12 |       body: Wrap(children: <Widget>[
13 |         const TagItem("Start"),
14 |         for (var item in tags) TagItem(item),
15 |         const TagItem("End"),
16 |       ]),
17 |     );
18 |   }
19 | }
20 | 
21 | class TagItem extends StatelessWidget {
22 |   final String text;
23 | 
24 |   const TagItem(this.text, {super.key});
25 | 
26 |   @override
27 |   Widget build(BuildContext context) {
28 |     return Container(
29 |       padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 5),
30 |       margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
31 |       decoration: BoxDecoration(
32 |           color: Colors.blueAccent.withAlpha(60),
33 |           borderRadius: const BorderRadius.all(Radius.circular(5))),
34 |       child: Text(text),
35 |     );
36 |   }
37 | }
38 | 
39 | const List<String> tags = [
40 |   "FFFFFFF",
41 |   "TTTTTT",
42 |   "LL",
43 |   "JJJJJJJJ",
44 |   "PPPPP",
45 |   "OOOOOOOOOOOO",
46 |   "9999999",
47 |   "*&",
48 |   "5%%%%%",
49 |   "¥¥¥¥¥¥",
50 |   "UUUUUUUUUU",
51 |   "))@@@@@@"
52 | ];
53 | 


--------------------------------------------------------------------------------
/lib/widget/test_center_sliver/test_center_sliver_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | import 'package:gsy_flutter_demo/widget/test_center_sliver/test_center_sliver.dart';
 3 | 
 4 | 
 5 | class TestCenterSliverPage extends StatefulWidget {
 6 |   const TestCenterSliverPage({super.key});
 7 | 
 8 |   @override
 9 |   TestCenterSliverPageState createState() => TestCenterSliverPageState();
10 | }
11 | 
12 | class TestCenterSliverPageState extends State<TestCenterSliverPage> {
13 | 
14 | 
15 |   @override
16 |   Widget build(BuildContext context) {
17 |     return Scaffold(
18 |       appBar: AppBar(
19 |         title: const Text("TestCenterSliverPage"),
20 |       ),
21 |       body: const CustomScrollView(
22 |           anchor: 0.5,
23 |           ///回弹效果
24 |           physics: BouncingScrollPhysics(
25 |               parent: AlwaysScrollableScrollPhysics()),
26 |           slivers: <Widget>[
27 |             TestCenterSliver(
28 |               initLayoutExtent: 100,
29 |               containerExtent: 100,
30 |               triggerPullDistance: 100,
31 |               pinned: false,
32 |             ),
33 | 
34 |           ],
35 |         ),
36 |     );
37 |   }
38 | }
39 | 


--------------------------------------------------------------------------------
/lib/widget/text_line_height_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | /// Text 行间距的设置方案
 4 | /// 因为 Flutter 没有 Line Space ,只有字体权重
 5 | /// 这里利用了 fontSize 和 leading 的特性去模拟行高
 6 | class TextLineHeightDemoPage extends StatelessWidget {
 7 | 
 8 |   final double leading = 0.9;
 9 | 
10 |   final double fontSize = 16;
11 | 
12 |   const TextLineHeightDemoPage({super.key});
13 | 
14 |   @override
15 |   Widget build(BuildContext context) {
16 |     return Scaffold(
17 |       appBar: AppBar(
18 |         title: const Text("TextLineHeightDemoPage"),
19 |       ),
20 |       body: Container(
21 |         color: Colors.blueGrey,
22 |         margin: const EdgeInsets.all(20),
23 | 
24 |         ///利用 Transform 偏移将对应权重部分位置
25 |         child: Transform.translate(
26 |           offset: Offset(0, -fontSize * leading / 2),
27 |           child: Text(
28 |             textContent,
29 |             strutStyle:
30 |                 StrutStyle(forceStrutHeight: true, height: 1, leading: leading),
31 |             style: TextStyle(
32 |                 fontSize: fontSize,
33 |                 color: Colors.black,
34 |                 //backgroundColor: Colors.greenAccent),
35 |                 ),
36 |           ),
37 |         ),
38 |       ),
39 |     );
40 |   }
41 | }
42 | 
43 | const textContent =
44 |     "Today I was amazed to see the usually positive and friendly VueJS community descend into a bitter war. Two weeks ago Vue creator Evan You released a Request for Comment (RFC) for a new function-based way of writing Vue components in the upcoming Vue 3.0. Today a critical "
45 |     "Reddit thread followed by similarly "
46 |     "critical comments in a Hacker News thread caused a "
47 |     "flood of developers to flock to the original RFC to "
48 |     "voice their outrage, some of which were borderline abusive. "
49 |     "It was claimed in various places that";
50 | 


--------------------------------------------------------------------------------
/lib/widget/text_size_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class TextSizeDemoPage extends StatefulWidget {
 4 |   const TextSizeDemoPage({super.key});
 5 | 
 6 |   @override
 7 |   _TextSizeDemoPageState createState() => _TextSizeDemoPageState();
 8 | }
 9 | 
10 | class _TextSizeDemoPageState extends State<TextSizeDemoPage> {
11 |   TextScaler textScaler = TextScaler.noScaling;
12 |   int scale = 1;
13 | 
14 |   @override
15 |   void initState() {
16 |     super.initState();
17 |   }
18 | 
19 |   @override
20 |   Widget build(BuildContext context) {
21 |     return MediaQuery(
22 |         data: MediaQueryData.fromView(
23 |                 WidgetsBinding.instance.platformDispatcher.views.first)
24 |             .copyWith(textScaler: textScaler),
25 |         child: Scaffold(
26 |           appBar: AppBar(
27 |             title: const Text("TextLineHeightDemoPage"),
28 |           ),
29 |           body: Stack(
30 |             children: <Widget>[
31 |               Container(
32 |                 color: Colors.blueGrey,
33 |                 margin: const EdgeInsets.all(20),
34 | 
35 |                 ///利用 Transform 偏移将对应权重部分位置
36 |                 child: const Text(
37 |                   textContent,
38 |                   style: TextStyle(color: Colors.black),
39 |                 ),
40 |               ),
41 |               Align(
42 |                 alignment: Alignment.bottomCenter,
43 |                 child: Padding(
44 |                   padding: const EdgeInsets.only(bottom: 50),
45 |                   child: Row(
46 |                     mainAxisAlignment: MainAxisAlignment.center,
47 |                     children: <Widget>[
48 |                       TextButton(
49 |                         onPressed: () {
50 |                           if (scale > 1) {
51 |                             setState(() {
52 |                               textScaler.scale(scale - 1);
53 |                               scale--;
54 |                             });
55 |                           }
56 |                         },
57 |                         style: TextButton.styleFrom(
58 |                             backgroundColor: Colors.redAccent),
59 |                         child: const Text("-"),
60 |                       ),
61 |                       const SizedBox(
62 |                         width: 10,
63 |                       ),
64 |                       TextButton(
65 |                         onPressed: () {
66 |                           setState(() {
67 |                             textScaler.scale(scale + 1);
68 |                             scale++;
69 |                           });
70 |                         },
71 |                         style: TextButton.styleFrom(
72 |                             backgroundColor: Colors.greenAccent),
73 |                         child: const Text("+"),
74 |                       )
75 |                     ],
76 |                   ),
77 |                 ),
78 |               )
79 |             ],
80 |           ),
81 |         ));
82 |   }
83 | }
84 | 
85 | const textContent =
86 |     "Today I was amazed to see the usually positive and friendly VueJS community descend into a bitter war. Two weeks ago Vue creator Evan You released a Request for Comment (RFC) for a new function-based way of writing Vue components in the upcoming Vue 3.0. Today a critical "
87 |     "Reddit thread followed by similarly "
88 |     "critical comments in a Hacker News thread caused a "
89 |     "flood of developers to flock to the original RFC to "
90 |     "voice their outrage, some of which were borderline abusive. "
91 |     "It was claimed in various places that";
92 | 


--------------------------------------------------------------------------------
/lib/widget/transform_demo_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | class TransformDemoPage extends StatelessWidget {
 4 |   const TransformDemoPage({super.key});
 5 | 
 6 | 
 7 |   ///头像
 8 |   getHeader(context) {
 9 |     ///向上偏移 -30 位置
10 |     return Transform.translate(
11 |       offset: const Offset(0, -30),
12 |       child: Container(
13 |         width: 72.0,
14 |         height: 72.0,
15 |         decoration: BoxDecoration(
16 |           ///阴影
17 |           boxShadow: [
18 |             BoxShadow(color: Theme.of(context).cardColor, blurRadius: 4.0)
19 |           ],
20 | 
21 |           ///形状
22 |           shape: BoxShape.circle,
23 | 
24 |           ///图片
25 |           image: const DecorationImage(
26 |             fit: BoxFit.cover,
27 |             image: AssetImage(
28 |               "static/gsy_cat.png",
29 |             ),
30 |           ),
31 |         ),
32 |       ),
33 |     );
34 | 
35 |     ///圆形头像还可以 CircleAvatar, ClipOval等实现
36 |   }
37 | 
38 |   @override
39 |   Widget build(BuildContext context) {
40 |     return Scaffold(
41 |       backgroundColor: Theme.of(context).primaryColorDark,
42 |       appBar: AppBar(
43 |         title: const Text("TransformDemoPage"),
44 |       ),
45 |       body: Container(
46 |         alignment: Alignment.center,
47 |         child: Card(
48 |           margin: const EdgeInsets.all(10),
49 |           child: Container(
50 |             height: 150,
51 |             padding: const EdgeInsets.all(10),
52 |             child: Column(
53 |               crossAxisAlignment: CrossAxisAlignment.center,
54 |               children: <Widget>[
55 |                 getHeader(context),
56 |                 const Text(
57 |                   "Flutter is Google's portable UI toolkit for crafting "
58 |                   "beautiful, natively compiled applications for mobile, "
59 |                   "web, and desktop from a single codebase. ",
60 |                   overflow: TextOverflow.ellipsis,
61 |                   softWrap: true,
62 |                   maxLines: 3,
63 |                   style: TextStyle(),
64 |                 )
65 |               ],
66 |             ),
67 |           ),
68 |         ),
69 |       ),
70 |     );
71 |   }
72 | }
73 | 


--------------------------------------------------------------------------------
/lib/widget/wrap_content_page.dart:
--------------------------------------------------------------------------------
 1 | import 'package:flutter/material.dart';
 2 | 
 3 | ///展示如何在 Flutter 里实现 WrapContent 的状态
 4 | class WrapContentPage extends StatelessWidget {
 5 |   const WrapContentPage({super.key});
 6 | 
 7 |   @override
 8 |   Widget build(BuildContext context) {
 9 |     return Scaffold(
10 |       appBar: AppBar(
11 |         title: const Text(
12 |           "WrapContentPage",
13 |         ),
14 |       ),
15 |       body: SingleChildScrollView(
16 |         child: Container(
17 |           constraints:
18 | 
19 |               ///关键就是 minHeight 和  double.infinity
20 |               ///这样就可以由内部 children 来支撑决定外部大小
21 |               const BoxConstraints(minHeight: 100, maxHeight: double.infinity),
22 |           child: Column(
23 |             ///min而不是max
24 |             mainAxisSize: MainAxisSize.min,
25 |             children: [
26 |               Container(
27 |                 ///关键就是 minHeight 和  double.infinity
28 |                 constraints: const BoxConstraints(
29 |                   minHeight: 100,
30 |                   maxHeight: double.infinity,
31 |                 ),
32 | 
33 |                 /// Stack 默认是 StackFit.loose, 需要内部一个固定的最大大小来支撑
34 |                 child: Stack(
35 |                   children: [
36 |                     Container(
37 |                       height: 400,
38 |                       color: Colors.yellow,
39 |                     ),
40 |                     Container(
41 |                       height: 50,
42 |                       color: Colors.red,
43 |                     ),
44 |                     Positioned(
45 |                       left: 0,
46 |                       right: 0,
47 |                       top: 0,
48 |                       child: Container(
49 |                         height: 56,
50 |                         alignment: Alignment.centerLeft,
51 |                         color: Colors.blueGrey,
52 |                         child: Container(
53 |                           width: 33,
54 |                           height: 33,
55 |                           color: Colors.black,
56 |                         ),
57 |                       ),
58 |                     ),
59 |                   ],
60 |                 ),
61 |               ),
62 |               Container(
63 |                 margin: const EdgeInsets.only(top: 20),
64 | 
65 |                 ///关键就是 minHeight 和  double.infinity
66 |                 constraints:
67 |                     const BoxConstraints(minHeight: 100, maxHeight: double.infinity),
68 |                 child: Column(
69 |                   mainAxisSize: MainAxisSize.min,
70 |                   children: [
71 |                     Container(
72 |                       height: 600,
73 |                       color: Colors.green,
74 |                     ),
75 |                     Container(
76 |                       height: 50,
77 |                       color: Colors.amber,
78 |                     ),
79 |                   ],
80 |                 ),
81 |               ),
82 |             ],
83 |           ),
84 |         ),
85 |       ),
86 |     );
87 |   }
88 | }
89 | 


--------------------------------------------------------------------------------
/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 | 


--------------------------------------------------------------------------------
/linux/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | # This file controls Flutter-level build steps. It should not be edited.
 2 | cmake_minimum_required(VERSION 3.10)
 3 | 
 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
 5 | 
 6 | # Configuration provided via flutter tool.
 7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
 8 | 
 9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 | 
12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...),
13 | # which isn't available in 3.10.
14 | function(list_prepend LIST_NAME PREFIX)
15 |     set(NEW_LIST "")
16 |     foreach(element ${${LIST_NAME}})
17 |         list(APPEND NEW_LIST "${PREFIX}${element}")
18 |     endforeach(element)
19 |     set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
20 | endfunction()
21 | 
22 | # === Flutter Library ===
23 | # System-level dependencies.
24 | find_package(PkgConfig REQUIRED)
25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
28 | 
29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
30 | 
31 | # Published to parent scope for install step.
32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
36 | 
37 | list(APPEND FLUTTER_LIBRARY_HEADERS
38 |   "fl_basic_message_channel.h"
39 |   "fl_binary_codec.h"
40 |   "fl_binary_messenger.h"
41 |   "fl_dart_project.h"
42 |   "fl_engine.h"
43 |   "fl_json_message_codec.h"
44 |   "fl_json_method_codec.h"
45 |   "fl_message_codec.h"
46 |   "fl_method_call.h"
47 |   "fl_method_channel.h"
48 |   "fl_method_codec.h"
49 |   "fl_method_response.h"
50 |   "fl_plugin_registrar.h"
51 |   "fl_plugin_registry.h"
52 |   "fl_standard_message_codec.h"
53 |   "fl_standard_method_codec.h"
54 |   "fl_string_codec.h"
55 |   "fl_value.h"
56 |   "fl_view.h"
57 |   "flutter_linux.h"
58 | )
59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
60 | add_library(flutter INTERFACE)
61 | target_include_directories(flutter INTERFACE
62 |   "${EPHEMERAL_DIR}"
63 | )
64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
65 | target_link_libraries(flutter INTERFACE
66 |   PkgConfig::GTK
67 |   PkgConfig::GLIB
68 |   PkgConfig::GIO
69 | )
70 | add_dependencies(flutter flutter_assemble)
71 | 
72 | # === Flutter tool backend ===
73 | # _phony_ is a non-existent file to force this command to run every time,
74 | # since currently there's no way to get a full input/output list from the
75 | # flutter tool.
76 | add_custom_command(
77 |   OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
78 |     ${CMAKE_CURRENT_BINARY_DIR}/_phony_
79 |   COMMAND ${CMAKE_COMMAND} -E env
80 |     ${FLUTTER_TOOL_ENVIRONMENT}
81 |     "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
82 |       ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
83 |   VERBATIM
84 | )
85 | add_custom_target(flutter_assemble DEPENDS
86 |   "${FLUTTER_LIBRARY}"
87 |   ${FLUTTER_LIBRARY_HEADERS}
88 | )
89 | 


--------------------------------------------------------------------------------
/linux/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
 1 | //
 2 | //  Generated file. Do not edit.
 3 | //
 4 | 
 5 | // clang-format off
 6 | 
 7 | #include "generated_plugin_registrant.h"
 8 | 
 9 | #include <rive_common/rive_plugin.h>
10 | 
11 | void fl_register_plugins(FlPluginRegistry* registry) {
12 |   g_autoptr(FlPluginRegistrar) rive_common_registrar =
13 |       fl_plugin_registry_get_registrar_for_plugin(registry, "RivePlugin");
14 |   rive_plugin_register_with_registrar(rive_common_registrar);
15 | }
16 | 


--------------------------------------------------------------------------------
/linux/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  Generated file. Do not edit.
 3 | //
 4 | 
 5 | // clang-format off
 6 | 
 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
 8 | #define GENERATED_PLUGIN_REGISTRANT_
 9 | 
10 | #include <flutter_linux/flutter_linux.h>
11 | 
12 | // Registers Flutter plugins.
13 | void fl_register_plugins(FlPluginRegistry* registry);
14 | 
15 | #endif  // GENERATED_PLUGIN_REGISTRANT_
16 | 


--------------------------------------------------------------------------------
/linux/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
 1 | #
 2 | # Generated file, do not edit.
 3 | #
 4 | 
 5 | list(APPEND FLUTTER_PLUGIN_LIST
 6 |   rive_common
 7 | )
 8 | 
 9 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
10 | )
11 | 
12 | set(PLUGIN_BUNDLED_LIBRARIES)
13 | 
14 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
15 |   add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
16 |   target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
17 |   list(APPEND PLUGIN_BUNDLED_LIBRARIES 
lt;TARGET_FILE:${plugin}_plugin>)
18 |   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
19 | endforeach(plugin)
20 | 
21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
22 |   add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
23 |   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
24 | endforeach(ffi_plugin)
25 | 


--------------------------------------------------------------------------------
/linux/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | cmake_minimum_required(VERSION 3.13)
 2 | project(runner LANGUAGES CXX)
 3 | 
 4 | # Define the application target. To change its name, change BINARY_NAME in the
 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
 6 | # work.
 7 | #
 8 | # Any new source files that you add to the application should be added here.
 9 | add_executable(${BINARY_NAME}
10 |   "main.cc"
11 |   "my_application.cc"
12 |   "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
13 | )
14 | 
15 | # Apply the standard set of build settings. This can be removed for applications
16 | # that need different build settings.
17 | apply_standard_settings(${BINARY_NAME})
18 | 
19 | # Add preprocessor definitions for the application ID.
20 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
21 | 
22 | # Add dependency libraries. Add any application-specific dependencies here.
23 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
24 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
25 | 
26 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
27 | 


--------------------------------------------------------------------------------
/linux/runner/main.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 | 
3 | int main(int argc, char** argv) {
4 |   g_autoptr(MyApplication) app = my_application_new();
5 |   return g_application_run(G_APPLICATION(app), argc, argv);
6 | }
7 | 


--------------------------------------------------------------------------------
/linux/runner/my_application.h:
--------------------------------------------------------------------------------
 1 | #ifndef FLUTTER_MY_APPLICATION_H_
 2 | #define FLUTTER_MY_APPLICATION_H_
 3 | 
 4 | #include <gtk/gtk.h>
 5 | 
 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
 7 |                      GtkApplication)
 8 | 
 9 | /**
10 |  * my_application_new:
11 |  *
12 |  * Creates a new Flutter-based application.
13 |  *
14 |  * Returns: a new #MyApplication.
15 |  */
16 | MyApplication* my_application_new();
17 | 
18 | #endif  // FLUTTER_MY_APPLICATION_H_
19 | 


--------------------------------------------------------------------------------
/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 | 
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 | 


--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 | 


--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 | 


--------------------------------------------------------------------------------
/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
 1 | //
 2 | //  Generated file. Do not edit.
 3 | //
 4 | 
 5 | import FlutterMacOS
 6 | import Foundation
 7 | 
 8 | import rive_common
 9 | 
10 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
11 |   RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin"))
12 | }
13 | 


--------------------------------------------------------------------------------
/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>IDEDidComputeMac32BitWarning</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Workspace
3 |    version = "1.0">
4 |    <FileRef
5 |       location = "group:Runner.xcodeproj">
6 |    </FileRef>
7 | </Workspace>
8 | 


--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>IDEDidComputeMac32BitWarning</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
 1 | import Cocoa
 2 | import FlutterMacOS
 3 | 
 4 | @main
 5 | class AppDelegate: FlutterAppDelegate {
 6 |   override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
 7 |     return true
 8 |   }
 9 | 
10 |   override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
11 |     return true
12 |   }
13 | }
14 | 


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "size" : "16x16",
 5 |       "idiom" : "mac",
 6 |       "filename" : "app_icon_16.png",
 7 |       "scale" : "1x"
 8 |     },
 9 |     {
10 |       "size" : "16x16",
11 |       "idiom" : "mac",
12 |       "filename" : "app_icon_32.png",
13 |       "scale" : "2x"
14 |     },
15 |     {
16 |       "size" : "32x32",
17 |       "idiom" : "mac",
18 |       "filename" : "app_icon_32.png",
19 |       "scale" : "1x"
20 |     },
21 |     {
22 |       "size" : "32x32",
23 |       "idiom" : "mac",
24 |       "filename" : "app_icon_64.png",
25 |       "scale" : "2x"
26 |     },
27 |     {
28 |       "size" : "128x128",
29 |       "idiom" : "mac",
30 |       "filename" : "app_icon_128.png",
31 |       "scale" : "1x"
32 |     },
33 |     {
34 |       "size" : "128x128",
35 |       "idiom" : "mac",
36 |       "filename" : "app_icon_256.png",
37 |       "scale" : "2x"
38 |     },
39 |     {
40 |       "size" : "256x256",
41 |       "idiom" : "mac",
42 |       "filename" : "app_icon_256.png",
43 |       "scale" : "1x"
44 |     },
45 |     {
46 |       "size" : "256x256",
47 |       "idiom" : "mac",
48 |       "filename" : "app_icon_512.png",
49 |       "scale" : "2x"
50 |     },
51 |     {
52 |       "size" : "512x512",
53 |       "idiom" : "mac",
54 |       "filename" : "app_icon_512.png",
55 |       "scale" : "1x"
56 |     },
57 |     {
58 |       "size" : "512x512",
59 |       "idiom" : "mac",
60 |       "filename" : "app_icon_1024.png",
61 |       "scale" : "2x"
62 |     }
63 |   ],
64 |   "info" : {
65 |     "version" : 1,
66 |     "author" : "xcode"
67 |   }
68 | }
69 | 


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png


--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png


--------------------------------------------------------------------------------
/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
 1 | // Application-level settings for the Runner target.
 2 | //
 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
 4 | // future. If not, the values below would default to using the project name when this becomes a
 5 | // 'flutter create' template.
 6 | 
 7 | // The application's name. By default this is also the title of the Flutter window.
 8 | PRODUCT_NAME = gsy_flutter_demo
 9 | 
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.gsy.shuyu.gsyFlutterDemo
12 | 
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2025 com.gsy.shuyu. All rights reserved.
15 | 


--------------------------------------------------------------------------------
/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 | 


--------------------------------------------------------------------------------
/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 | 


--------------------------------------------------------------------------------
/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
 2 | GCC_WARN_UNDECLARED_SELECTOR = YES
 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
 6 | CLANG_WARN_PRAGMA_PACK = YES
 7 | CLANG_WARN_STRICT_PROTOTYPES = YES
 8 | CLANG_WARN_COMMA = YES
 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 | 


--------------------------------------------------------------------------------
/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 | 	<key>com.apple.security.app-sandbox</key>
 6 | 	<true/>
 7 | 	<key>com.apple.security.cs.allow-jit</key>
 8 | 	<true/>
 9 | 	<key>com.apple.security.network.server</key>
10 | 	<true/>
11 | </dict>
12 | </plist>
13 | 


--------------------------------------------------------------------------------
/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 | 	<key>CFBundleDevelopmentRegion</key>
 6 | 	<string>$(DEVELOPMENT_LANGUAGE)</string>
 7 | 	<key>CFBundleExecutable</key>
 8 | 	<string>$(EXECUTABLE_NAME)</string>
 9 | 	<key>CFBundleIconFile</key>
10 | 	<string></string>
11 | 	<key>CFBundleIdentifier</key>
12 | 	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13 | 	<key>CFBundleInfoDictionaryVersion</key>
14 | 	<string>6.0</string>
15 | 	<key>CFBundleName</key>
16 | 	<string>$(PRODUCT_NAME)</string>
17 | 	<key>CFBundlePackageType</key>
18 | 	<string>APPL</string>
19 | 	<key>CFBundleShortVersionString</key>
20 | 	<string>$(FLUTTER_BUILD_NAME)</string>
21 | 	<key>CFBundleVersion</key>
22 | 	<string>$(FLUTTER_BUILD_NUMBER)</string>
23 | 	<key>LSMinimumSystemVersion</key>
24 | 	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
25 | 	<key>NSHumanReadableCopyright</key>
26 | 	<string>$(PRODUCT_COPYRIGHT)</string>
27 | 	<key>NSMainNibFile</key>
28 | 	<string>MainMenu</string>
29 | 	<key>NSPrincipalClass</key>
30 | 	<string>NSApplication</string>
31 | </dict>
32 | </plist>
33 | 


--------------------------------------------------------------------------------
/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
 1 | import Cocoa
 2 | import FlutterMacOS
 3 | 
 4 | class MainFlutterWindow: NSWindow {
 5 |   override func awakeFromNib() {
 6 |     let flutterViewController = FlutterViewController()
 7 |     let windowFrame = self.frame
 8 |     self.contentViewController = flutterViewController
 9 |     self.setFrame(windowFrame, display: true)
10 | 
11 |     RegisterGeneratedPlugins(registry: flutterViewController)
12 | 
13 |     super.awakeFromNib()
14 |   }
15 | }
16 | 


--------------------------------------------------------------------------------
/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>com.apple.security.app-sandbox</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/macos/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
 1 | import Cocoa
 2 | import FlutterMacOS
 3 | import XCTest
 4 | 
 5 | class RunnerTests: XCTestCase {
 6 | 
 7 |   func testExample() {
 8 |     // If you add code to the Runner application, consider adding tests here.
 9 |     // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 |   }
11 | 
12 | }
13 | 


--------------------------------------------------------------------------------
/privacy.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/privacy.html


--------------------------------------------------------------------------------
/shaders/liquid_glass.frag:
--------------------------------------------------------------------------------
 1 | #version 460 core
 2 | #include <flutter/runtime_effect.glsl>
 3 | 
 4 | //
 5 | // ========================= 核心修正 =========================
 6 | //
 7 | // 明确声明片段着色器的输出变量。这是必需的。
 8 | out vec4 fragColor;
 9 | //
10 | // ==========================================================
11 | //
12 | 
13 | // 输入变量,由 Flutter 的 Dart 代码传入
14 | uniform vec2 uResolution; // 画面分辨率 (宽, 高)
15 | uniform vec4 uMouse;      // 鼠标/触摸位置 (x, y, z, w),z > 0 表示按下
16 | uniform sampler2D uTexture; // 输入的纹理 (iChannel0)
17 | 
18 | // 全局宏定义
19 | #define R uResolution.xy
20 | #define PI 3.14159265
21 | #define S smoothstep
22 | #define PX(a) a/R.y
23 | 
24 | // 旋转矩阵
25 | mat2 Rot(float a) {
26 |     return mat2(cos(a), -sin(a), sin(a), cos(a));
27 | }
28 | 
29 | // 矩形距离函数
30 | float Box(vec2 p, vec2 b) {
31 |     vec2 d = abs(p) - b;
32 |     return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
33 | }
34 | 
35 | // “照片”图标的形状
36 | float IconPhoto(vec2 uv) {
37 |     float c = 0.0;
38 |     for (float i = 0.0; i < 1.0; i += 1.0/8.0) {
39 |         vec2 u = uv;
40 |         u *= Rot(i * 2.0 * PI);
41 |         u += vec2(0.0, PX(40.0));
42 |         float b = Box(u, vec2(PX(0.0), PX(13.0)));
43 |         c += S(PX(1.5), 0.0, b - PX(15.0)) * 0.2;
44 | }
45 | return c;
46 | }
47 | 
48 | // 液态玻璃模糊效果
49 | vec4 LiquidGlass(sampler2D tex, vec2 uv, float direction, float quality, float size) {
50 |     vec2 radius = size / R;
51 |     vec4 color = texture(tex, uv);
52 | 
53 |     for (float d = 0.0; d < PI; d += PI / direction) {
54 |         for (float i = 1.0 / quality; i <= 1.0; i += 1.0 / quality) {
55 |             color += texture(tex, uv + vec2(cos(d), sin(d)) * radius * i);
56 |         }
57 |     }
58 | 
59 |     color /= (quality * direction + 1.0); // +1.0 for the initial color
60 |     return color;
61 | }
62 | 
63 | // 主图标逻辑
64 | vec4 Icon(vec2 uv) {
65 |     float box = Box(uv, vec2(PX(50.0)));
66 |     float boxShape = S(PX(1.5), 0.0, box - PX(50.0));
67 | float boxDisp = S(PX(35.0), 0.0, box - PX(25.0));
68 | float boxLight = boxShape * S(0.0, PX(30.0), box - PX(40.0));
69 | float icon = IconPhoto(uv);
70 | return vec4(boxShape, boxDisp, boxLight, icon);
71 | }
72 | 
73 | // Flutter 的主函数
74 | void main() {
75 |     vec2 uv = FlutterFragCoord().xy / uResolution.xy;
76 |     vec2 st = (FlutterFragCoord().xy - 0.5 * R) / R.y;
77 |     vec2 M = uMouse.z > 0.0 ? (uMouse.xy - 0.5 * R) / R.y : vec2(0.0);
78 | 
79 |     vec4 icon = Icon(st - M);
80 | 
81 |     vec2 uv2 = uv - uMouse.xy / R;
82 |     uv2 *= 0.5 + 0.5 * S(0.5, 1.0, icon.y);
83 |     uv2 += uMouse.xy / R;
84 | 
85 |     vec3 col = mix(
86 |     texture(uTexture, uv).rgb * 0.8,
87 |     0.2 + LiquidGlass(uTexture, uv2, 10.0, 10.0, 20.0).rgb * 0.7,
88 |     icon.x
89 |     );
90 |     col += icon.z * 0.9 + icon.w;
91 | 
92 |     col *= 1.0 - 0.2 * S(PX(80.0), 0.0, Box(st - M + vec2(0.0, PX(40.0)), vec2(PX(50.0))));
93 | 
94 | // 输出最终颜色 (现在这行代码可以正确工作了)
95 | fragColor = vec4(col, 1.0);
96 | }


--------------------------------------------------------------------------------
/static/card_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/card_down.png


--------------------------------------------------------------------------------
/static/card_down_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/card_down_2.png


--------------------------------------------------------------------------------
/static/card_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/card_up.png


--------------------------------------------------------------------------------
/static/card_up_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/card_up_2.png


--------------------------------------------------------------------------------
/static/gsy_cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/gsy_cat.png


--------------------------------------------------------------------------------
/static/iOS26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/iOS26.png


--------------------------------------------------------------------------------
/static/juejin.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/juejin.riv


--------------------------------------------------------------------------------
/static/person.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/person.jpg


--------------------------------------------------------------------------------
/static/test.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/test.jpeg


--------------------------------------------------------------------------------
/static/test_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/static/test_logo.png


--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
 1 | // This is a basic Flutter widget test.
 2 | //
 3 | // To perform an interaction with a widget in your test, use the WidgetTester
 4 | // utility that Flutter provides. For example, you can send tap and scroll
 5 | // gestures. You can also use WidgetTester to find child widgets in the widget
 6 | // tree, read text, and verify that the values of widget properties are correct.
 7 | 
 8 | import 'package:flutter/material.dart';
 9 | import 'package:flutter_test/flutter_test.dart';
10 | 
11 | import 'package:gsy_flutter_demo/main.dart';
12 | 
13 | void main() {
14 |   testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 |     // Build our app and trigger a frame.
16 |     await tester.pumpWidget(const MyApp());
17 | 
18 |     // Verify that our counter starts at 0.
19 |     expect(find.text('0'), findsOneWidget);
20 |     expect(find.text('1'), findsNothing);
21 | 
22 |     // Tap the '+' icon and trigger a frame.
23 |     await tester.tap(find.byIcon(Icons.add));
24 |     await tester.pump();
25 | 
26 |     // Verify that our counter has incremented.
27 |     expect(find.text('0'), findsNothing);
28 |     expect(find.text('1'), findsOneWidget);
29 |   });
30 | }
31 | 


--------------------------------------------------------------------------------
/thanks.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/thanks.jpg


--------------------------------------------------------------------------------
/web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/web.jpg


--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/web/favicon.png


--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/web/icons/Icon-192.png


--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/web/icons/Icon-512.png


--------------------------------------------------------------------------------
/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/web/icons/Icon-maskable-192.png


--------------------------------------------------------------------------------
/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/web/icons/Icon-maskable-512.png


--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html>
 3 | <head>
 4 |   <meta charset="UTF-8">
 5 |   <title>gsy_flutter_demo</title>
 6 |   <style>
 7 |     .loading {
 8 |       display: flex;
 9 |       justify-content: center;
10 |       align-items: center;
11 |       margin: 0;
12 |       position: absolute;
13 |       top: 50%;
14 |       left: 50%;
15 |       -ms-transform: translate(-50%, -50%);
16 |       transform: translate(-50%, -50%);
17 |     }
18 | 
19 |     .loader {
20 |       border: 16px solid #f3f3f3;
21 |       border-radius: 50%;
22 |       border: 15px solid ;
23 |       border-top: 16px solid blue;
24 |       border-right: 16px solid white;
25 |       border-bottom: 16px solid blue;
26 |       border-left: 16px solid white;
27 |       width: 120px;
28 |       height: 120px;
29 |       -webkit-animation: spin 2s linear infinite;
30 |       animation: spin 2s linear infinite;
31 |     }
32 | 
33 |     @-webkit-keyframes spin {
34 |       0% {
35 |         -webkit-transform: rotate(0deg);
36 |       }
37 |       100% {
38 |         -webkit-transform: rotate(360deg);
39 |       }
40 |     }
41 | 
42 |     @keyframes spin {
43 |       0% {
44 |         transform: rotate(0deg);
45 |       }
46 |       100% {
47 |         transform: rotate(360deg);
48 |       }
49 |     }
50 |   </style>
51 | </head>
52 | <body>
53 |   <div class="loading">
54 |     <div class="loader"></div>
55 |   </div>
56 |   <script src="main.dart.js" type="application/javascript"></script>
57 | </body>
58 | </html>
59 | 


--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
 1 | {
 2 |     "name": "gsy_flutter_demo",
 3 |     "short_name": "gsy_flutter_demo",
 4 |     "start_url": ".",
 5 |     "display": "standalone",
 6 |     "background_color": "#0175C2",
 7 |     "theme_color": "#0175C2",
 8 |     "description": "A new Flutter project.",
 9 |     "orientation": "portrait-primary",
10 |     "prefer_related_applications": false,
11 |     "icons": [
12 |         {
13 |             "src": "icons/Icon-192.png",
14 |             "sizes": "192x192",
15 |             "type": "image/png"
16 |         },
17 |         {
18 |             "src": "icons/Icon-512.png",
19 |             "sizes": "512x512",
20 |             "type": "image/png"
21 |         },
22 |         {
23 |             "src": "icons/Icon-maskable-192.png",
24 |             "sizes": "192x192",
25 |             "type": "image/png",
26 |             "purpose": "maskable"
27 |         },
28 |         {
29 |             "src": "icons/Icon-maskable-512.png",
30 |             "sizes": "512x512",
31 |             "type": "image/png",
32 |             "purpose": "maskable"
33 |         }
34 |     ]
35 | }
36 | 


--------------------------------------------------------------------------------
/windows/.gitignore:
--------------------------------------------------------------------------------
 1 | flutter/ephemeral/
 2 | 
 3 | # Visual Studio user-specific files.
 4 | *.suo
 5 | *.user
 6 | *.userosscache
 7 | *.sln.docstates
 8 | 
 9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 | 
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 | 


--------------------------------------------------------------------------------
/windows/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
 1 | //
 2 | //  Generated file. Do not edit.
 3 | //
 4 | 
 5 | // clang-format off
 6 | 
 7 | #include "generated_plugin_registrant.h"
 8 | 
 9 | #include <rive_common/rive_plugin.h>
10 | 
11 | void RegisterPlugins(flutter::PluginRegistry* registry) {
12 |   RivePluginRegisterWithRegistrar(
13 |       registry->GetRegistrarForPlugin("RivePlugin"));
14 | }
15 | 


--------------------------------------------------------------------------------
/windows/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  Generated file. Do not edit.
 3 | //
 4 | 
 5 | // clang-format off
 6 | 
 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
 8 | #define GENERATED_PLUGIN_REGISTRANT_
 9 | 
10 | #include <flutter/plugin_registry.h>
11 | 
12 | // Registers Flutter plugins.
13 | void RegisterPlugins(flutter::PluginRegistry* registry);
14 | 
15 | #endif  // GENERATED_PLUGIN_REGISTRANT_
16 | 


--------------------------------------------------------------------------------
/windows/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
 1 | #
 2 | # Generated file, do not edit.
 3 | #
 4 | 
 5 | list(APPEND FLUTTER_PLUGIN_LIST
 6 |   rive_common
 7 | )
 8 | 
 9 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
10 | )
11 | 
12 | set(PLUGIN_BUNDLED_LIBRARIES)
13 | 
14 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
15 |   add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
16 |   target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
17 |   list(APPEND PLUGIN_BUNDLED_LIBRARIES 
lt;TARGET_FILE:${plugin}_plugin>)
18 |   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
19 | endforeach(plugin)
20 | 
21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
22 |   add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
23 |   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
24 | endforeach(ffi_plugin)
25 | 


--------------------------------------------------------------------------------
/windows/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | cmake_minimum_required(VERSION 3.14)
 2 | project(runner LANGUAGES CXX)
 3 | 
 4 | # Define the application target. To change its name, change BINARY_NAME in the
 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
 6 | # work.
 7 | #
 8 | # Any new source files that you add to the application should be added here.
 9 | add_executable(${BINARY_NAME} WIN32
10 |   "flutter_window.cpp"
11 |   "main.cpp"
12 |   "utils.cpp"
13 |   "win32_window.cpp"
14 |   "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
15 |   "Runner.rc"
16 |   "runner.exe.manifest"
17 | )
18 | 
19 | # Apply the standard set of build settings. This can be removed for applications
20 | # that need different build settings.
21 | apply_standard_settings(${BINARY_NAME})
22 | 
23 | # Add preprocessor definitions for the build version.
24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
29 | 
30 | # Disable Windows macros that collide with C++ standard library functions.
31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
32 | 
33 | # Add dependency libraries and include directories. Add any application-specific
34 | # dependencies here.
35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
38 | 
39 | # Run the Flutter tool portions of the build. This must not be removed.
40 | add_dependencies(${BINARY_NAME} flutter_assemble)
41 | 


--------------------------------------------------------------------------------
/windows/runner/flutter_window.cpp:
--------------------------------------------------------------------------------
 1 | #include "flutter_window.h"
 2 | 
 3 | #include <optional>
 4 | 
 5 | #include "flutter/generated_plugin_registrant.h"
 6 | 
 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project)
 8 |     : project_(project) {}
 9 | 
10 | FlutterWindow::~FlutterWindow() {}
11 | 
12 | bool FlutterWindow::OnCreate() {
13 |   if (!Win32Window::OnCreate()) {
14 |     return false;
15 |   }
16 | 
17 |   RECT frame = GetClientArea();
18 | 
19 |   // The size here must match the window dimensions to avoid unnecessary surface
20 |   // creation / destruction in the startup path.
21 |   flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
22 |       frame.right - frame.left, frame.bottom - frame.top, project_);
23 |   // Ensure that basic setup of the controller was successful.
24 |   if (!flutter_controller_->engine() || !flutter_controller_->view()) {
25 |     return false;
26 |   }
27 |   RegisterPlugins(flutter_controller_->engine());
28 |   SetChildContent(flutter_controller_->view()->GetNativeWindow());
29 | 
30 |   flutter_controller_->engine()->SetNextFrameCallback([&]() {
31 |     this->Show();
32 |   });
33 | 
34 |   // Flutter can complete the first frame before the "show window" callback is
35 |   // registered. The following call ensures a frame is pending to ensure the
36 |   // window is shown. It is a no-op if the first frame hasn't completed yet.
37 |   flutter_controller_->ForceRedraw();
38 | 
39 |   return true;
40 | }
41 | 
42 | void FlutterWindow::OnDestroy() {
43 |   if (flutter_controller_) {
44 |     flutter_controller_ = nullptr;
45 |   }
46 | 
47 |   Win32Window::OnDestroy();
48 | }
49 | 
50 | LRESULT
51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
52 |                               WPARAM const wparam,
53 |                               LPARAM const lparam) noexcept {
54 |   // Give Flutter, including plugins, an opportunity to handle window messages.
55 |   if (flutter_controller_) {
56 |     std::optional<LRESULT> result =
57 |         flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
58 |                                                       lparam);
59 |     if (result) {
60 |       return *result;
61 |     }
62 |   }
63 | 
64 |   switch (message) {
65 |     case WM_FONTCHANGE:
66 |       flutter_controller_->engine()->ReloadSystemFonts();
67 |       break;
68 |   }
69 | 
70 |   return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
71 | }
72 | 


--------------------------------------------------------------------------------
/windows/runner/flutter_window.h:
--------------------------------------------------------------------------------
 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_
 2 | #define RUNNER_FLUTTER_WINDOW_H_
 3 | 
 4 | #include <flutter/dart_project.h>
 5 | #include <flutter/flutter_view_controller.h>
 6 | 
 7 | #include <memory>
 8 | 
 9 | #include "win32_window.h"
10 | 
11 | // A window that does nothing but host a Flutter view.
12 | class FlutterWindow : public Win32Window {
13 |  public:
14 |   // Creates a new FlutterWindow hosting a Flutter view running |project|.
15 |   explicit FlutterWindow(const flutter::DartProject& project);
16 |   virtual ~FlutterWindow();
17 | 
18 |  protected:
19 |   // Win32Window:
20 |   bool OnCreate() override;
21 |   void OnDestroy() override;
22 |   LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
23 |                          LPARAM const lparam) noexcept override;
24 | 
25 |  private:
26 |   // The project to run.
27 |   flutter::DartProject project_;
28 | 
29 |   // The Flutter instance hosted by this window.
30 |   std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
31 | };
32 | 
33 | #endif  // RUNNER_FLUTTER_WINDOW_H_
34 | 


--------------------------------------------------------------------------------
/windows/runner/main.cpp:
--------------------------------------------------------------------------------
 1 | #include <flutter/dart_project.h>
 2 | #include <flutter/flutter_view_controller.h>
 3 | #include <windows.h>
 4 | 
 5 | #include "flutter_window.h"
 6 | #include "utils.h"
 7 | 
 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
 9 |                       _In_ wchar_t *command_line, _In_ int show_command) {
10 |   // Attach to console when present (e.g., 'flutter run') or create a
11 |   // new console when running with a debugger.
12 |   if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
13 |     CreateAndAttachConsole();
14 |   }
15 | 
16 |   // Initialize COM, so that it is available for use in the library and/or
17 |   // plugins.
18 |   ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
19 | 
20 |   flutter::DartProject project(L"data");
21 | 
22 |   std::vector<std::string> command_line_arguments =
23 |       GetCommandLineArguments();
24 | 
25 |   project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
26 | 
27 |   FlutterWindow window(project);
28 |   Win32Window::Point origin(10, 10);
29 |   Win32Window::Size size(1280, 720);
30 |   if (!window.Create(L"gsy_flutter_demo", origin, size)) {
31 |     return EXIT_FAILURE;
32 |   }
33 |   window.SetQuitOnClose(true);
34 | 
35 |   ::MSG msg;
36 |   while (::GetMessage(&msg, nullptr, 0, 0)) {
37 |     ::TranslateMessage(&msg);
38 |     ::DispatchMessage(&msg);
39 |   }
40 | 
41 |   ::CoUninitialize();
42 |   return EXIT_SUCCESS;
43 | }
44 | 


--------------------------------------------------------------------------------
/windows/runner/resource.h:
--------------------------------------------------------------------------------
 1 | //{{NO_DEPENDENCIES}}
 2 | // Microsoft Visual C++ generated include file.
 3 | // Used by Runner.rc
 4 | //
 5 | #define IDI_APP_ICON                    101
 6 | 
 7 | // Next default values for new objects
 8 | //
 9 | #ifdef APSTUDIO_INVOKED
10 | #ifndef APSTUDIO_READONLY_SYMBOLS
11 | #define _APS_NEXT_RESOURCE_VALUE        102
12 | #define _APS_NEXT_COMMAND_VALUE         40001
13 | #define _APS_NEXT_CONTROL_VALUE         1001
14 | #define _APS_NEXT_SYMED_VALUE           101
15 | #endif
16 | #endif
17 | 


--------------------------------------------------------------------------------
/windows/runner/resources/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CarGuo/gsy_flutter_demo/fcdec77ed84711197dc1371a2cdd9a02c85c3e4b/windows/runner/resources/app_icon.ico


--------------------------------------------------------------------------------
/windows/runner/runner.exe.manifest:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 2 | <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 3 |   <application xmlns="urn:schemas-microsoft-com:asm.v3">
 4 |     <windowsSettings>
 5 |       <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
 6 |     </windowsSettings>
 7 |   </application>
 8 |   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
 9 |     <application>
10 |       <!-- Windows 10 and Windows 11 -->
11 |       <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
12 |     </application>
13 |   </compatibility>
14 | </assembly>
15 | 


--------------------------------------------------------------------------------
/windows/runner/utils.cpp:
--------------------------------------------------------------------------------
 1 | #include "utils.h"
 2 | 
 3 | #include <flutter_windows.h>
 4 | #include <io.h>
 5 | #include <stdio.h>
 6 | #include <windows.h>
 7 | 
 8 | #include <iostream>
 9 | 
10 | void CreateAndAttachConsole() {
11 |   if (::AllocConsole()) {
12 |     FILE *unused;
13 |     if (freopen_s(&unused, "CONOUT
quot;, "w", stdout)) {
14 |       _dup2(_fileno(stdout), 1);
15 |     }
16 |     if (freopen_s(&unused, "CONOUT
quot;, "w", stderr)) {
17 |       _dup2(_fileno(stdout), 2);
18 |     }
19 |     std::ios::sync_with_stdio();
20 |     FlutterDesktopResyncOutputStreams();
21 |   }
22 | }
23 | 
24 | std::vector<std::string> GetCommandLineArguments() {
25 |   // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
26 |   int argc;
27 |   wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
28 |   if (argv == nullptr) {
29 |     return std::vector<std::string>();
30 |   }
31 | 
32 |   std::vector<std::string> command_line_arguments;
33 | 
34 |   // Skip the first argument as it's the binary name.
35 |   for (int i = 1; i < argc; i++) {
36 |     command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
37 |   }
38 | 
39 |   ::LocalFree(argv);
40 | 
41 |   return command_line_arguments;
42 | }
43 | 
44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) {
45 |   if (utf16_string == nullptr) {
46 |     return std::string();
47 |   }
48 |   unsigned int target_length = ::WideCharToMultiByte(
49 |       CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
50 |       -1, nullptr, 0, nullptr, nullptr)
51 |     -1; // remove the trailing null character
52 |   int input_length = (int)wcslen(utf16_string);
53 |   std::string utf8_string;
54 |   if (target_length == 0 || target_length > utf8_string.max_size()) {
55 |     return utf8_string;
56 |   }
57 |   utf8_string.resize(target_length);
58 |   int converted_length = ::WideCharToMultiByte(
59 |       CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
60 |       input_length, utf8_string.data(), target_length, nullptr, nullptr);
61 |   if (converted_length == 0) {
62 |     return std::string();
63 |   }
64 |   return utf8_string;
65 | }
66 | 


--------------------------------------------------------------------------------
/windows/runner/utils.h:
--------------------------------------------------------------------------------
 1 | #ifndef RUNNER_UTILS_H_
 2 | #define RUNNER_UTILS_H_
 3 | 
 4 | #include <string>
 5 | #include <vector>
 6 | 
 7 | // Creates a console for the process, and redirects stdout and stderr to
 8 | // it for both the runner and the Flutter library.
 9 | void CreateAndAttachConsole();
10 | 
11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
12 | // encoded in UTF-8. Returns an empty std::string on failure.
13 | std::string Utf8FromUtf16(const wchar_t* utf16_string);
14 | 
15 | // Gets the command line arguments passed in as a std::vector<std::string>,
16 | // encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
17 | std::vector<std::string> GetCommandLineArguments();
18 | 
19 | #endif  // RUNNER_UTILS_H_
20 | 


--------------------------------------------------------------------------------