├── README.md
└── flutter_k_chart-master
├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── example
├── .gitignore
├── .metadata
├── README.md
├── android
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── 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
│ ├── depth.json
│ ├── kline.json
│ └── kmon.json
├── images
│ ├── depth.2019-09-01 2010_21_31.gif
│ ├── k_chart.2019-09-01 2010_19_56.gif
│ └── screenshots.png
├── ios
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── flutter_export_environment.sh
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── Runner
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── 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
│ │ └── main.m
├── lib
│ └── main.dart
├── pubspec.lock
├── pubspec.yaml
└── test
│ └── widget_test.dart
├── k_chart.apk
├── lib
├── chart_style.dart
├── depth_chart.dart
├── entity
│ ├── candle_entity.dart
│ ├── depth_entity.dart
│ ├── info_window_entity.dart
│ ├── k_entity.dart
│ ├── k_line_entity.dart
│ ├── kdj_entity.dart
│ ├── macd_entity.dart
│ ├── rsi_entity.dart
│ ├── rw_entity.dart
│ └── volume_entity.dart
├── flutter_k_chart.dart
├── generated
│ └── i18n.dart
├── k_chart_widget.dart
├── renderer
│ ├── base_chart_painter.dart
│ ├── base_chart_renderer.dart
│ ├── chart_painter.dart
│ ├── main_renderer.dart
│ ├── secondary_renderer.dart
│ └── vol_renderer.dart
└── utils
│ ├── data_util.dart
│ ├── date_format_util.dart
│ └── number_util.dart
├── pubspec.lock
├── pubspec.yaml
├── res
└── values
│ └── strings_en.arb
└── test
└── flutter_k_chart_test.dart
/README.md:
--------------------------------------------------------------------------------
1 | # flutter_k_chart
2 |
3 | [](/LICENSE)
4 |
5 | ## 介绍
6 | 一个仿火币的flutter图表库包含深度图,支持各种指标及放大缩小、平移等操作
7 |
8 | Demo v0.1.0:[下载 APK](https://github.com/bianxiang/flutter_kline/blob/master/flutter_k_chart-master/k_chart.apk?raw=true)
9 |
10 | ## 演示
11 | 
12 | 
13 | 
14 |
15 | ## 简单用例
16 | #### 1.在 pubspec.yaml 中添加依赖
17 | 本项目数据来自火币openApi,火币的接口可能需要翻墙,接口失败后会加载本地json。由于项目没有很好的封装,建议使用本地方式使用
18 | ```yaml
19 | //本地导入方式
20 | dependencies:
21 | flutter_k_chart:
22 | path: 项目路径
23 | ```
24 |
25 | #### 2.在布局文件中添加
26 | ```dart
27 | import 'package:flutter_k_chart/flutter_k_chart.dart';
28 | ....
29 | Container(
30 | height: 450,
31 | width: double.infinity,
32 | child: KChartWidget(
33 | datas,//数据
34 | isLine: isLine,//是否显示折线图
35 | mainState: _mainState,//控制主视图指标线
36 | secondaryState: _secondaryState,//控制副视图指标线
37 | volState: VolState.VOL,//控制成交量指标线
38 | fractionDigits: 4,//保留小数位数
39 | ),
40 | )
41 |
42 | //深度图使用
43 | Container(
44 | height: 230,
45 | width: double.infinity,
46 | child: DepthChart(_bids, _asks),
47 | )
48 | ```
49 | ### 3.修改样式
50 | 可在chart_style.dart里面修改图表样式
51 |
52 | #### 4.数据处理
53 | ```dart
54 | //接口获取数据后,计算数据
55 | DataUtil.calculate(datas);
56 | //更新最后一条数据
57 | DataUtil.updateLastData(datas);
58 | //添加数据
59 | DataUtil.addLastData(datas,kLineEntity);
60 | ```
61 |
62 | ## 问题
63 | 使用中如果有问题可以加QQ群:160603792
64 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/.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 | # Visual Studio Code related
19 | .vscode/
20 |
21 | # Flutter/Dart/Pub related
22 | **/doc/api/
23 | .dart_tool/
24 | .flutter-plugins
25 | .packages
26 | .pub-cache/
27 | .pub/
28 | build/
29 |
30 | # Android related
31 | **/android/**/gradle-wrapper.jar
32 | **/android/.gradle
33 | **/android/captures/
34 | **/android/gradlew
35 | **/android/gradlew.bat
36 | **/android/local.properties
37 | **/android/**/GeneratedPluginRegistrant.java
38 |
39 | # iOS/XCode related
40 | **/ios/**/*.mode1v3
41 | **/ios/**/*.mode2v3
42 | **/ios/**/*.moved-aside
43 | **/ios/**/*.pbxuser
44 | **/ios/**/*.perspectivev3
45 | **/ios/**/*sync/
46 | **/ios/**/.sconsign.dblite
47 | **/ios/**/.tags*
48 | **/ios/**/.vagrant/
49 | **/ios/**/DerivedData/
50 | **/ios/**/Icon?
51 | **/ios/**/Pods/
52 | **/ios/**/.symlinks/
53 | **/ios/**/profile
54 | **/ios/**/xcuserdata
55 | **/ios/.generated/
56 | **/ios/Flutter/App.framework
57 | **/ios/Flutter/Flutter.framework
58 | **/ios/Flutter/Generated.xcconfig
59 | **/ios/Flutter/app.flx
60 | **/ios/Flutter/app.zip
61 | **/ios/Flutter/flutter_assets/
62 | **/ios/ServiceDefinitions.json
63 | **/ios/Runner/GeneratedPluginRegistrant.*
64 |
65 | # Exceptions to above rules.
66 | !**/ios/**/default.mode1v3
67 | !**/ios/**/default.mode2v3
68 | !**/ios/**/default.pbxuser
69 | !**/ios/**/default.perspectivev3
70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
71 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/.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: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b
8 | channel: unknown
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [0.1.0] - TODO: Add release date.
2 |
3 | * TODO: Describe initial release.
4 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 gwh
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 | # Visual Studio Code related
19 | .vscode/
20 |
21 | # Flutter/Dart/Pub related
22 | **/doc/api/
23 | .dart_tool/
24 | .flutter-plugins
25 | .packages
26 | .pub-cache/
27 | .pub/
28 | /build/
29 |
30 | # Android related
31 | **/android/**/gradle-wrapper.jar
32 | **/android/.gradle
33 | **/android/captures/
34 | **/android/gradlew
35 | **/android/gradlew.bat
36 | **/android/local.properties
37 | **/android/**/GeneratedPluginRegistrant.java
38 |
39 | # iOS/XCode related
40 | **/ios/**/*.mode1v3
41 | **/ios/**/*.mode2v3
42 | **/ios/**/*.moved-aside
43 | **/ios/**/*.pbxuser
44 | **/ios/**/*.perspectivev3
45 | **/ios/**/*sync/
46 | **/ios/**/.sconsign.dblite
47 | **/ios/**/.tags*
48 | **/ios/**/.vagrant/
49 | **/ios/**/DerivedData/
50 | **/ios/**/Icon?
51 | **/ios/**/Pods/
52 | **/ios/**/.symlinks/
53 | **/ios/**/profile
54 | **/ios/**/xcuserdata
55 | **/ios/.generated/
56 | **/ios/Flutter/App.framework
57 | **/ios/Flutter/Flutter.framework
58 | **/ios/Flutter/Generated.xcconfig
59 | **/ios/Flutter/app.flx
60 | **/ios/Flutter/app.zip
61 | **/ios/Flutter/flutter_assets/
62 | **/ios/ServiceDefinitions.json
63 | **/ios/Runner/GeneratedPluginRegistrant.*
64 |
65 | # Exceptions to above rules.
66 | !**/ios/**/default.mode1v3
67 | !**/ios/**/default.mode2v3
68 | !**/ios/**/default.pbxuser
69 | !**/ios/**/default.perspectivev3
70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
71 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b
8 | channel: unknown
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/README.md:
--------------------------------------------------------------------------------
1 | # example
2 |
3 | A new Flutter project.
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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 "com.example.example"
37 | minSdkVersion 16
38 | targetSdkVersion 28
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | testImplementation 'junit:junit:4.12'
59 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
61 | }
62 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
13 |
20 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/java/com/example/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.example;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | public class MainActivity extends FlutterActivity {
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | GeneratedPluginRegistrant.registerWith(this);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.2.1'
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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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-4.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/assets/kmon.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "ok",
3 | "ch": "market.btcusdt.kline.1mon",
4 | "ts": 1580885101624,
5 | "data": [
6 | {
7 | "amount": 123527.105944981171846470,
8 | "open": 9337.100000000000000000,
9 | "close": 9280.470000000000000000,
10 | "high": 9600.000000000000000000,
11 | "id": 1580486400,
12 | "count": 1095638,
13 | "low": 9100.000000000000000000,
14 | "vol": 1151593772.529603656613804285450000000000000000
15 | },
16 | {
17 | "amount": 1202012.456391286064699800,
18 | "open": 7194.700000000000000000,
19 | "close": 9337.100000000000000000,
20 | "high": 9576.220000000000000000,
21 | "id": 1577808000,
22 | "count": 9864195,
23 | "low": 6871.000000000000000000,
24 | "vol": 10038645567.217605490281740305930000000000000000
25 | },
26 | {
27 | "id": 1575129600,
28 | "open": 7538.110000000000000000,
29 | "close": 7195.000000000000000000,
30 | "high": 7750.000000000000000000,
31 | "low": 6433.000000000000000000,
32 | "vol": 7333120887.111299660681173418,
33 | "amount": 1012514.543074772694721137,
34 | "count": 8142107
35 | },
36 | {
37 | "id": 1572537600,
38 | "open": 9212.090000000000000000,
39 | "close": 7538.000000000000000000,
40 | "high": 9500.000000000000000000,
41 | "low": 6514.000000000000000000,
42 | "vol": 9060209718.633427075559052342,
43 | "amount": 1127726.590752640890177204,
44 | "count": 9646549
45 | },
46 | {
47 | "id": 1569859200,
48 | "open": 8283.840000000000000000,
49 | "close": 9212.100000000000000000,
50 | "high": 10350.000000000000000000,
51 | "low": 7300.000000000000000000,
52 | "vol": 9097635071.818781897694963232,
53 | "amount": 1061202.517633262389120474,
54 | "count": 10050932
55 | },
56 | {
57 | "id": 1567267200,
58 | "open": 9593.710000000000000000,
59 | "close": 8284.660000000000000000,
60 | "high": 10907.470000000000000000,
61 | "low": 7700.000000000000000000,
62 | "vol": 8241884192.365670234002120846,
63 | "amount": 866607.628912485392903958,
64 | "count": 9598200
65 | },
66 | {
67 | "id": 1564588800,
68 | "open": 10044.840000000000000000,
69 | "close": 9593.620000000000000000,
70 | "high": 12300.000000000000000000,
71 | "low": 9311.000000000000000000,
72 | "vol": 11179919585.876565593854077962,
73 | "amount": 1048616.861714258999291636,
74 | "count": 10115503
75 | },
76 | {
77 | "id": 1561910400,
78 | "open": 11155.320000000000000000,
79 | "close": 10044.840000000000000000,
80 | "high": 13150.840000000000000000,
81 | "low": 9056.560000000000000000,
82 | "vol": 17141122551.347227888235620922,
83 | "amount": 1594416.832993592260179637,
84 | "count": 14236915
85 | },
86 | {
87 | "id": 1559318400,
88 | "open": 8351.650000000000000000,
89 | "close": 11154.360000000000000000,
90 | "high": 13968.760000000000000000,
91 | "low": 7450.000000000000000000,
92 | "vol": 12588854400.344795531877385472,
93 | "amount": 1231310.545038317446389941,
94 | "count": 14340886
95 | },
96 | {
97 | "id": 1556640000,
98 | "open": 5311.950000000000000000,
99 | "close": 8351.670000000000000000,
100 | "high": 9063.920000000000000000,
101 | "low": 5286.040000000000000000,
102 | "vol": 8898579158.558368100564708328,
103 | "amount": 1200601.735349462109291095,
104 | "count": 10452987
105 | },
106 | {
107 | "id": 1554048000,
108 | "open": 4098.210000000000000000,
109 | "close": 5311.590000000000000000,
110 | "high": 5605.000000000000000000,
111 | "low": 4069.860000000000000000,
112 | "vol": 3540652299.912440976664491566,
113 | "amount": 698468.284552441871680638,
114 | "count": 6393364
115 | },
116 | {
117 | "id": 1551369600,
118 | "open": 3851.750000000000000000,
119 | "close": 4098.200000000000000000,
120 | "high": 4122.790000000000000000,
121 | "low": 3672.610000000000000000,
122 | "vol": 3138466418.829721338801332724,
123 | "amount": 800653.563299826424120101,
124 | "count": 7173722
125 | },
126 | {
127 | "id": 1548950400,
128 | "open": 3435.240000000000000000,
129 | "close": 3851.740000000000000000,
130 | "high": 4200.020000000000000000,
131 | "low": 3380.000000000000000000,
132 | "vol": 2292159681.814156710739105313,
133 | "amount": 615523.489763932999111442,
134 | "count": 4726849
135 | },
136 | {
137 | "id": 1546272000,
138 | "open": 3754.370000000000000000,
139 | "close": 3435.240000000000000000,
140 | "high": 4068.000000000000000000,
141 | "low": 3353.030000000000000000,
142 | "vol": 2569820348.265060939817009359,
143 | "amount": 704741.345393831366736470,
144 | "count": 3765142
145 | },
146 | {
147 | "id": 1543593600,
148 | "open": 4026.930000000000000000,
149 | "close": 3754.470000000000000000,
150 | "high": 4314.180000000000000000,
151 | "low": 3155.000000000000000000,
152 | "vol": 4296251572.565865996384411198,
153 | "amount": 1162091.083276736514943449,
154 | "count": 5532917
155 | },
156 | {
157 | "id": 1541001600,
158 | "open": 6393.540000000000000000,
159 | "close": 4028.300000000000000000,
160 | "high": 6620.000000000000000000,
161 | "low": 3652.510000000000000000,
162 | "vol": 4547612917.513865663562967005,
163 | "amount": 893105.689670100286404505,
164 | "count": 5269967
165 | },
166 | {
167 | "id": 1538323200,
168 | "open": 6605.180000000000000000,
169 | "close": 6392.330000000000000000,
170 | "high": 7591.000000000000000000,
171 | "low": 6208.510000000000000000,
172 | "vol": 2407286624.708725325403136623,
173 | "amount": 365673.968925920771509683,
174 | "count": 2306188
175 | },
176 | {
177 | "id": 1535731200,
178 | "open": 6959.410000000000000000,
179 | "close": 6605.180000000000000000,
180 | "high": 7418.000000000000000000,
181 | "low": 6120.000000000000000000,
182 | "vol": 3291282236.298983205190230548,
183 | "amount": 497682.315005887378011415,
184 | "count": 2871282
185 | },
186 | {
187 | "id": 1533052800,
188 | "open": 7757.990000000000000000,
189 | "close": 6959.420000000000000000,
190 | "high": 7834.800000000000000000,
191 | "low": 5884.150000000000000000,
192 | "vol": 4364226086.188119718846745617,
193 | "amount": 651614.498761274666971936,
194 | "count": 5037719
195 | },
196 | {
197 | "id": 1530374400,
198 | "open": 6377.480000000000000000,
199 | "close": 7757.990000000000000000,
200 | "high": 8487.300000000000000000,
201 | "low": 6078.050000000000000000,
202 | "vol": 3178001703.947077092529260533,
203 | "amount": 439087.586211131390678750,
204 | "count": 5361272
205 | },
206 | {
207 | "id": 1527782400,
208 | "open": 7555.660000000000000000,
209 | "close": 6379.100000000000000000,
210 | "high": 7775.090000000000000000,
211 | "low": 5760.000000000000000000,
212 | "vol": 2850653528.202903834752234330,
213 | "amount": 414774.839655033242317482,
214 | "count": 3738365
215 | },
216 | {
217 | "id": 1525104000,
218 | "open": 9313.710000000000000000,
219 | "close": 7555.750000000000000000,
220 | "high": 10005.500000000000000000,
221 | "low": 7038.080000000000000000,
222 | "vol": 4130746065.421510640596175785,
223 | "amount": 489799.111802027055518948,
224 | "count": 4204699
225 | },
226 | {
227 | "id": 1522512000,
228 | "open": 7063.230000000000000000,
229 | "close": 9313.720000000000000000,
230 | "high": 9750.000000000000000000,
231 | "low": 6440.000000000000000000,
232 | "vol": 4968477407.500877687305636796,
233 | "amount": 618867.234664759825254142,
234 | "count": 4812515
235 | },
236 | {
237 | "id": 1519833600,
238 | "open": 10512.010000000000000000,
239 | "close": 7063.190000000000000000,
240 | "high": 11688.320000000000000000,
241 | "low": 6613.000000000000000000,
242 | "vol": 5897876568.509813025935222486,
243 | "amount": 669347.372228039808463257,
244 | "count": 3835496
245 | },
246 | {
247 | "id": 1517414400,
248 | "open": 10045.740000000000000000,
249 | "close": 10518.530000000000000000,
250 | "high": 11785.000000000000000000,
251 | "low": 6051.190000000000000000,
252 | "vol": 4024346662.073572261130839410,
253 | "amount": 443942.576008455857783123,
254 | "count": 3570833
255 | },
256 | {
257 | "id": 1514736000,
258 | "open": 13249.250000000000000000,
259 | "close": 10031.550000000000000000,
260 | "high": 17157.480000000000000000,
261 | "low": 9100.000000000000000000,
262 | "vol": 3957145729.381039761231067394,
263 | "amount": 316060.101892476419110928,
264 | "count": 4996371
265 | },
266 | {
267 | "id": 1512057600,
268 | "open": 9124.560000000000000000,
269 | "close": 13284.180000000000000000,
270 | "high": 19875.850000000000000000,
271 | "low": 9099.710000000000000000,
272 | "vol": 4105830627.350015922468211578,
273 | "amount": 278823.658881254264565683,
274 | "count": 3347256
275 | },
276 | {
277 | "id": 1509465600,
278 | "open": 6339.180000000000000000,
279 | "close": 9113.390000000000000000,
280 | "high": 11296.000000000000000000,
281 | "low": 5205.000000000000000000,
282 | "vol": 1302495843.915109071609681441,
283 | "amount": 162740.410588501985744239,
284 | "count": 1136968
285 | },
286 | {
287 | "id": 1506787200,
288 | "open": 5656.460000000000000000,
289 | "close": 6150.000000000000000000,
290 | "high": 6198.490000000000000000,
291 | "low": 5648.030000000000000000,
292 | "vol": 2868736.921540147860595041,
293 | "amount": 486.653285294312342242,
294 | "count": 5183
295 | }
296 | ]
297 | }
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/images/depth.2019-09-01 2010_21_31.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/images/depth.2019-09-01 2010_21_31.gif
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/images/k_chart.2019-09-01 2010_19_56.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/images/k_chart.2019-09-01 2010_19_56.gif
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/images/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/images/screenshots.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Flutter/flutter_export_environment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=/Users/bianxiang/flutter"
4 | export "FLUTTER_APPLICATION_PATH=/Users/bianxiang/Downloads/flutter_k_chart-master/example"
5 | export "FLUTTER_TARGET=lib/main.dart"
6 | export "FLUTTER_BUILD_DIR=build"
7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios"
8 | export "FLUTTER_FRAMEWORK_DIR=/Users/bianxiang/flutter/bin/cache/artifacts/engine/ios"
9 | export "FLUTTER_BUILD_NAME=1.0.0"
10 | export "FLUTTER_BUILD_NUMBER=1"
11 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
14 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
15 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
16 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
17 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
18 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
19 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
20 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
21 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXCopyFilesBuildPhase section */
25 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
26 | isa = PBXCopyFilesBuildPhase;
27 | buildActionMask = 2147483647;
28 | dstPath = "";
29 | dstSubfolderSpec = 10;
30 | files = (
31 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
32 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
33 | );
34 | name = "Embed Frameworks";
35 | runOnlyForDeploymentPostprocessing = 0;
36 | };
37 | /* End PBXCopyFilesBuildPhase section */
38 |
39 | /* Begin PBXFileReference section */
40 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
41 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
42 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
43 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
44 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
45 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
46 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
47 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
48 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
49 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
50 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
51 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
52 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
53 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
54 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
55 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
56 | /* End PBXFileReference section */
57 |
58 | /* Begin PBXFrameworksBuildPhase section */
59 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
60 | isa = PBXFrameworksBuildPhase;
61 | buildActionMask = 2147483647;
62 | files = (
63 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
64 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
65 | );
66 | runOnlyForDeploymentPostprocessing = 0;
67 | };
68 | /* End PBXFrameworksBuildPhase section */
69 |
70 | /* Begin PBXGroup section */
71 | 9740EEB11CF90186004384FC /* Flutter */ = {
72 | isa = PBXGroup;
73 | children = (
74 | 3B80C3931E831B6300D905FE /* App.framework */,
75 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
76 | 9740EEBA1CF902C7004384FC /* Flutter.framework */,
77 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
78 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
79 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
80 | );
81 | name = Flutter;
82 | sourceTree = "";
83 | };
84 | 97C146E51CF9000F007C117D = {
85 | isa = PBXGroup;
86 | children = (
87 | 9740EEB11CF90186004384FC /* Flutter */,
88 | 97C146F01CF9000F007C117D /* Runner */,
89 | 97C146EF1CF9000F007C117D /* Products */,
90 | );
91 | sourceTree = "";
92 | };
93 | 97C146EF1CF9000F007C117D /* Products */ = {
94 | isa = PBXGroup;
95 | children = (
96 | 97C146EE1CF9000F007C117D /* Runner.app */,
97 | );
98 | name = Products;
99 | sourceTree = "";
100 | };
101 | 97C146F01CF9000F007C117D /* Runner */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
105 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
106 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
107 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
108 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
109 | 97C147021CF9000F007C117D /* Info.plist */,
110 | 97C146F11CF9000F007C117D /* Supporting Files */,
111 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
112 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
113 | );
114 | path = Runner;
115 | sourceTree = "";
116 | };
117 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
118 | isa = PBXGroup;
119 | children = (
120 | 97C146F21CF9000F007C117D /* main.m */,
121 | );
122 | name = "Supporting Files";
123 | sourceTree = "";
124 | };
125 | /* End PBXGroup section */
126 |
127 | /* Begin PBXNativeTarget section */
128 | 97C146ED1CF9000F007C117D /* Runner */ = {
129 | isa = PBXNativeTarget;
130 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
131 | buildPhases = (
132 | 9740EEB61CF901F6004384FC /* Run Script */,
133 | 97C146EA1CF9000F007C117D /* Sources */,
134 | 97C146EB1CF9000F007C117D /* Frameworks */,
135 | 97C146EC1CF9000F007C117D /* Resources */,
136 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
137 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
138 | );
139 | buildRules = (
140 | );
141 | dependencies = (
142 | );
143 | name = Runner;
144 | productName = Runner;
145 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
146 | productType = "com.apple.product-type.application";
147 | };
148 | /* End PBXNativeTarget section */
149 |
150 | /* Begin PBXProject section */
151 | 97C146E61CF9000F007C117D /* Project object */ = {
152 | isa = PBXProject;
153 | attributes = {
154 | LastUpgradeCheck = 0910;
155 | ORGANIZATIONNAME = "The Chromium Authors";
156 | TargetAttributes = {
157 | 97C146ED1CF9000F007C117D = {
158 | CreatedOnToolsVersion = 7.3.1;
159 | DevelopmentTeam = ART262R7U6;
160 | };
161 | };
162 | };
163 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
164 | compatibilityVersion = "Xcode 3.2";
165 | developmentRegion = English;
166 | hasScannedForEncodings = 0;
167 | knownRegions = (
168 | English,
169 | en,
170 | Base,
171 | );
172 | mainGroup = 97C146E51CF9000F007C117D;
173 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
174 | projectDirPath = "";
175 | projectRoot = "";
176 | targets = (
177 | 97C146ED1CF9000F007C117D /* Runner */,
178 | );
179 | };
180 | /* End PBXProject section */
181 |
182 | /* Begin PBXResourcesBuildPhase section */
183 | 97C146EC1CF9000F007C117D /* Resources */ = {
184 | isa = PBXResourcesBuildPhase;
185 | buildActionMask = 2147483647;
186 | files = (
187 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
188 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
189 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
190 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
191 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
192 | );
193 | runOnlyForDeploymentPostprocessing = 0;
194 | };
195 | /* End PBXResourcesBuildPhase section */
196 |
197 | /* Begin PBXShellScriptBuildPhase section */
198 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
199 | isa = PBXShellScriptBuildPhase;
200 | buildActionMask = 2147483647;
201 | files = (
202 | );
203 | inputPaths = (
204 | );
205 | name = "Thin Binary";
206 | outputPaths = (
207 | );
208 | runOnlyForDeploymentPostprocessing = 0;
209 | shellPath = /bin/sh;
210 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
211 | };
212 | 9740EEB61CF901F6004384FC /* Run Script */ = {
213 | isa = PBXShellScriptBuildPhase;
214 | buildActionMask = 2147483647;
215 | files = (
216 | );
217 | inputPaths = (
218 | );
219 | name = "Run Script";
220 | outputPaths = (
221 | );
222 | runOnlyForDeploymentPostprocessing = 0;
223 | shellPath = /bin/sh;
224 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
225 | };
226 | /* End PBXShellScriptBuildPhase section */
227 |
228 | /* Begin PBXSourcesBuildPhase section */
229 | 97C146EA1CF9000F007C117D /* Sources */ = {
230 | isa = PBXSourcesBuildPhase;
231 | buildActionMask = 2147483647;
232 | files = (
233 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
234 | 97C146F31CF9000F007C117D /* main.m in Sources */,
235 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
236 | );
237 | runOnlyForDeploymentPostprocessing = 0;
238 | };
239 | /* End PBXSourcesBuildPhase section */
240 |
241 | /* Begin PBXVariantGroup section */
242 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
243 | isa = PBXVariantGroup;
244 | children = (
245 | 97C146FB1CF9000F007C117D /* Base */,
246 | );
247 | name = Main.storyboard;
248 | sourceTree = "";
249 | };
250 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
251 | isa = PBXVariantGroup;
252 | children = (
253 | 97C147001CF9000F007C117D /* Base */,
254 | );
255 | name = LaunchScreen.storyboard;
256 | sourceTree = "";
257 | };
258 | /* End PBXVariantGroup section */
259 |
260 | /* Begin XCBuildConfiguration section */
261 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
262 | isa = XCBuildConfiguration;
263 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
264 | buildSettings = {
265 | ALWAYS_SEARCH_USER_PATHS = NO;
266 | CLANG_ANALYZER_NONNULL = YES;
267 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
268 | CLANG_CXX_LIBRARY = "libc++";
269 | CLANG_ENABLE_MODULES = YES;
270 | CLANG_ENABLE_OBJC_ARC = YES;
271 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
272 | CLANG_WARN_BOOL_CONVERSION = YES;
273 | CLANG_WARN_COMMA = YES;
274 | CLANG_WARN_CONSTANT_CONVERSION = YES;
275 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
276 | CLANG_WARN_EMPTY_BODY = YES;
277 | CLANG_WARN_ENUM_CONVERSION = YES;
278 | CLANG_WARN_INFINITE_RECURSION = YES;
279 | CLANG_WARN_INT_CONVERSION = YES;
280 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
281 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
282 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
283 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
284 | CLANG_WARN_STRICT_PROTOTYPES = YES;
285 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
286 | CLANG_WARN_UNREACHABLE_CODE = YES;
287 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
288 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
289 | COPY_PHASE_STRIP = NO;
290 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
291 | ENABLE_NS_ASSERTIONS = NO;
292 | ENABLE_STRICT_OBJC_MSGSEND = YES;
293 | GCC_C_LANGUAGE_STANDARD = gnu99;
294 | GCC_NO_COMMON_BLOCKS = YES;
295 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
296 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
297 | GCC_WARN_UNDECLARED_SELECTOR = YES;
298 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
299 | GCC_WARN_UNUSED_FUNCTION = YES;
300 | GCC_WARN_UNUSED_VARIABLE = YES;
301 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
302 | MTL_ENABLE_DEBUG_INFO = NO;
303 | SDKROOT = iphoneos;
304 | TARGETED_DEVICE_FAMILY = "1,2";
305 | VALIDATE_PRODUCT = YES;
306 | };
307 | name = Profile;
308 | };
309 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
310 | isa = XCBuildConfiguration;
311 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
312 | buildSettings = {
313 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
314 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
315 | DEVELOPMENT_TEAM = ART262R7U6;
316 | ENABLE_BITCODE = NO;
317 | FRAMEWORK_SEARCH_PATHS = (
318 | "$(inherited)",
319 | "$(PROJECT_DIR)/Flutter",
320 | );
321 | INFOPLIST_FILE = Runner/Info.plist;
322 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
323 | LIBRARY_SEARCH_PATHS = (
324 | "$(inherited)",
325 | "$(PROJECT_DIR)/Flutter",
326 | );
327 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
328 | PRODUCT_NAME = "$(TARGET_NAME)";
329 | VERSIONING_SYSTEM = "apple-generic";
330 | };
331 | name = Profile;
332 | };
333 | 97C147031CF9000F007C117D /* Debug */ = {
334 | isa = XCBuildConfiguration;
335 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
336 | buildSettings = {
337 | ALWAYS_SEARCH_USER_PATHS = NO;
338 | CLANG_ANALYZER_NONNULL = YES;
339 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
340 | CLANG_CXX_LIBRARY = "libc++";
341 | CLANG_ENABLE_MODULES = YES;
342 | CLANG_ENABLE_OBJC_ARC = YES;
343 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
344 | CLANG_WARN_BOOL_CONVERSION = YES;
345 | CLANG_WARN_COMMA = YES;
346 | CLANG_WARN_CONSTANT_CONVERSION = YES;
347 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
348 | CLANG_WARN_EMPTY_BODY = YES;
349 | CLANG_WARN_ENUM_CONVERSION = YES;
350 | CLANG_WARN_INFINITE_RECURSION = YES;
351 | CLANG_WARN_INT_CONVERSION = YES;
352 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
353 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
355 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
356 | CLANG_WARN_STRICT_PROTOTYPES = YES;
357 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
358 | CLANG_WARN_UNREACHABLE_CODE = YES;
359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
361 | COPY_PHASE_STRIP = NO;
362 | DEBUG_INFORMATION_FORMAT = dwarf;
363 | ENABLE_STRICT_OBJC_MSGSEND = YES;
364 | ENABLE_TESTABILITY = YES;
365 | GCC_C_LANGUAGE_STANDARD = gnu99;
366 | GCC_DYNAMIC_NO_PIC = NO;
367 | GCC_NO_COMMON_BLOCKS = YES;
368 | GCC_OPTIMIZATION_LEVEL = 0;
369 | GCC_PREPROCESSOR_DEFINITIONS = (
370 | "DEBUG=1",
371 | "$(inherited)",
372 | );
373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
375 | GCC_WARN_UNDECLARED_SELECTOR = YES;
376 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
377 | GCC_WARN_UNUSED_FUNCTION = YES;
378 | GCC_WARN_UNUSED_VARIABLE = YES;
379 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
380 | MTL_ENABLE_DEBUG_INFO = YES;
381 | ONLY_ACTIVE_ARCH = YES;
382 | SDKROOT = iphoneos;
383 | TARGETED_DEVICE_FAMILY = "1,2";
384 | };
385 | name = Debug;
386 | };
387 | 97C147041CF9000F007C117D /* Release */ = {
388 | isa = XCBuildConfiguration;
389 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
390 | buildSettings = {
391 | ALWAYS_SEARCH_USER_PATHS = NO;
392 | CLANG_ANALYZER_NONNULL = YES;
393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
394 | CLANG_CXX_LIBRARY = "libc++";
395 | CLANG_ENABLE_MODULES = YES;
396 | CLANG_ENABLE_OBJC_ARC = YES;
397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
398 | CLANG_WARN_BOOL_CONVERSION = YES;
399 | CLANG_WARN_COMMA = YES;
400 | CLANG_WARN_CONSTANT_CONVERSION = YES;
401 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
402 | CLANG_WARN_EMPTY_BODY = YES;
403 | CLANG_WARN_ENUM_CONVERSION = YES;
404 | CLANG_WARN_INFINITE_RECURSION = YES;
405 | CLANG_WARN_INT_CONVERSION = YES;
406 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
407 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
408 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
409 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
410 | CLANG_WARN_STRICT_PROTOTYPES = YES;
411 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
412 | CLANG_WARN_UNREACHABLE_CODE = YES;
413 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
414 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
415 | COPY_PHASE_STRIP = NO;
416 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
417 | ENABLE_NS_ASSERTIONS = NO;
418 | ENABLE_STRICT_OBJC_MSGSEND = YES;
419 | GCC_C_LANGUAGE_STANDARD = gnu99;
420 | GCC_NO_COMMON_BLOCKS = YES;
421 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
422 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
423 | GCC_WARN_UNDECLARED_SELECTOR = YES;
424 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
425 | GCC_WARN_UNUSED_FUNCTION = YES;
426 | GCC_WARN_UNUSED_VARIABLE = YES;
427 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
428 | MTL_ENABLE_DEBUG_INFO = NO;
429 | SDKROOT = iphoneos;
430 | TARGETED_DEVICE_FAMILY = "1,2";
431 | VALIDATE_PRODUCT = YES;
432 | };
433 | name = Release;
434 | };
435 | 97C147061CF9000F007C117D /* Debug */ = {
436 | isa = XCBuildConfiguration;
437 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
438 | buildSettings = {
439 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
440 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
441 | DEVELOPMENT_TEAM = ART262R7U6;
442 | ENABLE_BITCODE = NO;
443 | FRAMEWORK_SEARCH_PATHS = (
444 | "$(inherited)",
445 | "$(PROJECT_DIR)/Flutter",
446 | );
447 | INFOPLIST_FILE = Runner/Info.plist;
448 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
449 | LIBRARY_SEARCH_PATHS = (
450 | "$(inherited)",
451 | "$(PROJECT_DIR)/Flutter",
452 | );
453 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
454 | PRODUCT_NAME = "$(TARGET_NAME)";
455 | VERSIONING_SYSTEM = "apple-generic";
456 | };
457 | name = Debug;
458 | };
459 | 97C147071CF9000F007C117D /* Release */ = {
460 | isa = XCBuildConfiguration;
461 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
462 | buildSettings = {
463 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
464 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
465 | DEVELOPMENT_TEAM = ART262R7U6;
466 | ENABLE_BITCODE = NO;
467 | FRAMEWORK_SEARCH_PATHS = (
468 | "$(inherited)",
469 | "$(PROJECT_DIR)/Flutter",
470 | );
471 | INFOPLIST_FILE = Runner/Info.plist;
472 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
473 | LIBRARY_SEARCH_PATHS = (
474 | "$(inherited)",
475 | "$(PROJECT_DIR)/Flutter",
476 | );
477 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
478 | PRODUCT_NAME = "$(TARGET_NAME)";
479 | VERSIONING_SYSTEM = "apple-generic";
480 | };
481 | name = Release;
482 | };
483 | /* End XCBuildConfiguration section */
484 |
485 | /* Begin XCConfigurationList section */
486 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
487 | isa = XCConfigurationList;
488 | buildConfigurations = (
489 | 97C147031CF9000F007C117D /* Debug */,
490 | 97C147041CF9000F007C117D /* Release */,
491 | 249021D3217E4FDB00AE95B9 /* Profile */,
492 | );
493 | defaultConfigurationIsVisible = 0;
494 | defaultConfigurationName = Release;
495 | };
496 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
497 | isa = XCConfigurationList;
498 | buildConfigurations = (
499 | 97C147061CF9000F007C117D /* Debug */,
500 | 97C147071CF9000F007C117D /* Release */,
501 | 249021D4217E4FDB00AE95B9 /* Profile */,
502 | );
503 | defaultConfigurationIsVisible = 0;
504 | defaultConfigurationName = Release;
505 | };
506 | /* End XCConfigurationList section */
507 | };
508 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
509 | }
510 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/flutter_k_chart-master/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.
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | 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 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:math';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/services.dart';
6 | import 'package:flutter_k_chart/flutter_k_chart.dart';
7 | import 'package:flutter_k_chart/k_chart_widget.dart';
8 | import 'package:http/http.dart' as http;
9 |
10 | void main() => runApp(MyApp());
11 |
12 | class MyApp extends StatelessWidget {
13 | @override
14 | Widget build(BuildContext context) {
15 | return MaterialApp(
16 | title: 'Flutter Demo',
17 | theme: ThemeData(
18 | primarySwatch: Colors.blue,
19 | ),
20 | home: MyHomePage(title: 'Flutter Demo Home Page'),
21 | );
22 | }
23 | }
24 |
25 | class MyHomePage extends StatefulWidget {
26 | MyHomePage({Key key, this.title}) : super(key: key);
27 |
28 | final String title;
29 |
30 | @override
31 | _MyHomePageState createState() => _MyHomePageState();
32 | }
33 |
34 | class _MyHomePageState extends State {
35 | List datas;
36 | bool showLoading = true;
37 | MainState _mainState = MainState.MA;
38 | SecondaryState _secondaryState = SecondaryState.MACD;
39 | bool isLine = true;
40 | List _bids, _asks;
41 |
42 | @override
43 | void initState() {
44 | super.initState();
45 | getData('1day');
46 | rootBundle.loadString('assets/depth.json').then((result) {
47 | final parseJson = json.decode(result);
48 | Map tick = parseJson['tick'];
49 | var bids = tick['bids'].map((item) => DepthEntity(item[0], item[1])).toList().cast();
50 | var asks = tick['asks'].map((item) => DepthEntity(item[0], item[1])).toList().cast();
51 | initDepth(bids, asks);
52 | });
53 | }
54 |
55 | void initDepth(List bids, List asks) {
56 | if (bids == null || asks == null || bids.isEmpty || asks.isEmpty) return;
57 | _bids = List();
58 | _asks = List();
59 | double amount = 0.0;
60 | bids?.sort((left, right) => left.price.compareTo(right.price));
61 | //倒序循环 //累加买入委托量
62 | bids.reversed.forEach((item) {
63 | amount += item.amount;
64 | item.amount = amount;
65 | _bids.insert(0, item);
66 | });
67 |
68 | amount = 0.0;
69 | asks?.sort((left, right) => left.price.compareTo(right.price));
70 | //循环 //累加买入委托量
71 | asks?.forEach((item) {
72 | amount += item.amount;
73 | item.amount = amount;
74 | _asks.add(item);
75 | });
76 | setState(() {});
77 | }
78 |
79 | @override
80 | Widget build(BuildContext context) {
81 | return Scaffold(
82 | backgroundColor: Color(0xff17212F),
83 | // appBar: AppBar(title: Text(widget.title)),
84 | body: ListView(
85 | children: [
86 | Stack(children: [
87 | Container(
88 | height: 450,
89 | width: double.infinity,
90 | child: KChartWidget(
91 | datas,
92 | isLine: isLine,
93 | mainState: _mainState,
94 | secondaryState: _secondaryState,
95 | volState: VolState.VOL,
96 | fractionDigits: 4,
97 | ),
98 | ),
99 | if (showLoading)
100 | Container(
101 | width: double.infinity, height: 450, alignment: Alignment.center, child: CircularProgressIndicator()),
102 | ]),
103 | buildButtons(),
104 | Container(
105 | height: 230,
106 | width: double.infinity,
107 | child: DepthChart(_bids, _asks),
108 | )
109 | ],
110 | ),
111 | );
112 | }
113 |
114 | Widget buildButtons() {
115 | return Wrap(
116 | alignment: WrapAlignment.spaceEvenly,
117 | children: [
118 | button("分时", onPressed: () => isLine = true),
119 | button("k线", onPressed: () => isLine = false),
120 | button("MA", onPressed: () => _mainState = MainState.MA),
121 | button("BOLL", onPressed: () => _mainState = MainState.BOLL),
122 | button("隐藏", onPressed: () => _mainState = MainState.NONE),
123 | button("MACD", onPressed: () => _secondaryState = SecondaryState.MACD),
124 | button("KDJ", onPressed: () => _secondaryState = SecondaryState.KDJ),
125 | button("RSI", onPressed: () => _secondaryState = SecondaryState.RSI),
126 | button("WR", onPressed: () => _secondaryState = SecondaryState.WR),
127 | button("隐藏副视图", onPressed: () => _secondaryState = SecondaryState.NONE),
128 | button("update", onPressed: () {
129 | //更新最后一条数据
130 | datas.last.close += (Random().nextInt(100) - 50).toDouble();
131 | datas.last.high = max(datas.last.high, datas.last.close);
132 | datas.last.low = min(datas.last.low, datas.last.close);
133 | DataUtil.updateLastData(datas);
134 | }),
135 | button("addData", onPressed: () {
136 | //拷贝一个对象,修改数据
137 | var kLineEntity = KLineEntity.fromJson(datas.last.toJson());
138 | kLineEntity.id += 60 * 60 * 24;
139 | kLineEntity.open = kLineEntity.close;
140 | kLineEntity.close += (Random().nextInt(100) - 50).toDouble();
141 | datas.last.high = max(datas.last.high, datas.last.close);
142 | datas.last.low = min(datas.last.low, datas.last.close);
143 | DataUtil.addLastData(datas, kLineEntity);
144 | }),
145 | button("1month", onPressed: () async {
146 | // showLoading = true;
147 | // setState(() {});
148 | //getData('1mon');
149 | String result = await rootBundle.loadString('assets/kmon.json');
150 | Map parseJson = json.decode(result);
151 | List list = parseJson['data'];
152 | datas = list.map((item) => KLineEntity.fromJson(item)).toList().reversed.toList().cast();
153 | DataUtil.calculate(datas);
154 | }),
155 | FlatButton(
156 | onPressed: (){
157 | showLoading = true;
158 | setState(() {});
159 | getData('1day');
160 | },
161 | child: Text("1day"),
162 | color: Colors.blue),
163 | ],
164 | );
165 | }
166 |
167 | Widget button(String text, {VoidCallback onPressed}) {
168 | return FlatButton(
169 | onPressed: () {
170 | if (onPressed != null) {
171 | onPressed();
172 | setState(() {});
173 | }
174 | },
175 | child: Text("$text"),
176 | color: Colors.blue);
177 | }
178 |
179 | void getData(String period) async {
180 | String result;
181 | try {
182 | result = await getIPAddress('$period');
183 | } catch (e) {
184 | print('获取数据失败,获取本地数据');
185 | result = await rootBundle.loadString('assets/kline.json');
186 | } finally {
187 | Map parseJson = json.decode(result);
188 | List list = parseJson['data'];
189 | datas = list.map((item) => KLineEntity.fromJson(item)).toList().reversed.toList().cast();
190 |
191 | DataUtil.calculate(datas);
192 | showLoading = false;
193 | setState(() {});
194 | }
195 | }
196 |
197 | Future getIPAddress(String period) async {
198 | //火币api,需要翻墙
199 | var url = 'https://api.huobi.br.com/market/history/kline?period=${period ?? '1day'}&size=300&symbol=btcusdt';
200 | String result;
201 | var response = await http.get(url).timeout(Duration(seconds: 7));
202 | if (response.statusCode == 200) {
203 | result = response.body;
204 | } else {
205 | return Future.error("获取失败");
206 | }
207 | return result;
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | archive:
5 | dependency: transitive
6 | description:
7 | name: archive
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.0.11"
11 | args:
12 | dependency: transitive
13 | description:
14 | name: args
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "1.5.2"
18 | async:
19 | dependency: transitive
20 | description:
21 | name: async
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "2.4.0"
25 | boolean_selector:
26 | dependency: transitive
27 | description:
28 | name: boolean_selector
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.0.5"
32 | charcode:
33 | dependency: transitive
34 | description:
35 | name: charcode
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.2"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.14.11"
46 | convert:
47 | dependency: transitive
48 | description:
49 | name: convert
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "2.1.1"
53 | crypto:
54 | dependency: transitive
55 | description:
56 | name: crypto
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "2.1.3"
60 | cupertino_icons:
61 | dependency: "direct main"
62 | description:
63 | name: cupertino_icons
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "0.1.3"
67 | flutter:
68 | dependency: "direct main"
69 | description: flutter
70 | source: sdk
71 | version: "0.0.0"
72 | flutter_k_chart:
73 | dependency: "direct main"
74 | description:
75 | path: ".."
76 | relative: true
77 | source: path
78 | version: "0.1.0"
79 | flutter_test:
80 | dependency: "direct dev"
81 | description: flutter
82 | source: sdk
83 | version: "0.0.0"
84 | http:
85 | dependency: "direct main"
86 | description:
87 | name: http
88 | url: "https://pub.dartlang.org"
89 | source: hosted
90 | version: "0.12.0+4"
91 | http_parser:
92 | dependency: transitive
93 | description:
94 | name: http_parser
95 | url: "https://pub.dartlang.org"
96 | source: hosted
97 | version: "3.1.3"
98 | image:
99 | dependency: transitive
100 | description:
101 | name: image
102 | url: "https://pub.dartlang.org"
103 | source: hosted
104 | version: "2.1.4"
105 | matcher:
106 | dependency: transitive
107 | description:
108 | name: matcher
109 | url: "https://pub.dartlang.org"
110 | source: hosted
111 | version: "0.12.6"
112 | meta:
113 | dependency: transitive
114 | description:
115 | name: meta
116 | url: "https://pub.dartlang.org"
117 | source: hosted
118 | version: "1.1.8"
119 | path:
120 | dependency: transitive
121 | description:
122 | name: path
123 | url: "https://pub.dartlang.org"
124 | source: hosted
125 | version: "1.6.4"
126 | pedantic:
127 | dependency: transitive
128 | description:
129 | name: pedantic
130 | url: "https://pub.dartlang.org"
131 | source: hosted
132 | version: "1.8.0+1"
133 | petitparser:
134 | dependency: transitive
135 | description:
136 | name: petitparser
137 | url: "https://pub.dartlang.org"
138 | source: hosted
139 | version: "2.4.0"
140 | quiver:
141 | dependency: transitive
142 | description:
143 | name: quiver
144 | url: "https://pub.dartlang.org"
145 | source: hosted
146 | version: "2.0.5"
147 | sky_engine:
148 | dependency: transitive
149 | description: flutter
150 | source: sdk
151 | version: "0.0.99"
152 | source_span:
153 | dependency: transitive
154 | description:
155 | name: source_span
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "1.5.5"
159 | stack_trace:
160 | dependency: transitive
161 | description:
162 | name: stack_trace
163 | url: "https://pub.dartlang.org"
164 | source: hosted
165 | version: "1.9.3"
166 | stream_channel:
167 | dependency: transitive
168 | description:
169 | name: stream_channel
170 | url: "https://pub.dartlang.org"
171 | source: hosted
172 | version: "2.0.0"
173 | string_scanner:
174 | dependency: transitive
175 | description:
176 | name: string_scanner
177 | url: "https://pub.dartlang.org"
178 | source: hosted
179 | version: "1.0.5"
180 | term_glyph:
181 | dependency: transitive
182 | description:
183 | name: term_glyph
184 | url: "https://pub.dartlang.org"
185 | source: hosted
186 | version: "1.1.0"
187 | test_api:
188 | dependency: transitive
189 | description:
190 | name: test_api
191 | url: "https://pub.dartlang.org"
192 | source: hosted
193 | version: "0.2.11"
194 | typed_data:
195 | dependency: transitive
196 | description:
197 | name: typed_data
198 | url: "https://pub.dartlang.org"
199 | source: hosted
200 | version: "1.1.6"
201 | vector_math:
202 | dependency: transitive
203 | description:
204 | name: vector_math
205 | url: "https://pub.dartlang.org"
206 | source: hosted
207 | version: "2.0.8"
208 | xml:
209 | dependency: transitive
210 | description:
211 | name: xml
212 | url: "https://pub.dartlang.org"
213 | source: hosted
214 | version: "3.5.0"
215 | sdks:
216 | dart: ">=2.4.0 <3.0.0"
217 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # In Android, build-name is used as versionName while build-number used as versionCode.
10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 | # Read more about iOS versioning at
13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 | version: 1.0.0+1
15 |
16 | environment:
17 | sdk: ">=2.2.2 <3.0.0"
18 |
19 | dependencies:
20 | flutter:
21 | sdk: flutter
22 |
23 | # The following adds the Cupertino Icons font to your application.
24 | # Use with the CupertinoIcons class for iOS style icons.
25 | cupertino_icons: ^0.1.2
26 | http: ^0.12.0+2
27 | flutter_k_chart:
28 | path: ../
29 |
30 | dev_dependencies:
31 | flutter_test:
32 | sdk: flutter
33 |
34 |
35 | # For information on the generic Dart part of this file, see the
36 | # following page: https://www.dartlang.org/tools/pub/pubspec
37 |
38 | # The following section is specific to Flutter.
39 | flutter:
40 |
41 | # The following line ensures that the Material Icons font is
42 | # included with your application, so that you can use the icons in
43 | # the material Icons class.
44 | uses-material-design: true
45 | assets:
46 | - assets/depth.json
47 | - assets/kline.json
48 | - assets/kmon.json
49 | # To add assets to your application, add an assets section, like this:
50 | # assets:
51 | # - images/a_dot_burr.jpeg
52 | # - images/a_dot_ham.jpeg
53 |
54 | # An image asset can refer to one or more resolution-specific "variants", see
55 | # https://flutter.dev/assets-and-images/#resolution-aware.
56 |
57 | # For details regarding adding assets from package dependencies, see
58 | # https://flutter.dev/assets-and-images/#from-packages
59 |
60 | # To add custom fonts to your application, add a fonts section here,
61 | # in this "flutter" section. Each entry in this list should have a
62 | # "family" key with the font family name, and a "fonts" key with a
63 | # list giving the asset and other descriptors for the font. For
64 | # example:
65 | # fonts:
66 | # - family: Schyler
67 | # fonts:
68 | # - asset: fonts/Schyler-Regular.ttf
69 | # - asset: fonts/Schyler-Italic.ttf
70 | # style: italic
71 | # - family: Trajan Pro
72 | # fonts:
73 | # - asset: fonts/TrajanPro.ttf
74 | # - asset: fonts/TrajanPro_Bold.ttf
75 | # weight: 700
76 | #
77 | # For details regarding fonts from package dependencies,
78 | # see https://flutter.dev/custom-fonts/#from-packages
79 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/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 '../lib/main.dart';
12 |
13 |
14 |
15 | void main() {
16 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
17 | // Build our app and trigger a frame.
18 | await tester.pumpWidget(MyApp());
19 |
20 | // Verify that our counter starts at 0.
21 | expect(find.text('0'), findsOneWidget);
22 | expect(find.text('1'), findsNothing);
23 |
24 | // Tap the '+' icon and trigger a frame.
25 | await tester.tap(find.byIcon(Icons.add));
26 | await tester.pump();
27 |
28 | // Verify that our counter has incremented.
29 | expect(find.text('0'), findsNothing);
30 | expect(find.text('1'), findsOneWidget);
31 | });
32 | }
33 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/k_chart.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bianxiang/flutter_kline/a0f060f5b5087f3cbb510188e0dbd9ccba5c0fc1/flutter_k_chart-master/k_chart.apk
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/chart_style.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart' show Color;
2 |
3 | class ChartColors {
4 | ChartColors._();
5 |
6 | //背景颜色
7 | static const Color bgColor = Color(0xff0D141E);
8 | static const Color kLineColor = Color(0xff4C86CD);
9 | static const Color gridColor = Color(0xff4c5c74);
10 | static const List kLineShadowColor = [Color(0x554C86CD), Color(0x00000000)]; //k线阴影渐变
11 | static const Color ma5Color = Color(0xffC9B885);
12 | static const Color ma10Color = Color(0xff6CB0A6);
13 | static const Color ma30Color = Color(0xff9979C6);
14 | static const Color upColor = Color(0xff4DAA90);
15 | static const Color dnColor = Color(0xffC15466);
16 | static const Color volColor = Color(0xff4729AE);
17 |
18 | static const Color macdColor = Color(0xff4729AE);
19 | static const Color difColor = Color(0xffC9B885);
20 | static const Color deaColor = Color(0xff6CB0A6);
21 |
22 | static const Color kColor = Color(0xffC9B885);
23 | static const Color dColor = Color(0xff6CB0A6);
24 | static const Color jColor = Color(0xff9979C6);
25 | static const Color rsiColor = Color(0xffC9B885);
26 |
27 | static const Color yAxisTextColor = Color(0xff60738E); //右边y轴刻度
28 | static const Color xAxisTextColor = Color(0xff60738E); //下方时间刻度
29 |
30 | static const Color maxMinTextColor = Color(0xffffffff); //最大最小值的颜色
31 |
32 | //深度颜色
33 | static const Color depthBuyColor = Color(0xff60A893);
34 | static const Color depthSellColor = Color(0xffC15866);
35 |
36 | //选中后显示值边框颜色
37 | static const Color markerBorderColor = Color(0xff6C7A86);
38 |
39 | //选中后显示值背景的填充颜色
40 | static const Color markerBgColor = Color(0xff0D1722);
41 |
42 | //实时线颜色等
43 | static const Color realTimeBgColor = Color(0xff0D1722);
44 | static const Color rightRealTimeTextColor = Color(0xff4C86CD);
45 | static const Color realTimeTextBorderColor = Color(0xffffffff);
46 | static const Color realTimeTextColor = Color(0xffffffff);
47 |
48 | //实时线
49 | static const Color realTimeLineColor = Color(0xffffffff);
50 | static const Color realTimeLongLineColor = Color(0xff4C86CD);
51 | }
52 |
53 | class ChartStyle {
54 | ChartStyle._();
55 |
56 | //点与点的距离
57 | static const double pointWidth = 11.0;
58 |
59 | //蜡烛宽度
60 | static const double candleWidth = 8.5;
61 |
62 | //蜡烛中间线的宽度
63 | static const double candleLineWidth = 1.5;
64 |
65 | //vol柱子宽度
66 | static const double volWidth = 8.5;
67 |
68 | //macd柱子宽度
69 | static const double macdWidth = 3.0;
70 |
71 | //垂直交叉线宽度
72 | static const double vCrossWidth = 8.5;
73 |
74 | //水平交叉线宽度
75 | static const double hCrossWidth = 0.5;
76 |
77 | //网格
78 | static const int gridRows = 3, gridColumns = 4;
79 |
80 | static const double topPadding = 30.0, bottomDateHigh = 20.0, childPadding = 25.0;
81 |
82 | static const double defaultTextSize = 10.0;
83 | }
84 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/depth_chart.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'chart_style.dart';
5 | import 'entity/depth_entity.dart';
6 |
7 | class DepthChart extends StatefulWidget {
8 | final List bids, asks;
9 |
10 | DepthChart(this.bids, this.asks);
11 |
12 | @override
13 | _DepthChartState createState() => _DepthChartState();
14 | }
15 |
16 | class _DepthChartState extends State {
17 | Offset pressOffset;
18 | bool isLongPress = false;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return GestureDetector(
23 | onLongPressStart: (details) {
24 | pressOffset = details.globalPosition;
25 | isLongPress = true;
26 | setState(() {});
27 | },
28 | onLongPressMoveUpdate: (details) {
29 | pressOffset = details.globalPosition;
30 | isLongPress = true;
31 | setState(() {});
32 | },
33 | onTap: () {
34 | if (isLongPress) {
35 | isLongPress = false;
36 | setState(() {});
37 | }
38 | },
39 | child: CustomPaint(
40 | size: Size(double.infinity, double.infinity),
41 | painter: DepthChartPainter(widget.bids, widget.asks, pressOffset, isLongPress),
42 | ),
43 | );
44 | }
45 | }
46 |
47 | class DepthChartPainter extends CustomPainter {
48 | //买入//卖出
49 | List mBuyData, mSellData;
50 | Offset pressOffset;
51 | bool isLongPress;
52 |
53 | double mPaddingBottom = 18.0;
54 | double mWidth = 0.0, mDrawHeight = 0.0, mDrawWidth = 0.0, mBuyPointWidth, mSellPointWidth;
55 |
56 | //最大的委托量
57 | double mMaxVolume, mMultiple;
58 |
59 | //右侧绘制个数
60 | int mLineCount = 4;
61 |
62 | Path mBuyPath, mSellPath;
63 |
64 | //买卖出区域边线绘制画笔 //买卖出取悦绘制画笔
65 | Paint mBuyLinePaint, mSellLinePaint, mBuyPathPaint, mSellPathPaint;
66 |
67 | DepthChartPainter(this.mBuyData, this.mSellData, this.pressOffset, this.isLongPress) {
68 | mBuyLinePaint ??= Paint()
69 | ..isAntiAlias = true
70 | ..color = ChartColors.depthBuyColor
71 | ..style = PaintingStyle.stroke
72 | ..strokeWidth = 1.0;
73 | mSellLinePaint ??= Paint()
74 | ..isAntiAlias = true
75 | ..color = ChartColors.depthSellColor
76 | ..style = PaintingStyle.stroke
77 | ..strokeWidth = 1.0;
78 |
79 | mBuyPathPaint ??= Paint()
80 | ..isAntiAlias = true
81 | ..color = ChartColors.depthBuyColor.withOpacity(0.2);
82 | mSellPathPaint ??= Paint()
83 | ..isAntiAlias = true
84 | ..color = ChartColors.depthSellColor.withOpacity(0.2);
85 | mBuyPath ??= Path();
86 | mSellPath ??= Path();
87 | init();
88 | }
89 |
90 | void init() {
91 | if (mBuyData == null || mSellData == null || mBuyData.isEmpty || mSellData.isEmpty) return;
92 | mMaxVolume = mBuyData[0].amount;
93 | mMaxVolume = max(mMaxVolume, mSellData.last.amount);
94 | mMaxVolume = mMaxVolume * 1.05;
95 | mMultiple = mMaxVolume / mLineCount;
96 | }
97 |
98 | @override
99 | void paint(Canvas canvas, Size size) {
100 | if (mBuyData == null || mSellData == null || mBuyData.isEmpty || mSellData.isEmpty) return;
101 | mWidth = size.width;
102 | mDrawWidth = mWidth / 2;
103 | mDrawHeight = size.height - mPaddingBottom;
104 | // canvas.drawColor(Colors.black, BlendMode.color);
105 | canvas.save();
106 | //绘制买入区域
107 | drawBuy(canvas);
108 | //绘制卖出区域
109 | drawSell(canvas);
110 |
111 | //绘制界面相关文案
112 | drawText(canvas);
113 | canvas.restore();
114 | }
115 |
116 | void drawBuy(Canvas canvas) {
117 | mBuyPointWidth = (mDrawWidth / (mBuyData.length - 1 == 0 ? 1 : mBuyData.length - 1));
118 | mBuyPath.reset();
119 | double x;
120 | double y;
121 | for (int i = 0; i < mBuyData.length; i++) {
122 | if (i == 0) {
123 | mBuyPath.moveTo(0, getY(mBuyData[0].amount));
124 | }
125 | y = getY(mBuyData[i].amount);
126 | if (i >= 1) {
127 | canvas.drawLine(Offset(mBuyPointWidth * (i - 1), getY(mBuyData[i - 1].amount)),
128 | Offset(mBuyPointWidth * i, y), mBuyLinePaint);
129 | }
130 | if (i != mBuyData.length - 1) {
131 | mBuyPath.quadraticBezierTo(
132 | mBuyPointWidth * i, y, mBuyPointWidth * (i + 1), getY(mBuyData[i + 1].amount));
133 | }
134 |
135 | x = mBuyPointWidth * i;
136 | if (i == mBuyData.length - 1) {
137 | mBuyPath.quadraticBezierTo(mBuyPointWidth * i, y, mBuyPointWidth * i, mDrawHeight);
138 | mBuyPath.quadraticBezierTo(mBuyPointWidth * i, mDrawHeight, 0, mDrawHeight);
139 | mBuyPath.close();
140 | }
141 | }
142 | canvas.drawPath(mBuyPath, mBuyPathPaint);
143 | }
144 |
145 | void drawSell(Canvas canvas) {
146 | mSellPointWidth = (mDrawWidth / (mSellData.length - 1 == 0 ? 1 : mSellData.length - 1));
147 | mSellPath.reset();
148 | double x;
149 | double y;
150 | for (int i = 0; i < mSellData.length; i++) {
151 | if (i == 0) {
152 | mSellPath.moveTo(mDrawWidth, getY(mSellData[0].amount));
153 | }
154 | y = getY(mSellData[i].amount);
155 | if (i >= 1) {
156 | canvas.drawLine(Offset((mSellPointWidth * (i - 1)) + mDrawWidth, getY(mSellData[i - 1].amount)),
157 | Offset((mSellPointWidth * i) + mDrawWidth, y), mSellLinePaint);
158 | }
159 | if (i != mSellData.length - 1) {
160 | mSellPath.quadraticBezierTo((mSellPointWidth * i) + mDrawWidth, y,
161 | (mSellPointWidth * (i + 1)) + mDrawWidth, getY(mSellData[i + 1].amount));
162 | }
163 | x = (mSellPointWidth * i) + mDrawWidth;
164 | if (i == mSellData.length - 1) {
165 | mSellPath.quadraticBezierTo(mWidth, y, (mSellPointWidth * i) + mDrawWidth, mDrawHeight);
166 | mSellPath.quadraticBezierTo((mSellPointWidth * i) + mDrawWidth, mDrawHeight, mDrawWidth, mDrawHeight);
167 | mSellPath.close();
168 | }
169 | }
170 | canvas.drawPath(mSellPath, mSellPathPaint);
171 | }
172 |
173 | int mLastPosition;
174 |
175 | void drawText(Canvas canvas) {
176 | double value;
177 | String str;
178 | for (int j = 0; j < mLineCount; j++) {
179 | value = mMaxVolume - mMultiple * j;
180 | str = value.toStringAsFixed(2);
181 | var tp = getTextPainter(str);
182 | tp.layout();
183 | tp.paint(canvas, Offset(mWidth - tp.width, mDrawHeight / mLineCount * j + tp.height / 2));
184 | }
185 | var startText = mBuyData.first.price.toStringAsFixed(2);
186 | TextPainter startTP = getTextPainter(startText);
187 | startTP.layout();
188 | startTP.paint(canvas, Offset(0, getBottomTextY(startTP.height)));
189 |
190 | var center = ((mBuyData.last.price + mSellData.first.price) / 2).toStringAsFixed(2);
191 | TextPainter centerTP = getTextPainter(center);
192 | centerTP.layout();
193 | centerTP.paint(canvas, Offset(mDrawWidth - centerTP.width / 2, getBottomTextY(centerTP.height)));
194 |
195 | var endText = mSellData.last.price.toStringAsFixed(2);
196 | TextPainter endTP = getTextPainter(endText);
197 | endTP.layout();
198 | endTP.paint(canvas, Offset(mWidth - endTP.width, getBottomTextY(endTP.height)));
199 |
200 | if (isLongPress == true) {
201 | if (pressOffset.dx <= mDrawWidth) {
202 | int index = _indexOfTranslateX(pressOffset.dx, 0, mBuyData.length, getBuyX);
203 | drawSelectView(canvas, index, true);
204 | } else {
205 | int index = _indexOfTranslateX(pressOffset.dx, 0, mSellData.length, getSellX);
206 | drawSelectView(canvas, index, false);
207 | }
208 | }
209 | }
210 |
211 | Paint selectPaint = Paint()
212 | ..isAntiAlias = true
213 | ..color = ChartColors.markerBgColor;
214 | Paint selectBorderPaint = Paint()
215 | ..isAntiAlias = true
216 | ..color = ChartColors.markerBorderColor
217 | ..style = PaintingStyle.stroke
218 | ..strokeWidth = 0.5;
219 |
220 | void drawSelectView(Canvas canvas, int index, bool isLeft) {
221 | DepthEntity entity = isLeft ? mBuyData[index] : mSellData[index];
222 | double dx = isLeft ? getBuyX(index) : getSellX(index);
223 |
224 | double radius = 8.0;
225 | if (dx < mDrawWidth) {
226 | canvas.drawCircle(
227 | Offset(dx, getY(entity.amount)), radius / 3, mBuyLinePaint..style = PaintingStyle.fill);
228 | canvas.drawCircle(Offset(dx, getY(entity.amount)), radius, mBuyLinePaint..style = PaintingStyle.stroke);
229 | } else {
230 | canvas.drawCircle(
231 | Offset(dx, getY(entity.amount)), radius / 3, mSellLinePaint..style = PaintingStyle.fill);
232 | canvas.drawCircle(
233 | Offset(dx, getY(entity.amount)), radius, mSellLinePaint..style = PaintingStyle.stroke);
234 | }
235 |
236 | //画底部
237 | TextPainter priceTP = getTextPainter(entity.price.toStringAsFixed(2));
238 | priceTP.layout();
239 | double left;
240 | if (dx <= priceTP.width / 2) {
241 | left = 0;
242 | } else if (dx >= mWidth - priceTP.width / 2) {
243 | left = mWidth - priceTP.width;
244 | } else {
245 | left = dx - priceTP.width / 2;
246 | }
247 | Rect bottomRect =
248 | Rect.fromLTRB(left - 3, mDrawHeight + 3, left + priceTP.width + 3, mDrawHeight + mPaddingBottom);
249 | canvas.drawRect(bottomRect, selectPaint);
250 | canvas.drawRect(bottomRect, selectBorderPaint);
251 | priceTP.paint(
252 | canvas,
253 | Offset(bottomRect.left + (bottomRect.width - priceTP.width) / 2,
254 | bottomRect.top + (bottomRect.height - priceTP.height) / 2));
255 | //画左边
256 | TextPainter amountTP = getTextPainter(entity.amount.toStringAsFixed(2));
257 | amountTP.layout();
258 | double y = getY(entity.amount);
259 | double rightRectTop;
260 | if (y <= amountTP.height / 2) {
261 | rightRectTop = 0;
262 | } else if (y >= mDrawHeight - amountTP.height / 2) {
263 | rightRectTop = mDrawHeight - amountTP.height;
264 | } else {
265 | rightRectTop = y - amountTP.height / 2;
266 | }
267 | Rect rightRect = Rect.fromLTRB(
268 | mWidth - amountTP.width - 6, rightRectTop - 3, mWidth, rightRectTop + amountTP.height + 3);
269 | canvas.drawRect(rightRect, selectPaint);
270 | canvas.drawRect(rightRect, selectBorderPaint);
271 | amountTP.paint(
272 | canvas,
273 | Offset(rightRect.left + (rightRect.width - amountTP.width) / 2,
274 | rightRect.top + (rightRect.height - amountTP.height) / 2));
275 | }
276 |
277 | ///二分查找当前值的index
278 | int _indexOfTranslateX(double translateX, int start, int end, Function getX) {
279 | if (end == start || end == -1) {
280 | return start;
281 | }
282 | if (end - start == 1) {
283 | double startValue = getX(start);
284 | double endValue = getX(end);
285 | return (translateX - startValue).abs() < (translateX - endValue).abs() ? start : end;
286 | }
287 | int mid = start + (end - start) ~/ 2;
288 | double midValue = getX(mid);
289 | if (translateX < midValue) {
290 | return _indexOfTranslateX(translateX, start, mid, getX);
291 | } else if (translateX > midValue) {
292 | return _indexOfTranslateX(translateX, mid, end, getX);
293 | } else {
294 | return mid;
295 | }
296 | }
297 |
298 | double getBuyX(int position) => position * mBuyPointWidth;
299 |
300 | double getSellX(int position) => position * mSellPointWidth + mDrawWidth;
301 |
302 | getTextPainter(String text, [Color color = Colors.white]) => TextPainter(
303 | text: TextSpan(text: "$text", style: TextStyle(color: color, fontSize: 10)),
304 | textDirection: TextDirection.ltr);
305 |
306 | double getBottomTextY(double textHeight) => (mPaddingBottom - textHeight) / 2 + mDrawHeight;
307 |
308 | double getY(double volume) => mDrawHeight - (mDrawHeight) * volume / mMaxVolume;
309 |
310 | @override
311 | bool shouldRepaint(DepthChartPainter oldDelegate) {
312 | // return oldDelegate.mBuyData != mBuyData ||
313 | // oldDelegate.mSellData != mSellData ||
314 | // oldDelegate.isLongPress != isLongPress ||
315 | // oldDelegate.pressOffset != pressOffset;
316 | return true;
317 | }
318 | }
319 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/candle_entity.dart:
--------------------------------------------------------------------------------
1 |
2 | mixin CandleEntity{
3 |
4 | double open;
5 | double high;
6 | double low;
7 | double close;
8 | double MA5Price;
9 | double MA10Price;
10 | double MA20Price;
11 | double MA30Price;
12 | double MA60Price;
13 | // 上轨线
14 | double up;
15 | // 中轨线
16 | double mb;
17 | // 下轨线
18 | double dn;
19 | }
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/depth_entity.dart:
--------------------------------------------------------------------------------
1 | class DepthEntity {
2 | double price;
3 | double amount;
4 |
5 | DepthEntity(this.price, this.amount);
6 |
7 | @override
8 | String toString() {
9 | return 'Data{price: $price, amount: $amount}';
10 | }
11 | }
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/info_window_entity.dart:
--------------------------------------------------------------------------------
1 | import '../entity/k_line_entity.dart';
2 |
3 | class InfoWindowEntity {
4 | KLineEntity kLineEntity;
5 | bool isLeft = false;
6 |
7 | InfoWindowEntity(this.kLineEntity, this.isLeft);
8 | }
9 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/k_entity.dart:
--------------------------------------------------------------------------------
1 | import 'candle_entity.dart';
2 | import 'kdj_entity.dart';
3 | import 'macd_entity.dart';
4 | import 'rsi_entity.dart';
5 | import 'rw_entity.dart';
6 | import 'volume_entity.dart';
7 |
8 | class KEntity with CandleEntity, VolumeEntity, KDJEntity, RSIEntity, WREntity, MACDEntity {}
9 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/k_line_entity.dart:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | import '../entity/k_entity.dart';
5 |
6 | class KLineEntity extends KEntity {
7 | double open;
8 | double high;
9 | double low;
10 | double close;
11 | double vol;
12 | double amount;
13 | int count;
14 | int id;
15 |
16 | KLineEntity.fromJson(Map json) {
17 | open = (json['open'] as num)?.toDouble();
18 | high = (json['high'] as num)?.toDouble();
19 | low = (json['low'] as num)?.toDouble();
20 | close = (json['close'] as num)?.toDouble();
21 | vol = (json['vol'] as num)?.toDouble();
22 | amount = (json['amount'] as num)?.toDouble();
23 | count = (json['count'] as num)?.toInt();
24 | id = (json['id'] as num)?.toInt();
25 | }
26 |
27 | Map toJson(){
28 | final Map data = new Map();
29 | data['id'] = this.id;
30 | data['open'] = this.open;
31 | data['close'] = this.close;
32 | data['high'] = this.high;
33 | data['low'] = this.low;
34 | data['vol'] = this.vol;
35 | data['amount'] = this.amount;
36 | data['count'] = this.count;
37 | return data;
38 | }
39 |
40 | @override
41 | String toString() {
42 | return 'MarketModel{open: $open, high: $high, low: $low, close: $close, vol: $vol, id: $id}';
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/kdj_entity.dart:
--------------------------------------------------------------------------------
1 | mixin KDJEntity {
2 | double k;
3 | double d;
4 | double j;
5 | }
6 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/macd_entity.dart:
--------------------------------------------------------------------------------
1 | import 'kdj_entity.dart';
2 | import 'rsi_entity.dart';
3 | import 'rw_entity.dart';
4 |
5 | mixin MACDEntity on KDJEntity, RSIEntity, WREntity {
6 | double dea;
7 | double dif;
8 | double macd;
9 | double ema12;
10 | double ema26;
11 | }
12 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/rsi_entity.dart:
--------------------------------------------------------------------------------
1 | mixin RSIEntity {
2 | /// RSI值
3 | double rsi;
4 | double rsiABSEma;
5 | double rsiMaxEma;
6 | }
7 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/rw_entity.dart:
--------------------------------------------------------------------------------
1 | mixin WREntity {
2 | /// %R值
3 | double r;
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/entity/volume_entity.dart:
--------------------------------------------------------------------------------
1 | mixin VolumeEntity {
2 |
3 | double open;
4 | double close;
5 | double vol;
6 | double MA5Volume;
7 | double MA10Volume;
8 | }
9 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/flutter_k_chart.dart:
--------------------------------------------------------------------------------
1 | library flutter_k_chart;
2 |
3 | export 'k_chart_widget.dart';//布局
4 | export 'utils/data_util.dart';//数据加工
5 | export 'entity/k_line_entity.dart';//数据
6 |
7 | export 'entity/depth_entity.dart';
8 | export 'depth_chart.dart';
9 |
10 | ///// A Calculator.
11 | //class Calculator {
12 | // /// Returns [value] plus 1.
13 | // int addOne(int value) => value + 1;
14 | //}
15 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/generated/i18n.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/foundation.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | // ignore_for_file: non_constant_identifier_names
7 | // ignore_for_file: camel_case_types
8 | // ignore_for_file: prefer_single_quotes
9 |
10 | // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
11 | class S implements WidgetsLocalizations {
12 | const S();
13 |
14 | static S current;
15 |
16 | static const GeneratedLocalizationsDelegate delegate =
17 | GeneratedLocalizationsDelegate();
18 |
19 | static S of(BuildContext context) => Localizations.of(context, S);
20 |
21 | @override
22 | TextDirection get textDirection => TextDirection.ltr;
23 |
24 | }
25 |
26 | class $en extends S {
27 | const $en();
28 | }
29 |
30 | class GeneratedLocalizationsDelegate extends LocalizationsDelegate {
31 | const GeneratedLocalizationsDelegate();
32 |
33 | List get supportedLocales {
34 | return const [
35 | Locale("en", ""),
36 | ];
37 | }
38 |
39 | LocaleListResolutionCallback listResolution({Locale fallback, bool withCountry = true}) {
40 | return (List locales, Iterable supported) {
41 | if (locales == null || locales.isEmpty) {
42 | return fallback ?? supported.first;
43 | } else {
44 | return _resolve(locales.first, fallback, supported, withCountry);
45 | }
46 | };
47 | }
48 |
49 | LocaleResolutionCallback resolution({Locale fallback, bool withCountry = true}) {
50 | return (Locale locale, Iterable supported) {
51 | return _resolve(locale, fallback, supported, withCountry);
52 | };
53 | }
54 |
55 | @override
56 | Future load(Locale locale) {
57 | final String lang = getLang(locale);
58 | if (lang != null) {
59 | switch (lang) {
60 | case "en":
61 | S.current = const $en();
62 | return SynchronousFuture(S.current);
63 | default:
64 | // NO-OP.
65 | }
66 | }
67 | S.current = const S();
68 | return SynchronousFuture(S.current);
69 | }
70 |
71 | @override
72 | bool isSupported(Locale locale) => _isSupported(locale, true);
73 |
74 | @override
75 | bool shouldReload(GeneratedLocalizationsDelegate old) => false;
76 |
77 | ///
78 | /// Internal method to resolve a locale from a list of locales.
79 | ///
80 | Locale _resolve(Locale locale, Locale fallback, Iterable supported, bool withCountry) {
81 | if (locale == null || !_isSupported(locale, withCountry)) {
82 | return fallback ?? supported.first;
83 | }
84 |
85 | final Locale languageLocale = Locale(locale.languageCode, "");
86 | if (supported.contains(locale)) {
87 | return locale;
88 | } else if (supported.contains(languageLocale)) {
89 | return languageLocale;
90 | } else {
91 | final Locale fallbackLocale = fallback ?? supported.first;
92 | return fallbackLocale;
93 | }
94 | }
95 |
96 | ///
97 | /// Returns true if the specified locale is supported, false otherwise.
98 | ///
99 | bool _isSupported(Locale locale, bool withCountry) {
100 | if (locale != null) {
101 | for (Locale supportedLocale in supportedLocales) {
102 | // Language must always match both locales.
103 | if (supportedLocale.languageCode != locale.languageCode) {
104 | continue;
105 | }
106 |
107 | // If country code matches, return this locale.
108 | if (supportedLocale.countryCode == locale.countryCode) {
109 | return true;
110 | }
111 |
112 | // If no country requirement is requested, check if this locale has no country.
113 | if (true != withCountry && (supportedLocale.countryCode == null || supportedLocale.countryCode.isEmpty)) {
114 | return true;
115 | }
116 | }
117 | }
118 | return false;
119 | }
120 | }
121 |
122 | String getLang(Locale l) => l == null
123 | ? null
124 | : l.countryCode != null && l.countryCode.isEmpty
125 | ? l.languageCode
126 | : l.toString();
127 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/k_chart_widget.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'chart_style.dart';
5 | import 'entity/info_window_entity.dart';
6 | import 'entity/k_line_entity.dart';
7 | import 'renderer/chart_painter.dart';
8 | import 'utils/date_format_util.dart';
9 | import 'utils/number_util.dart';
10 |
11 | enum MainState { MA, BOLL, NONE }
12 | enum VolState { VOL, NONE }
13 | enum SecondaryState { MACD, KDJ, RSI, WR, NONE }
14 |
15 | class KChartWidget extends StatefulWidget {
16 | final List datas;
17 | final MainState mainState;
18 | final VolState volState;
19 | final SecondaryState secondaryState;
20 | final bool isLine;
21 |
22 | KChartWidget(this.datas, {this.mainState = MainState.MA,this.volState = VolState.VOL, this.secondaryState = SecondaryState.MACD, this.isLine,int fractionDigits = 2}){
23 | NumberUtil.fractionDigits = fractionDigits;
24 | }
25 |
26 | @override
27 | _KChartWidgetState createState() => _KChartWidgetState();
28 | }
29 |
30 | class _KChartWidgetState extends State with SingleTickerProviderStateMixin{
31 | AnimationController _controller;
32 | Animation _animation;
33 | double mScaleX = 1.0, mScrollX = 0.0, mSelectX = 0.0;
34 | StreamController mInfoWindowStream;
35 | double mWidth = 0;
36 |
37 | double getMinScrollX() {
38 | return mScaleX;
39 | }
40 |
41 | double _lastScale = 1.0;
42 | bool isScale = false, isDrag = false, isLongPress = false;
43 |
44 | @override
45 | void initState() {
46 | super.initState();
47 | mInfoWindowStream = StreamController();
48 | _controller = AnimationController(duration: Duration(milliseconds: 850), vsync: this);
49 | _animation = Tween(begin: 0.9, end: 0.1).animate(_controller)..addListener(() => setState(() {}));
50 | }
51 |
52 | @override
53 | void didChangeDependencies() {
54 | super.didChangeDependencies();
55 | mWidth = MediaQuery.of(context).size.width;
56 | }
57 |
58 | @override
59 | void didUpdateWidget(KChartWidget oldWidget) {
60 | super.didUpdateWidget(oldWidget);
61 | if (oldWidget.datas != widget.datas) mScrollX = mSelectX = 0.0;
62 | }
63 |
64 | @override
65 | void dispose() {
66 | mInfoWindowStream?.close();
67 | _controller?.dispose();
68 | super.dispose();
69 | }
70 |
71 | @override
72 | Widget build(BuildContext context) {
73 | if (widget.datas == null || widget.datas.isEmpty) {
74 | mScrollX = mSelectX = 0.0;
75 | mScaleX = 1.0;
76 | }
77 | return GestureDetector(
78 | onHorizontalDragDown: (details) {
79 | isDrag = true;
80 | },
81 | onHorizontalDragUpdate: (details) {
82 | if (isScale || isLongPress) return;
83 | mScrollX = (details.primaryDelta / mScaleX + mScrollX).clamp(0.0, ChartPainter.maxScrollX);
84 | notifyChanged();
85 | },
86 | onHorizontalDragEnd: (DragEndDetails details) {
87 | isDrag = false;
88 | },
89 | onHorizontalDragCancel: () => isDrag = false,
90 | onScaleStart: (_) {
91 | isScale = true;
92 | },
93 | onScaleUpdate: (details) {
94 | if (isDrag || isLongPress) return;
95 | mScaleX = (_lastScale * details.scale).clamp(0.5, 2.2);
96 | notifyChanged();
97 | },
98 | onScaleEnd: (_) {
99 | isScale = false;
100 | _lastScale = mScaleX;
101 | },
102 | onLongPressStart: (details) {
103 | isLongPress = true;
104 | if (mSelectX != details.globalPosition.dx) {
105 | mSelectX = details.globalPosition.dx;
106 | notifyChanged();
107 | }
108 | },
109 | onLongPressMoveUpdate: (details) {
110 | if (mSelectX != details.globalPosition.dx) {
111 | mSelectX = details.globalPosition.dx;
112 | notifyChanged();
113 | }
114 | },
115 | onLongPressEnd: (details) {
116 | isLongPress = false;
117 | mInfoWindowStream?.sink?.add(null);
118 | notifyChanged();
119 | },
120 | child: Stack(
121 | children: [
122 | CustomPaint(
123 | size: Size(double.infinity, double.infinity),
124 | painter: ChartPainter(
125 | datas: widget.datas,
126 | scaleX: mScaleX,
127 | scrollX: mScrollX,
128 | selectX: mSelectX,
129 | isLongPass: isLongPress,
130 | mainState: widget.mainState,
131 | volState: widget.volState,
132 | secondaryState: widget.secondaryState,
133 | isLine: widget.isLine,
134 | sink: mInfoWindowStream?.sink,
135 | opacity: _animation.value,
136 | controller: _controller),
137 | ),
138 | _buildInfoDialog()
139 | ],
140 | ),
141 | );
142 | }
143 |
144 | void notifyChanged() => setState(() {});
145 |
146 | List infoNames = ["时间", "开", "高", "低", "收", "涨跌额", "涨幅", "成交量"];
147 | List infos;
148 |
149 | Widget _buildInfoDialog() {
150 | return StreamBuilder(
151 | stream: mInfoWindowStream?.stream,
152 | builder: (context, snapshot) {
153 | if (!isLongPress || widget.isLine == true || !snapshot.hasData || snapshot.data.kLineEntity == null)
154 | return Container();
155 | KLineEntity entity = snapshot.data.kLineEntity;
156 | double upDown = entity.close - entity.open;
157 | double upDownPercent = upDown / entity.open * 100;
158 | infos = [
159 | getDate(entity.id),
160 | NumberUtil.format(entity.open),
161 | NumberUtil.format(entity.high),
162 | NumberUtil.format(entity.low),
163 | NumberUtil.format(entity.close),
164 | "${upDown > 0 ? "+" : ""}${NumberUtil.format(upDown)}",
165 | "${upDownPercent > 0 ? "+" : ''}${upDownPercent.toStringAsFixed(2)}%",
166 | NumberUtil.volFormat(entity.vol)
167 | ];
168 | return Align(
169 | alignment: snapshot.data.isLeft ? Alignment.topLeft : Alignment.topRight,
170 | child: Container(
171 | margin: EdgeInsets.only(left: 10, right: 10, top: 25),
172 | padding: EdgeInsets.symmetric(horizontal: 8, vertical: 7),
173 | decoration: BoxDecoration(
174 | color: ChartColors.markerBgColor,
175 | border: Border.all(color: ChartColors.markerBorderColor, width: 0.5)),
176 | child: Column(
177 | mainAxisSize: MainAxisSize.min,
178 | children: List.generate(infoNames.length, (i) => _buildItem(infos[i].toString(), infoNames[i])),
179 | ),
180 | ),
181 | );
182 | });
183 | }
184 |
185 | Widget _buildItem(String info, String infoName) {
186 | Color color = Colors.white;
187 | if (info.startsWith("+"))
188 | color = Colors.green;
189 | else if (info.startsWith("-"))
190 | color = Colors.red;
191 | else
192 | color = Colors.white;
193 | return Container(
194 | constraints: BoxConstraints(minWidth: 95, maxWidth: 110, maxHeight: 14.0, minHeight: 14.0),
195 | child: Row(
196 | mainAxisSize: MainAxisSize.min,
197 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
198 | crossAxisAlignment: CrossAxisAlignment.center,
199 | children: [
200 | Text("$infoName", style: TextStyle(color: Colors.white, fontSize: ChartStyle.defaultTextSize)),
201 | SizedBox(width: 5),
202 | Text(info, style: TextStyle(color: color, fontSize: ChartStyle.defaultTextSize)),
203 | ],
204 | ),
205 | );
206 | }
207 |
208 | String getDate(int date) {
209 | return dateFormat(DateTime.fromMillisecondsSinceEpoch(date * 1000), [yy, '-', mm, '-', dd, ' ', HH, ':', nn]);
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/renderer/base_chart_painter.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | export 'package:flutter/material.dart' show Color, required, TextStyle, Rect, Canvas, Size, CustomPainter;
3 | import 'package:flutter/material.dart' show Color, required, TextStyle, Rect, Canvas, Size, CustomPainter;
4 | import 'package:flutter_k_chart/utils/date_format_util.dart';
5 | import 'package:flutter_k_chart/utils/number_util.dart';
6 | import '../entity/k_line_entity.dart';
7 | import '../k_chart_widget.dart';
8 | import '../chart_style.dart' show ChartStyle;
9 |
10 | abstract class BaseChartPainter extends CustomPainter {
11 | static double maxScrollX = 0.0;
12 | List datas;
13 | MainState mainState = MainState.MA;
14 | VolState volState = VolState.VOL;
15 | SecondaryState secondaryState = SecondaryState.MACD;
16 |
17 | double scaleX = 1.0, scrollX = 0.0, selectX;
18 | bool isLongPress = false;
19 | bool isLine = false;
20 |
21 | //3块区域大小与位置
22 | Rect mMainRect, mVolRect, mSecondaryRect;
23 | double mDisplayHeight, mWidth;
24 |
25 | int mStartIndex = 0, mStopIndex = 0;
26 | double mMainMaxValue = -double.maxFinite, mMainMinValue = double.maxFinite;
27 | double mVolMaxValue = -double.maxFinite, mVolMinValue = double.maxFinite;
28 | double mSecondaryMaxValue = -double.maxFinite, mSecondaryMinValue = double.maxFinite;
29 | double mTranslateX = -double.maxFinite;
30 | int mMainMaxIndex = 0, mMainMinIndex = 0;
31 | double mMainHighMaxValue = -double.maxFinite, mMainLowMinValue = double.maxFinite;
32 | int mItemCount = 0;
33 | double mDataLen = 0.0; //数据占屏幕总长度
34 | double mPointWidth = ChartStyle.pointWidth;
35 | List mFormats = [yyyy, '-', mm, '-', dd, ' ', HH, ':', nn]; //格式化时间
36 | double mMarginRight = 0.0; //k线右边空出来的距离
37 |
38 | BaseChartPainter(
39 | {@required this.datas,
40 | @required this.scaleX,
41 | @required this.scrollX,
42 | @required this.isLongPress,
43 | @required this.selectX,
44 | this.mainState,
45 | this.volState,
46 | this.secondaryState,
47 | this.isLine}) {
48 | mItemCount = datas?.length ?? 0;
49 | mDataLen = mItemCount * mPointWidth;
50 | initFormats();
51 | }
52 |
53 | void initFormats() {
54 | // [yyyy, '-', mm, '-', dd, ' ', HH, ':', nn]
55 | if (mItemCount < 2) return;
56 | int firstTime = datas.first?.id ?? 0;
57 | int secondTime = datas[1]?.id ?? 0;
58 | int time = secondTime - firstTime;
59 | //月线
60 | if (time >= 24 * 60 * 60 * 28)
61 | mFormats = [yy, '-', mm];
62 | //日线等
63 | else if (time >= 24 * 60 * 60)
64 | mFormats = [yy, '-', mm, '-', dd];
65 | //小时线等
66 | else
67 | mFormats = [mm, '-', dd, ' ', HH, ':', nn];
68 | }
69 |
70 | @override
71 | void paint(Canvas canvas, Size size) {
72 |
73 | canvas.clipRect(Rect.fromLTRB(0, 0, size.width, size.height));
74 | mDisplayHeight = size.height - ChartStyle.topPadding - ChartStyle.bottomDateHigh;
75 | mWidth = size.width;
76 | mMarginRight = (mWidth / ChartStyle.gridColumns - mPointWidth) / scaleX;
77 | initRect(size);
78 | calculateValue();
79 | initChartRenderer();
80 |
81 | canvas.save();
82 | canvas.scale(1, 1);
83 | drawBg(canvas, size);
84 | drawGrid(canvas);
85 | if (datas != null && datas.isNotEmpty) {
86 | drawChart(canvas, size);
87 | drawRightText(canvas);
88 | drawRealTimePrice(canvas, size);
89 | drawDate(canvas, size);
90 | if (isLongPress == true) drawCrossLineText(canvas, size);
91 | drawText(canvas, datas?.last, 5);
92 | drawMaxAndMin(canvas);
93 | }
94 | canvas.restore();
95 | }
96 |
97 | void initChartRenderer();
98 |
99 | //画背景
100 | void drawBg(Canvas canvas, Size size);
101 |
102 | //画网格
103 | void drawGrid(canvas);
104 |
105 | //画图表
106 | void drawChart(Canvas canvas, Size size);
107 |
108 | //画右边值
109 | void drawRightText(canvas);
110 |
111 | //画时间
112 | void drawDate(Canvas canvas, Size size);
113 |
114 | //画值
115 | void drawText(Canvas canvas, KLineEntity data, double x);
116 |
117 | //画最大最小值
118 | void drawMaxAndMin(Canvas canvas);
119 |
120 | //交叉线值
121 | void drawCrossLineText(Canvas canvas, Size size);
122 |
123 | void initRect(Size size) {
124 | double mainHeight = mDisplayHeight * 0.6;
125 | double volHeight = mDisplayHeight * 0.2;
126 | double secondaryHeight = mDisplayHeight * 0.2;
127 | if (volState == VolState.NONE && secondaryState == SecondaryState.NONE) {
128 | mainHeight = mDisplayHeight;
129 | } else if (volState == VolState.NONE || secondaryState == SecondaryState.NONE) {
130 | mainHeight = mDisplayHeight * 0.8;
131 | }
132 | mMainRect = Rect.fromLTRB(0, ChartStyle.topPadding, mWidth, ChartStyle.topPadding + mainHeight);
133 | if(volState != VolState.NONE){
134 | mVolRect = Rect.fromLTRB(0, mMainRect.bottom + ChartStyle.childPadding, mWidth, mMainRect.bottom + volHeight);
135 | }
136 | if (secondaryState != SecondaryState.NONE){
137 | mSecondaryRect = Rect.fromLTRB(0, (mVolRect?.bottom??mMainRect.bottom )+ ChartStyle.childPadding, mWidth, (mVolRect?.bottom??mMainRect.bottom) + secondaryHeight);
138 | }
139 |
140 | }
141 |
142 | calculateValue() {
143 | if (datas == null || datas.isEmpty) return;
144 | maxScrollX = getMinTranslateX().abs();
145 | setTranslateXFromScrollX(scrollX);
146 | mStartIndex = indexOfTranslateX(xToTranslateX(0));
147 | mStopIndex = indexOfTranslateX(xToTranslateX(mWidth));
148 | for (int i = mStartIndex; i <= mStopIndex; i++) {
149 | var item = datas[i];
150 | getMainMaxMinValue(item, i);
151 | getVolMaxMinValue(item);
152 | getSecondaryMaxMinValue(item);
153 | }
154 | }
155 |
156 | void getMainMaxMinValue(KLineEntity item, int i) {
157 | if (isLine == true) {
158 | mMainMaxValue = max(mMainMaxValue, item.close);
159 | mMainMinValue = min(mMainMinValue, item.close);
160 | } else {
161 | double maxPrice = item.high, minPrice = item.low;
162 | if (mainState == MainState.MA) {
163 | if(item.MA5Price != 0){
164 | maxPrice = max(maxPrice, item.MA5Price);
165 | minPrice = min(minPrice, item.MA5Price);
166 | }
167 | if(item.MA10Price != 0){
168 | maxPrice = max(maxPrice, item.MA10Price);
169 | minPrice = min(minPrice, item.MA10Price);
170 | }
171 | if(item.MA20Price != 0){
172 | maxPrice = max(maxPrice, item.MA20Price);
173 | minPrice = min(minPrice, item.MA20Price);
174 | }
175 | if(item.MA30Price != 0){
176 | maxPrice = max(maxPrice, item.MA30Price);
177 | minPrice = min(minPrice, item.MA30Price);
178 | }
179 | } else if (mainState == MainState.BOLL) {
180 | if(item.up!=0){
181 | maxPrice = max(item.up, item.high);
182 | }
183 | if(item.dn!=0){
184 | minPrice = min(item.dn, item.low);
185 | }
186 | }
187 | mMainMaxValue = max(mMainMaxValue, maxPrice);
188 | mMainMinValue = min(mMainMinValue, minPrice);
189 |
190 | if (mMainHighMaxValue < item.high) {
191 | mMainHighMaxValue = item.high;
192 | mMainMaxIndex = i;
193 | }
194 | if (mMainLowMinValue > item.low) {
195 | mMainLowMinValue = item.low;
196 | mMainMinIndex = i;
197 | }
198 | }
199 | }
200 |
201 | void getVolMaxMinValue(KLineEntity item) {
202 | mVolMaxValue = max(mVolMaxValue, max(item.vol, max(item.MA5Volume, item.MA10Volume)));
203 | mVolMinValue = min(mVolMinValue, min(item.vol, min(item.MA5Volume, item.MA10Volume)));
204 | }
205 |
206 | void getSecondaryMaxMinValue(KLineEntity item) {
207 | if (secondaryState == SecondaryState.MACD) {
208 | mSecondaryMaxValue = max(mSecondaryMaxValue, max(item.macd, max(item.dif, item.dea)));
209 | mSecondaryMinValue = min(mSecondaryMinValue, min(item.macd, min(item.dif, item.dea)));
210 | } else if (secondaryState == SecondaryState.KDJ) {
211 | mSecondaryMaxValue = max(mSecondaryMaxValue, max(item.k, max(item.d, item.j)));
212 | mSecondaryMinValue = min(mSecondaryMinValue, min(item.k, min(item.d, item.j)));
213 | } else if (secondaryState == SecondaryState.RSI) {
214 | mSecondaryMaxValue = max(mSecondaryMaxValue, item.rsi);
215 | mSecondaryMinValue = min(mSecondaryMinValue, item.rsi);
216 | } else {
217 | mSecondaryMaxValue = max(mSecondaryMaxValue, item.r);
218 | mSecondaryMinValue = min(mSecondaryMinValue, item.r);
219 | }
220 | }
221 |
222 | double xToTranslateX(double x) => -mTranslateX + x / scaleX;
223 |
224 | int indexOfTranslateX(double translateX) => _indexOfTranslateX(translateX, 0, mItemCount - 1);
225 |
226 | ///二分查找当前值的index
227 | int _indexOfTranslateX(double translateX, int start, int end) {
228 | if (end == start || end == -1) {
229 | return start;
230 | }
231 | if (end - start == 1) {
232 | double startValue = getX(start);
233 | double endValue = getX(end);
234 | return (translateX - startValue).abs() < (translateX - endValue).abs() ? start : end;
235 | }
236 | int mid = start + (end - start) ~/ 2;
237 | double midValue = getX(mid);
238 | if (translateX < midValue) {
239 | return _indexOfTranslateX(translateX, start, mid);
240 | } else if (translateX > midValue) {
241 | return _indexOfTranslateX(translateX, mid, end);
242 | } else {
243 | return mid;
244 | }
245 | }
246 |
247 | ///根据索引索取x坐标
248 | ///+ mPointWidth / 2防止第一根和最后一根k线显示不全
249 | ///@param position 索引值
250 | double getX(int position) => position * mPointWidth + mPointWidth / 2;
251 |
252 | Object getItem(int position) {
253 | if (datas != null) {
254 | return datas[position];
255 | } else {
256 | return null;
257 | }
258 | }
259 |
260 | ///scrollX 转换为 TranslateX
261 | void setTranslateXFromScrollX(double scrollX) => mTranslateX = scrollX + getMinTranslateX();
262 |
263 | ///获取平移的最小值
264 | double getMinTranslateX() {
265 | // var x = -mDataLen + mWidth / scaleX - mPointWidth / 2;
266 | var x = -mDataLen + mWidth / scaleX - mPointWidth / 2;
267 | x = x >= 0 ? 0.0 : x;
268 | //数据不足一屏
269 | if (x >= 0) {
270 | if (mWidth/scaleX - getX(datas.length) < mMarginRight) {
271 | //数据填充后剩余空间比mMarginRight小,求出差。x-=差
272 | x -= mMarginRight - mWidth/scaleX + getX(datas.length);
273 | } else {
274 | //数据填充后剩余空间比Right大
275 | mMarginRight = mWidth/scaleX - getX(datas.length);
276 | }
277 | } else if (x < 0) {
278 | //数据超过一屏
279 | x -= mMarginRight;
280 | }
281 | return x >= 0 ? 0.0 : x;
282 | }
283 |
284 | ///计算长按后x的值,转换为index
285 | int calculateSelectedX(double selectX) {
286 | int mSelectedIndex = indexOfTranslateX(xToTranslateX(selectX));
287 | if (mSelectedIndex < mStartIndex) {
288 | mSelectedIndex = mStartIndex;
289 | }
290 | if (mSelectedIndex > mStopIndex) {
291 | mSelectedIndex = mStopIndex;
292 | }
293 | return mSelectedIndex;
294 | }
295 |
296 | ///translateX转化为view中的x
297 | double translateXtoX(double translateX) => (translateX + mTranslateX) * scaleX;
298 |
299 | TextStyle getTextStyle(Color color) {
300 | return TextStyle(fontSize: ChartStyle.defaultTextSize, color: color);
301 | }
302 |
303 | void drawRealTimePrice(Canvas canvas, Size size);
304 |
305 | String format(double n) {
306 | return NumberUtil.format(n);
307 | }
308 |
309 | @override
310 | bool shouldRepaint(BaseChartPainter oldDelegate) {
311 | return true;
312 | // return oldDelegate.datas != datas ||
313 | // oldDelegate.datas?.length != datas?.length ||
314 | // oldDelegate.scaleX != scaleX ||
315 | // oldDelegate.scrollX != scrollX ||
316 | // oldDelegate.isLongPress != isLongPress ||
317 | // oldDelegate.selectX != selectX ||
318 | // oldDelegate.isLine != isLine ||
319 | // oldDelegate.mainState != mainState ||
320 | // oldDelegate.secondaryState != secondaryState;
321 | }
322 | }
323 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/renderer/base_chart_renderer.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_k_chart/chart_style.dart';
4 | import 'package:flutter_k_chart/utils/number_util.dart';
5 | export '../chart_style.dart';
6 |
7 | abstract class BaseChartRenderer {
8 | double maxValue, minValue;
9 | double scaleY;
10 | double topPadding;
11 | Rect chartRect;
12 | final Paint chartPaint = Paint()
13 | ..isAntiAlias = true
14 | ..filterQuality = FilterQuality.high
15 | ..strokeWidth = 1.0
16 | ..color = Colors.red;
17 | final Paint gridPaint = Paint()
18 | ..isAntiAlias = true
19 | ..filterQuality = FilterQuality.high
20 | ..strokeWidth = 0.5
21 | ..color = ChartColors.gridColor;
22 |
23 | BaseChartRenderer(
24 | {@required this.chartRect,
25 | @required this.maxValue,
26 | @required this.minValue,
27 | @required this.topPadding}) {
28 | if (maxValue == minValue) {
29 | maxValue += 0.5;
30 | minValue -= 0.5;
31 | }
32 | scaleY = chartRect.height / (maxValue - minValue);
33 | }
34 |
35 | double getY(double y) => (maxValue - y) * scaleY + chartRect.top;
36 |
37 | String format(double n) {
38 | return NumberUtil.format(n);
39 | }
40 |
41 | void drawGrid(Canvas canvas, int gridRows, int gridColumns);
42 |
43 | void drawText(Canvas canvas, T data, double x);
44 |
45 | void drawRightText(canvas, textStyle, int gridRows);
46 |
47 | void drawChart(T lastPoint, T curPoint, double lastX, double curX, Size size, Canvas canvas);
48 |
49 | void drawLine(double lastPrice, double curPrice, Canvas canvas, double lastX, double curX, Color color) {
50 | double lastY = getY(lastPrice);
51 | double curY = getY(curPrice);
52 | canvas.drawLine(Offset(lastX, lastY), Offset(curX, curY), chartPaint..color = color);
53 | }
54 |
55 | TextStyle getTextStyle(Color color){
56 | return TextStyle(fontSize: ChartStyle.defaultTextSize,color: color);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/renderer/chart_painter.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async' show StreamSink;
2 |
3 | import 'package:flutter/material.dart';
4 | import '../entity/k_line_entity.dart';
5 | import '../utils/date_format_util.dart';
6 | import '../entity/info_window_entity.dart';
7 |
8 | import 'base_chart_painter.dart';
9 | import 'base_chart_renderer.dart';
10 | import 'main_renderer.dart';
11 | import 'secondary_renderer.dart';
12 | import 'vol_renderer.dart';
13 |
14 | class ChartPainter extends BaseChartPainter {
15 | static get maxScrollX => BaseChartPainter.maxScrollX;
16 | BaseChartRenderer mMainRenderer, mVolRenderer, mSecondaryRenderer;
17 | StreamSink sink;
18 | AnimationController controller;
19 | double opacity;
20 |
21 | ChartPainter({@required datas,
22 | @required scaleX,
23 | @required scrollX,
24 | @required isLongPass,
25 | @required selectX,
26 | mainState,
27 | volState,
28 | secondaryState,
29 | this.sink,
30 | bool isLine,
31 | this.controller,
32 | this.opacity = 0.0})
33 | : super(
34 | datas: datas,
35 | scaleX: scaleX,
36 | scrollX: scrollX,
37 | isLongPress: isLongPass,
38 | selectX: selectX,
39 | mainState: mainState,
40 | volState: volState,
41 | secondaryState: secondaryState,
42 | isLine: isLine);
43 |
44 | @override
45 | void initChartRenderer() {
46 | mMainRenderer ??= MainRenderer(mMainRect, mMainMaxValue, mMainMinValue, ChartStyle.topPadding, mainState, isLine);
47 | if(mVolRect != null){
48 | mVolRenderer ??= VolRenderer(mVolRect, mVolMaxValue, mVolMinValue, ChartStyle.childPadding);
49 | }
50 | if (mSecondaryRect != null){
51 | mSecondaryRenderer ??= SecondaryRenderer(mSecondaryRect, mSecondaryMaxValue, mSecondaryMinValue, ChartStyle.childPadding, secondaryState);
52 | }
53 | }
54 |
55 | final Paint mBgPaint = Paint()..color=ChartColors.bgColor;
56 |
57 | @override
58 | void drawBg(Canvas canvas, Size size) {
59 | if (mMainRect != null) {
60 | Rect mainRect = Rect.fromLTRB(0, 0, mMainRect.width, mMainRect.height + ChartStyle.topPadding);
61 | canvas.drawRect(mainRect, mBgPaint);
62 | }
63 |
64 | if (mVolRect != null) {
65 | Rect volRect = Rect.fromLTRB(0, mVolRect.top - ChartStyle.childPadding, mVolRect.width, mVolRect.bottom);
66 | canvas.drawRect(volRect, mBgPaint);
67 | }
68 |
69 | if (mSecondaryRect != null) {
70 | Rect secondaryRect =
71 | Rect.fromLTRB(0, mSecondaryRect.top - ChartStyle.childPadding, mSecondaryRect.width, mSecondaryRect.bottom);
72 | canvas.drawRect(secondaryRect, mBgPaint);
73 | }
74 | Rect dateRect = Rect.fromLTRB(0, size.height - ChartStyle.bottomDateHigh, size.width, size.height);
75 | canvas.drawRect(dateRect, mBgPaint);
76 | }
77 |
78 | @override
79 | void drawGrid(canvas) {
80 | mMainRenderer?.drawGrid(canvas, ChartStyle.gridRows, ChartStyle.gridColumns);
81 | mVolRenderer?.drawGrid(canvas, ChartStyle.gridRows, ChartStyle.gridColumns);
82 | mSecondaryRenderer?.drawGrid(canvas, ChartStyle.gridRows, ChartStyle.gridColumns);
83 | }
84 |
85 | @override
86 | void drawChart(Canvas canvas, Size size) {
87 | canvas.save();
88 | canvas.translate(mTranslateX * scaleX, 0.0);
89 | canvas.scale(scaleX, 1.0);
90 | for (int i = mStartIndex; datas != null && i <= mStopIndex; i++) {
91 | KLineEntity curPoint = datas[i];
92 | if (curPoint == null) continue;
93 | KLineEntity lastPoint = i == 0 ? curPoint : datas[i - 1];
94 | double curX = getX(i);
95 | double lastX = i == 0 ? curX : getX(i - 1);
96 |
97 | mMainRenderer?.drawChart(lastPoint, curPoint, lastX, curX, size, canvas);
98 | mVolRenderer?.drawChart(lastPoint, curPoint, lastX, curX, size, canvas);
99 | mSecondaryRenderer?.drawChart(lastPoint, curPoint, lastX, curX, size, canvas);
100 | }
101 |
102 | if (isLongPress == true) drawCrossLine(canvas, size);
103 | canvas.restore();
104 | }
105 |
106 | @override
107 | void drawRightText(canvas) {
108 | var textStyle = getTextStyle(ChartColors.yAxisTextColor);
109 | mMainRenderer?.drawRightText(canvas, textStyle, ChartStyle.gridRows);
110 | mVolRenderer?.drawRightText(canvas, textStyle, ChartStyle.gridRows);
111 | mSecondaryRenderer?.drawRightText(canvas, textStyle, ChartStyle.gridRows);
112 | }
113 |
114 | @override
115 | void drawDate(Canvas canvas, Size size) {
116 | double columnSpace = size.width / ChartStyle.gridColumns;
117 | double startX = getX(mStartIndex) - mPointWidth / 2;
118 | double stopX = getX(mStopIndex) + mPointWidth / 2;
119 | double y = 0.0;
120 | for (var i = 0; i <= ChartStyle.gridColumns; ++i) {
121 | double translateX = xToTranslateX(columnSpace * i);
122 | if (translateX >= startX && translateX <= stopX) {
123 | int index = indexOfTranslateX(translateX);
124 | if (datas[index] == null) continue;
125 | TextPainter tp = getTextPainter(getDate(datas[index].id),color: ChartColors.xAxisTextColor);
126 | y = size.height - (ChartStyle.bottomDateHigh - tp.height) / 2 - tp.height;
127 | tp.paint(canvas, Offset(columnSpace * i - tp.width / 2, y));
128 | }
129 | }
130 | }
131 |
132 | Paint selectPointPaint = Paint()
133 | ..isAntiAlias = true
134 | ..strokeWidth = 0.5
135 | ..color = ChartColors.markerBgColor;
136 | Paint selectorBorderPaint = Paint()
137 | ..isAntiAlias = true
138 | ..strokeWidth = 0.5
139 | ..style = PaintingStyle.stroke
140 | ..color = ChartColors.markerBorderColor;
141 |
142 | @override
143 | void drawCrossLineText(Canvas canvas, Size size) {
144 | var index = calculateSelectedX(selectX);
145 | KLineEntity point = getItem(index);
146 |
147 | TextPainter tp = getTextPainter(format(point.close), color:Colors.white);
148 | double textHeight = tp.height;
149 | double textWidth = tp.width;
150 |
151 | double w1 = 5;
152 | double w2 = 3;
153 | double r = textHeight / 2 + w2;
154 | double y = getMainY(point.close);
155 | double x;
156 | bool isLeft = false;
157 | if (translateXtoX(getX(index)) < mWidth / 2) {
158 | isLeft = false;
159 | x = 1;
160 | Path path = new Path();
161 | path.moveTo(x, y - r);
162 | path.lineTo(x, y + r);
163 | path.lineTo(textWidth + 2 * w1, y + r);
164 | path.lineTo(textWidth + 2 * w1 + w2, y);
165 | path.lineTo(textWidth + 2 * w1, y - r);
166 | path.close();
167 | canvas.drawPath(path, selectPointPaint);
168 | canvas.drawPath(path, selectorBorderPaint);
169 | tp.paint(canvas, Offset(x + w1, y - textHeight / 2));
170 | } else {
171 | isLeft = true;
172 | x = mWidth - textWidth - 1 - 2 * w1 - w2;
173 | Path path = new Path();
174 | path.moveTo(x, y);
175 | path.lineTo(x + w2, y + r);
176 | path.lineTo(mWidth - 2, y + r);
177 | path.lineTo(mWidth - 2, y - r);
178 | path.lineTo(x + w2, y - r);
179 | path.close();
180 | canvas.drawPath(path, selectPointPaint);
181 | canvas.drawPath(path, selectorBorderPaint);
182 | tp.paint(canvas, Offset(x + w1 + w2, y - textHeight / 2));
183 | }
184 |
185 | TextPainter dateTp = getTextPainter(getDate(point.id),color: Colors.white);
186 | textWidth = dateTp.width;
187 | r = textHeight / 2;
188 | x = translateXtoX(getX(index));
189 | y = size.height - ChartStyle.bottomDateHigh;
190 |
191 | if (x < textWidth + 2 * w1) {
192 | x = 1 + textWidth / 2 + w1;
193 | } else if (mWidth - x < textWidth + 2 * w1) {
194 | x = mWidth - 1 - textWidth / 2 - w1;
195 | }
196 | double baseLine = textHeight / 2;
197 | canvas.drawRect(
198 | Rect.fromLTRB(x - textWidth / 2 - w1, y, x + textWidth / 2 + w1, y + baseLine + r), selectPointPaint);
199 | canvas.drawRect(Rect.fromLTRB(x - textWidth / 2 - w1, y, x + textWidth / 2 + w1, y + baseLine + r),
200 | selectorBorderPaint);
201 |
202 | dateTp.paint(canvas, Offset(x - textWidth / 2, y));
203 | //长按显示这条数据详情
204 | sink?.add(InfoWindowEntity(point, isLeft));
205 | }
206 |
207 | @override
208 | void drawText(Canvas canvas, KLineEntity data, double x) {
209 | //长按显示按中的数据
210 | if (isLongPress) {
211 | var index = calculateSelectedX(selectX);
212 | data = getItem(index);
213 | }
214 | //松开显示最后一条数据
215 | mMainRenderer?.drawText(canvas, data, x);
216 | mVolRenderer?.drawText(canvas, data, x);
217 | mSecondaryRenderer?.drawText(canvas, data, x);
218 | }
219 |
220 | @override
221 | void drawMaxAndMin(Canvas canvas) {
222 | if (isLine == true) return;
223 | //绘制最大值和最小值
224 | double x = translateXtoX(getX(mMainMinIndex));
225 | double y = getMainY(mMainLowMinValue);
226 | if (x < mWidth / 2) {
227 | //画右边
228 | TextPainter tp = getTextPainter("── ${format(mMainLowMinValue)}",color: ChartColors.maxMinTextColor);
229 | tp.paint(canvas, Offset(x, y - tp.height / 2));
230 | } else {
231 | TextPainter tp = getTextPainter("${format(mMainLowMinValue)} ──",color: ChartColors.maxMinTextColor);
232 | tp.paint(canvas, Offset(x - tp.width, y - tp.height / 2));
233 | }
234 | x = translateXtoX(getX(mMainMaxIndex));
235 | y = getMainY(mMainHighMaxValue);
236 | if (x < mWidth / 2) {
237 | //画右边
238 | TextPainter tp = getTextPainter("── ${format(mMainHighMaxValue)}",color: ChartColors.maxMinTextColor);
239 | tp.paint(canvas, Offset(x, y - tp.height / 2));
240 | } else {
241 | TextPainter tp = getTextPainter("${format(mMainHighMaxValue)} ──",color: ChartColors.maxMinTextColor);
242 | tp.paint(canvas, Offset(x - tp.width, y - tp.height / 2));
243 | }
244 | }
245 |
246 | ///画交叉线
247 | void drawCrossLine(Canvas canvas, Size size) {
248 | var index = calculateSelectedX(selectX);
249 | KLineEntity point = getItem(index);
250 | Paint paintY = Paint()
251 | ..color = Colors.white12
252 | ..strokeWidth = ChartStyle.vCrossWidth
253 | ..isAntiAlias = true;
254 | double x = getX(index);
255 | double y = getMainY(point.close);
256 | // k线图竖线
257 | canvas.drawLine(Offset(x, ChartStyle.topPadding), Offset(x, size.height - ChartStyle.bottomDateHigh), paintY);
258 |
259 | Paint paintX = Paint()
260 | ..color = Colors.white
261 | ..strokeWidth = ChartStyle.hCrossWidth
262 | ..isAntiAlias = true;
263 | // k线图横线
264 | canvas.drawLine(Offset(-mTranslateX, y), Offset(-mTranslateX + mWidth / scaleX, y), paintX);
265 | canvas.drawCircle(Offset(x, y), 2.0, paintX);
266 | }
267 |
268 | final Paint realTimePaint = Paint()
269 | ..strokeWidth = 1.0
270 | ..isAntiAlias = true,
271 | pointPaint = Paint();
272 |
273 | ///画实时价格线
274 | @override
275 | void drawRealTimePrice(Canvas canvas, Size size) {
276 | if (mMarginRight == 0 || datas?.isEmpty == true) return;
277 | KLineEntity point = datas.last;
278 | TextPainter tp = getTextPainter(format(point.close),color: ChartColors.rightRealTimeTextColor);
279 | double y = getMainY(point.close);
280 | //max越往右边滑值越小
281 | var max = (mTranslateX.abs() + mMarginRight - getMinTranslateX().abs() + mPointWidth) * scaleX;
282 | double x = mWidth - max;
283 | if (!isLine) x += mPointWidth / 2;
284 | var dashWidth = 10;
285 | var dashSpace = 5;
286 | double startX = 0;
287 | final space = (dashSpace + dashWidth);
288 | if (tp.width < max) {
289 | while (startX < max) {
290 | canvas.drawLine(Offset(x + startX, y), Offset(x + startX + dashWidth, y),
291 | realTimePaint..color = ChartColors.realTimeLineColor);
292 | startX += space;
293 | }
294 | //画一闪一闪
295 | if (isLine) {
296 | startAnimation();
297 | Gradient pointGradient =
298 | RadialGradient(colors: [Colors.white.withOpacity(opacity ?? 0.0), Colors.transparent]);
299 | pointPaint.shader = pointGradient.createShader(Rect.fromCircle(center: Offset(x, y), radius: 14.0));
300 | canvas.drawCircle(Offset(x, y), 14.0, pointPaint);
301 | canvas.drawCircle(Offset(x, y), 2.0, realTimePaint..color = Colors.white);
302 | } else {
303 | stopAnimation(); //停止一闪闪
304 | }
305 | double left = mWidth - tp.width;
306 | double top = y - tp.height / 2;
307 | canvas.drawRect(Rect.fromLTRB(left, top, left + tp.width, top + tp.height),
308 | realTimePaint..color = ChartColors.realTimeBgColor);
309 | tp.paint(canvas, Offset(left, top));
310 | } else {
311 | stopAnimation(); //停止一闪闪
312 | startX = 0;
313 | if (point.close > mMainMaxValue) {
314 | y = getMainY(mMainMaxValue);
315 | } else if (point.close < mMainMinValue) {
316 | y = getMainY(mMainMinValue);
317 | }
318 | while (startX < mWidth) {
319 | canvas.drawLine(Offset(startX, y), Offset(startX + dashWidth, y),
320 | realTimePaint..color = ChartColors.realTimeLongLineColor);
321 | startX += space;
322 | }
323 |
324 | const padding = 3.0;
325 | const triangleHeight = 8.0; //三角高度
326 | const triangleWidth = 5.0; //三角宽度
327 |
328 | double left = mWidth - mWidth / ChartStyle.gridColumns - tp.width / 2 - padding * 2;
329 | double top = y - tp.height / 2 - padding;
330 | //加上三角形的宽以及padding
331 | double right = left + tp.width + padding * 2 + triangleWidth + padding;
332 | double bottom = top + tp.height + padding * 2;
333 | double radius = (bottom - top) / 2;
334 | //画椭圆背景
335 | RRect rectBg1 = RRect.fromLTRBR(left, top, right, bottom, Radius.circular(radius));
336 | RRect rectBg2 = RRect.fromLTRBR(left - 1, top - 1, right + 1, bottom + 1, Radius.circular(radius + 2));
337 | canvas.drawRRect(rectBg2, realTimePaint..color = ChartColors.realTimeTextBorderColor);
338 | canvas.drawRRect(rectBg1, realTimePaint..color = ChartColors.realTimeBgColor);
339 | tp = getTextPainter(format(point.close),color: ChartColors.realTimeTextColor);
340 | Offset textOffset = Offset(left + padding, y - tp.height / 2);
341 | tp.paint(canvas, textOffset);
342 | //画三角
343 | Path path = Path();
344 | double dx = tp.width + textOffset.dx + padding;
345 | double dy = top + (bottom - top - triangleHeight) / 2;
346 | path.moveTo(dx, dy);
347 | path.lineTo(dx + triangleWidth, dy + triangleHeight / 2);
348 | path.lineTo(dx, dy + triangleHeight);
349 | path.close();
350 | canvas.drawPath(path, realTimePaint..color = ChartColors.realTimeTextColor..shader=null);
351 | }
352 | }
353 |
354 | TextPainter getTextPainter(text, {color = Colors.white}) {
355 | TextSpan span = TextSpan(text: "$text", style: getTextStyle(color));
356 | TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
357 | tp.layout();
358 | return tp;
359 | }
360 |
361 | String getDate(int date) => dateFormat(DateTime.fromMillisecondsSinceEpoch(date * 1000), mFormats);
362 |
363 | double getMainY(double y) => mMainRenderer?.getY(y) ?? 0.0;
364 |
365 | startAnimation() {
366 | if (controller?.isAnimating != true) controller?.repeat(reverse: true);
367 | }
368 |
369 | stopAnimation() {
370 | if (controller?.isAnimating == true) controller?.stop();
371 | }
372 | }
373 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/renderer/main_renderer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import '../entity/candle_entity.dart';
3 | import '../k_chart_widget.dart' show MainState;
4 | import 'base_chart_renderer.dart';
5 |
6 | class MainRenderer extends BaseChartRenderer {
7 | double mCandleWidth = ChartStyle.candleWidth;
8 | double mCandleLineWidth = ChartStyle.candleLineWidth;
9 | MainState state;
10 | bool isLine;
11 |
12 | double _contentPadding = 12.0;
13 |
14 | MainRenderer(Rect mainRect, double maxValue, double minValue, double topPadding, this.state, this.isLine)
15 | : super(chartRect: mainRect, maxValue: maxValue, minValue: minValue, topPadding: topPadding) {
16 | var diff = maxValue - minValue; //计算差
17 | var newScaleY = (chartRect.height - _contentPadding) / diff; //内容区域高度/差=新的比例
18 | var newDiff = chartRect.height / newScaleY; //高/新比例=新的差
19 | var value = (newDiff - diff) / 2; //新差-差/2=y轴需要扩大的值
20 | if (newDiff > diff) {
21 | this.scaleY = newScaleY;
22 | this.maxValue += value;
23 | this.minValue -= value;
24 | }
25 | }
26 |
27 | @override
28 | void drawText(Canvas canvas, CandleEntity data, double x) {
29 | if (isLine == true) return;
30 | TextSpan span;
31 | if (state == MainState.MA) {
32 | span = TextSpan(
33 | children: [
34 | if (data.MA5Price != 0)
35 | TextSpan(text: "MA5:${format(data.MA5Price)} ", style: getTextStyle(ChartColors.ma5Color)),
36 | if (data.MA10Price != 0)
37 | TextSpan(text: "MA10:${format(data.MA10Price)} ", style: getTextStyle(ChartColors.ma10Color)),
38 | if (data.MA30Price != 0)
39 | TextSpan(text: "MA30:${format(data.MA30Price)} ", style: getTextStyle(ChartColors.ma30Color)),
40 | ],
41 | );
42 | } else if (state == MainState.BOLL) {
43 | span = TextSpan(
44 | children: [
45 | if (data.mb != 0)
46 | TextSpan(text: "BOLL:${format(data.mb)} ", style: getTextStyle(ChartColors.ma5Color)),
47 | if (data.up != 0)
48 | TextSpan(text: "UP:${format(data.up)} ", style: getTextStyle(ChartColors.ma10Color)),
49 | if (data.dn != 0)
50 | TextSpan(text: "LB:${format(data.dn)} ", style: getTextStyle(ChartColors.ma30Color)),
51 | ],
52 | );
53 | }
54 | if (span == null) return;
55 | TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
56 | tp.layout();
57 | tp.paint(canvas, Offset(x, chartRect.top - topPadding));
58 | }
59 |
60 | @override
61 | void drawChart(
62 | CandleEntity lastPoint, CandleEntity curPoint, double lastX, double curX, Size size, Canvas canvas) {
63 | if (isLine != true) drawCandle(curPoint, canvas, curX);
64 | if (isLine == true) {
65 | draLine(lastPoint.close, curPoint.close, canvas, lastX, curX);
66 | } else if (state == MainState.MA) {
67 | drawMaLine(lastPoint, curPoint, canvas, lastX, curX);
68 | } else if (state == MainState.BOLL) {
69 | drawBollLine(lastPoint, curPoint, canvas, lastX, curX);
70 | }
71 | }
72 |
73 | Shader mLineFillShader;
74 | Path mLinePath, mLineFillPath;
75 | Paint mLinePaint = Paint()
76 | ..isAntiAlias = true
77 | ..style = PaintingStyle.stroke
78 | ..strokeWidth = 1.0
79 | ..color = ChartColors.kLineColor;
80 | Paint mLineFillPaint = Paint()
81 | ..style = PaintingStyle.fill
82 | ..isAntiAlias = true;
83 |
84 | //画折线图
85 | draLine(double lastPrice, double curPrice, Canvas canvas, double lastX, double curX) {
86 | // drawLine(lastPrice + 100, curPrice + 100, canvas, lastX, curX, ChartColors.kLineColor);
87 | mLinePath ??= Path();
88 |
89 | // if (lastX == curX) {
90 | // mLinePath.moveTo(lastX, getY(lastPrice));
91 | // } else {
92 | //// mLinePath.lineTo(curX, getY(curPrice));
93 | // mLinePath.cubicTo(
94 | // (lastX + curX) / 2, getY(lastPrice), (lastX + curX) / 2, getY(curPrice), curX, getY(curPrice));
95 | // }
96 | if (lastX == curX) lastX = 0;//起点位置填充
97 | mLinePath.moveTo(lastX, getY(lastPrice));
98 | mLinePath.cubicTo(
99 | (lastX + curX) / 2, getY(lastPrice), (lastX + curX) / 2, getY(curPrice), curX, getY(curPrice));
100 |
101 | // //画阴影
102 | mLineFillShader ??= LinearGradient(
103 | begin: Alignment.topCenter,
104 | end: Alignment.bottomCenter,
105 | tileMode: TileMode.clamp,
106 | colors: ChartColors.kLineShadowColor,
107 | ).createShader(Rect.fromLTRB(chartRect.left, chartRect.top, chartRect.right, chartRect.bottom));
108 | mLineFillPaint..shader = mLineFillShader;
109 |
110 | mLineFillPath ??= Path();
111 |
112 | mLineFillPath.moveTo(lastX, chartRect.height + chartRect.top);
113 | mLineFillPath.lineTo(lastX, getY(lastPrice));
114 | mLineFillPath.cubicTo(
115 | (lastX + curX) / 2, getY(lastPrice), (lastX + curX) / 2, getY(curPrice), curX, getY(curPrice));
116 | mLineFillPath.lineTo(curX, chartRect.height + chartRect.top);
117 | mLineFillPath.close();
118 |
119 | canvas.drawPath(mLineFillPath, mLineFillPaint);
120 | mLineFillPath.reset();
121 |
122 | canvas.drawPath(mLinePath, mLinePaint);
123 | mLinePath.reset();
124 | }
125 |
126 | void drawMaLine(CandleEntity lastPoint, CandleEntity curPoint, Canvas canvas, double lastX, double curX) {
127 | if (lastPoint.MA5Price != 0) {
128 | drawLine(lastPoint.MA5Price, curPoint.MA5Price, canvas, lastX, curX, ChartColors.ma5Color);
129 | }
130 | if (lastPoint.MA10Price != 0) {
131 | drawLine(lastPoint.MA10Price, curPoint.MA10Price, canvas, lastX, curX, ChartColors.ma10Color);
132 | }
133 | if (lastPoint.MA30Price != 0) {
134 | drawLine(lastPoint.MA30Price, curPoint.MA30Price, canvas, lastX, curX, ChartColors.ma30Color);
135 | }
136 | }
137 |
138 | void drawBollLine(CandleEntity lastPoint, CandleEntity curPoint, Canvas canvas, double lastX, double curX) {
139 | if (lastPoint.up != 0) {
140 | drawLine(lastPoint.up, curPoint.up, canvas, lastX, curX, ChartColors.ma10Color);
141 | }
142 | if (lastPoint.mb != 0) {
143 | drawLine(lastPoint.mb, curPoint.mb, canvas, lastX, curX, ChartColors.ma5Color);
144 | }
145 | if (lastPoint.dn != 0) {
146 | drawLine(lastPoint.dn, curPoint.dn, canvas, lastX, curX, ChartColors.ma30Color);
147 | }
148 | }
149 |
150 | void drawCandle(CandleEntity curPoint, Canvas canvas, double curX) {
151 | var high = getY(curPoint.high);
152 | var low = getY(curPoint.low);
153 | var open = getY(curPoint.open);
154 | var close = getY(curPoint.close);
155 | double r = mCandleWidth / 2;
156 | double lineR = mCandleLineWidth / 2;
157 |
158 | if (open > close) {
159 | chartPaint.color = ChartColors.upColor;
160 | canvas.drawRect(Rect.fromLTRB(curX - r, close, curX + r, open), chartPaint);
161 | canvas.drawRect(Rect.fromLTRB(curX - lineR, high, curX + lineR, low), chartPaint);
162 | } else {
163 | chartPaint.color = ChartColors.dnColor;
164 | canvas.drawRect(Rect.fromLTRB(curX - r, open, curX + r, close), chartPaint);
165 | canvas.drawRect(Rect.fromLTRB(curX - lineR, high, curX + lineR, low), chartPaint);
166 | }
167 | }
168 |
169 | @override
170 | void drawRightText(canvas, textStyle, int gridRows) {
171 | double rowSpace = chartRect.height / gridRows;
172 | for (var i = 0; i <= gridRows; ++i) {
173 | double position = 0;
174 | if (i == 0) {
175 | position = (gridRows - i) * rowSpace - _contentPadding / 2;
176 | } else if (i == gridRows) {
177 | position = (gridRows - i) * rowSpace + _contentPadding / 2;
178 | } else {
179 | position = (gridRows - i) * rowSpace;
180 | }
181 | var value = position / scaleY + minValue;
182 | TextSpan span = TextSpan(text: "${format(value)}", style: textStyle);
183 | TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
184 | tp.layout();
185 | double y;
186 | if (i == 0||i == gridRows) {
187 | y = getY(value) - tp.height / 2;
188 | } else {
189 | y = getY(value) - tp.height;
190 | }
191 | tp.paint(canvas, Offset(chartRect.width - tp.width, y));
192 | }
193 | }
194 |
195 | @override
196 | void drawGrid(Canvas canvas, int gridRows, int gridColumns) {
197 | // final int gridRows = 4, gridColumns = 4;
198 | double rowSpace = chartRect.height / gridRows;
199 | for (int i = 0; i <= gridRows; i++) {
200 | canvas.drawLine(Offset(0, rowSpace * i + topPadding),
201 | Offset(chartRect.width, rowSpace * i + topPadding), gridPaint);
202 | }
203 | double columnSpace = chartRect.width / gridColumns;
204 | for (int i = 0; i <= columnSpace; i++) {
205 | canvas.drawLine(
206 | Offset(columnSpace * i, topPadding / 3), Offset(columnSpace * i, chartRect.bottom), gridPaint);
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/renderer/secondary_renderer.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 | import '../entity/macd_entity.dart';
5 | import '../k_chart_widget.dart' show SecondaryState;
6 |
7 | import 'base_chart_renderer.dart';
8 |
9 | class SecondaryRenderer extends BaseChartRenderer {
10 | double mMACDWidth = ChartStyle.macdWidth;
11 | SecondaryState state;
12 |
13 | SecondaryRenderer(Rect mainRect, double maxValue, double minValue, double topPadding, this.state)
14 | : super(chartRect: mainRect, maxValue: maxValue, minValue: minValue, topPadding: topPadding);
15 |
16 | @override
17 | void drawChart(
18 | MACDEntity lastPoint, MACDEntity curPoint, double lastX, double curX, Size size, Canvas canvas) {
19 | switch (state) {
20 | case SecondaryState.MACD:
21 | drawMACD(curPoint, canvas, curX, lastPoint, lastX);
22 | break;
23 | case SecondaryState.KDJ:
24 | if (lastPoint.k != 0) drawLine(lastPoint.k, curPoint.k, canvas, lastX, curX, ChartColors.kColor);
25 | if (lastPoint.d != 0) drawLine(lastPoint.d, curPoint.d, canvas, lastX, curX, ChartColors.dColor);
26 | if (lastPoint.j != 0) drawLine(lastPoint.j, curPoint.j, canvas, lastX, curX, ChartColors.jColor);
27 | break;
28 | case SecondaryState.RSI:
29 | if (lastPoint.rsi != 0)
30 | drawLine(lastPoint.rsi, curPoint.rsi, canvas, lastX, curX, ChartColors.rsiColor);
31 | break;
32 | case SecondaryState.WR:
33 | if (lastPoint.r != 0) drawLine(lastPoint.r, curPoint.r, canvas, lastX, curX, ChartColors.rsiColor);
34 | break;
35 | default:
36 | break;
37 | }
38 | }
39 |
40 | void drawMACD(MACDEntity curPoint, Canvas canvas, double curX, MACDEntity lastPoint, double lastX) {
41 | double macdY = getY(curPoint.macd);
42 | double r = mMACDWidth / 2;
43 | double zeroy = getY(0);
44 | if (curPoint.macd > 0) {
45 | canvas.drawRect(
46 | Rect.fromLTRB(curX - r, macdY, curX + r, zeroy), chartPaint..color = ChartColors.upColor);
47 | } else {
48 | canvas.drawRect(
49 | Rect.fromLTRB(curX - r, zeroy, curX + r, macdY), chartPaint..color = ChartColors.dnColor);
50 | }
51 | if (lastPoint.dif != 0) {
52 | drawLine(lastPoint.dif, curPoint.dif, canvas, lastX, curX, ChartColors.difColor);
53 | }
54 | if (lastPoint.dea != 0) {
55 | drawLine(lastPoint.dea, curPoint.dea, canvas, lastX, curX, ChartColors.deaColor);
56 | }
57 | }
58 |
59 | @override
60 | void drawText(Canvas canvas, MACDEntity data, double x) {
61 | ;
62 | List children;
63 | switch (state) {
64 | case SecondaryState.MACD:
65 | children = [
66 | TextSpan(text: "MACD(12,26,9) ", style: getTextStyle(ChartColors.yAxisTextColor)),
67 | if (data.macd != 0)
68 | TextSpan(text: "MACD:${format(data.macd)} ", style: getTextStyle(ChartColors.macdColor)),
69 | if (data.dif != 0)
70 | TextSpan(text: "DIF:${format(data.dif)} ", style: getTextStyle(ChartColors.difColor)),
71 | if (data.dea != 0)
72 | TextSpan(text: "DEA:${format(data.dea)} ", style: getTextStyle(ChartColors.deaColor)),
73 | ];
74 | break;
75 | case SecondaryState.KDJ:
76 | children = [
77 | TextSpan(text: "KDJ(14,1,3) ", style: getTextStyle(ChartColors.yAxisTextColor)),
78 | if (data.macd != 0)
79 | TextSpan(text: "K:${format(data.k)} ", style: getTextStyle(ChartColors.kColor)),
80 | if (data.dif != 0)
81 | TextSpan(text: "D:${format(data.d)} ", style: getTextStyle(ChartColors.dColor)),
82 | if (data.dea != 0)
83 | TextSpan(text: "J:${format(data.j)} ", style: getTextStyle(ChartColors.jColor)),
84 | ];
85 | break;
86 | case SecondaryState.RSI:
87 | children = [
88 | TextSpan(text: "RSI(14):${format(data.rsi)} ", style: getTextStyle(ChartColors.rsiColor)),
89 | ];
90 | break;
91 | case SecondaryState.WR:
92 | children = [
93 | TextSpan(text: "WR(14):${format(data.r)} ", style: getTextStyle(ChartColors.rsiColor)),
94 | ];
95 | break;
96 | default:
97 | break;
98 | }
99 | TextPainter tp = TextPainter(text: TextSpan(children: children ?? []), textDirection: TextDirection.ltr);
100 | tp.layout();
101 | tp.paint(canvas, Offset(x, chartRect.top - topPadding));
102 | }
103 |
104 | @override
105 | void drawRightText(canvas, textStyle, int gridRows) {
106 | TextPainter maxTp = TextPainter(
107 | text: TextSpan(text: "${format(maxValue)}", style: textStyle), textDirection: TextDirection.ltr);
108 | maxTp.layout();
109 | TextPainter minTp = TextPainter(
110 | text: TextSpan(text: "${format(minValue)}", style: textStyle), textDirection: TextDirection.ltr);
111 | minTp.layout();
112 |
113 | maxTp.paint(canvas, Offset(chartRect.width - maxTp.width, chartRect.top - topPadding));
114 | minTp.paint(canvas, Offset(chartRect.width - minTp.width, chartRect.bottom - minTp.height));
115 | }
116 |
117 | @override
118 | void drawGrid(Canvas canvas, int gridRows, int gridColumns) {
119 | canvas.drawLine(Offset(0, chartRect.bottom), Offset(chartRect.width, chartRect.bottom), gridPaint);
120 | double columnSpace = chartRect.width / gridColumns;
121 | for (int i = 0; i <= columnSpace; i++) {
122 | //mSecondaryRect垂直线
123 | canvas.drawLine(Offset(columnSpace * i, chartRect.top - topPadding),
124 | Offset(columnSpace * i, chartRect.bottom), gridPaint);
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/renderer/vol_renderer.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 | import '../entity/volume_entity.dart';
5 | import '../renderer/base_chart_renderer.dart';
6 | import '../utils/number_util.dart';
7 |
8 | class VolRenderer extends BaseChartRenderer {
9 | double mVolWidth = ChartStyle.volWidth;
10 |
11 | VolRenderer(Rect mainRect, double maxValue, double minValue, double topPadding)
12 | : super(chartRect: mainRect, maxValue: maxValue, minValue: minValue, topPadding: topPadding);
13 |
14 | @override
15 | void drawChart(
16 | VolumeEntity lastPoint, VolumeEntity curPoint, double lastX, double curX, Size size, Canvas canvas) {
17 | double r = mVolWidth / 2;
18 | double top = getY(curPoint.vol);
19 | double bottom = chartRect.bottom;
20 | canvas.drawRect(Rect.fromLTRB(curX - r, top, curX + r, bottom),
21 | chartPaint..color = curPoint.close >= curPoint.open ? ChartColors.upColor : ChartColors.dnColor);
22 |
23 | if (lastPoint.MA5Volume != 0) {
24 | drawLine(lastPoint.MA5Volume, curPoint.MA5Volume, canvas, lastX, curX, ChartColors.ma5Color);
25 | }
26 |
27 | if (lastPoint.MA10Volume != 0) {
28 | drawLine(lastPoint.MA10Volume, curPoint.MA10Volume, canvas, lastX, curX, ChartColors.ma10Color);
29 | }
30 | }
31 |
32 | @override
33 | double getY(double y){
34 | if (maxValue == 0) return chartRect.bottom;
35 | return (maxValue - y) * (chartRect.height / maxValue) + chartRect.top;
36 | }
37 |
38 | @override
39 | void drawText(Canvas canvas, VolumeEntity data, double x) {
40 | TextSpan span = TextSpan(
41 | children: [
42 | TextSpan(text: "VOL:${NumberUtil.volFormat(data.vol)} ", style: getTextStyle(ChartColors.volColor)),
43 | TextSpan(text: "MA5:${NumberUtil.volFormat(data.MA5Volume)} ", style: getTextStyle(ChartColors.ma5Color)),
44 | TextSpan(text: "MA10:${NumberUtil.volFormat(data.MA10Volume)} ", style: getTextStyle(ChartColors.ma10Color)),
45 | ],
46 | );
47 | TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
48 | tp.layout();
49 | tp.paint(canvas, Offset(x, chartRect.top - topPadding));
50 | }
51 |
52 | @override
53 | void drawRightText(canvas, textStyle, int gridRows) {
54 | TextSpan span = TextSpan(text: "${NumberUtil.volFormat(maxValue)}", style: textStyle);
55 | TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
56 | tp.layout();
57 | tp.paint(canvas, Offset(chartRect.width - tp.width, chartRect.top - topPadding));
58 | }
59 |
60 | @override
61 | void drawGrid(Canvas canvas, int gridRows, int gridColumns) {
62 | canvas.drawLine(Offset(0, chartRect.bottom), Offset(chartRect.width, chartRect.bottom), gridPaint);
63 | double columnSpace = chartRect.width / gridColumns;
64 | for (int i = 0; i <= columnSpace; i++) {
65 | //vol垂直线
66 | canvas.drawLine(Offset(columnSpace * i, chartRect.top - topPadding),
67 | Offset(columnSpace * i, chartRect.bottom), gridPaint);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/utils/data_util.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import '../entity/k_line_entity.dart';
4 |
5 | class DataUtil {
6 | static calculate(List dataList) {
7 | if (dataList == null) return;
8 | _calcMA(dataList);
9 | _calcBOLL(dataList);
10 | _calcVolumeMA(dataList);
11 | _calcKDJ(dataList);
12 | _calcMACD(dataList);
13 | _calcRSI(dataList);
14 | _calcWR(dataList);
15 | }
16 |
17 | static _calcMA(List dataList, [bool isLast = false]) {
18 | double ma5 = 0;
19 | double ma10 = 0;
20 | double ma20 = 0;
21 | double ma30 = 0;
22 | // double ma60 = 0;
23 |
24 | int i = 0;
25 | if (isLast && dataList.length > 1) {
26 | i = dataList.length - 1;
27 | var data = dataList[dataList.length - 2];
28 | ma5 = data.MA5Price * 5;
29 | ma10 = data.MA10Price * 10;
30 | ma20 = data.MA20Price * 20;
31 | ma30 = data.MA30Price * 30;
32 | // ma60 = data.MA60Price * 60;
33 | }
34 | for (; i < dataList.length; i++) {
35 | KLineEntity entity = dataList[i];
36 | final closePrice = entity.close;
37 | ma5 += closePrice;
38 | ma10 += closePrice;
39 | ma20 += closePrice;
40 | ma30 += closePrice;
41 | // ma60 += closePrice;
42 |
43 | if (i == 4) {
44 | entity.MA5Price = ma5 / 5;
45 | } else if (i >= 5) {
46 | ma5 -= dataList[i - 5].close;
47 | entity.MA5Price = ma5 / 5;
48 | } else {
49 | entity.MA5Price = 0;
50 | }
51 | if (i == 9) {
52 | entity.MA10Price = ma10 / 10;
53 | } else if (i >= 10) {
54 | ma10 -= dataList[i - 10].close;
55 | entity.MA10Price = ma10 / 10;
56 | } else {
57 | entity.MA10Price = 0;
58 | }
59 | if (i == 19) {
60 | entity.MA20Price = ma20 / 20;
61 | } else if (i >= 20) {
62 | ma20 -= dataList[i - 20].close;
63 | entity.MA20Price = ma20 / 20;
64 | } else {
65 | entity.MA20Price = 0;
66 | }
67 | if (i == 29) {
68 | entity.MA30Price = ma30 / 30;
69 | } else if (i >= 30) {
70 | ma30 -= dataList[i - 30].close;
71 | entity.MA30Price = ma30 / 30;
72 | } else {
73 | entity.MA30Price = 0;
74 | }
75 | // if (i == 59) {
76 | // entity.MA60Price = ma60 / 60;
77 | // } else if (i >= 60) {
78 | // ma60 -= dataList[i - 60].close;
79 | // entity.MA60Price = ma60 / 60;
80 | // } else {
81 | // entity.MA60Price = 0;
82 | // }
83 | }
84 | }
85 |
86 | static void _calcBOLL(List dataList, [bool isLast = false]) {
87 | int i = 0;
88 | if (isLast && dataList.length > 1) {
89 | i = dataList.length - 1;
90 | }
91 | for (; i < dataList.length; i++) {
92 | KLineEntity entity = dataList[i];
93 | if (i < 19) {
94 | entity.mb = 0;
95 | entity.up = 0;
96 | entity.dn = 0;
97 | } else {
98 | int n = 20;
99 | double md = 0;
100 | for (int j = i - n + 1; j <= i; j++) {
101 | double c = dataList[j].close;
102 | double m = entity.MA20Price;
103 | double value = c - m;
104 | md += value * value;
105 | }
106 | md = md / (n - 1);
107 | md = sqrt(md);
108 | entity.mb = entity.MA20Price;
109 | entity.up = entity.mb + 2.0 * md;
110 | entity.dn = entity.mb - 2.0 * md;
111 | }
112 | }
113 | }
114 |
115 | static void _calcMACD(List dataList, [bool isLast = false]) {
116 | double ema12 = 0;
117 | double ema26 = 0;
118 | double dif = 0;
119 | double dea = 0;
120 | double macd = 0;
121 |
122 | int i = 0;
123 | if (isLast && dataList.length > 1) {
124 | i = dataList.length - 1;
125 | var data = dataList[dataList.length - 2];
126 | dif = data.dif;
127 | dea = data.dea;
128 | macd = data.macd;
129 | ema12 = data.ema12;
130 | ema26 = data.ema26;
131 | }
132 |
133 | for (; i < dataList.length; i++) {
134 | KLineEntity entity = dataList[i];
135 | final closePrice = entity.close;
136 | if (i == 0) {
137 | ema12 = closePrice;
138 | ema26 = closePrice;
139 | } else {
140 | // EMA(12) = 前一日EMA(12) X 11/13 + 今日收盘价 X 2/13
141 | ema12 = ema12 * 11 / 13 + closePrice * 2 / 13;
142 | // EMA(26) = 前一日EMA(26) X 25/27 + 今日收盘价 X 2/27
143 | ema26 = ema26 * 25 / 27 + closePrice * 2 / 27;
144 | }
145 | // DIF = EMA(12) - EMA(26) 。
146 | // 今日DEA = (前一日DEA X 8/10 + 今日DIF X 2/10)
147 | // 用(DIF-DEA)*2即为MACD柱状图。
148 | dif = ema12 - ema26;
149 | dea = dea * 8 / 10 + dif * 2 / 10;
150 | macd = (dif - dea) * 2;
151 | entity.dif = dif;
152 | entity.dea = dea;
153 | entity.macd = macd;
154 | entity.ema12 = ema12;
155 | entity.ema26 = ema26;
156 | }
157 | }
158 |
159 | static void _calcVolumeMA(List dataList, [bool isLast = false]) {
160 | double volumeMa5 = 0;
161 | double volumeMa10 = 0;
162 |
163 | int i = 0;
164 | if (isLast && dataList.length > 1) {
165 | i = dataList.length - 1;
166 | var data = dataList[dataList.length - 2];
167 | volumeMa5 = data.MA5Volume * 5;
168 | volumeMa10 = data.MA10Volume * 10;
169 | }
170 |
171 | for (; i < dataList.length; i++) {
172 | KLineEntity entry = dataList[i];
173 |
174 | volumeMa5 += entry.vol;
175 | volumeMa10 += entry.vol;
176 |
177 | if (i == 4) {
178 | entry.MA5Volume = (volumeMa5 / 5);
179 | } else if (i > 4) {
180 | volumeMa5 -= dataList[i - 5].vol;
181 | entry.MA5Volume = volumeMa5 / 5;
182 | } else {
183 | entry.MA5Volume = 0;
184 | }
185 |
186 | if (i == 9) {
187 | entry.MA10Volume = volumeMa10 / 10;
188 | } else if (i > 9) {
189 | volumeMa10 -= dataList[i - 10].vol;
190 | entry.MA10Volume = volumeMa10 / 10;
191 | } else {
192 | entry.MA10Volume = 0;
193 | }
194 | }
195 | }
196 |
197 | static void _calcRSI(List dataList, [bool isLast = false]) {
198 | double rsi;
199 | double rsiABSEma = 0;
200 | double rsiMaxEma = 0;
201 |
202 | int i = 0;
203 | if (isLast && dataList.length > 1) {
204 | i = dataList.length - 1;
205 | var data = dataList[dataList.length - 2];
206 | rsi = data.rsi;
207 | rsiABSEma = data.rsiABSEma;
208 | rsiMaxEma = data.rsiMaxEma;
209 | }
210 |
211 | for (; i < dataList.length; i++) {
212 | KLineEntity entity = dataList[i];
213 | final double closePrice = entity.close;
214 | if (i == 0) {
215 | rsi = 0;
216 | rsiABSEma = 0;
217 | rsiMaxEma = 0;
218 | } else {
219 | double Rmax = max(0, closePrice - dataList[i - 1].close);
220 | double RAbs = (closePrice - dataList[i - 1].close).abs();
221 |
222 | rsiMaxEma = (Rmax + (14 - 1) * rsiMaxEma) / 14;
223 | rsiABSEma = (RAbs + (14 - 1) * rsiABSEma) / 14;
224 | rsi = (rsiMaxEma / rsiABSEma) * 100;
225 | }
226 | if (i < 13) rsi = 0;
227 | if (rsi.isNaN) rsi = 0;
228 | entity.rsi = rsi;
229 | entity.rsiABSEma = rsiABSEma;
230 | entity.rsiMaxEma = rsiMaxEma;
231 | }
232 | }
233 |
234 | static void _calcKDJ(List dataList, [bool isLast = false]) {
235 | double k = 0;
236 | double d = 0;
237 |
238 | int i = 0;
239 | if (isLast && dataList.length > 1) {
240 | i = dataList.length - 1;
241 | var data = dataList[dataList.length - 2];
242 | k = data.k;
243 | d = data.d;
244 | }
245 |
246 | for (; i < dataList.length; i++) {
247 | KLineEntity entity = dataList[i];
248 | final double closePrice = entity.close;
249 | int startIndex = i - 13;
250 | if (startIndex < 0) {
251 | startIndex = 0;
252 | }
253 | double max14 = -double.maxFinite;
254 | double min14 = double.maxFinite;
255 | for (int index = startIndex; index <= i; index++) {
256 | max14 = max(max14, dataList[index].high);
257 | min14 = min(min14, dataList[index].low);
258 | }
259 | double rsv = 100 * (closePrice - min14) / (max14 - min14);
260 | if (rsv.isNaN) {
261 | rsv = 0;
262 | }
263 | if (i == 0) {
264 | k = 50;
265 | d = 50;
266 | } else {
267 | k = (rsv + 2 * k) / 3;
268 | d = (k + 2 * d) / 3;
269 | }
270 | if (i < 13) {
271 | entity.k = 0;
272 | entity.d = 0;
273 | entity.j = 0;
274 | } else if (i == 13 || i == 14) {
275 | entity.k = k;
276 | entity.d = 0;
277 | entity.j = 0;
278 | } else {
279 | entity.k = k;
280 | entity.d = d;
281 | entity.j = 3 * k - 2 * d;
282 | }
283 | }
284 | }
285 |
286 | //WR(N) = 100 * [ HIGH(N)-C ] / [ HIGH(N)-LOW(N) ]
287 | static void _calcWR(List dataList, [bool isLast = false]) {
288 | int i = 0;
289 | if (isLast && dataList.length > 1) {
290 | i = dataList.length - 1;
291 | }
292 | for (; i < dataList.length; i++) {
293 | KLineEntity entity = dataList[i];
294 | int startIndex = i - 14;
295 | if (startIndex < 0) {
296 | startIndex = 0;
297 | }
298 | double max14 = -double.maxFinite;
299 | double min14 = double.maxFinite;
300 | for (int index = startIndex; index <= i; index++) {
301 | max14 = max(max14, dataList[index].high);
302 | min14 = min(min14, dataList[index].low);
303 | }
304 | if (i < 13) {
305 | entity.r = 0;
306 | } else {
307 | if ((max14 - min14) == 0) {
308 | entity.r = 0;
309 | } else {
310 | entity.r = 100 * (max14 - dataList[i].close) / (max14 - min14);
311 | }
312 | }
313 | }
314 | }
315 |
316 | //增量更新时计算最后一个数据
317 | static addLastData(List dataList, KLineEntity data) {
318 | if (dataList == null || data == null) return;
319 | dataList.add(data);
320 | _calcMA(dataList, true);
321 | _calcBOLL(dataList, true);
322 | _calcVolumeMA(dataList, true);
323 | _calcKDJ(dataList, true);
324 | _calcMACD(dataList, true);
325 | _calcRSI(dataList, true);
326 | _calcWR(dataList, true);
327 | }
328 |
329 | //更新最后一条数据
330 | static updateLastData(List dataList) {
331 | if (dataList == null) return;
332 | _calcMA(dataList, true);
333 | _calcBOLL(dataList, true);
334 | _calcVolumeMA(dataList, true);
335 | _calcKDJ(dataList, true);
336 | _calcMACD(dataList, true);
337 | _calcRSI(dataList, true);
338 | _calcWR(dataList, true);
339 | }
340 | }
341 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/utils/date_format_util.dart:
--------------------------------------------------------------------------------
1 | /// Outputs year as four digits
2 | ///
3 | /// Example:
4 | /// formatDate(DateTime(1989), [yyyy]);
5 | /// // => 1989
6 | const String yyyy = 'yyyy';
7 |
8 | /// Outputs year as two digits
9 | ///
10 | /// Example:
11 | /// formatDate(DateTime(1989), [yy]);
12 | /// // => 89
13 | const String yy = 'yy';
14 |
15 | /// Outputs month as two digits
16 | ///
17 | /// Example:
18 | /// formatDate(DateTime(1989, 11), [mm]);
19 | /// // => 11
20 | /// formatDate(DateTime(1989, 5), [mm]);
21 | /// // => 05
22 | const String mm = 'mm';
23 |
24 | /// Outputs month compactly
25 | ///
26 | /// Example:
27 | /// formatDate(DateTime(1989, 11), [mm]);
28 | /// // => 11
29 | /// formatDate(DateTime(1989, 5), [m]);
30 | /// // => 5
31 | const String m = 'm';
32 |
33 | /// Outputs month as long name
34 | ///
35 | /// Example:
36 | /// formatDate(DateTime(1989, 2), [MM]);
37 | /// // => february
38 | const String MM = 'MM';
39 |
40 | /// Outputs month as short name
41 | ///
42 | /// Example:
43 | /// formatDate(DateTime(1989, 2), [M]);
44 | /// // => feb
45 | const String M = 'M';
46 |
47 | /// Outputs day as two digits
48 | ///
49 | /// Example:
50 | /// formatDate(DateTime(1989, 2, 21), [dd]);
51 | /// // => 21
52 | /// formatDate(DateTime(1989, 2, 5), [dd]);
53 | /// // => 05
54 | const String dd = 'dd';
55 |
56 | /// Outputs day compactly
57 | ///
58 | /// Example:
59 | /// formatDate(DateTime(1989, 2, 21), [d]);
60 | /// // => 21
61 | /// formatDate(DateTime(1989, 2, 5), [d]);
62 | /// // => 5
63 | const String d = 'd';
64 |
65 | /// Outputs week in month
66 | ///
67 | /// Example:
68 | /// formatDate(DateTime(1989, 2, 21), [w]);
69 | /// // => 4
70 | const String w = 'w';
71 |
72 | /// Outputs week in year as two digits
73 | ///
74 | /// Example:
75 | /// formatDate(DateTime(1989, 12, 31), [W]);
76 | /// // => 53
77 | /// formatDate(DateTime(1989, 2, 21), [W]);
78 | /// // => 08
79 | const String WW = 'WW';
80 |
81 | /// Outputs week in year compactly
82 | ///
83 | /// Example:
84 | /// formatDate(DateTime(1989, 2, 21), [W]);
85 | /// // => 8
86 | const String W = 'W';
87 |
88 | /// Outputs week day as long name
89 | ///
90 | /// Example:
91 | /// formatDate(DateTime(2018, 1, 14), [DD]);
92 | /// // => sunday
93 | const String DD = 'DD';
94 |
95 | /// Outputs week day as long name
96 | ///
97 | /// Example:
98 | /// formatDate(DateTime(2018, 1, 14), [D]);
99 | /// // => sun
100 | const String D = 'D';
101 |
102 | /// Outputs hour (0 - 11) as two digits
103 | ///
104 | /// Example:
105 | /// formatDate(DateTime(1989, 02, 1, 15), [hh]);
106 | /// // => 03
107 | const String hh = 'hh';
108 |
109 | /// Outputs hour (0 - 11) compactly
110 | ///
111 | /// Example:
112 | /// formatDate(DateTime(1989, 02, 1, 15), [h]);
113 | /// // => 3
114 | const String h = 'h';
115 |
116 | /// Outputs hour (0 to 23) as two digits
117 | ///
118 | /// Example:
119 | /// formatDate(DateTime(1989, 02, 1, 15), [HH]);
120 | /// // => 15
121 | const String HH = 'HH';
122 |
123 | /// Outputs hour (0 to 23) compactly
124 | ///
125 | /// Example:
126 | /// formatDate(DateTime(1989, 02, 1, 5), [H]);
127 | /// // => 5
128 | const String H = 'H';
129 |
130 | /// Outputs minute as two digits
131 | ///
132 | /// Example:
133 | /// formatDate(DateTime(1989, 02, 1, 15, 40), [nn]);
134 | /// // => 40
135 | /// formatDate(DateTime(1989, 02, 1, 15, 4), [nn]);
136 | /// // => 04
137 | const String nn = 'nn';
138 |
139 | /// Outputs minute compactly
140 | ///
141 | /// Example:
142 | /// formatDate(DateTime(1989, 02, 1, 15, 4), [n]);
143 | /// // => 4
144 | const String n = 'n';
145 |
146 | /// Outputs second as two digits
147 | ///
148 | /// Example:
149 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10), [ss]);
150 | /// // => 10
151 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 5), [ss]);
152 | /// // => 05
153 | const String ss = 'ss';
154 |
155 | /// Outputs second compactly
156 | ///
157 | /// Example:
158 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 5), [s]);
159 | /// // => 5
160 | const String s = 's';
161 |
162 | /// Outputs millisecond as three digits
163 | ///
164 | /// Example:
165 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 999), [SSS]);
166 | /// // => 999
167 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 99), [SS]);
168 | /// // => 099
169 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 0), [SS]);
170 | /// // => 009
171 | const String SSS = 'SSS';
172 |
173 | /// Outputs millisecond compactly
174 | ///
175 | /// Example:
176 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 999), [SSS]);
177 | /// // => 999
178 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 99), [SS]);
179 | /// // => 99
180 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 9), [SS]);
181 | /// // => 9
182 | const String S = 'S';
183 |
184 | /// Outputs microsecond as three digits
185 | ///
186 | /// Example:
187 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 0, 999), [uuu]);
188 | /// // => 999
189 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 0, 99), [uuu]);
190 | /// // => 099
191 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 0, 9), [uuu]);
192 | /// // => 009
193 | const String uuu = 'uuu';
194 |
195 | /// Outputs millisecond compactly
196 | ///
197 | /// Example:
198 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 0, 999), [u]);
199 | /// // => 999
200 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 0, 99), [u]);
201 | /// // => 99
202 | /// formatDate(DateTime(1989, 02, 1, 15, 40, 10, 0, 9), [u]);
203 | /// // => 9
204 | const String u = 'u';
205 |
206 | /// Outputs if hour is AM or PM
207 | ///
208 | /// Example:
209 | /// print(formatDate(DateTime(1989, 02, 1, 5), [am]));
210 | /// // => AM
211 | /// print(formatDate(DateTime(1989, 02, 1, 15), [am]));
212 | /// // => PM
213 | const String am = 'am';
214 |
215 | /// Outputs timezone as time offset
216 | ///
217 | /// Example:
218 | ///
219 | const String z = 'z';
220 | const String Z = 'Z';
221 |
222 | String dateFormat(DateTime date, List formats) {
223 | final sb = StringBuffer();
224 |
225 | for (String format in formats) {
226 | if (format == yyyy) {
227 | sb.write(_digits(date.year, 4));
228 | } else if (format == yy) {
229 | sb.write(_digits(date.year % 100, 2));
230 | } else if (format == mm) {
231 | sb.write(_digits(date.month, 2));
232 | } else if (format == m) {
233 | sb.write(date.month);
234 | } else if (format == MM) {
235 | sb.write(monthLong[date.month - 1]);
236 | } else if (format == M) {
237 | sb.write(monthShort[date.month - 1]);
238 | } else if (format == dd) {
239 | sb.write(_digits(date.day, 2));
240 | } else if (format == d) {
241 | sb.write(date.day);
242 | } else if (format == w) {
243 | sb.write((date.day + 7) ~/ 7);
244 | } else if (format == W) {
245 | sb.write((dayInYear(date) + 7) ~/ 7);
246 | } else if (format == WW) {
247 | sb.write(_digits((dayInYear(date) + 7) ~/ 7, 2));
248 | } else if (format == DD) {
249 | sb.write(dayLong[date.weekday - 1]);
250 | } else if (format == D) {
251 | sb.write(dayShort[date.weekday - 1]);
252 | } else if (format == HH) {
253 | sb.write(_digits(date.hour, 2));
254 | } else if (format == H) {
255 | sb.write(date.hour);
256 | } else if (format == hh) {
257 | int hour = date.hour % 12;
258 | if (hour == 0) hour = 12;
259 | sb.write(_digits(hour, 2));
260 | } else if (format == h) {
261 | int hour = date.hour % 12;
262 | if (hour == 0) hour = 12;
263 | sb.write(hour);
264 | } else if (format == am) {
265 | sb.write(date.hour < 12 ? 'AM' : 'PM');
266 | } else if (format == nn) {
267 | sb.write(_digits(date.minute, 2));
268 | } else if (format == n) {
269 | sb.write(date.minute);
270 | } else if (format == ss) {
271 | sb.write(_digits(date.second, 2));
272 | } else if (format == s) {
273 | sb.write(date.second);
274 | } else if (format == SSS) {
275 | sb.write(_digits(date.millisecond, 3));
276 | } else if (format == S) {
277 | sb.write(date.second);
278 | } else if (format == uuu) {
279 | sb.write(_digits(date.microsecond, 2));
280 | } else if (format == u) {
281 | sb.write(date.microsecond);
282 | } else if (format == z) {
283 | if (date.timeZoneOffset.inMinutes == 0) {
284 | sb.write('Z');
285 | } else {
286 | if (date.timeZoneOffset.isNegative) {
287 | sb.write('-');
288 | sb.write(_digits((-date.timeZoneOffset.inHours) % 24, 2));
289 | sb.write(_digits((-date.timeZoneOffset.inMinutes) % 60, 2));
290 | } else {
291 | sb.write('+');
292 | sb.write(_digits(date.timeZoneOffset.inHours % 24, 2));
293 | sb.write(_digits(date.timeZoneOffset.inMinutes % 60, 2));
294 | }
295 | }
296 | } else if (format == Z) {
297 | sb.write(date.timeZoneName);
298 | } else {
299 | sb.write(format);
300 | }
301 | }
302 |
303 | return sb.toString();
304 | }
305 |
306 | String _digits(int value, int length) {
307 | String ret = '$value';
308 | if (ret.length < length) {
309 | ret = '0' * (length - ret.length) + ret;
310 | }
311 | return ret;
312 | }
313 |
314 | const List monthShort = const [
315 | 'Jan',
316 | 'Feb',
317 | 'Mar',
318 | 'Apr',
319 | 'May',
320 | 'Jun',
321 | 'Jul',
322 | 'Aug',
323 | 'Sep',
324 | 'Oct',
325 | 'Nov',
326 | 'Dec'
327 | ];
328 |
329 | const List monthLong = const [
330 | 'January',
331 | 'February',
332 | 'March',
333 | 'April',
334 | 'May',
335 | 'June',
336 | 'July',
337 | 'August',
338 | 'September',
339 | 'October',
340 | 'November',
341 | 'December'
342 | ];
343 |
344 | const List dayShort = const [
345 | 'Mon',
346 | 'Tue',
347 | 'Wed',
348 | 'Thur',
349 | 'Fri',
350 | 'Sat',
351 | 'Sun'
352 | ];
353 |
354 | const List dayLong = const [
355 | 'Monday',
356 | 'Tuesday',
357 | 'Wednesday',
358 | 'Thursday',
359 | 'Friday',
360 | 'Saturday',
361 | 'Sunday'
362 | ];
363 |
364 | int dayInYear(DateTime date) =>
365 | date.difference(DateTime(date.year, 1, 1)).inDays;
--------------------------------------------------------------------------------
/flutter_k_chart-master/lib/utils/number_util.dart:
--------------------------------------------------------------------------------
1 | class NumberUtil {
2 | static String volFormat(double n) {
3 | if (n > 10000 && n < 999999) {
4 | double d = n / 1000;
5 | return "${d.toStringAsFixed(2)}K";
6 | } else if (n > 1000000) {
7 | double d = n / 1000000;
8 | return "${d.toStringAsFixed(2)}M";
9 | }
10 | return n.toStringAsFixed(2);
11 | }
12 |
13 | //保留多少位小数
14 | static int _fractionDigits = 2;
15 |
16 | static set fractionDigits(int value) {
17 | if (value != _fractionDigits) _fractionDigits = value;
18 | }
19 |
20 | static String format(double price) {
21 | return price.toStringAsFixed(_fractionDigits);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | archive:
5 | dependency: transitive
6 | description:
7 | name: archive
8 | url: "https://pub.flutter-io.cn"
9 | source: hosted
10 | version: "2.0.11"
11 | args:
12 | dependency: transitive
13 | description:
14 | name: args
15 | url: "https://pub.flutter-io.cn"
16 | source: hosted
17 | version: "1.5.2"
18 | async:
19 | dependency: transitive
20 | description:
21 | name: async
22 | url: "https://pub.flutter-io.cn"
23 | source: hosted
24 | version: "2.4.0"
25 | boolean_selector:
26 | dependency: transitive
27 | description:
28 | name: boolean_selector
29 | url: "https://pub.flutter-io.cn"
30 | source: hosted
31 | version: "1.0.5"
32 | charcode:
33 | dependency: transitive
34 | description:
35 | name: charcode
36 | url: "https://pub.flutter-io.cn"
37 | source: hosted
38 | version: "1.1.2"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.flutter-io.cn"
44 | source: hosted
45 | version: "1.14.11"
46 | convert:
47 | dependency: transitive
48 | description:
49 | name: convert
50 | url: "https://pub.flutter-io.cn"
51 | source: hosted
52 | version: "2.1.1"
53 | crypto:
54 | dependency: transitive
55 | description:
56 | name: crypto
57 | url: "https://pub.flutter-io.cn"
58 | source: hosted
59 | version: "2.1.3"
60 | flutter:
61 | dependency: "direct main"
62 | description: flutter
63 | source: sdk
64 | version: "0.0.0"
65 | flutter_test:
66 | dependency: "direct dev"
67 | description: flutter
68 | source: sdk
69 | version: "0.0.0"
70 | image:
71 | dependency: transitive
72 | description:
73 | name: image
74 | url: "https://pub.flutter-io.cn"
75 | source: hosted
76 | version: "2.1.4"
77 | matcher:
78 | dependency: transitive
79 | description:
80 | name: matcher
81 | url: "https://pub.flutter-io.cn"
82 | source: hosted
83 | version: "0.12.6"
84 | meta:
85 | dependency: transitive
86 | description:
87 | name: meta
88 | url: "https://pub.flutter-io.cn"
89 | source: hosted
90 | version: "1.1.8"
91 | path:
92 | dependency: transitive
93 | description:
94 | name: path
95 | url: "https://pub.flutter-io.cn"
96 | source: hosted
97 | version: "1.6.4"
98 | pedantic:
99 | dependency: transitive
100 | description:
101 | name: pedantic
102 | url: "https://pub.flutter-io.cn"
103 | source: hosted
104 | version: "1.8.0+1"
105 | petitparser:
106 | dependency: transitive
107 | description:
108 | name: petitparser
109 | url: "https://pub.flutter-io.cn"
110 | source: hosted
111 | version: "2.4.0"
112 | quiver:
113 | dependency: transitive
114 | description:
115 | name: quiver
116 | url: "https://pub.flutter-io.cn"
117 | source: hosted
118 | version: "2.0.5"
119 | sky_engine:
120 | dependency: transitive
121 | description: flutter
122 | source: sdk
123 | version: "0.0.99"
124 | source_span:
125 | dependency: transitive
126 | description:
127 | name: source_span
128 | url: "https://pub.flutter-io.cn"
129 | source: hosted
130 | version: "1.5.5"
131 | stack_trace:
132 | dependency: transitive
133 | description:
134 | name: stack_trace
135 | url: "https://pub.flutter-io.cn"
136 | source: hosted
137 | version: "1.9.3"
138 | stream_channel:
139 | dependency: transitive
140 | description:
141 | name: stream_channel
142 | url: "https://pub.flutter-io.cn"
143 | source: hosted
144 | version: "2.0.0"
145 | string_scanner:
146 | dependency: transitive
147 | description:
148 | name: string_scanner
149 | url: "https://pub.flutter-io.cn"
150 | source: hosted
151 | version: "1.0.5"
152 | term_glyph:
153 | dependency: transitive
154 | description:
155 | name: term_glyph
156 | url: "https://pub.flutter-io.cn"
157 | source: hosted
158 | version: "1.1.0"
159 | test_api:
160 | dependency: transitive
161 | description:
162 | name: test_api
163 | url: "https://pub.flutter-io.cn"
164 | source: hosted
165 | version: "0.2.11"
166 | typed_data:
167 | dependency: transitive
168 | description:
169 | name: typed_data
170 | url: "https://pub.flutter-io.cn"
171 | source: hosted
172 | version: "1.1.6"
173 | vector_math:
174 | dependency: transitive
175 | description:
176 | name: vector_math
177 | url: "https://pub.flutter-io.cn"
178 | source: hosted
179 | version: "2.0.8"
180 | xml:
181 | dependency: transitive
182 | description:
183 | name: xml
184 | url: "https://pub.flutter-io.cn"
185 | source: hosted
186 | version: "3.5.0"
187 | sdks:
188 | dart: ">=2.4.0 <3.0.0"
189 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_k_chart
2 | description: A new Flutter package project.
3 | version: 0.1.0
4 | author: gwh <415593725@qq.com>
5 | homepage: https://github.com/gwh/flutter_k_chart
6 |
7 | environment:
8 | sdk: ">=2.2.2 <3.0.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 |
14 | dev_dependencies:
15 | flutter_test:
16 | sdk: flutter
17 |
18 | # For information on the generic Dart part of this file, see the
19 | # following page: https://www.dartlang.org/tools/pub/pubspec
20 |
21 | # The following section is specific to Flutter.
22 | flutter:
23 |
24 | # To add assets to your package, add an assets section, like this:
25 | # assets:
26 | # - images/a_dot_burr.jpeg
27 | # - images/a_dot_ham.jpeg
28 | #
29 | # For details regarding assets in packages, see
30 | # https://flutter.dev/assets-and-images/#from-packages
31 | #
32 | # An image asset can refer to one or more resolution-specific "variants", see
33 | # https://flutter.dev/assets-and-images/#resolution-aware.
34 |
35 | # To add custom fonts to your package, add a fonts section here,
36 | # in this "flutter" section. Each entry in this list should have a
37 | # "family" key with the font family name, and a "fonts" key with a
38 | # list giving the asset and other descriptors for the font. For
39 | # example:
40 | # fonts:
41 | # - family: Schyler
42 | # fonts:
43 | # - asset: fonts/Schyler-Regular.ttf
44 | # - asset: fonts/Schyler-Italic.ttf
45 | # style: italic
46 | # - family: Trajan Pro
47 | # fonts:
48 | # - asset: fonts/TrajanPro.ttf
49 | # - asset: fonts/TrajanPro_Bold.ttf
50 | # weight: 700
51 | #
52 | # For details regarding fonts in packages, see
53 | # https://flutter.dev/custom-fonts/#from-packages
54 |
--------------------------------------------------------------------------------
/flutter_k_chart-master/res/values/strings_en.arb:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/flutter_k_chart-master/test/flutter_k_chart_test.dart:
--------------------------------------------------------------------------------
1 |
2 |
3 | //void main() {
4 | // test('adds one to input values', () {
5 | // final calculator = Calculator();
6 | // expect(calculator.addOne(2), 3);
7 | // expect(calculator.addOne(-7), -6);
8 | // expect(calculator.addOne(0), 1);
9 | // expect(() => calculator.addOne(null), throwsNoSuchMethodError);
10 | // });
11 | //}
12 |
--------------------------------------------------------------------------------