├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README-ZH.md ├── README.md ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── club │ │ │ │ │ └── flutterchina │ │ │ │ │ └── azlistview_example │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── 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 │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── assets │ ├── data │ │ ├── car_models.json │ │ ├── china.json │ │ └── contacts.json │ └── images │ │ ├── ali_connors.png │ │ ├── avatar.png │ │ ├── ic_car_models_header1.png │ │ ├── ic_car_models_header2.png │ │ ├── ic_favorite.png │ │ ├── ic_index_bar_bubble_gray.png │ │ └── ic_index_bar_bubble_white.png ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── 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 ├── lib │ ├── common │ │ ├── index.dart │ │ ├── models.dart │ │ ├── res.dart │ │ └── utils.dart │ ├── main.dart │ └── ui │ │ ├── car_models_page.dart │ │ ├── citylist_custom_header_page.dart │ │ ├── citylist_page.dart │ │ ├── contacts_list_page.dart │ │ ├── contacts_page.dart │ │ ├── github_language_page.dart │ │ ├── index.dart │ │ ├── large_data_page.dart │ │ └── page_scaffold.dart ├── pkgget ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart ├── lib ├── azlistview.dart └── src │ ├── az_common.dart │ ├── az_listview.dart │ ├── index_bar.dart │ └── suspension_view.dart ├── pkgget ├── pubspec.lock ├── pubspec.yaml ├── screenshots ├── azlistview1.jpg ├── azlistview2.jpg ├── azlistview3.jpg ├── azlistview4.jpg ├── azlistview5.jpg └── azlistview6.jpg └── uploadMaster /.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 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/app.flx 64 | **/ios/Flutter/app.zip 65 | **/ios/Flutter/flutter_assets/ 66 | **/ios/Flutter/flutter_export_environment.sh 67 | **/ios/ServiceDefinitions.json 68 | **/ios/Runner/GeneratedPluginRegistrant.* 69 | 70 | # Exceptions to above rules. 71 | !**/ios/**/default.mode1v3 72 | !**/ios/**/default.mode2v3 73 | !**/ios/**/default.pbxuser 74 | !**/ios/**/default.perspectivev3 75 | -------------------------------------------------------------------------------- /.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: 81a45ec2e5f80fa71d5135f1702ce540558b416d 8 | channel: beta 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.0.0 release 2 | * TODO: scrollable_positioned_list: ^0.2.3, Indexbar add haptic feedback. 3 | 4 | ## 2.0.0 5 | * TODO: Migrate to null-safety. 6 | 7 | ## 1.1.1 8 | * TODO: fix analysis. 9 | 10 | ## 1.1.0 11 | * TODO: itemBuilder do not include the header, because it is automatically merged internally. fix [#38](https://github.com/flutterchina/azlistview/issues/38). 12 | 13 | ## 1.0.2 14 | * TODO: fix bugs and add search classification example. 15 | 16 | ## 1.0.1 17 | * TODO: fix analysis. 18 | 19 | ## 1.0.0 20 | 21 | * TODO: A Flutter sticky headers & index ListView. Based on [scrollable_positioned_list](https://pub.flutter-io.cn/packages/scrollable_positioned_list). 22 | 23 | ## 0.1.2 24 | 25 | * TODO: Open ScrollController, ScrollPhysics... 26 | 27 | ## 0.1.1 28 | 29 | * TODO: fix IndexBar onTapUp. 30 | 31 | ## 0.1.0 32 | 33 | * TODO: AzListView, SuspensionView, IndexBar. 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Flutter中文网 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README-ZH.md: -------------------------------------------------------------------------------- 1 | Language: [English](https://github.com/flutterchina/azlistview) | 中文简体 2 | 3 | # azlistview 4 | 5 | Flutter 城市列表、联系人列表,索引&悬停。基于[scrollable_positioned_list](https://pub.flutter-io.cn/packages/scrollable_positioned_list). 6 | AzListView, SuspensionView, IndexBar. 7 | 8 | ## Features 9 | 10 | * 轻松创建城市列表或联系人列表界面。 11 | * 列表项按A-Z分组。 12 | * 带有悬停效果Header。 13 | * 支持自定义Header。 14 | * 支持索引联动。 15 | * IndexBar支持自定义样式。 16 | * IndexBar支持本地图片。 17 | * 允许滚动到列表中的特定项目。 18 | 19 | ## Pub 20 | ```yaml 21 | dependencies: 22 | azlistview: #latest version 23 | ``` 24 | 25 | ## Screenshots 26 | 27 | |![](https://s1.ax1x.com/2020/09/09/w3DOZq.png)|![](https://s1.ax1x.com/2020/09/09/w3rZFK.png)|![](https://s1.ax1x.com/2020/09/09/w3rKQH.png)| 28 | |:---:|:---:|:---:| 29 | |![](https://s1.ax1x.com/2020/09/09/w3rJFf.png)|![](https://s1.ax1x.com/2020/09/09/w3rUSg.png)|![](https://s3.ax1x.com/2020/11/20/DQJCHs.jpg)| 30 | 31 | 32 | ## Changelog 33 | 34 | Please see the [Changelog](https://github.com/flutterchina/azlistview/blob/master/CHANGELOG.md) page to know what's recently changed. 35 | v1.1.0 36 | itemBuilder不要包含Header,因为它是在内部自动合并的。fix [#38](https://github.com/flutterchina/azlistview/issues/38). 37 | 38 | ## App 39 | [Moss App](https://github.com/Sky24n/Moss) 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Language: English | [中文简体](README-ZH.md) 2 | 3 | # azlistview 4 | A Flutter sticky headers & index ListView. Based on [scrollable_positioned_list](https://pub.flutter-io.cn/packages/scrollable_positioned_list). 5 | AzListView, SuspensionView, IndexBar. 6 | 7 | ## Features 8 | * Easy creation of city list or contact list interfaces. 9 | * List items can be grouped A-Z. 10 | * Sticky headers with floating option. 11 | * Support custom header. 12 | * Support index linkage. 13 | * IndexBar supports custom styles. 14 | * IndexBar supports local images. 15 | * Allows scrolling to a specific item in the list. 16 | 17 | ## Pub 18 | ```yaml 19 | dependencies: 20 | azlistview: ^2.0.0 21 | ``` 22 | 23 | ## Screenshots 24 | |![](https://s1.ax1x.com/2020/09/09/w3DOZq.png)|![](https://s1.ax1x.com/2020/09/09/w3rZFK.png)|![](https://s1.ax1x.com/2020/09/09/w3rKQH.png)| 25 | |:---:|:---:|:---:| 26 | |![](https://s1.ax1x.com/2020/09/09/w3rJFf.png)|![](https://s1.ax1x.com/2020/09/09/w3rUSg.png)|![](https://s3.ax1x.com/2020/11/20/DQ8MM4.jpg)| 27 | 28 | 29 | ## Changelog 30 | Please see the [Changelog](https://github.com/flutterchina/azlistview/blob/master/CHANGELOG.md) page to know what's recently changed. 31 | v1.1.0 32 | itemBuilder do not include the header, because it is automatically merged internally. fix [#38](https://github.com/flutterchina/azlistview/issues/38). 33 | 34 | ## App 35 | [Moss](https://github.com/Sky24n/Moss). 36 | A GitHub client app developed with Flutter, which supports Android iOS Web. 37 | Web :[Flutter Web](https://sky24n.github.io/Sky24n/moss). 38 | 39 | |![](https://z3.ax1x.com/2021/04/26/gp1hm6.jpg)|![](https://z3.ax1x.com/2021/04/26/gp1Tte.jpg)|![](https://z3.ax1x.com/2021/04/26/gp17fH.jpg)| 40 | |:---:|:---:|:---:| 41 | 42 | -------------------------------------------------------------------------------- /example/.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 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Exceptions to above rules. 44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 45 | -------------------------------------------------------------------------------- /example/.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: bbfbf1770cca2da7c82e887e4e4af910034800b6 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # azlistview_example 2 | 3 | A new Flutter application. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "club.flutterchina.azlistview_example" 37 | minSdkVersion 16 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | } 42 | 43 | buildTypes { 44 | release { 45 | // TODO: Add your own signing config for the release build. 46 | // Signing with the debug keys for now, so `flutter run --release` works. 47 | signingConfig signingConfigs.debug 48 | } 49 | } 50 | } 51 | 52 | flutter { 53 | source '../..' 54 | } 55 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 9 | 12 | 19 | 23 | 26 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/club/flutterchina/azlistview_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package club.flutterchina.azlistview_example; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /example/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-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/assets/data/car_models.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "奥迪" 4 | }, 5 | { 6 | "name": "阿斯顿・马丁" 7 | }, 8 | { 9 | "name": "阿尔法・罗密欧" 10 | }, 11 | { 12 | "name": "ARCFOX" 13 | }, 14 | { 15 | "name": "AUXUN傲旋" 16 | }, 17 | { 18 | "name": "爱驰" 19 | }, 20 | { 21 | "name": "ALPINA" 22 | }, 23 | { 24 | "name": "AC Schnitzer" 25 | }, 26 | { 27 | "name": "安凯客车" 28 | }, 29 | { 30 | "name": "铂驰" 31 | }, 32 | { 33 | "name": "比德文汽车" 34 | }, 35 | { 36 | "name": "博郡汽车" 37 | }, 38 | { 39 | "name": "宝骐汽车" 40 | }, 41 | { 42 | "name": "北京清行" 43 | }, 44 | { 45 | "name": "北汽昌河" 46 | }, 47 | { 48 | "name": "布加迪" 49 | }, 50 | { 51 | "name": "宾利" 52 | }, 53 | { 54 | "name": "别克" 55 | }, 56 | { 57 | "name": "标致" 58 | }, 59 | { 60 | "name": "比亚迪" 61 | }, 62 | { 63 | "name": "比速汽车" 64 | }, 65 | { 66 | "name": "本田" 67 | }, 68 | { 69 | "name": "奔腾" 70 | }, 71 | { 72 | "name": "奔驰" 73 | }, 74 | { 75 | "name": "北汽制造" 76 | }, 77 | { 78 | "name": "北汽新能源" 79 | }, 80 | { 81 | "name": "北汽威旺" 82 | }, 83 | { 84 | "name": "北汽绅宝" 85 | }, 86 | { 87 | "name": "北汽幻速" 88 | }, 89 | { 90 | "name": "北汽道达" 91 | }, 92 | { 93 | "name": "北京" 94 | }, 95 | { 96 | "name": "保时捷" 97 | }, 98 | { 99 | "name": "宝沃" 100 | }, 101 | { 102 | "name": "宝马" 103 | }, 104 | { 105 | "name": "宝骏" 106 | }, 107 | { 108 | "name": "巴博斯" 109 | }, 110 | { 111 | "name": "车驰汽车" 112 | }, 113 | { 114 | "name": "成功汽车" 115 | }, 116 | { 117 | "name": "长城" 118 | }, 119 | { 120 | "name": "长安轻型车" 121 | }, 122 | { 123 | "name": "长安欧尚" 124 | }, 125 | { 126 | "name": "长安跨越" 127 | }, 128 | { 129 | "name": "长安" 130 | }, 131 | { 132 | "name": "大乘汽车" 133 | }, 134 | { 135 | "name": "东风・瑞泰特" 136 | }, 137 | { 138 | "name": "东南" 139 | }, 140 | { 141 | "name": "东风小康" 142 | }, 143 | { 144 | "name": "东风风行" 145 | }, 146 | { 147 | "name": "东风风神" 148 | }, 149 | { 150 | "name": "东风风光" 151 | }, 152 | { 153 | "name": "东风风度" 154 | }, 155 | { 156 | "name": "东风" 157 | }, 158 | { 159 | "name": "电咖" 160 | }, 161 | { 162 | "name": "道奇" 163 | }, 164 | { 165 | "name": "大众" 166 | }, 167 | { 168 | "name": "大发" 169 | }, 170 | { 171 | "name": "DS" 172 | }, 173 | { 174 | "name": "福田乘用车" 175 | }, 176 | { 177 | "name": "福田" 178 | }, 179 | { 180 | "name": "福特" 181 | }, 182 | { 183 | "name": "福汽启腾" 184 | }, 185 | { 186 | "name": "福迪" 187 | }, 188 | { 189 | "name": "丰田" 190 | }, 191 | { 192 | "name": "菲亚特" 193 | }, 194 | { 195 | "name": "法拉利" 196 | }, 197 | { 198 | "name": "国机智骏" 199 | }, 200 | { 201 | "name": "Genesis现代" 202 | }, 203 | { 204 | "name": "广汽集团" 205 | }, 206 | { 207 | "name": "广汽新能源" 208 | }, 209 | { 210 | "name": "国金汽车" 211 | }, 212 | { 213 | "name": "广汽吉奥" 214 | }, 215 | { 216 | "name": "广汽传祺" 217 | }, 218 | { 219 | "name": "光冈" 220 | }, 221 | { 222 | "name": "观致" 223 | }, 224 | { 225 | "name": "GMC" 226 | }, 227 | { 228 | "name": "HYCAN合创" 229 | }, 230 | { 231 | "name": "汉龙汽车" 232 | }, 233 | { 234 | "name": "合众汽车" 235 | }, 236 | { 237 | "name": "红星汽车" 238 | }, 239 | { 240 | "name": "黄海" 241 | }, 242 | { 243 | "name": "华泰新能源" 244 | }, 245 | { 246 | "name": "华泰" 247 | }, 248 | { 249 | "name": "华颂" 250 | }, 251 | { 252 | "name": "华骐" 253 | }, 254 | { 255 | "name": "华普" 256 | }, 257 | { 258 | "name": "华利" 259 | }, 260 | { 261 | "name": "华凯" 262 | }, 263 | { 264 | "name": "红旗" 265 | }, 266 | { 267 | "name": "恒天" 268 | }, 269 | { 270 | "name": "悍马" 271 | }, 272 | { 273 | "name": "汉腾汽车" 274 | }, 275 | { 276 | "name": "海马" 277 | }, 278 | { 279 | "name": "海格" 280 | }, 281 | { 282 | "name": "哈弗" 283 | }, 284 | { 285 | "name": "哈飞" 286 | }, 287 | { 288 | "name": "Icona" 289 | }, 290 | { 291 | "name": "捷达" 292 | }, 293 | { 294 | "name": "几何汽车" 295 | }, 296 | { 297 | "name": "钧天" 298 | }, 299 | { 300 | "name": "捷途" 301 | }, 302 | { 303 | "name": "君马汽车" 304 | }, 305 | { 306 | "name": "九龙" 307 | }, 308 | { 309 | "name": "金旅" 310 | }, 311 | { 312 | "name": "金龙" 313 | }, 314 | { 315 | "name": "金杯" 316 | }, 317 | { 318 | "name": "捷豹" 319 | }, 320 | { 321 | "name": "江铃集团新能源" 322 | }, 323 | { 324 | "name": "江铃集团轻汽" 325 | }, 326 | { 327 | "name": "江铃" 328 | }, 329 | { 330 | "name": "江淮" 331 | }, 332 | { 333 | "name": "吉利汽车" 334 | }, 335 | { 336 | "name": "Jeep" 337 | }, 338 | { 339 | "name": "Karma" 340 | }, 341 | { 342 | "name": "克莱斯勒" 343 | }, 344 | { 345 | "name": "科尼赛克" 346 | }, 347 | { 348 | "name": "凯翼" 349 | }, 350 | { 351 | "name": "凯迪拉克" 352 | }, 353 | { 354 | "name": "开瑞" 355 | }, 356 | { 357 | "name": "卡威" 358 | }, 359 | { 360 | "name": "卡升" 361 | }, 362 | { 363 | "name": "卡尔森" 364 | }, 365 | { 366 | "name": "KTM" 367 | }, 368 | { 369 | "name": "雷丁" 370 | }, 371 | { 372 | "name": "罗夫哈特" 373 | }, 374 | { 375 | "name": "理想智造" 376 | }, 377 | { 378 | "name": "领途汽车" 379 | }, 380 | { 381 | "name": "零跑汽车" 382 | }, 383 | { 384 | "name": "LITE" 385 | }, 386 | { 387 | "name": "路特斯" 388 | }, 389 | { 390 | "name": "路虎" 391 | }, 392 | { 393 | "name": "陆风" 394 | }, 395 | { 396 | "name": "陆地方舟" 397 | }, 398 | { 399 | "name": "领克" 400 | }, 401 | { 402 | "name": "铃木" 403 | }, 404 | { 405 | "name": "林肯" 406 | }, 407 | { 408 | "name": "猎豹汽车" 409 | }, 410 | { 411 | "name": "莲花汽车" 412 | }, 413 | { 414 | "name": "力帆汽车" 415 | }, 416 | { 417 | "name": "理念" 418 | }, 419 | { 420 | "name": "雷诺" 421 | }, 422 | { 423 | "name": "雷克萨斯" 424 | }, 425 | { 426 | "name": "劳斯莱斯" 427 | }, 428 | { 429 | "name": "兰博基尼" 430 | }, 431 | { 432 | "name": "Lorinser" 433 | }, 434 | { 435 | "name": "LOCAL MOTORS" 436 | }, 437 | { 438 | "name": "迈迈" 439 | }, 440 | { 441 | "name": "迈莎锐" 442 | }, 443 | { 444 | "name": "摩根" 445 | }, 446 | { 447 | "name": "名爵" 448 | }, 449 | { 450 | "name": "迈凯伦" 451 | }, 452 | { 453 | "name": "迈巴赫" 454 | }, 455 | { 456 | "name": "玛莎拉蒂" 457 | }, 458 | { 459 | "name": "马自达" 460 | }, 461 | { 462 | "name": "MINI" 463 | }, 464 | { 465 | "name": "哪吒汽车" 466 | }, 467 | { 468 | "name": "NEVS国能汽车" 469 | }, 470 | { 471 | "name": "南京金龙" 472 | }, 473 | { 474 | "name": "纳智捷" 475 | }, 476 | { 477 | "name": "欧拉" 478 | }, 479 | { 480 | "name": "欧尚汽车" 481 | }, 482 | { 483 | "name": "欧朗" 484 | }, 485 | { 486 | "name": "欧宝" 487 | }, 488 | { 489 | "name": "讴歌" 490 | }, 491 | { 492 | "name": "Polestar" 493 | }, 494 | { 495 | "name": "帕加尼" 496 | }, 497 | { 498 | "name": "乔治・巴顿" 499 | }, 500 | { 501 | "name": "庆铃汽车" 502 | }, 503 | { 504 | "name": "前途" 505 | }, 506 | { 507 | "name": "起亚" 508 | }, 509 | { 510 | "name": "启辰" 511 | }, 512 | { 513 | "name": "祺智" 514 | }, 515 | { 516 | "name": "奇瑞" 517 | }, 518 | { 519 | "name": "全球鹰" 520 | }, 521 | { 522 | "name": "容大智造" 523 | }, 524 | { 525 | "name": "瑞麒" 526 | }, 527 | { 528 | "name": "瑞驰新能源" 529 | }, 530 | { 531 | "name": "如虎" 532 | }, 533 | { 534 | "name": "荣威" 535 | }, 536 | { 537 | "name": "日产" 538 | }, 539 | { 540 | "name": "思皓" 541 | }, 542 | { 543 | "name": "SHELBY" 544 | }, 545 | { 546 | "name": "SERES赛力斯" 547 | }, 548 | { 549 | "name": "斯柯达" 550 | }, 551 | { 552 | "name": "斯达泰克" 553 | }, 554 | { 555 | "name": "斯巴鲁" 556 | }, 557 | { 558 | "name": "思铭" 559 | }, 560 | { 561 | "name": "双龙" 562 | }, 563 | { 564 | "name": "双环" 565 | }, 566 | { 567 | "name": "世爵" 568 | }, 569 | { 570 | "name": "上汽大通" 571 | }, 572 | { 573 | "name": "陕汽通家" 574 | }, 575 | { 576 | "name": "三菱" 577 | }, 578 | { 579 | "name": "赛麟" 580 | }, 581 | { 582 | "name": "萨博" 583 | }, 584 | { 585 | "name": "SWM斯威汽车" 586 | }, 587 | { 588 | "name": "smart" 589 | }, 590 | { 591 | "name": "天际汽车" 592 | }, 593 | { 594 | "name": "腾势" 595 | }, 596 | { 597 | "name": "特斯拉" 598 | }, 599 | { 600 | "name": "泰卡特" 601 | }, 602 | { 603 | "name": "潍柴汽车" 604 | }, 605 | { 606 | "name": "威马汽车" 607 | }, 608 | { 609 | "name": "五十铃" 610 | }, 611 | { 612 | "name": "五菱汽车" 613 | }, 614 | { 615 | "name": "沃尔沃" 616 | }, 617 | { 618 | "name": "蔚来" 619 | }, 620 | { 621 | "name": "潍柴英致" 622 | }, 623 | { 624 | "name": "威兹曼" 625 | }, 626 | { 627 | "name": "威麟" 628 | }, 629 | { 630 | "name": "WEY" 631 | }, 632 | { 633 | "name": "新宝骏" 634 | }, 635 | { 636 | "name": "星途" 637 | }, 638 | { 639 | "name": "小鹏汽车" 640 | }, 641 | { 642 | "name": "新特汽车" 643 | }, 644 | { 645 | "name": "雪铁龙" 646 | }, 647 | { 648 | "name": "雪佛兰" 649 | }, 650 | { 651 | "name": "鑫源" 652 | }, 653 | { 654 | "name": "新凯" 655 | }, 656 | { 657 | "name": "现代" 658 | }, 659 | { 660 | "name": "西雅特" 661 | }, 662 | { 663 | "name": "一汽凌河" 664 | }, 665 | { 666 | "name": "远程汽车" 667 | }, 668 | { 669 | "name": "银隆新能源" 670 | }, 671 | { 672 | "name": "云雀汽车" 673 | }, 674 | { 675 | "name": "云度" 676 | }, 677 | { 678 | "name": "裕路" 679 | }, 680 | { 681 | "name": "御捷" 682 | }, 683 | { 684 | "name": "驭胜" 685 | }, 686 | { 687 | "name": "宇通客车" 688 | }, 689 | { 690 | "name": "永源" 691 | }, 692 | { 693 | "name": "英菲尼迪" 694 | }, 695 | { 696 | "name": "依维柯" 697 | }, 698 | { 699 | "name": "一汽" 700 | }, 701 | { 702 | "name": "野马汽车" 703 | }, 704 | { 705 | "name": "众泰" 706 | }, 707 | { 708 | "name": "中兴" 709 | }, 710 | { 711 | "name": "中华" 712 | }, 713 | { 714 | "name": "知豆" 715 | }, 716 | { 717 | "name": "之诺" 718 | } 719 | ] -------------------------------------------------------------------------------- /example/assets/data/china.json: -------------------------------------------------------------------------------- 1 | { 2 | "china": [ 3 | { 4 | "name": "北京市" 5 | }, 6 | { 7 | "name": "天津市" 8 | }, 9 | { 10 | "name": "石家庄市" 11 | }, 12 | { 13 | "name": "唐山市" 14 | }, 15 | { 16 | "name": "秦皇岛市" 17 | }, 18 | { 19 | "name": "邯郸市" 20 | }, 21 | { 22 | "name": "邢台市" 23 | }, 24 | { 25 | "name": "保定市" 26 | }, 27 | { 28 | "name": "张家口市" 29 | }, 30 | { 31 | "name": "承德市" 32 | }, 33 | { 34 | "name": "沧州市" 35 | }, 36 | { 37 | "name": "廊坊市" 38 | }, 39 | { 40 | "name": "衡水市" 41 | }, 42 | { 43 | "name": "太原市" 44 | }, 45 | { 46 | "name": "大同市" 47 | }, 48 | { 49 | "name": "阳泉市" 50 | }, 51 | { 52 | "name": "长治市" 53 | }, 54 | { 55 | "name": "晋城市" 56 | }, 57 | { 58 | "name": "朔州市" 59 | }, 60 | { 61 | "name": "晋中市" 62 | }, 63 | { 64 | "name": "运城市" 65 | }, 66 | { 67 | "name": "忻州市" 68 | }, 69 | { 70 | "name": "临汾市" 71 | }, 72 | { 73 | "name": "吕梁市" 74 | }, 75 | { 76 | "name": "呼和浩特市" 77 | }, 78 | { 79 | "name": "包头市" 80 | }, 81 | { 82 | "name": "乌海市" 83 | }, 84 | { 85 | "name": "赤峰市" 86 | }, 87 | { 88 | "name": "通辽市" 89 | }, 90 | { 91 | "name": "鄂尔多斯市" 92 | }, 93 | { 94 | "name": "呼伦贝尔市" 95 | }, 96 | { 97 | "name": "巴彦淖尔市" 98 | }, 99 | { 100 | "name": "乌兰察布市" 101 | }, 102 | { 103 | "name": "兴安盟" 104 | }, 105 | { 106 | "name": "锡林郭勒盟" 107 | }, 108 | { 109 | "name": "阿拉善盟" 110 | }, 111 | { 112 | "name": "沈阳市" 113 | }, 114 | { 115 | "name": "大连市" 116 | }, 117 | { 118 | "name": "鞍山市" 119 | }, 120 | { 121 | "name": "抚顺市" 122 | }, 123 | { 124 | "name": "本溪市" 125 | }, 126 | { 127 | "name": "丹东市" 128 | }, 129 | { 130 | "name": "锦州市" 131 | }, 132 | { 133 | "name": "营口市" 134 | }, 135 | { 136 | "name": "阜新市" 137 | }, 138 | { 139 | "name": "辽阳市" 140 | }, 141 | { 142 | "name": "盘锦市" 143 | }, 144 | { 145 | "name": "铁岭市" 146 | }, 147 | { 148 | "name": "朝阳市" 149 | }, 150 | { 151 | "name": "葫芦岛市" 152 | }, 153 | { 154 | "name": "长春市" 155 | }, 156 | { 157 | "name": "吉林市" 158 | }, 159 | { 160 | "name": "四平市" 161 | }, 162 | { 163 | "name": "辽源市" 164 | }, 165 | { 166 | "name": "通化市" 167 | }, 168 | { 169 | "name": "白山市" 170 | }, 171 | { 172 | "name": "松原市" 173 | }, 174 | { 175 | "name": "白城市" 176 | }, 177 | { 178 | "name": "延边朝鲜族自治州" 179 | }, 180 | { 181 | "name": "哈尔滨市" 182 | }, 183 | { 184 | "name": "齐齐哈尔市" 185 | }, 186 | { 187 | "name": "鸡西市" 188 | }, 189 | { 190 | "name": "鹤岗市" 191 | }, 192 | { 193 | "name": "双鸭山市" 194 | }, 195 | { 196 | "name": "大庆市" 197 | }, 198 | { 199 | "name": "伊春市" 200 | }, 201 | { 202 | "name": "佳木斯市" 203 | }, 204 | { 205 | "name": "七台河市" 206 | }, 207 | { 208 | "name": "牡丹江市" 209 | }, 210 | { 211 | "name": "黑河市" 212 | }, 213 | { 214 | "name": "绥化市" 215 | }, 216 | { 217 | "name": "大兴安岭地区" 218 | }, 219 | { 220 | "name": "上海市" 221 | }, 222 | { 223 | "name": "南京市" 224 | }, 225 | { 226 | "name": "无锡市" 227 | }, 228 | { 229 | "name": "徐州市" 230 | }, 231 | { 232 | "name": "常州市" 233 | }, 234 | { 235 | "name": "苏州市" 236 | }, 237 | { 238 | "name": "南通市" 239 | }, 240 | { 241 | "name": "连云港市" 242 | }, 243 | { 244 | "name": "淮安市" 245 | }, 246 | { 247 | "name": "盐城市" 248 | }, 249 | { 250 | "name": "扬州市" 251 | }, 252 | { 253 | "name": "镇江市" 254 | }, 255 | { 256 | "name": "泰州市" 257 | }, 258 | { 259 | "name": "宿迁市" 260 | }, 261 | { 262 | "name": "杭州市" 263 | }, 264 | { 265 | "name": "宁波市" 266 | }, 267 | { 268 | "name": "温州市" 269 | }, 270 | { 271 | "name": "嘉兴市" 272 | }, 273 | { 274 | "name": "湖州市" 275 | }, 276 | { 277 | "name": "绍兴市" 278 | }, 279 | { 280 | "name": "金华市" 281 | }, 282 | { 283 | "name": "衢州市" 284 | }, 285 | { 286 | "name": "舟山市" 287 | }, 288 | { 289 | "name": "台州市" 290 | }, 291 | { 292 | "name": "丽水市" 293 | }, 294 | { 295 | "name": "合肥市" 296 | }, 297 | { 298 | "name": "芜湖市" 299 | }, 300 | { 301 | "name": "蚌埠市" 302 | }, 303 | { 304 | "name": "淮南市" 305 | }, 306 | { 307 | "name": "马鞍山市" 308 | }, 309 | { 310 | "name": "淮北市" 311 | }, 312 | { 313 | "name": "铜陵市" 314 | }, 315 | { 316 | "name": "安庆市" 317 | }, 318 | { 319 | "name": "黄山市" 320 | }, 321 | { 322 | "name": "滁州市" 323 | }, 324 | { 325 | "name": "阜阳市" 326 | }, 327 | { 328 | "name": "宿州市" 329 | }, 330 | { 331 | "name": "巢湖市" 332 | }, 333 | { 334 | "name": "六安市" 335 | }, 336 | { 337 | "name": "亳州市" 338 | }, 339 | { 340 | "name": "池州市" 341 | }, 342 | { 343 | "name": "宣城市" 344 | }, 345 | { 346 | "name": "福州市" 347 | }, 348 | { 349 | "name": "厦门市" 350 | }, 351 | { 352 | "name": "莆田市" 353 | }, 354 | { 355 | "name": "三明市" 356 | }, 357 | { 358 | "name": "泉州市" 359 | }, 360 | { 361 | "name": "漳州市" 362 | }, 363 | { 364 | "name": "南平市" 365 | }, 366 | { 367 | "name": "龙岩市" 368 | }, 369 | { 370 | "name": "宁德市" 371 | }, 372 | { 373 | "name": "南昌市" 374 | }, 375 | { 376 | "name": "景德镇市" 377 | }, 378 | { 379 | "name": "萍乡市" 380 | }, 381 | { 382 | "name": "九江市" 383 | }, 384 | { 385 | "name": "新余市" 386 | }, 387 | { 388 | "name": "鹰潭市" 389 | }, 390 | { 391 | "name": "赣州市" 392 | }, 393 | { 394 | "name": "吉安市" 395 | }, 396 | { 397 | "name": "宜春市" 398 | }, 399 | { 400 | "name": "抚州市" 401 | }, 402 | { 403 | "name": "上饶市" 404 | }, 405 | { 406 | "name": "济南市" 407 | }, 408 | { 409 | "name": "青岛市" 410 | }, 411 | { 412 | "name": "淄博市" 413 | }, 414 | { 415 | "name": "枣庄市" 416 | }, 417 | { 418 | "name": "东营市" 419 | }, 420 | { 421 | "name": "烟台市" 422 | }, 423 | { 424 | "name": "潍坊市" 425 | }, 426 | { 427 | "name": "济宁市" 428 | }, 429 | { 430 | "name": "泰安市" 431 | }, 432 | { 433 | "name": "威海市" 434 | }, 435 | { 436 | "name": "日照市" 437 | }, 438 | { 439 | "name": "莱芜市" 440 | }, 441 | { 442 | "name": "临沂市" 443 | }, 444 | { 445 | "name": "德州市" 446 | }, 447 | { 448 | "name": "聊城市" 449 | }, 450 | { 451 | "name": "滨州市" 452 | }, 453 | { 454 | "name": "菏泽市" 455 | }, 456 | { 457 | "name": "郑州市" 458 | }, 459 | { 460 | "name": "开封市" 461 | }, 462 | { 463 | "name": "洛阳市" 464 | }, 465 | { 466 | "name": "平顶山市" 467 | }, 468 | { 469 | "name": "安阳市" 470 | }, 471 | { 472 | "name": "鹤壁市" 473 | }, 474 | { 475 | "name": "新乡市" 476 | }, 477 | { 478 | "name": "焦作市" 479 | }, 480 | { 481 | "name": "濮阳市" 482 | }, 483 | { 484 | "name": "许昌市" 485 | }, 486 | { 487 | "name": "漯河市" 488 | }, 489 | { 490 | "name": "三门峡市" 491 | }, 492 | { 493 | "name": "南阳市" 494 | }, 495 | { 496 | "name": "商丘市" 497 | }, 498 | { 499 | "name": "信阳市" 500 | }, 501 | { 502 | "name": "周口市" 503 | }, 504 | { 505 | "name": "驻马店市" 506 | }, 507 | { 508 | "name": "武汉市" 509 | }, 510 | { 511 | "name": "黄石市" 512 | }, 513 | { 514 | "name": "十堰市" 515 | }, 516 | { 517 | "name": "宜昌市" 518 | }, 519 | { 520 | "name": "襄樊市" 521 | }, 522 | { 523 | "name": "鄂州市" 524 | }, 525 | { 526 | "name": "荆门市" 527 | }, 528 | { 529 | "name": "孝感市" 530 | }, 531 | { 532 | "name": "荆州市" 533 | }, 534 | { 535 | "name": "黄冈市" 536 | }, 537 | { 538 | "name": "咸宁市" 539 | }, 540 | { 541 | "name": "随州市" 542 | }, 543 | { 544 | "name": "恩施土家族苗族自治州" 545 | }, 546 | { 547 | "name": "仙桃市" 548 | }, 549 | { 550 | "name": "潜江市" 551 | }, 552 | { 553 | "name": "天门市" 554 | }, 555 | { 556 | "name": "神农架林区" 557 | }, 558 | { 559 | "name": "长沙市" 560 | }, 561 | { 562 | "name": "株洲市" 563 | }, 564 | { 565 | "name": "湘潭市" 566 | }, 567 | { 568 | "name": "衡阳市" 569 | }, 570 | { 571 | "name": "邵阳市" 572 | }, 573 | { 574 | "name": "岳阳市" 575 | }, 576 | { 577 | "name": "常德市" 578 | }, 579 | { 580 | "name": "张家界市" 581 | }, 582 | { 583 | "name": "益阳市" 584 | }, 585 | { 586 | "name": "郴州市" 587 | }, 588 | { 589 | "name": "永州市" 590 | }, 591 | { 592 | "name": "怀化市" 593 | }, 594 | { 595 | "name": "娄底市" 596 | }, 597 | { 598 | "name": "湘西土家族苗族自治州" 599 | }, 600 | { 601 | "name": "广州市" 602 | }, 603 | { 604 | "name": "韶关市" 605 | }, 606 | { 607 | "name": "深圳市" 608 | }, 609 | { 610 | "name": "珠海市" 611 | }, 612 | { 613 | "name": "汕头市" 614 | }, 615 | { 616 | "name": "佛山市" 617 | }, 618 | { 619 | "name": "江门市" 620 | }, 621 | { 622 | "name": "湛江市" 623 | }, 624 | { 625 | "name": "茂名市" 626 | }, 627 | { 628 | "name": "肇庆市" 629 | }, 630 | { 631 | "name": "惠州市" 632 | }, 633 | { 634 | "name": "梅州市" 635 | }, 636 | { 637 | "name": "汕尾市" 638 | }, 639 | { 640 | "name": "河源市" 641 | }, 642 | { 643 | "name": "阳江市" 644 | }, 645 | { 646 | "name": "清远市" 647 | }, 648 | { 649 | "name": "东莞市" 650 | }, 651 | { 652 | "name": "中山市" 653 | }, 654 | { 655 | "name": "潮州市" 656 | }, 657 | { 658 | "name": "揭阳市" 659 | }, 660 | { 661 | "name": "云浮市" 662 | }, 663 | { 664 | "name": "南宁市" 665 | }, 666 | { 667 | "name": "柳州市" 668 | }, 669 | { 670 | "name": "桂林市" 671 | }, 672 | { 673 | "name": "梧州市" 674 | }, 675 | { 676 | "name": "北海市" 677 | }, 678 | { 679 | "name": "防城港市" 680 | }, 681 | { 682 | "name": "钦州市" 683 | }, 684 | { 685 | "name": "贵港市" 686 | }, 687 | { 688 | "name": "玉林市" 689 | }, 690 | { 691 | "name": "百色市" 692 | }, 693 | { 694 | "name": "贺州市" 695 | }, 696 | { 697 | "name": "河池市" 698 | }, 699 | { 700 | "name": "来宾市" 701 | }, 702 | { 703 | "name": "崇左市" 704 | }, 705 | { 706 | "name": "海口市" 707 | }, 708 | { 709 | "name": "三亚市" 710 | }, 711 | { 712 | "name": "重庆市" 713 | }, 714 | { 715 | "name": "成都市" 716 | }, 717 | { 718 | "name": "自贡市" 719 | }, 720 | { 721 | "name": "攀枝花市" 722 | }, 723 | { 724 | "name": "泸州市" 725 | }, 726 | { 727 | "name": "德阳市" 728 | }, 729 | { 730 | "name": "绵阳市" 731 | }, 732 | { 733 | "name": "广元市" 734 | }, 735 | { 736 | "name": "遂宁市" 737 | }, 738 | { 739 | "name": "内江市" 740 | }, 741 | { 742 | "name": "乐山市" 743 | }, 744 | { 745 | "name": "南充市" 746 | }, 747 | { 748 | "name": "眉山市" 749 | }, 750 | { 751 | "name": "宜宾市" 752 | }, 753 | { 754 | "name": "广安市" 755 | }, 756 | { 757 | "name": "达州市" 758 | }, 759 | { 760 | "name": "雅安市" 761 | }, 762 | { 763 | "name": "巴中市" 764 | }, 765 | { 766 | "name": "资阳市" 767 | }, 768 | { 769 | "name": "阿坝藏族羌族自治州" 770 | }, 771 | { 772 | "name": "甘孜藏族自治州" 773 | }, 774 | { 775 | "name": "凉山彝族自治州" 776 | }, 777 | { 778 | "name": "贵阳市" 779 | }, 780 | { 781 | "name": "六盘水市" 782 | }, 783 | { 784 | "name": "遵义市" 785 | }, 786 | { 787 | "name": "安顺市" 788 | }, 789 | { 790 | "name": "铜仁市" 791 | }, 792 | { 793 | "name": "黔西南布依族苗族自治州" 794 | }, 795 | { 796 | "name": "毕节市" 797 | }, 798 | { 799 | "name": "黔东南苗族侗族自治州" 800 | }, 801 | { 802 | "name": "黔南布依族苗族自治州" 803 | }, 804 | { 805 | "name": "昆明市" 806 | }, 807 | { 808 | "name": "曲靖市" 809 | }, 810 | { 811 | "name": "玉溪市" 812 | }, 813 | { 814 | "name": "保山市" 815 | }, 816 | { 817 | "name": "昭通市" 818 | }, 819 | { 820 | "name": "丽江市" 821 | }, 822 | { 823 | "name": "思茅市" 824 | }, 825 | { 826 | "name": "临沧市" 827 | }, 828 | { 829 | "name": "楚雄彝族自治州" 830 | }, 831 | { 832 | "name": "红河哈尼族彝族自治州" 833 | }, 834 | { 835 | "name": "文山壮族苗族自治州" 836 | }, 837 | { 838 | "name": "西双版纳傣族自治州" 839 | }, 840 | { 841 | "name": "大理白族自治州" 842 | }, 843 | { 844 | "name": "德宏傣族景颇族自治州" 845 | }, 846 | { 847 | "name": "怒江傈僳族自治州" 848 | }, 849 | { 850 | "name": "迪庆藏族自治州" 851 | }, 852 | { 853 | "name": "拉萨市" 854 | }, 855 | { 856 | "name": "昌都地区" 857 | }, 858 | { 859 | "name": "山南地区" 860 | }, 861 | { 862 | "name": "日喀则地区" 863 | }, 864 | { 865 | "name": "那曲地区" 866 | }, 867 | { 868 | "name": "阿里地区" 869 | }, 870 | { 871 | "name": "林芝地区" 872 | }, 873 | { 874 | "name": "西安市" 875 | }, 876 | { 877 | "name": "铜川市" 878 | }, 879 | { 880 | "name": "宝鸡市" 881 | }, 882 | { 883 | "name": "咸阳市" 884 | }, 885 | { 886 | "name": "渭南市" 887 | }, 888 | { 889 | "name": "延安市" 890 | }, 891 | { 892 | "name": "汉中市" 893 | }, 894 | { 895 | "name": "榆林市" 896 | }, 897 | { 898 | "name": "安康市" 899 | }, 900 | { 901 | "name": "商洛市" 902 | }, 903 | { 904 | "name": "兰州市" 905 | }, 906 | { 907 | "name": "嘉峪关市" 908 | }, 909 | { 910 | "name": "金昌市" 911 | }, 912 | { 913 | "name": "白银市" 914 | }, 915 | { 916 | "name": "天水市" 917 | }, 918 | { 919 | "name": "武威市" 920 | }, 921 | { 922 | "name": "张掖市" 923 | }, 924 | { 925 | "name": "平凉市" 926 | }, 927 | { 928 | "name": "酒泉市" 929 | }, 930 | { 931 | "name": "庆阳市" 932 | }, 933 | { 934 | "name": "定西市" 935 | }, 936 | { 937 | "name": "陇南市" 938 | }, 939 | { 940 | "name": "临夏回族自治州" 941 | }, 942 | { 943 | "name": "甘南藏族自治州" 944 | }, 945 | { 946 | "name": "西宁市" 947 | }, 948 | { 949 | "name": "海东地区" 950 | }, 951 | { 952 | "name": "海北藏族自治州" 953 | }, 954 | { 955 | "name": "黄南藏族自治州" 956 | }, 957 | { 958 | "name": "海南藏族自治州" 959 | }, 960 | { 961 | "name": "果洛藏族自治州" 962 | }, 963 | { 964 | "name": "玉树藏族自治州" 965 | }, 966 | { 967 | "name": "海西蒙古族藏族自治州" 968 | }, 969 | { 970 | "name": "银川市" 971 | }, 972 | { 973 | "name": "石嘴山市" 974 | }, 975 | { 976 | "name": "吴忠市" 977 | }, 978 | { 979 | "name": "固原市" 980 | }, 981 | { 982 | "name": "中卫市" 983 | }, 984 | { 985 | "name": "乌鲁木齐市" 986 | }, 987 | { 988 | "name": "克拉玛依市" 989 | }, 990 | { 991 | "name": "吐鲁番地区" 992 | }, 993 | { 994 | "name": "哈密地区" 995 | }, 996 | { 997 | "name": "昌吉回族自治州" 998 | }, 999 | { 1000 | "name": "博尔塔拉蒙古自治州" 1001 | }, 1002 | { 1003 | "name": "巴音郭楞蒙古自治州" 1004 | }, 1005 | { 1006 | "name": "阿克苏地区" 1007 | }, 1008 | { 1009 | "name": "克孜勒苏柯尔克孜自治州" 1010 | }, 1011 | { 1012 | "name": "喀什地区" 1013 | }, 1014 | { 1015 | "name": "和田地区" 1016 | }, 1017 | { 1018 | "name": "伊犁哈萨克" 1019 | }, 1020 | { 1021 | "name": "塔城地区" 1022 | }, 1023 | { 1024 | "name": "阿勒泰地区" 1025 | }, 1026 | { 1027 | "name": "石河子市" 1028 | }, 1029 | { 1030 | "name": "阿拉尔市" 1031 | }, 1032 | { 1033 | "name": "图木舒克市" 1034 | }, 1035 | { 1036 | "name": "五家渠市" 1037 | }, 1038 | { 1039 | "name": "台北" 1040 | }, 1041 | { 1042 | "name": "高雄" 1043 | }, 1044 | { 1045 | "name": "基隆" 1046 | }, 1047 | { 1048 | "name": "台中" 1049 | }, 1050 | { 1051 | "name": "台南" 1052 | }, 1053 | { 1054 | "name": "新竹" 1055 | }, 1056 | { 1057 | "name": "嘉义" 1058 | }, 1059 | { 1060 | "name": "宜兰" 1061 | }, 1062 | { 1063 | "name": "桃园" 1064 | }, 1065 | { 1066 | "name": "苗栗" 1067 | }, 1068 | { 1069 | "name": "彰化" 1070 | }, 1071 | { 1072 | "name": "南投" 1073 | }, 1074 | { 1075 | "name": "云林" 1076 | }, 1077 | { 1078 | "name": "屏东" 1079 | }, 1080 | { 1081 | "name": "台东" 1082 | }, 1083 | { 1084 | "name": "花莲" 1085 | }, 1086 | { 1087 | "name": "澎湖" 1088 | }, 1089 | { 1090 | "name": "香港岛" 1091 | }, 1092 | { 1093 | "name": "九龙" 1094 | }, 1095 | { 1096 | "name": "新界" 1097 | }, 1098 | { 1099 | "name": "澳门半岛" 1100 | }, 1101 | { 1102 | "name": "氹仔岛" 1103 | }, 1104 | { 1105 | "name": "路环岛" 1106 | }, 1107 | { 1108 | "name": "路氹城" 1109 | } 1110 | ] 1111 | } 1112 | -------------------------------------------------------------------------------- /example/assets/data/contacts.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"Alice", 4 | "phone":[ 5 | "18221338086" 6 | ] 7 | }, 8 | { 9 | "name":"阿发", 10 | "phone":[ 11 | "18221338086" 12 | ] 13 | }, 14 | { 15 | "name":"Bob", 16 | "phone":[ 17 | "18221338086" 18 | ] 19 | }, 20 | { 21 | "name":"David", 22 | "phone":[ 23 | "18221338086" 24 | ] 25 | }, 26 | { 27 | "name":"Doris", 28 | "phone":[ 29 | "18221338086" 30 | ] 31 | }, 32 | { 33 | "name":"杜娟", 34 | "phone":[ 35 | "18221338086" 36 | ] 37 | }, 38 | { 39 | "name":"Jack", 40 | "phone":[ 41 | "18221338086" 42 | ] 43 | }, 44 | { 45 | "name":"Rose", 46 | "phone":[ 47 | "18221338086" 48 | ] 49 | }, 50 | { 51 | "name":"任盈盈", 52 | "phone":[ 53 | "18221338086" 54 | ] 55 | }, 56 | { 57 | "name":"孙正义", 58 | "phone":[ 59 | "18221338086" 60 | ] 61 | }, 62 | { 63 | "name":"Sally", 64 | "phone":[ 65 | "18221338086" 66 | ] 67 | } 68 | ] -------------------------------------------------------------------------------- /example/assets/images/ali_connors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/assets/images/ali_connors.png -------------------------------------------------------------------------------- /example/assets/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/assets/images/avatar.png -------------------------------------------------------------------------------- /example/assets/images/ic_car_models_header1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/assets/images/ic_car_models_header1.png -------------------------------------------------------------------------------- /example/assets/images/ic_car_models_header2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/assets/images/ic_car_models_header2.png -------------------------------------------------------------------------------- /example/assets/images/ic_favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/assets/images/ic_favorite.png -------------------------------------------------------------------------------- /example/assets/images/ic_index_bar_bubble_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/assets/images/ic_index_bar_bubble_gray.png -------------------------------------------------------------------------------- /example/assets/images/ic_index_bar_bubble_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/assets/images/ic_index_bar_bubble_white.png -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | generated_key_values = {} 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) do |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | generated_key_values[podname] = podpath 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | end 32 | generated_key_values 33 | end 34 | 35 | target 'Runner' do 36 | use_frameworks! 37 | use_modular_headers! 38 | 39 | # Flutter Pod 40 | 41 | copied_flutter_dir = File.join(__dir__, 'Flutter') 42 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') 43 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') 44 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) 45 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. 46 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. 47 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. 48 | 49 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') 50 | unless File.exist?(generated_xcode_build_settings_path) 51 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" 52 | end 53 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) 54 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; 55 | 56 | unless File.exist?(copied_framework_path) 57 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) 58 | end 59 | unless File.exist?(copied_podspec_path) 60 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) 61 | end 62 | end 63 | 64 | # Keep pod path relative so it can be checked into Podfile.lock. 65 | pod 'Flutter', :path => 'Flutter' 66 | 67 | # Plugin Pods 68 | 69 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 70 | # referring to absolute paths on developers' machines. 71 | system('rm -rf .symlinks') 72 | system('mkdir -p .symlinks/plugins') 73 | plugin_pods = parse_KV_file('../.flutter-plugins') 74 | plugin_pods.each do |name, path| 75 | symlink = File.join('.symlinks', 'plugins', name) 76 | File.symlink(path, symlink) 77 | pod name, :path => File.join(symlink, 'ios') 78 | end 79 | end 80 | 81 | post_install do |installer| 82 | installer.pods_project.targets.each do |target| 83 | target.build_configurations.each do |config| 84 | config.build_settings['ENABLE_BITCODE'] = 'NO' 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - FMDB (2.7.5): 4 | - FMDB/standard (= 2.7.5) 5 | - FMDB/standard (2.7.5) 6 | - path_provider (0.0.1): 7 | - Flutter 8 | - path_provider_linux (0.0.1): 9 | - Flutter 10 | - path_provider_macos (0.0.1): 11 | - Flutter 12 | - sqflite (0.0.1): 13 | - Flutter 14 | - FMDB (~> 2.7.2) 15 | 16 | DEPENDENCIES: 17 | - Flutter (from `Flutter`) 18 | - path_provider (from `.symlinks/plugins/path_provider/ios`) 19 | - path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`) 20 | - path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`) 21 | - sqflite (from `.symlinks/plugins/sqflite/ios`) 22 | 23 | SPEC REPOS: 24 | trunk: 25 | - FMDB 26 | 27 | EXTERNAL SOURCES: 28 | Flutter: 29 | :path: Flutter 30 | path_provider: 31 | :path: ".symlinks/plugins/path_provider/ios" 32 | path_provider_linux: 33 | :path: ".symlinks/plugins/path_provider_linux/ios" 34 | path_provider_macos: 35 | :path: ".symlinks/plugins/path_provider_macos/ios" 36 | sqflite: 37 | :path: ".symlinks/plugins/sqflite/ios" 38 | 39 | SPEC CHECKSUMS: 40 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec 41 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a 42 | path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c 43 | path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4 44 | path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0 45 | sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0 46 | 47 | PODFILE CHECKSUM: c34e2287a9ccaa606aeceab922830efb9a6ff69a 48 | 49 | COCOAPODS: 1.8.4 50 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | CE6203087DBD7A8E841D7774 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D10AD785B4A6315ECC23DCDE /* Pods_Runner.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXCopyFilesBuildPhase section */ 20 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 21 | isa = PBXCopyFilesBuildPhase; 22 | buildActionMask = 2147483647; 23 | dstPath = ""; 24 | dstSubfolderSpec = 10; 25 | files = ( 26 | ); 27 | name = "Embed Frameworks"; 28 | runOnlyForDeploymentPostprocessing = 0; 29 | }; 30 | /* End PBXCopyFilesBuildPhase section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 34 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 35 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 36 | 4583996D90605FE936F7A1D6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 37 | 499A43082F7CE4882CEE5205 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 38 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 39 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 41 | 8F0F95455ADF3AD6DC275CD4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 42 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 43 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 44 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 46 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 47 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 48 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | D10AD785B4A6315ECC23DCDE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | CE6203087DBD7A8E841D7774 /* Pods_Runner.framework in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 9740EEB11CF90186004384FC /* Flutter */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 68 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 69 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 70 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 71 | ); 72 | name = Flutter; 73 | sourceTree = ""; 74 | }; 75 | 97C146E51CF9000F007C117D = { 76 | isa = PBXGroup; 77 | children = ( 78 | 9740EEB11CF90186004384FC /* Flutter */, 79 | 97C146F01CF9000F007C117D /* Runner */, 80 | 97C146EF1CF9000F007C117D /* Products */, 81 | EB53942A12133464C56B5EC9 /* Pods */, 82 | E84AB69AC495D2940C1E5035 /* Frameworks */, 83 | ); 84 | sourceTree = ""; 85 | }; 86 | 97C146EF1CF9000F007C117D /* Products */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146EE1CF9000F007C117D /* Runner.app */, 90 | ); 91 | name = Products; 92 | sourceTree = ""; 93 | }; 94 | 97C146F01CF9000F007C117D /* Runner */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 98 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 99 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 100 | 97C147021CF9000F007C117D /* Info.plist */, 101 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 102 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 103 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 104 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 105 | ); 106 | path = Runner; 107 | sourceTree = ""; 108 | }; 109 | E84AB69AC495D2940C1E5035 /* Frameworks */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | D10AD785B4A6315ECC23DCDE /* Pods_Runner.framework */, 113 | ); 114 | name = Frameworks; 115 | sourceTree = ""; 116 | }; 117 | EB53942A12133464C56B5EC9 /* Pods */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 8F0F95455ADF3AD6DC275CD4 /* Pods-Runner.debug.xcconfig */, 121 | 499A43082F7CE4882CEE5205 /* Pods-Runner.release.xcconfig */, 122 | 4583996D90605FE936F7A1D6 /* Pods-Runner.profile.xcconfig */, 123 | ); 124 | name = Pods; 125 | path = Pods; 126 | sourceTree = ""; 127 | }; 128 | /* End PBXGroup section */ 129 | 130 | /* Begin PBXNativeTarget section */ 131 | 97C146ED1CF9000F007C117D /* Runner */ = { 132 | isa = PBXNativeTarget; 133 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 134 | buildPhases = ( 135 | 6A3DD026FB050040666983D1 /* [CP] Check Pods Manifest.lock */, 136 | 9740EEB61CF901F6004384FC /* Run Script */, 137 | 97C146EA1CF9000F007C117D /* Sources */, 138 | 97C146EB1CF9000F007C117D /* Frameworks */, 139 | 97C146EC1CF9000F007C117D /* Resources */, 140 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 141 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 142 | 58A7F13BF9B17BEA80A6D729 /* [CP] Embed Pods Frameworks */, 143 | ); 144 | buildRules = ( 145 | ); 146 | dependencies = ( 147 | ); 148 | name = Runner; 149 | productName = Runner; 150 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 151 | productType = "com.apple.product-type.application"; 152 | }; 153 | /* End PBXNativeTarget section */ 154 | 155 | /* Begin PBXProject section */ 156 | 97C146E61CF9000F007C117D /* Project object */ = { 157 | isa = PBXProject; 158 | attributes = { 159 | LastUpgradeCheck = 1020; 160 | ORGANIZATIONNAME = ""; 161 | TargetAttributes = { 162 | 97C146ED1CF9000F007C117D = { 163 | CreatedOnToolsVersion = 7.3.1; 164 | LastSwiftMigration = 1100; 165 | }; 166 | }; 167 | }; 168 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 169 | compatibilityVersion = "Xcode 9.3"; 170 | developmentRegion = en; 171 | hasScannedForEncodings = 0; 172 | knownRegions = ( 173 | en, 174 | Base, 175 | ); 176 | mainGroup = 97C146E51CF9000F007C117D; 177 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 178 | projectDirPath = ""; 179 | projectRoot = ""; 180 | targets = ( 181 | 97C146ED1CF9000F007C117D /* Runner */, 182 | ); 183 | }; 184 | /* End PBXProject section */ 185 | 186 | /* Begin PBXResourcesBuildPhase section */ 187 | 97C146EC1CF9000F007C117D /* Resources */ = { 188 | isa = PBXResourcesBuildPhase; 189 | buildActionMask = 2147483647; 190 | files = ( 191 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 192 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 193 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 194 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXResourcesBuildPhase section */ 199 | 200 | /* Begin PBXShellScriptBuildPhase section */ 201 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 202 | isa = PBXShellScriptBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | ); 206 | inputPaths = ( 207 | ); 208 | name = "Thin Binary"; 209 | outputPaths = ( 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | shellPath = /bin/sh; 213 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 214 | }; 215 | 58A7F13BF9B17BEA80A6D729 /* [CP] Embed Pods Frameworks */ = { 216 | isa = PBXShellScriptBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | ); 220 | inputPaths = ( 221 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 222 | "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", 223 | "${PODS_ROOT}/../Flutter/Flutter.framework", 224 | "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", 225 | "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", 226 | ); 227 | name = "[CP] Embed Pods Frameworks"; 228 | outputPaths = ( 229 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", 230 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 231 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", 232 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | shellPath = /bin/sh; 236 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 237 | showEnvVarsInLog = 0; 238 | }; 239 | 6A3DD026FB050040666983D1 /* [CP] Check Pods Manifest.lock */ = { 240 | isa = PBXShellScriptBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | ); 244 | inputFileListPaths = ( 245 | ); 246 | inputPaths = ( 247 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 248 | "${PODS_ROOT}/Manifest.lock", 249 | ); 250 | name = "[CP] Check Pods Manifest.lock"; 251 | outputFileListPaths = ( 252 | ); 253 | outputPaths = ( 254 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | shellPath = /bin/sh; 258 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 259 | showEnvVarsInLog = 0; 260 | }; 261 | 9740EEB61CF901F6004384FC /* Run Script */ = { 262 | isa = PBXShellScriptBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | inputPaths = ( 267 | ); 268 | name = "Run Script"; 269 | outputPaths = ( 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | shellPath = /bin/sh; 273 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 274 | }; 275 | /* End PBXShellScriptBuildPhase section */ 276 | 277 | /* Begin PBXSourcesBuildPhase section */ 278 | 97C146EA1CF9000F007C117D /* Sources */ = { 279 | isa = PBXSourcesBuildPhase; 280 | buildActionMask = 2147483647; 281 | files = ( 282 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 283 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | /* End PBXSourcesBuildPhase section */ 288 | 289 | /* Begin PBXVariantGroup section */ 290 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 291 | isa = PBXVariantGroup; 292 | children = ( 293 | 97C146FB1CF9000F007C117D /* Base */, 294 | ); 295 | name = Main.storyboard; 296 | sourceTree = ""; 297 | }; 298 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 299 | isa = PBXVariantGroup; 300 | children = ( 301 | 97C147001CF9000F007C117D /* Base */, 302 | ); 303 | name = LaunchScreen.storyboard; 304 | sourceTree = ""; 305 | }; 306 | /* End PBXVariantGroup section */ 307 | 308 | /* Begin XCBuildConfiguration section */ 309 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 310 | isa = XCBuildConfiguration; 311 | buildSettings = { 312 | ALWAYS_SEARCH_USER_PATHS = NO; 313 | CLANG_ANALYZER_NONNULL = YES; 314 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 315 | CLANG_CXX_LIBRARY = "libc++"; 316 | CLANG_ENABLE_MODULES = YES; 317 | CLANG_ENABLE_OBJC_ARC = YES; 318 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 319 | CLANG_WARN_BOOL_CONVERSION = YES; 320 | CLANG_WARN_COMMA = YES; 321 | CLANG_WARN_CONSTANT_CONVERSION = YES; 322 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 323 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 324 | CLANG_WARN_EMPTY_BODY = YES; 325 | CLANG_WARN_ENUM_CONVERSION = YES; 326 | CLANG_WARN_INFINITE_RECURSION = YES; 327 | CLANG_WARN_INT_CONVERSION = YES; 328 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 330 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 331 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 332 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 333 | CLANG_WARN_STRICT_PROTOTYPES = YES; 334 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 335 | CLANG_WARN_UNREACHABLE_CODE = YES; 336 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 337 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 338 | COPY_PHASE_STRIP = NO; 339 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 340 | ENABLE_NS_ASSERTIONS = NO; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | GCC_C_LANGUAGE_STANDARD = gnu99; 343 | GCC_NO_COMMON_BLOCKS = YES; 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VARIABLE = YES; 350 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 351 | MTL_ENABLE_DEBUG_INFO = NO; 352 | SDKROOT = iphoneos; 353 | SUPPORTED_PLATFORMS = iphoneos; 354 | TARGETED_DEVICE_FAMILY = "1,2"; 355 | VALIDATE_PRODUCT = YES; 356 | }; 357 | name = Profile; 358 | }; 359 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 360 | isa = XCBuildConfiguration; 361 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 362 | buildSettings = { 363 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 364 | CLANG_ENABLE_MODULES = YES; 365 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 366 | ENABLE_BITCODE = NO; 367 | FRAMEWORK_SEARCH_PATHS = ( 368 | "$(inherited)", 369 | "$(PROJECT_DIR)/Flutter", 370 | ); 371 | INFOPLIST_FILE = Runner/Info.plist; 372 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 373 | LIBRARY_SEARCH_PATHS = ( 374 | "$(inherited)", 375 | "$(PROJECT_DIR)/Flutter", 376 | ); 377 | PRODUCT_BUNDLE_IDENTIFIER = club.flutterchina.azlistviewExample; 378 | PRODUCT_NAME = "$(TARGET_NAME)"; 379 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 380 | SWIFT_VERSION = 5.0; 381 | VERSIONING_SYSTEM = "apple-generic"; 382 | }; 383 | name = Profile; 384 | }; 385 | 97C147031CF9000F007C117D /* Debug */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | ALWAYS_SEARCH_USER_PATHS = NO; 389 | CLANG_ANALYZER_NONNULL = YES; 390 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 391 | CLANG_CXX_LIBRARY = "libc++"; 392 | CLANG_ENABLE_MODULES = YES; 393 | CLANG_ENABLE_OBJC_ARC = YES; 394 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 395 | CLANG_WARN_BOOL_CONVERSION = YES; 396 | CLANG_WARN_COMMA = YES; 397 | CLANG_WARN_CONSTANT_CONVERSION = YES; 398 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 399 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 400 | CLANG_WARN_EMPTY_BODY = YES; 401 | CLANG_WARN_ENUM_CONVERSION = YES; 402 | CLANG_WARN_INFINITE_RECURSION = YES; 403 | CLANG_WARN_INT_CONVERSION = YES; 404 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 405 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 406 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 407 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 408 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 409 | CLANG_WARN_STRICT_PROTOTYPES = YES; 410 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 411 | CLANG_WARN_UNREACHABLE_CODE = YES; 412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 413 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 414 | COPY_PHASE_STRIP = NO; 415 | DEBUG_INFORMATION_FORMAT = dwarf; 416 | ENABLE_STRICT_OBJC_MSGSEND = YES; 417 | ENABLE_TESTABILITY = YES; 418 | GCC_C_LANGUAGE_STANDARD = gnu99; 419 | GCC_DYNAMIC_NO_PIC = NO; 420 | GCC_NO_COMMON_BLOCKS = YES; 421 | GCC_OPTIMIZATION_LEVEL = 0; 422 | GCC_PREPROCESSOR_DEFINITIONS = ( 423 | "DEBUG=1", 424 | "$(inherited)", 425 | ); 426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 428 | GCC_WARN_UNDECLARED_SELECTOR = YES; 429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 430 | GCC_WARN_UNUSED_FUNCTION = YES; 431 | GCC_WARN_UNUSED_VARIABLE = YES; 432 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 433 | MTL_ENABLE_DEBUG_INFO = YES; 434 | ONLY_ACTIVE_ARCH = YES; 435 | SDKROOT = iphoneos; 436 | TARGETED_DEVICE_FAMILY = "1,2"; 437 | }; 438 | name = Debug; 439 | }; 440 | 97C147041CF9000F007C117D /* Release */ = { 441 | isa = XCBuildConfiguration; 442 | buildSettings = { 443 | ALWAYS_SEARCH_USER_PATHS = NO; 444 | CLANG_ANALYZER_NONNULL = YES; 445 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 446 | CLANG_CXX_LIBRARY = "libc++"; 447 | CLANG_ENABLE_MODULES = YES; 448 | CLANG_ENABLE_OBJC_ARC = YES; 449 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 450 | CLANG_WARN_BOOL_CONVERSION = YES; 451 | CLANG_WARN_COMMA = YES; 452 | CLANG_WARN_CONSTANT_CONVERSION = YES; 453 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 454 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 455 | CLANG_WARN_EMPTY_BODY = YES; 456 | CLANG_WARN_ENUM_CONVERSION = YES; 457 | CLANG_WARN_INFINITE_RECURSION = YES; 458 | CLANG_WARN_INT_CONVERSION = YES; 459 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 460 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 461 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 462 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 463 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 464 | CLANG_WARN_STRICT_PROTOTYPES = YES; 465 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 466 | CLANG_WARN_UNREACHABLE_CODE = YES; 467 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 468 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 469 | COPY_PHASE_STRIP = NO; 470 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 471 | ENABLE_NS_ASSERTIONS = NO; 472 | ENABLE_STRICT_OBJC_MSGSEND = YES; 473 | GCC_C_LANGUAGE_STANDARD = gnu99; 474 | GCC_NO_COMMON_BLOCKS = YES; 475 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 476 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 477 | GCC_WARN_UNDECLARED_SELECTOR = YES; 478 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 479 | GCC_WARN_UNUSED_FUNCTION = YES; 480 | GCC_WARN_UNUSED_VARIABLE = YES; 481 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 482 | MTL_ENABLE_DEBUG_INFO = NO; 483 | SDKROOT = iphoneos; 484 | SUPPORTED_PLATFORMS = iphoneos; 485 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 486 | TARGETED_DEVICE_FAMILY = "1,2"; 487 | VALIDATE_PRODUCT = YES; 488 | }; 489 | name = Release; 490 | }; 491 | 97C147061CF9000F007C117D /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 494 | buildSettings = { 495 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 496 | CLANG_ENABLE_MODULES = YES; 497 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 498 | ENABLE_BITCODE = NO; 499 | FRAMEWORK_SEARCH_PATHS = ( 500 | "$(inherited)", 501 | "$(PROJECT_DIR)/Flutter", 502 | ); 503 | INFOPLIST_FILE = Runner/Info.plist; 504 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 505 | LIBRARY_SEARCH_PATHS = ( 506 | "$(inherited)", 507 | "$(PROJECT_DIR)/Flutter", 508 | ); 509 | PRODUCT_BUNDLE_IDENTIFIER = club.flutterchina.azlistviewExample; 510 | PRODUCT_NAME = "$(TARGET_NAME)"; 511 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 512 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 513 | SWIFT_VERSION = 5.0; 514 | VERSIONING_SYSTEM = "apple-generic"; 515 | }; 516 | name = Debug; 517 | }; 518 | 97C147071CF9000F007C117D /* Release */ = { 519 | isa = XCBuildConfiguration; 520 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 521 | buildSettings = { 522 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 523 | CLANG_ENABLE_MODULES = YES; 524 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 525 | ENABLE_BITCODE = NO; 526 | FRAMEWORK_SEARCH_PATHS = ( 527 | "$(inherited)", 528 | "$(PROJECT_DIR)/Flutter", 529 | ); 530 | INFOPLIST_FILE = Runner/Info.plist; 531 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 532 | LIBRARY_SEARCH_PATHS = ( 533 | "$(inherited)", 534 | "$(PROJECT_DIR)/Flutter", 535 | ); 536 | PRODUCT_BUNDLE_IDENTIFIER = club.flutterchina.azlistviewExample; 537 | PRODUCT_NAME = "$(TARGET_NAME)"; 538 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 539 | SWIFT_VERSION = 5.0; 540 | VERSIONING_SYSTEM = "apple-generic"; 541 | }; 542 | name = Release; 543 | }; 544 | /* End XCBuildConfiguration section */ 545 | 546 | /* Begin XCConfigurationList section */ 547 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 548 | isa = XCConfigurationList; 549 | buildConfigurations = ( 550 | 97C147031CF9000F007C117D /* Debug */, 551 | 97C147041CF9000F007C117D /* Release */, 552 | 249021D3217E4FDB00AE95B9 /* Profile */, 553 | ); 554 | defaultConfigurationIsVisible = 0; 555 | defaultConfigurationName = Release; 556 | }; 557 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 558 | isa = XCConfigurationList; 559 | buildConfigurations = ( 560 | 97C147061CF9000F007C117D /* Debug */, 561 | 97C147071CF9000F007C117D /* Release */, 562 | 249021D4217E4FDB00AE95B9 /* Profile */, 563 | ); 564 | defaultConfigurationIsVisible = 0; 565 | defaultConfigurationName = Release; 566 | }; 567 | /* End XCConfigurationList section */ 568 | }; 569 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 570 | } 571 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/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 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/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 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/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. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | azlistview_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/common/index.dart: -------------------------------------------------------------------------------- 1 | export 'models.dart'; 2 | export 'utils.dart'; 3 | export 'res.dart'; 4 | 5 | export 'dart:convert'; 6 | 7 | export 'package:common_utils/common_utils.dart'; 8 | 9 | export 'package:lpinyin/lpinyin.dart'; 10 | -------------------------------------------------------------------------------- /example/lib/common/models.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:azlistview/azlistview.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'package:github_language_colors/github_language_colors.dart'; 7 | 8 | class CityModel extends ISuspensionBean { 9 | String name; 10 | String? tagIndex; 11 | String? namePinyin; 12 | 13 | CityModel({ 14 | required this.name, 15 | this.tagIndex, 16 | this.namePinyin, 17 | }); 18 | 19 | CityModel.fromJson(Map json) : name = json['name']; 20 | 21 | Map toJson() => { 22 | 'name': name, 23 | // 'tagIndex': tagIndex, 24 | // 'namePinyin': namePinyin, 25 | // 'isShowSuspension': isShowSuspension 26 | }; 27 | 28 | @override 29 | String getSuspensionTag() => tagIndex!; 30 | 31 | @override 32 | String toString() => json.encode(this); 33 | } 34 | 35 | class ContactInfo extends ISuspensionBean { 36 | String name; 37 | String? tagIndex; 38 | String? namePinyin; 39 | 40 | Color? bgColor; 41 | IconData? iconData; 42 | 43 | String? img; 44 | String? id; 45 | String? firstletter; 46 | 47 | ContactInfo({ 48 | required this.name, 49 | this.tagIndex, 50 | this.namePinyin, 51 | this.bgColor, 52 | this.iconData, 53 | this.img, 54 | this.id, 55 | this.firstletter, 56 | }); 57 | 58 | ContactInfo.fromJson(Map json) 59 | : name = json['name'], 60 | img = json['img'], 61 | id = json['id']?.toString(), 62 | firstletter = json['firstletter']; 63 | 64 | Map toJson() => { 65 | // 'id': id, 66 | 'name': name, 67 | 'img': img, 68 | // 'firstletter': firstletter, 69 | // 'tagIndex': tagIndex, 70 | // 'namePinyin': namePinyin, 71 | // 'isShowSuspension': isShowSuspension 72 | }; 73 | 74 | @override 75 | String getSuspensionTag() => tagIndex!; 76 | 77 | @override 78 | String toString() => json.encode(this); 79 | } 80 | 81 | class Languages extends GithubLanguage with ISuspensionBean { 82 | String? tagIndex; 83 | String? pinyin; 84 | String? shortPinyin; 85 | 86 | Languages.fromJson(Map json) : super.fromJson(json); 87 | 88 | @override 89 | Map toJson() { 90 | final Map map = super.toJson(); 91 | void addIfNonNull(String fieldName, dynamic value) { 92 | if (value != null) { 93 | map[fieldName] = value; 94 | } 95 | } 96 | 97 | // addIfNonNull('tagIndex', tagIndex); 98 | return map; 99 | } 100 | 101 | @override 102 | String getSuspensionTag() { 103 | return tagIndex!; 104 | } 105 | 106 | @override 107 | String toString() { 108 | return json.encode(this); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /example/lib/common/res.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Colours { 4 | static const Color gray_33 = Color(0xFF333333); 5 | static const Color gray_66 = Color(0xFF666666); 6 | static const Color gray_99 = Color(0xFF999999); 7 | } 8 | -------------------------------------------------------------------------------- /example/lib/common/utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:azlistview_example/common/index.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class Utils { 5 | static String getImgPath(String name, {String format: 'png'}) { 6 | return 'assets/images/$name.$format'; 7 | } 8 | 9 | static void showSnackBar(BuildContext context, String msg) { 10 | ScaffoldMessenger.of(context).showSnackBar( 11 | SnackBar( 12 | content: Text(msg), 13 | duration: Duration(seconds: 2), 14 | ), 15 | ); 16 | } 17 | 18 | static Widget getSusItem(BuildContext context, String tag, 19 | {double susHeight = 40}) { 20 | if (tag == '★') { 21 | tag = '★ 热门城市'; 22 | } 23 | return Container( 24 | height: susHeight, 25 | width: MediaQuery.of(context).size.width, 26 | padding: EdgeInsets.only(left: 16.0), 27 | color: Color(0xFFF3F4F5), 28 | alignment: Alignment.centerLeft, 29 | child: Text( 30 | '$tag', 31 | softWrap: false, 32 | style: TextStyle( 33 | fontSize: 14.0, 34 | color: Color(0xFF666666), 35 | ), 36 | ), 37 | ); 38 | } 39 | 40 | static Widget getListItem(BuildContext context, CityModel model, 41 | {double susHeight = 40}) { 42 | return ListTile( 43 | title: Text(model.name), 44 | onTap: () { 45 | LogUtil.e("onItemClick : $model"); 46 | Utils.showSnackBar(context, 'onItemClick : ${model.name}'); 47 | }, 48 | ); 49 | // return Column( 50 | // mainAxisSize: MainAxisSize.min, 51 | // children: [ 52 | // Offstage( 53 | // offstage: !(model.isShowSuspension == true), 54 | // child: getSusItem(context, model.getSuspensionTag(), 55 | // susHeight: susHeight), 56 | // ), 57 | // ListTile( 58 | // title: Text(model.name), 59 | // onTap: () { 60 | // LogUtil.e("onItemClick : $model"); 61 | // Utils.showSnackBar(context, 'onItemClick : ${model.name}'); 62 | // }, 63 | // ) 64 | // ], 65 | // ); 66 | } 67 | 68 | static Widget getWeChatListItem( 69 | BuildContext context, 70 | ContactInfo model, { 71 | double susHeight = 40, 72 | Color? defHeaderBgColor, 73 | }) { 74 | return getWeChatItem(context, model, defHeaderBgColor: defHeaderBgColor); 75 | // return Column( 76 | // mainAxisSize: MainAxisSize.min, 77 | // children: [ 78 | // Offstage( 79 | // offstage: !(model.isShowSuspension == true), 80 | // child: getSusItem(context, model.getSuspensionTag(), 81 | // susHeight: susHeight), 82 | // ), 83 | // getWeChatItem(context, model, defHeaderBgColor: defHeaderBgColor), 84 | // ], 85 | // ); 86 | } 87 | 88 | static Widget getWeChatItem( 89 | BuildContext context, 90 | ContactInfo model, { 91 | Color? defHeaderBgColor, 92 | }) { 93 | DecorationImage? image; 94 | // if (model.img != null && model.img.isNotEmpty) { 95 | // image = DecorationImage( 96 | // image: CachedNetworkImageProvider(model.img), 97 | // fit: BoxFit.contain, 98 | // ); 99 | // } 100 | return ListTile( 101 | leading: Container( 102 | width: 36, 103 | height: 36, 104 | decoration: BoxDecoration( 105 | shape: BoxShape.rectangle, 106 | borderRadius: BorderRadius.circular(4.0), 107 | color: model.bgColor ?? defHeaderBgColor, 108 | image: image, 109 | ), 110 | child: model.iconData == null 111 | ? null 112 | : Icon( 113 | model.iconData, 114 | color: Colors.white, 115 | size: 20, 116 | ), 117 | ), 118 | title: Text(model.name), 119 | onTap: () { 120 | LogUtil.e("onItemClick : $model"); 121 | Utils.showSnackBar(context, 'onItemClick : ${model.name}'); 122 | }, 123 | ); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | 6 | import 'ui/index.dart'; 7 | 8 | void main() { 9 | runApp(MyApp()); 10 | if (Platform.isAndroid) { 11 | SystemChrome.setSystemUIOverlayStyle( 12 | SystemUiOverlayStyle(statusBarColor: Colors.transparent)); 13 | } 14 | } 15 | 16 | class MyApp extends StatelessWidget { 17 | @override 18 | Widget build(BuildContext context) { 19 | return MaterialApp( 20 | title: 'AzListView Demo', 21 | theme: ThemeData( 22 | primaryColor: Colors.white, 23 | accentColor: Colors.grey, 24 | //primarySwatch: Colors.white, 25 | visualDensity: VisualDensity.adaptivePlatformDensity, 26 | ), 27 | home: Scaffold( 28 | appBar: AppBar( 29 | title: const Text( 30 | 'AzListView', 31 | ), 32 | ), 33 | body: ListPage([ 34 | PageInfo("GitHub Languages", (ctx) => GitHubLanguagePage(), false), 35 | PageInfo("Contacts", (ctx) => ContactsPage(), false), 36 | PageInfo("Contacts List", (ctx) => ContactListPage()), 37 | PageInfo("City List", (ctx) => CityListPage(), false), 38 | PageInfo( 39 | "City List(Custom header)", (ctx) => CityListCustomHeaderPage()), 40 | PageInfo("Car models", (ctx) => CarModelsPage(), false), 41 | PageInfo("10000 data", (ctx) => LargeDataPage(), false), 42 | ]), 43 | ), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /example/lib/ui/car_models_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:azlistview/azlistview.dart'; 4 | import 'package:azlistview_example/common/index.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | 8 | class CarModelsPage extends StatefulWidget { 9 | @override 10 | _CarModelsPageState createState() => _CarModelsPageState(); 11 | } 12 | 13 | class _CarModelsPageState extends State { 14 | List contactList = []; 15 | 16 | double susItemHeight = 24; 17 | 18 | @override 19 | void initState() { 20 | super.initState(); 21 | loadData(); 22 | } 23 | 24 | void loadData() async { 25 | rootBundle.loadString('assets/data/car_models.json').then((value) { 26 | List list = json.decode(value); 27 | list.forEach((v) { 28 | contactList.add(ContactInfo.fromJson(v)); 29 | }); 30 | // contactList = contactList.reversed.toList(); 31 | // log('$contactList'); 32 | _handleList(contactList); 33 | }); 34 | } 35 | 36 | void _handleList(List list) { 37 | if (list.isEmpty) return; 38 | for (int i = 0, length = list.length; i < length; i++) { 39 | String pinyin = PinyinHelper.getPinyinE(list[i].name); 40 | String tag = pinyin.substring(0, 1).toUpperCase(); 41 | list[i].namePinyin = pinyin; 42 | if (RegExp("[A-Z]").hasMatch(tag)) { 43 | list[i].tagIndex = tag; 44 | } else { 45 | list[i].tagIndex = "#"; 46 | } 47 | } 48 | // A-Z sort. 49 | SuspensionUtil.sortListBySuspensionTag(contactList); 50 | 51 | // show sus tag. 52 | SuspensionUtil.setShowSuspensionStatus(contactList); 53 | 54 | // add header. 55 | contactList.insert(0, ContactInfo(name: 'header', tagIndex: '选')); 56 | 57 | setState(() {}); 58 | } 59 | 60 | Widget customHeader() { 61 | return Column( 62 | children: [ 63 | Container( 64 | color: Colors.white, 65 | padding: EdgeInsets.only(left: 32, top: 20, right: 32, bottom: 16), 66 | child: Image.asset( 67 | Utils.getImgPath('ic_car_models_header1'), 68 | fit: BoxFit.contain, 69 | ), 70 | ), 71 | Container( 72 | color: Colors.white, 73 | padding: EdgeInsets.only(left: 32, top: 0, right: 32, bottom: 16), 74 | child: Image.asset( 75 | Utils.getImgPath('ic_car_models_header2'), 76 | fit: BoxFit.contain, 77 | ), 78 | ), 79 | ], 80 | ); 81 | } 82 | 83 | @override 84 | Widget build(BuildContext context) { 85 | return Scaffold( 86 | appBar: AppBar( 87 | automaticallyImplyLeading: false, 88 | title: Text( 89 | 'Car models', 90 | style: TextStyle(color: Color(0xFF171717)), 91 | ), 92 | ), 93 | body: AzListView( 94 | data: contactList, 95 | itemCount: contactList.length, 96 | itemBuilder: (BuildContext context, int index) { 97 | if (index == 0) return customHeader(); 98 | ContactInfo model = contactList[index]; 99 | return Utils.getWeChatListItem(context, model, 100 | susHeight: susItemHeight); 101 | }, 102 | susItemHeight: susItemHeight, 103 | susItemBuilder: (BuildContext context, int index) { 104 | ContactInfo model = contactList[index]; 105 | if ('选' == model.getSuspensionTag()) { 106 | return Container(); 107 | } 108 | return Utils.getSusItem(context, model.getSuspensionTag(), 109 | susHeight: susItemHeight); 110 | }, 111 | indexBarData: ['选', ...kIndexBarData], 112 | indexBarOptions: IndexBarOptions( 113 | needRebuild: true, 114 | selectTextStyle: TextStyle( 115 | fontSize: 12, color: Colors.white, fontWeight: FontWeight.w500), 116 | selectItemDecoration: 117 | BoxDecoration(shape: BoxShape.circle, color: Color(0xFF333333)), 118 | indexHintWidth: 96, 119 | indexHintHeight: 97, 120 | indexHintDecoration: BoxDecoration( 121 | image: DecorationImage( 122 | image: AssetImage(Utils.getImgPath('ic_index_bar_bubble_white')), 123 | fit: BoxFit.contain, 124 | ), 125 | ), 126 | indexHintAlignment: Alignment.centerRight, 127 | indexHintTextStyle: TextStyle(fontSize: 24.0, color: Colors.black87), 128 | indexHintOffset: Offset(-30, 0), 129 | ), 130 | ), 131 | ); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /example/lib/ui/citylist_custom_header_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:azlistview/azlistview.dart'; 2 | import 'package:azlistview_example/common/index.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | 6 | class CityListCustomHeaderPage extends StatefulWidget { 7 | @override 8 | _CityListCustomHeaderPageState createState() => 9 | _CityListCustomHeaderPageState(); 10 | } 11 | 12 | class _CityListCustomHeaderPageState extends State { 13 | List cityList = []; 14 | double susItemHeight = 36; 15 | String imgFavorite = Utils.getImgPath('ic_favorite'); 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | Future.delayed(Duration(milliseconds: 500), () { 21 | loadData(); 22 | }); 23 | } 24 | 25 | void loadData() async { 26 | //加载城市列表 27 | rootBundle.loadString('assets/data/china.json').then((value) { 28 | cityList.clear(); 29 | Map countyMap = json.decode(value); 30 | List list = countyMap['china']; 31 | list.forEach((v) { 32 | cityList.add(CityModel.fromJson(v)); 33 | }); 34 | _handleList(cityList); 35 | }); 36 | } 37 | 38 | void _handleList(List list) { 39 | if (list.isEmpty) return; 40 | for (int i = 0, length = list.length; i < length; i++) { 41 | String pinyin = PinyinHelper.getPinyinE(list[i].name); 42 | String tag = pinyin.substring(0, 1).toUpperCase(); 43 | list[i].namePinyin = pinyin; 44 | if (RegExp('[A-Z]').hasMatch(tag)) { 45 | list[i].tagIndex = tag; 46 | } else { 47 | list[i].tagIndex = '#'; 48 | } 49 | } 50 | // A-Z sort. 51 | SuspensionUtil.sortListBySuspensionTag(list); 52 | 53 | // show sus tag. 54 | SuspensionUtil.setShowSuspensionStatus(cityList); 55 | 56 | // add header. 57 | cityList.insert( 58 | 0, 59 | CityModel( 60 | name: 'header', 61 | tagIndex: imgFavorite)); //index bar support local images. 62 | 63 | setState(() {}); 64 | } 65 | 66 | Widget _buildHeader() { 67 | List hotCityList = []; 68 | hotCityList.addAll([ 69 | CityModel(name: "北京市"), 70 | CityModel(name: "广州市"), 71 | CityModel(name: "成都市"), 72 | CityModel(name: "深圳市"), 73 | CityModel(name: "杭州市"), 74 | CityModel(name: "武汉市"), 75 | ]); 76 | return Padding( 77 | padding: const EdgeInsets.all(20), 78 | child: Wrap( 79 | alignment: WrapAlignment.center, 80 | runAlignment: WrapAlignment.center, 81 | spacing: 10.0, 82 | children: hotCityList.map((e) { 83 | return OutlinedButton( 84 | style: ButtonStyle( 85 | //side: BorderSide(color: Colors.grey[300], width: .5), 86 | ), 87 | child: Padding( 88 | padding: EdgeInsets.only(left: 10, right: 10), 89 | child: Text(e.name), 90 | ), 91 | onPressed: () { 92 | print("OnItemClick: $e"); 93 | Navigator.pop(context, e); 94 | }, 95 | ); 96 | }).toList(), 97 | ), 98 | ); 99 | } 100 | 101 | @override 102 | Widget build(BuildContext context) { 103 | return Column( 104 | children: [ 105 | ListTile( 106 | title: Text("当前城市"), 107 | trailing: Row( 108 | mainAxisSize: MainAxisSize.min, 109 | children: [ 110 | Icon( 111 | Icons.place, 112 | size: 20.0, 113 | ), 114 | Text(" 成都市"), 115 | ], 116 | )), 117 | Divider( 118 | height: .0, 119 | ), 120 | Expanded( 121 | child: AzListView( 122 | data: cityList, 123 | itemCount: cityList.length, 124 | itemBuilder: (BuildContext context, int index) { 125 | if (index == 0) return _buildHeader(); 126 | CityModel model = cityList[index]; 127 | return Utils.getListItem(context, model, 128 | susHeight: susItemHeight); 129 | }, 130 | susItemHeight: susItemHeight, 131 | susItemBuilder: (BuildContext context, int index) { 132 | CityModel model = cityList[index]; 133 | String tag = model.getSuspensionTag(); 134 | if (imgFavorite == tag) { 135 | return Container(); 136 | } 137 | return Utils.getSusItem(context, tag, susHeight: susItemHeight); 138 | }, 139 | indexBarData: SuspensionUtil.getTagIndexList(cityList), 140 | indexBarOptions: IndexBarOptions( 141 | needRebuild: true, 142 | color: Colors.transparent, 143 | downColor: Color(0xFFEEEEEE), 144 | localImages: [imgFavorite], //local images. 145 | ), 146 | ), 147 | ), 148 | ], 149 | ); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /example/lib/ui/citylist_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:azlistview/azlistview.dart'; 2 | import 'package:azlistview_example/common/index.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | 6 | class CityListPage extends StatefulWidget { 7 | @override 8 | _CityListPageState createState() => _CityListPageState(); 9 | } 10 | 11 | class _CityListPageState extends State { 12 | List cityList = []; 13 | List _hotCityList = []; 14 | 15 | @override 16 | void initState() { 17 | super.initState(); 18 | _hotCityList.add(CityModel(name: '北京市', tagIndex: '★')); 19 | _hotCityList.add(CityModel(name: '广州市', tagIndex: '★')); 20 | _hotCityList.add(CityModel(name: '成都市', tagIndex: '★')); 21 | _hotCityList.add(CityModel(name: '深圳市', tagIndex: '★')); 22 | _hotCityList.add(CityModel(name: '杭州市', tagIndex: '★')); 23 | _hotCityList.add(CityModel(name: '武汉市', tagIndex: '★')); 24 | cityList.addAll(_hotCityList); 25 | SuspensionUtil.setShowSuspensionStatus(cityList); 26 | 27 | Future.delayed(Duration(milliseconds: 500), () { 28 | loadData(); 29 | }); 30 | } 31 | 32 | void loadData() async { 33 | //加载城市列表 34 | rootBundle.loadString('assets/data/china.json').then((value) { 35 | cityList.clear(); 36 | Map countyMap = json.decode(value); 37 | List list = countyMap['china']; 38 | list.forEach((v) { 39 | cityList.add(CityModel.fromJson(v)); 40 | }); 41 | _handleList(cityList); 42 | }); 43 | } 44 | 45 | void _handleList(List list) { 46 | if (list.isEmpty) return; 47 | for (int i = 0, length = list.length; i < length; i++) { 48 | String pinyin = PinyinHelper.getPinyinE(list[i].name); 49 | String tag = pinyin.substring(0, 1).toUpperCase(); 50 | list[i].namePinyin = pinyin; 51 | if (RegExp('[A-Z]').hasMatch(tag)) { 52 | list[i].tagIndex = tag; 53 | } else { 54 | list[i].tagIndex = '#'; 55 | } 56 | } 57 | // A-Z sort. 58 | SuspensionUtil.sortListBySuspensionTag(list); 59 | 60 | // add hotCityList. 61 | cityList.insertAll(0, _hotCityList); 62 | 63 | // show sus tag. 64 | SuspensionUtil.setShowSuspensionStatus(cityList); 65 | 66 | setState(() {}); 67 | } 68 | 69 | Widget header() { 70 | return Container( 71 | color: Colors.white, 72 | height: 44.0, 73 | child: Row( 74 | children: [ 75 | Expanded( 76 | child: TextField( 77 | autofocus: false, 78 | decoration: InputDecoration( 79 | contentPadding: EdgeInsets.only(left: 10, right: 10), 80 | border: InputBorder.none, 81 | labelStyle: TextStyle(fontSize: 14, color: Color(0xFF333333)), 82 | hintText: '城市中文名或拼音', 83 | hintStyle: TextStyle(fontSize: 14, color: Color(0xFFCCCCCC))), 84 | )), 85 | Container( 86 | width: 0.33, 87 | height: 14.0, 88 | color: Color(0xFFEFEFEF), 89 | ), 90 | InkWell( 91 | onTap: () { 92 | Navigator.pop(context); 93 | }, 94 | child: Padding( 95 | padding: const EdgeInsets.all(10.0), 96 | child: Text( 97 | "取消", 98 | style: TextStyle(color: Color(0xFF999999), fontSize: 14), 99 | ), 100 | ), 101 | ) 102 | ], 103 | ), 104 | ); 105 | } 106 | 107 | @override 108 | Widget build(BuildContext context) { 109 | return Scaffold( 110 | resizeToAvoidBottomInset: false, 111 | body: SafeArea( 112 | child: Column( 113 | children: [ 114 | header(), 115 | Expanded( 116 | child: Material( 117 | color: Color(0x80000000), 118 | child: Card( 119 | clipBehavior: Clip.hardEdge, 120 | margin: const EdgeInsets.only(left: 8, top: 8, right: 8), 121 | shape: const RoundedRectangleBorder( 122 | borderRadius: const BorderRadius.only( 123 | topLeft: Radius.circular(4.0), 124 | topRight: Radius.circular(4.0)), 125 | ), 126 | child: Column( 127 | children: [ 128 | Container( 129 | alignment: Alignment.centerLeft, 130 | padding: const EdgeInsets.only(left: 15.0), 131 | height: 50.0, 132 | child: Text("当前城市: 成都市"), 133 | ), 134 | Expanded( 135 | child: AzListView( 136 | data: cityList, 137 | itemCount: cityList.length, 138 | itemBuilder: (BuildContext context, int index) { 139 | CityModel model = cityList[index]; 140 | return Utils.getListItem(context, model); 141 | }, 142 | padding: EdgeInsets.zero, 143 | susItemBuilder: (BuildContext context, int index) { 144 | CityModel model = cityList[index]; 145 | String tag = model.getSuspensionTag(); 146 | return Utils.getSusItem(context, tag); 147 | }, 148 | indexBarData: ['★', ...kIndexBarData], 149 | ), 150 | ) 151 | ], 152 | ), 153 | ), 154 | ), 155 | ), 156 | ], 157 | )), 158 | ); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /example/lib/ui/contacts_list_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:azlistview/azlistview.dart'; 2 | import 'package:azlistview_example/common/index.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | 6 | class ContactListPage extends StatefulWidget { 7 | @override 8 | State createState() { 9 | return new _ContactListPageState(); 10 | } 11 | } 12 | 13 | class _ContactListPageState extends State { 14 | List _contacts = []; 15 | double susItemHeight = 40; 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | loadData(); 21 | } 22 | 23 | void loadData() async { 24 | //加载联系人列表 25 | rootBundle.loadString('assets/data/contacts.json').then((value) { 26 | List list = json.decode(value); 27 | list.forEach((v) { 28 | _contacts.add(ContactInfo.fromJson(v)); 29 | }); 30 | _handleList(_contacts); 31 | }); 32 | } 33 | 34 | void _handleList(List list) { 35 | if (list.isEmpty) return; 36 | for (int i = 0, length = list.length; i < length; i++) { 37 | String pinyin = PinyinHelper.getPinyinE(list[i].name); 38 | String tag = pinyin.substring(0, 1).toUpperCase(); 39 | list[i].namePinyin = pinyin; 40 | if (RegExp("[A-Z]").hasMatch(tag)) { 41 | list[i].tagIndex = tag; 42 | } else { 43 | list[i].tagIndex = "#"; 44 | } 45 | } 46 | // A-Z sort. 47 | SuspensionUtil.sortListBySuspensionTag(_contacts); 48 | 49 | // show sus tag. 50 | SuspensionUtil.setShowSuspensionStatus(_contacts); 51 | 52 | // add header. 53 | _contacts.insert(0, ContactInfo(name: 'header', tagIndex: '↑')); 54 | 55 | setState(() {}); 56 | } 57 | 58 | Widget _buildHeader() { 59 | return Container( 60 | padding: EdgeInsets.all(20), 61 | alignment: Alignment.center, 62 | child: Column( 63 | mainAxisAlignment: MainAxisAlignment.center, 64 | children: [ 65 | ClipOval( 66 | child: Image.asset( 67 | "./assets/images/avatar.png", 68 | width: 80.0, 69 | )), 70 | Padding( 71 | padding: const EdgeInsets.all(8.0), 72 | child: Text( 73 | "远行", 74 | textScaleFactor: 1.2, 75 | ), 76 | ), 77 | Text("+86 182-286-44678"), 78 | ], 79 | ), 80 | ); 81 | } 82 | 83 | Widget _buildSusWidget(String susTag) { 84 | return Container( 85 | padding: EdgeInsets.symmetric(horizontal: 15.0), 86 | height: susItemHeight, 87 | width: double.infinity, 88 | alignment: Alignment.centerLeft, 89 | child: Row( 90 | children: [ 91 | Text( 92 | '$susTag', 93 | textScaleFactor: 1.2, 94 | ), 95 | Expanded( 96 | child: Divider( 97 | height: .0, 98 | indent: 10.0, 99 | )) 100 | ], 101 | ), 102 | ); 103 | } 104 | 105 | Widget _buildListItem(ContactInfo model) { 106 | String susTag = model.getSuspensionTag(); 107 | return Column( 108 | children: [ 109 | Offstage( 110 | offstage: model.isShowSuspension != true, 111 | child: _buildSusWidget(susTag), 112 | ), 113 | ListTile( 114 | leading: CircleAvatar( 115 | backgroundColor: Colors.blue[700], 116 | child: Text( 117 | model.name[0], 118 | style: TextStyle(color: Colors.white), 119 | ), 120 | ), 121 | title: Text(model.name), 122 | onTap: () { 123 | print("OnItemClick: $model"); 124 | Navigator.pop(context, model); 125 | }, 126 | ) 127 | ], 128 | ); 129 | } 130 | 131 | Decoration getIndexBarDecoration(Color color) { 132 | return BoxDecoration( 133 | color: color, 134 | borderRadius: BorderRadius.circular(20.0), 135 | border: Border.all(color: Colors.grey[300]!, width: .5)); 136 | } 137 | 138 | @override 139 | Widget build(BuildContext context) { 140 | return AzListView( 141 | data: _contacts, 142 | itemCount: _contacts.length, 143 | itemBuilder: (BuildContext context, int index) { 144 | if (index == 0) return _buildHeader(); 145 | ContactInfo model = _contacts[index]; 146 | return _buildListItem(model); 147 | }, 148 | physics: BouncingScrollPhysics(), 149 | indexBarData: SuspensionUtil.getTagIndexList(_contacts), 150 | indexHintBuilder: (context, hint) { 151 | return Container( 152 | alignment: Alignment.center, 153 | width: 60.0, 154 | height: 60.0, 155 | decoration: BoxDecoration( 156 | color: Colors.blue[700]!.withAlpha(200), 157 | shape: BoxShape.circle, 158 | ), 159 | child: 160 | Text(hint, style: TextStyle(color: Colors.white, fontSize: 30.0)), 161 | ); 162 | }, 163 | indexBarMargin: EdgeInsets.all(10), 164 | indexBarOptions: IndexBarOptions( 165 | needRebuild: true, 166 | decoration: getIndexBarDecoration(Colors.grey[50]!), 167 | downDecoration: getIndexBarDecoration(Colors.grey[200]!), 168 | ), 169 | ); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /example/lib/ui/contacts_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:azlistview/azlistview.dart'; 2 | import 'package:azlistview_example/common/index.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | 6 | class ContactsPage extends StatefulWidget { 7 | @override 8 | _ContactsPageState createState() => _ContactsPageState(); 9 | } 10 | 11 | class _ContactsPageState extends State { 12 | List contactList = []; 13 | List topList = []; 14 | 15 | @override 16 | void initState() { 17 | super.initState(); 18 | topList.add(ContactInfo( 19 | name: '新的朋友', 20 | tagIndex: '↑', 21 | bgColor: Colors.orange, 22 | iconData: Icons.person_add)); 23 | topList.add(ContactInfo( 24 | name: '群聊', 25 | tagIndex: '↑', 26 | bgColor: Colors.green, 27 | iconData: Icons.people)); 28 | topList.add(ContactInfo( 29 | name: '标签', 30 | tagIndex: '↑', 31 | bgColor: Colors.blue, 32 | iconData: Icons.local_offer)); 33 | topList.add(ContactInfo( 34 | name: '公众号', 35 | tagIndex: '↑', 36 | bgColor: Colors.blueAccent, 37 | iconData: Icons.person)); 38 | loadData(); 39 | } 40 | 41 | void loadData() async { 42 | //加载联系人列表 43 | rootBundle.loadString('assets/data/car_models.json').then((value) { 44 | List list = json.decode(value); 45 | list.forEach((v) { 46 | contactList.add(ContactInfo.fromJson(v)); 47 | }); 48 | _handleList(contactList); 49 | }); 50 | } 51 | 52 | void _handleList(List list) { 53 | if (list.isEmpty) return; 54 | for (int i = 0, length = list.length; i < length; i++) { 55 | String pinyin = PinyinHelper.getPinyinE(list[i].name); 56 | String tag = pinyin.substring(0, 1).toUpperCase(); 57 | list[i].namePinyin = pinyin; 58 | if (RegExp("[A-Z]").hasMatch(tag)) { 59 | list[i].tagIndex = tag; 60 | } else { 61 | list[i].tagIndex = "#"; 62 | } 63 | } 64 | // A-Z sort. 65 | SuspensionUtil.sortListBySuspensionTag(contactList); 66 | 67 | // show sus tag. 68 | SuspensionUtil.setShowSuspensionStatus(contactList); 69 | 70 | // add topList. 71 | contactList.insertAll(0, topList); 72 | 73 | setState(() {}); 74 | } 75 | 76 | @override 77 | Widget build(BuildContext context) { 78 | return Scaffold( 79 | appBar: AppBar( 80 | automaticallyImplyLeading: false, 81 | backgroundColor: Color(0xFFEDEDED), 82 | title: Text( 83 | 'Contants', 84 | style: TextStyle(color: Color(0xFF171717)), 85 | ), 86 | ), 87 | body: AzListView( 88 | data: contactList, 89 | itemCount: contactList.length, 90 | itemBuilder: (BuildContext context, int index) { 91 | ContactInfo model = contactList[index]; 92 | return Utils.getWeChatListItem( 93 | context, 94 | model, 95 | defHeaderBgColor: Color(0xFFE5E5E5), 96 | ); 97 | }, 98 | physics: BouncingScrollPhysics(), 99 | susItemBuilder: (BuildContext context, int index) { 100 | ContactInfo model = contactList[index]; 101 | if ('↑' == model.getSuspensionTag()) { 102 | return Container(); 103 | } 104 | return Utils.getSusItem(context, model.getSuspensionTag()); 105 | }, 106 | indexBarData: ['↑', '☆', ...kIndexBarData], 107 | indexBarOptions: IndexBarOptions( 108 | needRebuild: true, 109 | ignoreDragCancel: true, 110 | downTextStyle: TextStyle(fontSize: 12, color: Colors.white), 111 | downItemDecoration: 112 | BoxDecoration(shape: BoxShape.circle, color: Colors.green), 113 | indexHintWidth: 120 / 2, 114 | indexHintHeight: 100 / 2, 115 | indexHintDecoration: BoxDecoration( 116 | image: DecorationImage( 117 | image: AssetImage(Utils.getImgPath('ic_index_bar_bubble_gray')), 118 | fit: BoxFit.contain, 119 | ), 120 | ), 121 | indexHintAlignment: Alignment.centerRight, 122 | indexHintChildAlignment: Alignment(-0.25, 0.0), 123 | indexHintOffset: Offset(-20, 0), 124 | ), 125 | ), 126 | ); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /example/lib/ui/github_language_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:azlistview/azlistview.dart'; 4 | import 'package:azlistview_example/common/index.dart'; 5 | 6 | import 'package:github_language_colors/github_language_colors.dart'; 7 | import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; 8 | 9 | class GitHubLanguagePage extends StatefulWidget { 10 | const GitHubLanguagePage({ 11 | Key? key, 12 | this.fromType, 13 | }) : super(key: key); 14 | final int? fromType; 15 | 16 | @override 17 | _GitHubLanguagePageState createState() => _GitHubLanguagePageState(); 18 | } 19 | 20 | class _GitHubLanguagePageState extends State { 21 | /// Controller to scroll or jump to a particular item. 22 | final ItemScrollController itemScrollController = ItemScrollController(); 23 | 24 | List originList = []; 25 | List dataList = []; 26 | 27 | late TextEditingController textEditingController; 28 | 29 | @override 30 | void initState() { 31 | super.initState(); 32 | textEditingController = TextEditingController(); 33 | loadData(); 34 | } 35 | 36 | @override 37 | void dispose() { 38 | textEditingController.dispose(); 39 | super.dispose(); 40 | } 41 | 42 | void loadData() async { 43 | originList = LanguageHelper.getGithubLanguages().map((v) { 44 | Languages model = Languages.fromJson(v.toJson()); 45 | String tag = model.name.substring(0, 1).toUpperCase(); 46 | if (RegExp("[A-Z]").hasMatch(tag)) { 47 | model.tagIndex = tag; 48 | } else { 49 | model.tagIndex = "#"; 50 | } 51 | return model; 52 | }).toList(); 53 | _handleList(originList); 54 | } 55 | 56 | void _handleList(List list) { 57 | dataList.clear(); 58 | if (ObjectUtil.isEmpty(list)) { 59 | setState(() {}); 60 | return; 61 | } 62 | dataList.addAll(list); 63 | 64 | // A-Z sort. 65 | SuspensionUtil.sortListBySuspensionTag(dataList); 66 | 67 | // show sus tag. 68 | SuspensionUtil.setShowSuspensionStatus(dataList); 69 | 70 | setState(() {}); 71 | 72 | if (itemScrollController.isAttached) { 73 | itemScrollController.jumpTo(index: 0); 74 | } 75 | } 76 | 77 | Widget getSusItem(BuildContext context, String tag, {double susHeight = 40}) { 78 | return Container( 79 | height: susHeight, 80 | width: MediaQuery.of(context).size.width, 81 | padding: EdgeInsets.only(left: 16.0), 82 | color: Color(0xFFF3F4F5), 83 | alignment: Alignment.centerLeft, 84 | child: Text( 85 | '$tag', 86 | softWrap: false, 87 | style: TextStyle( 88 | fontSize: 14.0, 89 | color: Color(0xFF666666), 90 | ), 91 | ), 92 | ); 93 | } 94 | 95 | Widget getListItem(BuildContext context, Languages model, 96 | {double susHeight = 40}) { 97 | return ListTile( 98 | title: Text(model.name), 99 | onTap: () { 100 | LogUtil.v("onItemClick : $model"); 101 | Utils.showSnackBar(context, "onItemClick : $model"); 102 | }, 103 | ); 104 | } 105 | 106 | void _search(String text) { 107 | if (ObjectUtil.isEmpty(text)) { 108 | _handleList(originList); 109 | } else { 110 | List list = originList.where((v) { 111 | return v.name.toLowerCase().contains(text.toLowerCase()); 112 | }).toList(); 113 | _handleList(list); 114 | } 115 | } 116 | 117 | @override 118 | Widget build(BuildContext context) { 119 | return Scaffold( 120 | resizeToAvoidBottomInset: false, 121 | body: SafeArea( 122 | child: Column( 123 | children: [ 124 | Container( 125 | margin: EdgeInsets.all(12), 126 | decoration: BoxDecoration( 127 | border: Border.all( 128 | color: Color.fromARGB(255, 225, 226, 230), width: 0.33), 129 | color: Color.fromARGB(255, 239, 240, 244), 130 | borderRadius: BorderRadius.circular(12)), 131 | child: TextField( 132 | autofocus: false, 133 | onChanged: (value) { 134 | _search(value); 135 | }, 136 | controller: textEditingController, 137 | decoration: InputDecoration( 138 | prefixIcon: Icon( 139 | Icons.search, 140 | color: Colours.gray_33, 141 | ), 142 | suffixIcon: Offstage( 143 | offstage: textEditingController.text.isEmpty, 144 | child: InkWell( 145 | onTap: () { 146 | textEditingController.clear(); 147 | _search(''); 148 | }, 149 | child: Icon( 150 | Icons.cancel, 151 | color: Colours.gray_99, 152 | ), 153 | ), 154 | ), 155 | border: InputBorder.none, 156 | hintText: 'Search language', 157 | hintStyle: TextStyle(color: Colours.gray_99)), 158 | ), 159 | ), 160 | Expanded( 161 | child: AzListView( 162 | data: dataList, 163 | physics: AlwaysScrollableScrollPhysics(), 164 | itemCount: dataList.length, 165 | itemBuilder: (BuildContext context, int index) { 166 | Languages model = dataList[index]; 167 | return getListItem(context, model); 168 | }, 169 | itemScrollController: itemScrollController, 170 | susItemBuilder: (BuildContext context, int index) { 171 | Languages model = dataList[index]; 172 | return getSusItem(context, model.getSuspensionTag()); 173 | }, 174 | indexBarOptions: IndexBarOptions( 175 | needRebuild: true, 176 | hapticFeedback: true, 177 | selectTextStyle: TextStyle( 178 | fontSize: 12, 179 | color: Colors.white, 180 | fontWeight: FontWeight.w500), 181 | selectItemDecoration: BoxDecoration( 182 | shape: BoxShape.circle, color: Color(0xFF333333)), 183 | indexHintWidth: 96, 184 | indexHintHeight: 97, 185 | indexHintDecoration: BoxDecoration( 186 | image: DecorationImage( 187 | image: AssetImage( 188 | Utils.getImgPath('ic_index_bar_bubble_white')), 189 | fit: BoxFit.contain, 190 | ), 191 | ), 192 | indexHintAlignment: Alignment.centerRight, 193 | indexHintTextStyle: 194 | TextStyle(fontSize: 24.0, color: Colors.black87), 195 | indexHintOffset: Offset(-30, 0), 196 | ), 197 | ), 198 | ) 199 | ], 200 | ), 201 | ), 202 | ); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /example/lib/ui/index.dart: -------------------------------------------------------------------------------- 1 | export 'page_scaffold.dart'; 2 | export 'github_language_page.dart'; 3 | export 'contacts_page.dart'; 4 | export 'contacts_list_page.dart'; 5 | export 'citylist_page.dart'; 6 | export 'citylist_custom_header_page.dart'; 7 | export 'car_models_page.dart'; 8 | export 'large_data_page.dart'; 9 | -------------------------------------------------------------------------------- /example/lib/ui/large_data_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:azlistview/azlistview.dart'; 2 | import 'package:azlistview_example/common/index.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class LargeDataPage extends StatefulWidget { 6 | @override 7 | _LargeDataPageState createState() => _LargeDataPageState(); 8 | } 9 | 10 | class _LargeDataPageState extends State { 11 | List cityList = []; 12 | int numberOfItems = 10000; 13 | double susItemHeight = 40; 14 | 15 | @override 16 | void initState() { 17 | super.initState(); 18 | int i = 0; 19 | cityList = List.generate(numberOfItems, (index) { 20 | if (index > (i + 1) * 385) { 21 | i = i + 1; 22 | } 23 | String tag = kIndexBarData[i]; 24 | CityModel model = CityModel(name: '$tag $index', tagIndex: tag); 25 | return model; 26 | }); 27 | SuspensionUtil.setShowSuspensionStatus(cityList); 28 | } 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return Scaffold( 33 | appBar: AppBar( 34 | title: Text('10000 data'), 35 | ), 36 | body: AzListView( 37 | data: cityList, 38 | itemCount: cityList.length, 39 | itemBuilder: (BuildContext context, int index) { 40 | CityModel model = cityList[index]; 41 | return Utils.getListItem(context, model); 42 | }, 43 | physics: BouncingScrollPhysics(), 44 | susItemHeight: susItemHeight, 45 | susItemBuilder: (BuildContext context, int index) { 46 | CityModel model = cityList[index]; 47 | return Utils.getSusItem(context, model.getSuspensionTag()); 48 | }, 49 | ), 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /example/lib/ui/page_scaffold.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class PageScaffold extends StatelessWidget { 5 | PageScaffold({required this.title, required this.body}); 6 | 7 | final String title; 8 | final Widget body; 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return Scaffold( 13 | appBar: AppBar( 14 | title: Text(title), 15 | ), 16 | body: body, 17 | ); 18 | } 19 | } 20 | 21 | class PageInfo { 22 | PageInfo(this.title, this.builder, [this.withScaffold = true]); 23 | 24 | String title; 25 | WidgetBuilder builder; 26 | bool withScaffold; 27 | } 28 | 29 | class ListPage extends StatelessWidget { 30 | ListPage(this.children); 31 | 32 | final List children; 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return ListView(children: _generateItem(context)); 37 | } 38 | 39 | void _openPage(BuildContext context, PageInfo page) { 40 | //CupertinoPageRoute 41 | //MaterialPageRoute 42 | Navigator.push(context, CupertinoPageRoute(builder: (context) { 43 | if (!page.withScaffold) { 44 | return page.builder(context); 45 | } 46 | return PageScaffold(title: page.title, body: page.builder(context)); 47 | })); 48 | } 49 | 50 | List _generateItem(BuildContext context) { 51 | return children.map((page) { 52 | return ListTile( 53 | title: Text(page.title), 54 | trailing: Icon(Icons.keyboard_arrow_right), 55 | onTap: () => _openPage(context, page), 56 | ); 57 | }).toList(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /example/pkgget: -------------------------------------------------------------------------------- 1 | export PUB_HOSTED_URL=https://pub.flutter-io.cn 2 | export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn 3 | flutter packages get -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.8.2" 11 | azlistview: 12 | dependency: "direct main" 13 | description: 14 | path: ".." 15 | relative: true 16 | source: path 17 | version: "2.0.0" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "2.1.0" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.2.0" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.3.1" 39 | clock: 40 | dependency: transitive 41 | description: 42 | name: clock 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.1.0" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "1.15.0" 53 | common_utils: 54 | dependency: "direct main" 55 | description: 56 | name: common_utils 57 | url: "https://pub.flutter-io.cn" 58 | source: hosted 59 | version: "2.0.1" 60 | convert: 61 | dependency: transitive 62 | description: 63 | name: convert 64 | url: "https://pub.flutter-io.cn" 65 | source: hosted 66 | version: "3.0.0" 67 | crypto: 68 | dependency: transitive 69 | description: 70 | name: crypto 71 | url: "https://pub.flutter-io.cn" 72 | source: hosted 73 | version: "3.0.0" 74 | cupertino_icons: 75 | dependency: "direct main" 76 | description: 77 | name: cupertino_icons 78 | url: "https://pub.flutter-io.cn" 79 | source: hosted 80 | version: "0.1.3" 81 | decimal: 82 | dependency: transitive 83 | description: 84 | name: decimal 85 | url: "https://pub.flutter-io.cn" 86 | source: hosted 87 | version: "1.0.0" 88 | fake_async: 89 | dependency: transitive 90 | description: 91 | name: fake_async 92 | url: "https://pub.flutter-io.cn" 93 | source: hosted 94 | version: "1.2.0" 95 | flutter: 96 | dependency: "direct main" 97 | description: flutter 98 | source: sdk 99 | version: "0.0.0" 100 | flutter_test: 101 | dependency: "direct dev" 102 | description: flutter 103 | source: sdk 104 | version: "0.0.0" 105 | github_language_colors: 106 | dependency: "direct main" 107 | description: 108 | path: "." 109 | ref: HEAD 110 | resolved-ref: b4f88207ebc0c5dcc8baa1676a0fd7796974173a 111 | url: "git://github.com/Sky24n/github_language_colors.git" 112 | source: git 113 | version: "2.0.0" 114 | lpinyin: 115 | dependency: "direct main" 116 | description: 117 | name: lpinyin 118 | url: "https://pub.flutter-io.cn" 119 | source: hosted 120 | version: "2.0.1" 121 | matcher: 122 | dependency: transitive 123 | description: 124 | name: matcher 125 | url: "https://pub.flutter-io.cn" 126 | source: hosted 127 | version: "0.12.11" 128 | material_color_utilities: 129 | dependency: transitive 130 | description: 131 | name: material_color_utilities 132 | url: "https://pub.flutter-io.cn" 133 | source: hosted 134 | version: "0.1.3" 135 | meta: 136 | dependency: transitive 137 | description: 138 | name: meta 139 | url: "https://pub.flutter-io.cn" 140 | source: hosted 141 | version: "1.7.0" 142 | path: 143 | dependency: transitive 144 | description: 145 | name: path 146 | url: "https://pub.flutter-io.cn" 147 | source: hosted 148 | version: "1.8.0" 149 | rational: 150 | dependency: transitive 151 | description: 152 | name: rational 153 | url: "https://pub.flutter-io.cn" 154 | source: hosted 155 | version: "1.0.0" 156 | scrollable_positioned_list: 157 | dependency: transitive 158 | description: 159 | name: scrollable_positioned_list 160 | url: "https://pub.flutter-io.cn" 161 | source: hosted 162 | version: "0.2.3" 163 | sky_engine: 164 | dependency: transitive 165 | description: flutter 166 | source: sdk 167 | version: "0.0.99" 168 | source_span: 169 | dependency: transitive 170 | description: 171 | name: source_span 172 | url: "https://pub.flutter-io.cn" 173 | source: hosted 174 | version: "1.8.1" 175 | stack_trace: 176 | dependency: transitive 177 | description: 178 | name: stack_trace 179 | url: "https://pub.flutter-io.cn" 180 | source: hosted 181 | version: "1.10.0" 182 | stream_channel: 183 | dependency: transitive 184 | description: 185 | name: stream_channel 186 | url: "https://pub.flutter-io.cn" 187 | source: hosted 188 | version: "2.1.0" 189 | string_scanner: 190 | dependency: transitive 191 | description: 192 | name: string_scanner 193 | url: "https://pub.flutter-io.cn" 194 | source: hosted 195 | version: "1.1.0" 196 | term_glyph: 197 | dependency: transitive 198 | description: 199 | name: term_glyph 200 | url: "https://pub.flutter-io.cn" 201 | source: hosted 202 | version: "1.2.0" 203 | test_api: 204 | dependency: transitive 205 | description: 206 | name: test_api 207 | url: "https://pub.flutter-io.cn" 208 | source: hosted 209 | version: "0.4.8" 210 | typed_data: 211 | dependency: transitive 212 | description: 213 | name: typed_data 214 | url: "https://pub.flutter-io.cn" 215 | source: hosted 216 | version: "1.3.0" 217 | vector_math: 218 | dependency: transitive 219 | description: 220 | name: vector_math 221 | url: "https://pub.flutter-io.cn" 222 | source: hosted 223 | version: "2.1.1" 224 | sdks: 225 | dart: ">=2.14.0 <3.0.0" 226 | flutter: ">=1.17.0" 227 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: azlistview_example 2 | description: A new Flutter application. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.12.0 <3.0.0" 22 | flutter: ">=1.17.0 <2.0.0" 23 | 24 | dependencies: 25 | flutter: 26 | sdk: flutter 27 | 28 | 29 | # The following adds the Cupertino Icons font to your application. 30 | # Use with the CupertinoIcons class for iOS style icons. 31 | cupertino_icons: ^0.1.3 32 | common_utils: ^2.0.0 33 | # 汉字转拼音 34 | lpinyin: ^2.0.0 35 | azlistview: 36 | path: ../ 37 | 38 | # github_language_colors 39 | # url: https://github.com/Sky24n/github_language_colors.git 40 | # or 41 | # url: git://github.com/Sky24n/github_language_colors.git 42 | github_language_colors: 43 | git: 44 | url: git://github.com/Sky24n/github_language_colors.git 45 | 46 | dev_dependencies: 47 | flutter_test: 48 | sdk: flutter 49 | 50 | # For information on the generic Dart part of this file, see the 51 | # following page: https://dart.dev/tools/pub/pubspec 52 | 53 | # The following section is specific to Flutter. 54 | flutter: 55 | 56 | # The following line ensures that the Material Icons font is 57 | # included with your application, so that you can use the icons in 58 | # the material Icons class. 59 | uses-material-design: true 60 | 61 | assets: 62 | - assets/images/ 63 | - assets/data/ 64 | 65 | # To add assets to your application, add an assets section, like this: 66 | # assets: 67 | # - images/a_dot_burr.jpeg 68 | # - images/a_dot_ham.jpeg 69 | 70 | # An image asset can refer to one or more resolution-specific "variants", see 71 | # https://flutter.dev/assets-and-images/#resolution-aware. 72 | 73 | # For details regarding adding assets from package dependencies, see 74 | # https://flutter.dev/assets-and-images/#from-packages 75 | 76 | # To add custom fonts to your application, add a fonts section here, 77 | # in this "flutter" section. Each entry in this list should have a 78 | # "family" key with the font family name, and a "fonts" key with a 79 | # list giving the asset and other descriptors for the font. For 80 | # example: 81 | # fonts: 82 | # - family: Schyler 83 | # fonts: 84 | # - asset: fonts/Schyler-Regular.ttf 85 | # - asset: fonts/Schyler-Italic.ttf 86 | # style: italic 87 | # - family: Trajan Pro 88 | # fonts: 89 | # - asset: fonts/TrajanPro.ttf 90 | # - asset: fonts/TrajanPro_Bold.ttf 91 | # weight: 700 92 | # 93 | # For details regarding fonts from package dependencies, 94 | # see https://flutter.dev/custom-fonts/#from-packages 95 | -------------------------------------------------------------------------------- /example/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:azlistview_example/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(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 | -------------------------------------------------------------------------------- /lib/azlistview.dart: -------------------------------------------------------------------------------- 1 | library azlistview; 2 | 3 | export 'src/az_common.dart'; 4 | export 'src/az_listview.dart'; 5 | export 'src/index_bar.dart'; 6 | export 'src/suspension_view.dart'; 7 | -------------------------------------------------------------------------------- /lib/src/az_common.dart: -------------------------------------------------------------------------------- 1 | /// ISuspension Bean. 2 | abstract class ISuspensionBean { 3 | bool isShowSuspension = false; 4 | 5 | String getSuspensionTag(); //Suspension Tag 6 | } 7 | 8 | /// Suspension Util. 9 | class SuspensionUtil { 10 | /// sort list by suspension tag. 11 | /// 根据[A-Z]排序。 12 | static void sortListBySuspensionTag(List? list) { 13 | if (list == null || list.isEmpty) return; 14 | list.sort((a, b) { 15 | if (a.getSuspensionTag() == "@" || b.getSuspensionTag() == "#") { 16 | return -1; 17 | } else if (a.getSuspensionTag() == "#" || b.getSuspensionTag() == "@") { 18 | return 1; 19 | } else { 20 | return a.getSuspensionTag().compareTo(b.getSuspensionTag()); 21 | } 22 | }); 23 | } 24 | 25 | /// get index data list by suspension tag. 26 | /// 获取索引列表。 27 | static List getTagIndexList(List? list) { 28 | List indexData = []; 29 | if (list != null && list.isNotEmpty) { 30 | String? tempTag; 31 | for (int i = 0, length = list.length; i < length; i++) { 32 | String tag = list[i].getSuspensionTag(); 33 | if (tempTag != tag) { 34 | indexData.add(tag); 35 | tempTag = tag; 36 | } 37 | } 38 | } 39 | return indexData; 40 | } 41 | 42 | /// set show suspension status. 43 | /// 设置显示悬停Header状态。 44 | static void setShowSuspensionStatus(List? list) { 45 | if (list == null || list.isEmpty) return; 46 | String? tempTag; 47 | for (int i = 0, length = list.length; i < length; i++) { 48 | String tag = list[i].getSuspensionTag(); 49 | if (tempTag != tag) { 50 | tempTag = tag; 51 | list[i].isShowSuspension = true; 52 | } else { 53 | list[i].isShowSuspension = false; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/src/az_listview.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; 3 | 4 | import 'az_common.dart'; 5 | import 'index_bar.dart'; 6 | import 'suspension_view.dart'; 7 | 8 | /// AzListView 9 | class AzListView extends StatefulWidget { 10 | AzListView({ 11 | Key? key, 12 | required this.data, 13 | required this.itemCount, 14 | required this.itemBuilder, 15 | this.itemScrollController, 16 | this.itemPositionsListener, 17 | this.physics, 18 | this.padding, 19 | this.susItemBuilder, 20 | this.susItemHeight = kSusItemHeight, 21 | this.susPosition, 22 | this.indexHintBuilder, 23 | this.indexBarData = kIndexBarData, 24 | this.indexBarWidth = kIndexBarWidth, 25 | this.indexBarHeight, 26 | this.indexBarItemHeight = kIndexBarItemHeight, 27 | this.hapticFeedback = false, 28 | this.indexBarAlignment = Alignment.centerRight, 29 | this.indexBarMargin, 30 | this.indexBarOptions = const IndexBarOptions(), 31 | }) : super(key: key); 32 | 33 | /// with ISuspensionBean Data 34 | final List data; 35 | 36 | /// Number of items the [itemBuilder] can produce. 37 | final int itemCount; 38 | 39 | /// Called to build children for the list with 40 | /// 0 <= index < itemCount. 41 | final IndexedWidgetBuilder itemBuilder; 42 | 43 | /// Controller for jumping or scrolling to an item. 44 | final ItemScrollController? itemScrollController; 45 | 46 | /// Notifier that reports the items laid out in the list after each frame. 47 | final ItemPositionsListener? itemPositionsListener; 48 | 49 | /// How the scroll view should respond to user input. 50 | /// 51 | /// For example, determines how the scroll view continues to animate after the 52 | /// user stops dragging the scroll view. 53 | /// 54 | /// See [ScrollView.physics]. 55 | final ScrollPhysics? physics; 56 | 57 | /// The amount of space by which to inset the children. 58 | final EdgeInsets? padding; 59 | 60 | /// Called to build suspension header. 61 | final IndexedWidgetBuilder? susItemBuilder; 62 | 63 | /// Suspension widget Height. 64 | final double susItemHeight; 65 | 66 | /// Suspension item position. 67 | final Offset? susPosition; 68 | 69 | /// IndexHintBuilder. 70 | final IndexHintBuilder? indexHintBuilder; 71 | 72 | /// Index data. 73 | final List indexBarData; 74 | 75 | /// IndexBar Width. 76 | final double indexBarWidth; 77 | 78 | /// IndexBar Height. 79 | final double? indexBarHeight; 80 | 81 | /// IndexBar Item Height. 82 | final double indexBarItemHeight; 83 | 84 | /// Haptic feedback. 85 | final bool hapticFeedback; 86 | 87 | /// IndexBar alignment. 88 | final AlignmentGeometry indexBarAlignment; 89 | 90 | /// IndexBar margin. 91 | final EdgeInsetsGeometry? indexBarMargin; 92 | 93 | /// IndexBar options. 94 | final IndexBarOptions indexBarOptions; 95 | 96 | @override 97 | _AzListViewState createState() => _AzListViewState(); 98 | } 99 | 100 | class _AzListViewState extends State { 101 | /// Controller to scroll or jump to a particular item. 102 | late ItemScrollController itemScrollController; 103 | 104 | /// Listener that reports the position of items when the list is scrolled. 105 | late ItemPositionsListener itemPositionsListener; 106 | 107 | IndexBarDragListener dragListener = IndexBarDragListener.create(); 108 | 109 | final IndexBarController indexBarController = IndexBarController(); 110 | 111 | String selectTag = ''; 112 | 113 | @override 114 | void initState() { 115 | super.initState(); 116 | itemScrollController = 117 | widget.itemScrollController ?? ItemScrollController(); 118 | itemPositionsListener = 119 | widget.itemPositionsListener ?? ItemPositionsListener.create(); 120 | dragListener.dragDetails.addListener(_valueChanged); 121 | if (widget.indexBarOptions.selectItemDecoration != null) { 122 | itemPositionsListener.itemPositions.addListener(_positionsChanged); 123 | } 124 | } 125 | 126 | @override 127 | void dispose() { 128 | super.dispose(); 129 | dragListener.dragDetails.removeListener(_valueChanged); 130 | if (widget.indexBarOptions.selectItemDecoration != null) { 131 | itemPositionsListener.itemPositions.removeListener(_positionsChanged); 132 | } 133 | } 134 | 135 | int _getIndex(String tag) { 136 | for (int i = 0; i < widget.itemCount; i++) { 137 | ISuspensionBean bean = widget.data[i]; 138 | if (tag == bean.getSuspensionTag()) { 139 | return i; 140 | } 141 | } 142 | return -1; 143 | } 144 | 145 | void _scrollTopIndex(String tag) { 146 | int index = _getIndex(tag); 147 | if (index != -1) { 148 | itemScrollController.jumpTo(index: index); 149 | } 150 | } 151 | 152 | void _valueChanged() { 153 | IndexBarDragDetails details = dragListener.dragDetails.value; 154 | String tag = details.tag!; 155 | if (details.action == IndexBarDragDetails.actionDown || 156 | details.action == IndexBarDragDetails.actionUpdate) { 157 | selectTag = tag; 158 | _scrollTopIndex(tag); 159 | } 160 | } 161 | 162 | void _positionsChanged() { 163 | Iterable positions = 164 | itemPositionsListener.itemPositions.value; 165 | if (positions.isNotEmpty) { 166 | ItemPosition itemPosition = positions 167 | .where((ItemPosition position) => position.itemTrailingEdge > 0) 168 | .reduce((ItemPosition min, ItemPosition position) => 169 | position.itemTrailingEdge < min.itemTrailingEdge 170 | ? position 171 | : min); 172 | int index = itemPosition.index; 173 | String tag = widget.data[index].getSuspensionTag(); 174 | if (selectTag != tag) { 175 | selectTag = tag; 176 | indexBarController.updateTagIndex(tag); 177 | } 178 | } 179 | } 180 | 181 | @override 182 | Widget build(BuildContext context) { 183 | return Stack( 184 | children: [ 185 | SuspensionView( 186 | data: widget.data, 187 | itemCount: widget.itemCount, 188 | itemBuilder: widget.itemBuilder, 189 | itemScrollController: itemScrollController, 190 | itemPositionsListener: itemPositionsListener, 191 | susItemBuilder: widget.susItemBuilder, 192 | susItemHeight: widget.susItemHeight, 193 | susPosition: widget.susPosition, 194 | padding: widget.padding, 195 | physics: widget.physics, 196 | ), 197 | Align( 198 | alignment: widget.indexBarAlignment, 199 | child: IndexBar( 200 | data: widget.indexBarData, 201 | width: widget.indexBarWidth, 202 | height: widget.indexBarHeight, 203 | itemHeight: widget.indexBarItemHeight, 204 | margin: widget.indexBarMargin, 205 | indexHintBuilder: widget.indexHintBuilder, 206 | indexBarDragListener: dragListener, 207 | options: widget.indexBarOptions, 208 | controller: indexBarController, 209 | ), 210 | ), 211 | ], 212 | ); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /lib/src/index_bar.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'dart:math' as math; 6 | 7 | import 'package:flutter/services.dart'; 8 | 9 | /// IndexHintBuilder. 10 | typedef IndexHintBuilder = Widget Function(BuildContext context, String tag); 11 | 12 | /// IndexBarDragListener. 13 | abstract class IndexBarDragListener { 14 | /// Creates an [IndexBarDragListener] that can be used by a 15 | /// [IndexBar] to return the drag listener. 16 | factory IndexBarDragListener.create() => IndexBarDragNotifier(); 17 | 18 | /// drag details. 19 | ValueListenable get dragDetails; 20 | } 21 | 22 | /// Internal implementation of [ItemPositionsListener]. 23 | class IndexBarDragNotifier implements IndexBarDragListener { 24 | @override 25 | final ValueNotifier dragDetails = 26 | ValueNotifier(IndexBarDragDetails()); 27 | } 28 | 29 | /// IndexModel. 30 | class IndexBarDragDetails { 31 | static const int actionDown = 0; 32 | static const int actionUp = 1; 33 | static const int actionUpdate = 2; 34 | static const int actionEnd = 3; 35 | static const int actionCancel = 4; 36 | 37 | int? action; 38 | int? index; //current touch index. 39 | String? tag; //current touch tag. 40 | 41 | double? localPositionY; 42 | double? globalPositionY; 43 | 44 | IndexBarDragDetails({ 45 | this.action, 46 | this.index, 47 | this.tag, 48 | this.localPositionY, 49 | this.globalPositionY, 50 | }); 51 | } 52 | 53 | ///Default Index data. 54 | const List kIndexBarData = const [ 55 | 'A', 56 | 'B', 57 | 'C', 58 | 'D', 59 | 'E', 60 | 'F', 61 | 'G', 62 | 'H', 63 | 'I', 64 | 'J', 65 | 'K', 66 | 'L', 67 | 'M', 68 | 'N', 69 | 'O', 70 | 'P', 71 | 'Q', 72 | 'R', 73 | 'S', 74 | 'T', 75 | 'U', 76 | 'V', 77 | 'W', 78 | 'X', 79 | 'Y', 80 | 'Z', 81 | '#' 82 | ]; 83 | 84 | const double kIndexBarWidth = 30; 85 | 86 | const double kIndexBarItemHeight = 16; 87 | 88 | /// IndexBar options. 89 | class IndexBarOptions { 90 | /// Creates IndexBar options. 91 | /// Examples. 92 | /// needReBuild = true 93 | /// ignoreDragCancel = true 94 | /// color = Colors.transparent 95 | /// downColor = Color(0xFFEEEEEE) 96 | /// decoration 97 | /// downDecoration 98 | /// textStyle = TextStyle(fontSize: 12, color: Color(0xFF666666)) 99 | /// downTextStyle = TextStyle(fontSize: 12, color: Colors.white) 100 | /// selectTextStyle = TextStyle(fontSize: 12, color: Colors.white) 101 | /// downItemDecoration = BoxDecoration(shape: BoxShape.circle, color: Colors.blueAccent) 102 | /// selectItemDecoration = BoxDecoration(shape: BoxShape.circle, color: Colors.blueAccent) 103 | /// indexHintWidth = 72 104 | /// indexHintHeight = 72 105 | /// indexHintDecoration = BoxDecoration(color: Colors.black87, shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(6)),) 106 | /// indexHintTextStyle = TextStyle(fontSize: 24.0, color: Colors.white) 107 | /// indexHintChildAlignment = Alignment.center 108 | /// indexHintAlignment = Alignment.center 109 | /// indexHintPosition 110 | /// indexHintOffset 111 | /// localImages 112 | const IndexBarOptions({ 113 | this.needRebuild = false, 114 | this.ignoreDragCancel = false, 115 | this.hapticFeedback = false, 116 | this.color, 117 | this.downColor, 118 | this.decoration, 119 | this.downDecoration, 120 | this.textStyle = const TextStyle(fontSize: 12, color: Color(0xFF666666)), 121 | this.downTextStyle, 122 | this.selectTextStyle, 123 | this.downItemDecoration, 124 | this.selectItemDecoration, 125 | this.indexHintWidth = 72, 126 | this.indexHintHeight = 72, 127 | this.indexHintDecoration = const BoxDecoration( 128 | color: Colors.black87, 129 | shape: BoxShape.rectangle, 130 | borderRadius: BorderRadius.all(Radius.circular(6)), 131 | ), 132 | this.indexHintTextStyle = 133 | const TextStyle(fontSize: 24.0, color: Colors.white), 134 | this.indexHintChildAlignment = Alignment.center, 135 | this.indexHintAlignment = Alignment.center, 136 | this.indexHintPosition, 137 | this.indexHintOffset = Offset.zero, 138 | this.localImages = const [], 139 | }); 140 | 141 | /// need to rebuild. 142 | final bool needRebuild; 143 | 144 | /// Ignore DragCancel. 145 | final bool ignoreDragCancel; 146 | 147 | /// Haptic feedback. 148 | final bool hapticFeedback; 149 | 150 | /// IndexBar background color. 151 | final Color? color; 152 | 153 | /// IndexBar down background color. 154 | final Color? downColor; 155 | 156 | /// IndexBar decoration. 157 | final Decoration? decoration; 158 | 159 | /// IndexBar down decoration. 160 | final Decoration? downDecoration; 161 | 162 | /// IndexBar textStyle. 163 | final TextStyle textStyle; 164 | 165 | /// IndexBar down textStyle. 166 | final TextStyle? downTextStyle; 167 | 168 | /// IndexBar select textStyle. 169 | final TextStyle? selectTextStyle; 170 | 171 | /// IndexBar down item decoration. 172 | final Decoration? downItemDecoration; 173 | 174 | /// IndexBar select item decoration. 175 | final Decoration? selectItemDecoration; 176 | 177 | /// Index hint width. 178 | final double indexHintWidth; 179 | 180 | /// Index hint height. 181 | final double indexHintHeight; 182 | 183 | /// Index hint decoration. 184 | final Decoration indexHintDecoration; 185 | 186 | /// Index hint alignment. 187 | final Alignment indexHintAlignment; 188 | 189 | /// Index hint child alignment. 190 | final Alignment indexHintChildAlignment; 191 | 192 | /// Index hint textStyle. 193 | final TextStyle indexHintTextStyle; 194 | 195 | /// Index hint position. 196 | final Offset? indexHintPosition; 197 | 198 | /// Index hint offset. 199 | final Offset indexHintOffset; 200 | 201 | /// local images. 202 | final List localImages; 203 | } 204 | 205 | /// IndexBarController. 206 | class IndexBarController { 207 | _IndexBarState? _indexBarState; 208 | 209 | bool get isAttached => _indexBarState != null; 210 | 211 | void updateTagIndex(String tag) { 212 | _indexBarState?._updateTagIndex(tag); 213 | } 214 | 215 | void _attach(_IndexBarState state) { 216 | _indexBarState = state; 217 | } 218 | 219 | void _detach() { 220 | _indexBarState = null; 221 | } 222 | } 223 | 224 | /// IndexBar. 225 | class IndexBar extends StatefulWidget { 226 | IndexBar({ 227 | Key? key, 228 | this.data = kIndexBarData, 229 | this.width = kIndexBarWidth, 230 | this.height, 231 | this.itemHeight = kIndexBarItemHeight, 232 | this.margin, 233 | this.indexHintBuilder, 234 | IndexBarDragListener? indexBarDragListener, 235 | this.options = const IndexBarOptions(), 236 | this.controller, 237 | }) : indexBarDragNotifier = indexBarDragListener as IndexBarDragNotifier?, 238 | super(key: key); 239 | 240 | /// Index data. 241 | final List data; 242 | 243 | /// IndexBar width(def:30). 244 | final double width; 245 | 246 | /// IndexBar height. 247 | final double? height; 248 | 249 | /// IndexBar item height(def:16). 250 | final double itemHeight; 251 | 252 | /// Empty space to surround the [decoration] and [child]. 253 | final EdgeInsetsGeometry? margin; 254 | 255 | /// IndexHint Builder 256 | final IndexHintBuilder? indexHintBuilder; 257 | 258 | /// IndexBar drag listener. 259 | final IndexBarDragNotifier? indexBarDragNotifier; 260 | 261 | /// IndexBar options. 262 | final IndexBarOptions options; 263 | 264 | /// IndexBarController. If non-null, this can be used to control the state of the IndexBar. 265 | final IndexBarController? controller; 266 | 267 | @override 268 | _IndexBarState createState() => _IndexBarState(); 269 | } 270 | 271 | class _IndexBarState extends State { 272 | /// overlay entry. 273 | static OverlayEntry? overlayEntry; 274 | 275 | double floatTop = 0; 276 | String indexTag = ''; 277 | int selectIndex = 0; 278 | int action = IndexBarDragDetails.actionEnd; 279 | 280 | @override 281 | void initState() { 282 | super.initState(); 283 | widget.indexBarDragNotifier?.dragDetails?.addListener(_valueChanged); 284 | widget.controller?._attach(this); 285 | } 286 | 287 | void _valueChanged() { 288 | if (widget.indexBarDragNotifier == null) return; 289 | IndexBarDragDetails details = 290 | widget.indexBarDragNotifier!.dragDetails.value; 291 | selectIndex = details.index!; 292 | indexTag = details.tag!; 293 | action = details.action!; 294 | floatTop = details.globalPositionY! + 295 | widget.itemHeight / 2 - 296 | widget.options.indexHintHeight / 2; 297 | 298 | if (_isActionDown()) { 299 | _addOverlay(context); 300 | } else { 301 | _removeOverlay(); 302 | } 303 | 304 | if (widget.options.needRebuild) { 305 | if (widget.options.ignoreDragCancel && 306 | action == IndexBarDragDetails.actionCancel) { 307 | } else { 308 | setState(() {}); 309 | } 310 | } 311 | } 312 | 313 | bool _isActionDown() { 314 | return action == IndexBarDragDetails.actionDown || 315 | action == IndexBarDragDetails.actionUpdate; 316 | } 317 | 318 | @override 319 | void dispose() { 320 | widget.controller?._detach(); 321 | _removeOverlay(); 322 | widget.indexBarDragNotifier?.dragDetails?.removeListener(_valueChanged); 323 | super.dispose(); 324 | } 325 | 326 | Widget _buildIndexHint(BuildContext context, String tag) { 327 | if (widget.indexHintBuilder != null) { 328 | return widget.indexHintBuilder!(context, tag); 329 | } 330 | Widget child; 331 | TextStyle textStyle = widget.options.indexHintTextStyle; 332 | List localImages = widget.options.localImages; 333 | if (localImages.contains(tag)) { 334 | child = Image.asset( 335 | tag, 336 | width: textStyle.fontSize, 337 | height: textStyle.fontSize, 338 | color: textStyle.color, 339 | ); 340 | } else { 341 | child = Text('$tag', style: textStyle); 342 | } 343 | return Container( 344 | width: widget.options.indexHintWidth, 345 | height: widget.options.indexHintHeight, 346 | alignment: widget.options.indexHintChildAlignment, 347 | decoration: widget.options.indexHintDecoration, 348 | child: child, 349 | ); 350 | } 351 | 352 | /// add overlay. 353 | void _addOverlay(BuildContext context) { 354 | OverlayState? overlayState = Overlay.of(context); 355 | if (overlayState == null) return; 356 | if (overlayEntry == null) { 357 | overlayEntry = OverlayEntry(builder: (BuildContext ctx) { 358 | double left; 359 | double top; 360 | if (widget.options.indexHintPosition != null) { 361 | left = widget.options.indexHintPosition!.dx; 362 | top = widget.options.indexHintPosition!.dy; 363 | } else { 364 | if (widget.options.indexHintAlignment == Alignment.centerRight) { 365 | left = MediaQuery.of(context).size.width - 366 | kIndexBarWidth - 367 | widget.options.indexHintWidth + 368 | widget.options.indexHintOffset.dx; 369 | top = floatTop + widget.options.indexHintOffset.dy; 370 | } else if (widget.options.indexHintAlignment == 371 | Alignment.centerLeft) { 372 | left = kIndexBarWidth + widget.options.indexHintOffset.dx; 373 | top = floatTop + widget.options.indexHintOffset.dy; 374 | } else { 375 | left = MediaQuery.of(context).size.width / 2 - 376 | widget.options.indexHintWidth / 2 + 377 | widget.options.indexHintOffset.dx; 378 | top = MediaQuery.of(context).size.height / 2 - 379 | widget.options.indexHintHeight / 2 + 380 | widget.options.indexHintOffset.dy; 381 | } 382 | } 383 | return Positioned( 384 | left: left, 385 | top: top, 386 | child: Material( 387 | color: Colors.transparent, 388 | child: _buildIndexHint(ctx, indexTag), 389 | )); 390 | }); 391 | overlayState.insert(overlayEntry!); 392 | } else { 393 | //重新绘制UI,类似setState 394 | overlayEntry?.markNeedsBuild(); 395 | } 396 | } 397 | 398 | /// remove overlay. 399 | void _removeOverlay() { 400 | overlayEntry?.remove(); 401 | overlayEntry = null; 402 | } 403 | 404 | Widget _buildItem(BuildContext context, int index) { 405 | String tag = widget.data[index]; 406 | Decoration? decoration; 407 | TextStyle? textStyle; 408 | if (widget.options.downItemDecoration != null) { 409 | decoration = (_isActionDown() && selectIndex == index) 410 | ? widget.options.downItemDecoration 411 | : null; 412 | textStyle = (_isActionDown() && selectIndex == index) 413 | ? widget.options.downTextStyle 414 | : widget.options.textStyle; 415 | } else if (widget.options.selectItemDecoration != null) { 416 | decoration = 417 | (selectIndex == index) ? widget.options.selectItemDecoration : null; 418 | textStyle = (selectIndex == index) 419 | ? widget.options.selectTextStyle 420 | : widget.options.textStyle; 421 | } else { 422 | textStyle = _isActionDown() 423 | ? (widget.options.downTextStyle ?? widget.options.textStyle) 424 | : widget.options.textStyle; 425 | } 426 | 427 | Widget child; 428 | List localImages = widget.options.localImages; 429 | if (localImages.contains(tag)) { 430 | child = Image.asset( 431 | tag, 432 | width: textStyle?.fontSize, 433 | height: textStyle?.fontSize, 434 | color: textStyle?.color, 435 | ); 436 | } else { 437 | child = Text('$tag', style: textStyle); 438 | } 439 | 440 | return Container( 441 | alignment: Alignment.center, 442 | decoration: decoration, 443 | child: child, 444 | ); 445 | } 446 | 447 | void _updateTagIndex(String tag) { 448 | if (_isActionDown()) return; 449 | selectIndex = widget.data.indexOf(tag); 450 | setState(() {}); 451 | } 452 | 453 | @override 454 | Widget build(BuildContext context) { 455 | return Container( 456 | color: _isActionDown() ? widget.options.downColor : widget.options.color, 457 | decoration: _isActionDown() 458 | ? widget.options.downDecoration 459 | : widget.options.decoration, 460 | width: widget.width, 461 | height: widget.height, 462 | margin: widget.margin, 463 | alignment: Alignment.center, 464 | child: BaseIndexBar( 465 | data: widget.data, 466 | width: widget.width, 467 | itemHeight: widget.itemHeight, 468 | hapticFeedback: widget.options.hapticFeedback, 469 | itemBuilder: (BuildContext context, int index) { 470 | return _buildItem(context, index); 471 | }, 472 | indexBarDragNotifier: widget.indexBarDragNotifier, 473 | ), 474 | ); 475 | } 476 | } 477 | 478 | class BaseIndexBar extends StatefulWidget { 479 | BaseIndexBar({ 480 | Key? key, 481 | this.data = kIndexBarData, 482 | this.width = kIndexBarWidth, 483 | this.itemHeight = kIndexBarItemHeight, 484 | this.hapticFeedback = false, 485 | this.textStyle = const TextStyle(fontSize: 12.0, color: Color(0xFF666666)), 486 | this.itemBuilder, 487 | this.indexBarDragNotifier, 488 | }) : super(key: key); 489 | 490 | /// index data. 491 | final List data; 492 | 493 | /// IndexBar width(def:30). 494 | final double width; 495 | 496 | /// IndexBar item height(def:16). 497 | final double itemHeight; 498 | 499 | /// Haptic feedback. 500 | final bool hapticFeedback; 501 | 502 | /// IndexBar text style. 503 | final TextStyle textStyle; 504 | 505 | final IndexedWidgetBuilder? itemBuilder; 506 | 507 | final IndexBarDragNotifier? indexBarDragNotifier; 508 | 509 | @override 510 | _BaseIndexBarState createState() => _BaseIndexBarState(); 511 | } 512 | 513 | class _BaseIndexBarState extends State { 514 | int lastIndex = -1; 515 | int _widgetTop = 0; 516 | 517 | /// get index. 518 | int _getIndex(double offset) { 519 | int index = offset ~/ widget.itemHeight; 520 | return math.min(index, widget.data.length - 1); 521 | } 522 | 523 | /// trigger drag event. 524 | _triggerDragEvent(int action) { 525 | if (widget.hapticFeedback && 526 | (action == IndexBarDragDetails.actionDown || 527 | action == IndexBarDragDetails.actionUpdate)) { 528 | HapticFeedback.vibrate(); 529 | } 530 | widget.indexBarDragNotifier?.dragDetails?.value = IndexBarDragDetails( 531 | action: action, 532 | index: lastIndex, 533 | tag: widget.data[lastIndex], 534 | localPositionY: lastIndex * widget.itemHeight, 535 | globalPositionY: lastIndex * widget.itemHeight + _widgetTop, 536 | ); 537 | } 538 | 539 | RenderBox? _getRenderBox(BuildContext context) { 540 | RenderObject? renderObject = context.findRenderObject(); 541 | RenderBox? box; 542 | if (renderObject != null) { 543 | box = renderObject as RenderBox; 544 | } 545 | return box; 546 | } 547 | 548 | @override 549 | Widget build(BuildContext context) { 550 | List children = List.generate(widget.data.length, (index) { 551 | Widget child = widget.itemBuilder == null 552 | ? Center( 553 | child: Text('${widget.data[index]}', style: widget.textStyle)) 554 | : widget.itemBuilder!(context, index); 555 | return SizedBox( 556 | width: widget.width, 557 | height: widget.itemHeight, 558 | child: child, 559 | ); 560 | }); 561 | 562 | return GestureDetector( 563 | onVerticalDragDown: (DragDownDetails details) { 564 | RenderBox? box = _getRenderBox(context); 565 | if (box == null) return; 566 | Offset topLeftPosition = box.localToGlobal(Offset.zero); 567 | _widgetTop = topLeftPosition.dy.toInt(); 568 | int index = _getIndex(details.localPosition.dy); 569 | if (index >= 0) { 570 | lastIndex = index; 571 | _triggerDragEvent(IndexBarDragDetails.actionDown); 572 | } 573 | }, 574 | onVerticalDragUpdate: (DragUpdateDetails details) { 575 | int index = _getIndex(details.localPosition.dy); 576 | if (index >= 0 && lastIndex != index) { 577 | lastIndex = index; 578 | //HapticFeedback.lightImpact(); 579 | //HapticFeedback.vibrate(); 580 | _triggerDragEvent(IndexBarDragDetails.actionUpdate); 581 | } 582 | }, 583 | onVerticalDragEnd: (DragEndDetails details) { 584 | _triggerDragEvent(IndexBarDragDetails.actionEnd); 585 | }, 586 | onVerticalDragCancel: () { 587 | _triggerDragEvent(IndexBarDragDetails.actionCancel); 588 | }, 589 | onTapUp: (TapUpDetails details) { 590 | //_triggerDragEvent(IndexBarDragDetails.actionUp); 591 | }, 592 | behavior: HitTestBehavior.translucent, 593 | child: Column( 594 | mainAxisSize: MainAxisSize.min, 595 | children: children, 596 | ), 597 | ); 598 | } 599 | } 600 | -------------------------------------------------------------------------------- /lib/src/suspension_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; 3 | import 'dart:math' as math; 4 | import 'az_common.dart'; 5 | 6 | const double kSusItemHeight = 40; 7 | 8 | /// SuspensionView. 9 | class SuspensionView extends StatefulWidget { 10 | SuspensionView({ 11 | Key? key, 12 | required this.data, 13 | required this.itemCount, 14 | required this.itemBuilder, 15 | this.itemScrollController, 16 | this.itemPositionsListener, 17 | this.susItemBuilder, 18 | this.susItemHeight = kSusItemHeight, 19 | this.susPosition, 20 | this.physics, 21 | this.padding, 22 | }) : super(key: key); 23 | 24 | /// Suspension data. 25 | final List data; 26 | 27 | /// Number of items the [itemBuilder] can produce. 28 | final int itemCount; 29 | 30 | /// Called to build children for the list with 31 | /// 0 <= index < itemCount. 32 | final IndexedWidgetBuilder itemBuilder; 33 | 34 | /// Controller for jumping or scrolling to an item. 35 | final ItemScrollController? itemScrollController; 36 | 37 | /// Notifier that reports the items laid out in the list after each frame. 38 | final ItemPositionsListener? itemPositionsListener; 39 | 40 | /// Called to build suspension header. 41 | final IndexedWidgetBuilder? susItemBuilder; 42 | 43 | /// Suspension item Height. 44 | final double susItemHeight; 45 | 46 | /// Suspension item position. 47 | final Offset? susPosition; 48 | 49 | /// How the scroll view should respond to user input. 50 | /// 51 | /// For example, determines how the scroll view continues to animate after the 52 | /// user stops dragging the scroll view. 53 | /// 54 | /// See [ScrollView.physics]. 55 | final ScrollPhysics? physics; 56 | 57 | /// The amount of space by which to inset the children. 58 | final EdgeInsets? padding; 59 | 60 | @override 61 | _SuspensionViewState createState() => _SuspensionViewState(); 62 | } 63 | 64 | class _SuspensionViewState extends State { 65 | /// Controller to scroll or jump to a particular item. 66 | late ItemScrollController itemScrollController; 67 | 68 | /// Listener that reports the position of items when the list is scrolled. 69 | late ItemPositionsListener itemPositionsListener; 70 | 71 | @override 72 | void initState() { 73 | super.initState(); 74 | itemScrollController = 75 | widget.itemScrollController ?? ItemScrollController(); 76 | itemPositionsListener = 77 | widget.itemPositionsListener ?? ItemPositionsListener.create(); 78 | } 79 | 80 | @override 81 | void dispose() { 82 | super.dispose(); 83 | } 84 | 85 | /// build sus widget. 86 | Widget _buildSusWidget(BuildContext context) { 87 | if (widget.susItemBuilder == null) { 88 | return Container(); 89 | } 90 | return ValueListenableBuilder>( 91 | valueListenable: itemPositionsListener.itemPositions, 92 | builder: (ctx, positions, child) { 93 | if (positions.isEmpty || widget.itemCount == 0) { 94 | return Container(); 95 | } 96 | ItemPosition itemPosition = positions 97 | .where((ItemPosition position) => position.itemTrailingEdge > 0) 98 | .reduce((ItemPosition min, ItemPosition position) => 99 | position.itemTrailingEdge < min.itemTrailingEdge 100 | ? position 101 | : min); 102 | if (itemPosition.itemLeadingEdge > 0) return Container(); 103 | int index = itemPosition.index; 104 | double left = 0; 105 | double top = 0; 106 | if (index < widget.itemCount) { 107 | if (widget.susPosition != null) { 108 | left = widget.susPosition!.dx; 109 | top = widget.susPosition!.dy; 110 | } else { 111 | int next = math.min(index + 1, widget.itemCount - 1); 112 | ISuspensionBean bean = widget.data[next]; 113 | if (bean.isShowSuspension) { 114 | double height = 115 | context.findRenderObject()?.paintBounds?.height ?? 0; 116 | double topTemp = itemPosition.itemTrailingEdge * height; 117 | top = math.min(widget.susItemHeight, topTemp) - 118 | widget.susItemHeight; 119 | } 120 | } 121 | } else { 122 | index = 0; 123 | } 124 | return Positioned( 125 | left: left, 126 | top: top, 127 | child: widget.susItemBuilder!(ctx, index), 128 | ); 129 | }, 130 | ); 131 | } 132 | 133 | Widget _buildItem(BuildContext context, int index) { 134 | ISuspensionBean bean = widget.data[index]; 135 | if (!bean.isShowSuspension || widget.susItemBuilder == null) { 136 | return widget.itemBuilder(context, index); 137 | } 138 | return Column( 139 | mainAxisSize: MainAxisSize.min, 140 | children: [ 141 | widget.susItemBuilder!(context, index), 142 | widget.itemBuilder(context, index), 143 | ], 144 | ); 145 | } 146 | 147 | @override 148 | Widget build(BuildContext context) { 149 | return Stack( 150 | children: [ 151 | widget.itemCount == 0 152 | ? Container() 153 | : ScrollablePositionedList.builder( 154 | itemCount: widget.itemCount, 155 | itemBuilder: (context, index) => _buildItem(context, index), 156 | itemScrollController: itemScrollController, 157 | itemPositionsListener: itemPositionsListener, 158 | physics: widget.physics, 159 | padding: widget.padding, 160 | ), 161 | _buildSusWidget(context), 162 | ], 163 | ); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /pkgget: -------------------------------------------------------------------------------- 1 | export PUB_HOSTED_URL=https://pub.flutter-io.cn 2 | export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn 3 | flutter packages get -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.2.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.15.0" 46 | fake_async: 47 | dependency: transitive 48 | description: 49 | name: fake_async 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "1.2.0" 53 | flutter: 54 | dependency: "direct main" 55 | description: flutter 56 | source: sdk 57 | version: "0.0.0" 58 | flutter_test: 59 | dependency: "direct dev" 60 | description: flutter 61 | source: sdk 62 | version: "0.0.0" 63 | matcher: 64 | dependency: transitive 65 | description: 66 | name: matcher 67 | url: "https://pub.flutter-io.cn" 68 | source: hosted 69 | version: "0.12.11" 70 | material_color_utilities: 71 | dependency: transitive 72 | description: 73 | name: material_color_utilities 74 | url: "https://pub.flutter-io.cn" 75 | source: hosted 76 | version: "0.1.3" 77 | meta: 78 | dependency: transitive 79 | description: 80 | name: meta 81 | url: "https://pub.flutter-io.cn" 82 | source: hosted 83 | version: "1.7.0" 84 | path: 85 | dependency: transitive 86 | description: 87 | name: path 88 | url: "https://pub.flutter-io.cn" 89 | source: hosted 90 | version: "1.8.0" 91 | scrollable_positioned_list: 92 | dependency: "direct main" 93 | description: 94 | name: scrollable_positioned_list 95 | url: "https://pub.flutter-io.cn" 96 | source: hosted 97 | version: "0.2.3" 98 | sky_engine: 99 | dependency: transitive 100 | description: flutter 101 | source: sdk 102 | version: "0.0.99" 103 | source_span: 104 | dependency: transitive 105 | description: 106 | name: source_span 107 | url: "https://pub.flutter-io.cn" 108 | source: hosted 109 | version: "1.8.1" 110 | stack_trace: 111 | dependency: transitive 112 | description: 113 | name: stack_trace 114 | url: "https://pub.flutter-io.cn" 115 | source: hosted 116 | version: "1.10.0" 117 | stream_channel: 118 | dependency: transitive 119 | description: 120 | name: stream_channel 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "2.1.0" 124 | string_scanner: 125 | dependency: transitive 126 | description: 127 | name: string_scanner 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "1.1.0" 131 | term_glyph: 132 | dependency: transitive 133 | description: 134 | name: term_glyph 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "1.2.0" 138 | test_api: 139 | dependency: transitive 140 | description: 141 | name: test_api 142 | url: "https://pub.flutter-io.cn" 143 | source: hosted 144 | version: "0.4.8" 145 | typed_data: 146 | dependency: transitive 147 | description: 148 | name: typed_data 149 | url: "https://pub.flutter-io.cn" 150 | source: hosted 151 | version: "1.3.0" 152 | vector_math: 153 | dependency: transitive 154 | description: 155 | name: vector_math 156 | url: "https://pub.flutter-io.cn" 157 | source: hosted 158 | version: "2.1.1" 159 | sdks: 160 | dart: ">=2.14.0 <3.0.0" 161 | flutter: ">=1.13.8" 162 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: azlistview 2 | description: A Flutter sticky headers & index ListView. IndexBar. such as citylist, contactlist. index and hover effect. 3 | version: 2.0.0 4 | homepage: https://github.com/flutterchina/azlistview 5 | 6 | environment: 7 | sdk: ">=2.12.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | # https://pub.flutter-io.cn/packages/scrollable_positioned_list 13 | scrollable_positioned_list: ^0.2.3 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | 19 | # For information on the generic Dart part of this file, see the 20 | # following page: https://dart.dev/tools/pub/pubspec 21 | 22 | # The following section is specific to Flutter. 23 | flutter: 24 | 25 | # To add assets to your package, add an assets section, like this: 26 | # assets: 27 | # - images/a_dot_burr.jpeg 28 | # - images/a_dot_ham.jpeg 29 | # 30 | # For details regarding assets in packages, see 31 | # https://flutter.dev/assets-and-images/#from-packages 32 | # 33 | # An image asset can refer to one or more resolution-specific "variants", see 34 | # https://flutter.dev/assets-and-images/#resolution-aware. 35 | 36 | # To add custom fonts to your package, add a fonts section here, 37 | # in this "flutter" section. Each entry in this list should have a 38 | # "family" key with the font family name, and a "fonts" key with a 39 | # list giving the asset and other descriptors for the font. For 40 | # example: 41 | # fonts: 42 | # - family: Schyler 43 | # fonts: 44 | # - asset: fonts/Schyler-Regular.ttf 45 | # - asset: fonts/Schyler-Italic.ttf 46 | # style: italic 47 | # - family: Trajan Pro 48 | # fonts: 49 | # - asset: fonts/TrajanPro.ttf 50 | # - asset: fonts/TrajanPro_Bold.ttf 51 | # weight: 700 52 | # 53 | # For details regarding fonts in packages, see 54 | # https://flutter.dev/custom-fonts/#from-packages 55 | -------------------------------------------------------------------------------- /screenshots/azlistview1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/screenshots/azlistview1.jpg -------------------------------------------------------------------------------- /screenshots/azlistview2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/screenshots/azlistview2.jpg -------------------------------------------------------------------------------- /screenshots/azlistview3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/screenshots/azlistview3.jpg -------------------------------------------------------------------------------- /screenshots/azlistview4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/screenshots/azlistview4.jpg -------------------------------------------------------------------------------- /screenshots/azlistview5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/screenshots/azlistview5.jpg -------------------------------------------------------------------------------- /screenshots/azlistview6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutterchina/azlistview/ea7e11660223c3b6b1f3491ab0e5e04a333cca5d/screenshots/azlistview6.jpg -------------------------------------------------------------------------------- /uploadMaster: -------------------------------------------------------------------------------- 1 | git push origin master 2 | --------------------------------------------------------------------------------