├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README_CN.md
├── example
├── .gitignore
├── .metadata
├── README.md
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── example
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v21
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values-night
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ ├── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ └── LaunchImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ └── README.md
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
│ └── RunnerTests
│ │ └── RunnerTests.swift
├── lib
│ ├── main.dart
│ └── smooth_corner_debug.dart
├── pubspec.yaml
├── test
│ └── widget_test.dart
└── web
│ ├── favicon.png
│ ├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
│ ├── index.html
│ └── manifest.json
├── lib
├── smooth_corner.dart
└── src
│ ├── smooth_card.dart
│ ├── smooth_clip_rrect.dart
│ ├── smooth_container.dart
│ └── smooth_rectangle_border.dart
├── pubspec.yaml
└── test
└── smooth_corner_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | .vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/pubspec.lock
25 | **/doc/api/
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | build/
33 |
34 | # Android related
35 | **/android/**/gradle-wrapper.jar
36 | **/android/.gradle
37 | **/android/captures/
38 | **/android/gradlew
39 | **/android/gradlew.bat
40 | **/android/local.properties
41 | **/android/**/GeneratedPluginRegistrant.java
42 |
43 | # iOS/XCode related
44 | **/ios/**/*.mode1v3
45 | **/ios/**/*.mode2v3
46 | **/ios/**/*.moved-aside
47 | **/ios/**/*.pbxuser
48 | **/ios/**/*.perspectivev3
49 | **/ios/**/*sync/
50 | **/ios/**/.sconsign.dblite
51 | **/ios/**/.tags*
52 | **/ios/**/.vagrant/
53 | **/ios/**/DerivedData/
54 | **/ios/**/Icon?
55 | **/ios/**/Pods/
56 | **/ios/**/.symlinks/
57 | **/ios/**/profile
58 | **/ios/**/xcuserdata
59 | **/ios/.generated/
60 | **/ios/Flutter/App.framework
61 | **/ios/Flutter/Flutter.framework
62 | **/ios/Flutter/Flutter.podspec
63 | **/ios/Flutter/Generated.xcconfig
64 | **/ios/Flutter/ephemeral
65 | **/ios/Flutter/app.flx
66 | **/ios/Flutter/app.zip
67 | **/ios/Flutter/flutter_assets/
68 | **/ios/Flutter/flutter_export_environment.sh
69 | **/ios/ServiceDefinitions.json
70 | **/ios/Runner/GeneratedPluginRegistrant.*
71 |
72 | # Exceptions to above rules.
73 | !**/ios/**/default.mode1v3
74 | !**/ios/**/default.mode2v3
75 | !**/ios/**/default.pbxuser
76 | !**/ios/**/default.perspectivev3
77 |
--------------------------------------------------------------------------------
/.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: d79295af24c3ed621c33713ecda14ad196fd9c31
8 | channel: stable
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## [Unreleased]
4 |
5 | - Support Interpolator
6 |
7 | ## 1.1.1
8 | - Support Flutter 3.27
9 |
10 | ## 1.1.0
11 |
12 | - Remove SmoothImage, Add SmoothClipRRect
13 |
14 | ## 1.0.0
15 |
16 | * First version
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, Hosea Tao
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Language: [English](README.md) | [中文简体](README_CN.md)
2 |
3 | # smooth_corner
4 |
5 | [](https://pub.dev/packages/smooth_corner) 
6 |
7 | Implement smooth iOS-style rounded corners in Flutter, mimicking Figma's "corner smoothing" feature. The algorithm is also inspired by Figma's blog post "[Desperately seeking squircles](https://www.figma.com/blog/desperately-seeking-squircles/)".
8 |
9 | The principle involves combining two Bezier curves and an arc to create smooth corners. Similar to Figma, the smoothness is adjustable. When the smoothness parameter is 0, it represents a normal rounded rectangle, and when the parameter is 1, the rounded corners are composed of only two Bezier curves, approaching a superellipse.
10 |
11 | You can view the debug rounded corner components and image examples I wrote in the example project, adjusting their smoothness and corner size to observe the changes in the corner curves.
12 |
13 |
14 |
15 |
16 |
17 | ## Usage
18 |
19 | ### Add dependency
20 |
21 | ```yaml
22 | dependencies:
23 | smooth_corner: ^1.1.1
24 | ```
25 |
26 |
27 |
28 | ### Built-in Widgets
29 |
30 | This library provides several commonly used widgets that allow you to adjust smooth rounded corners.
31 |
32 | All widgets provide three parameters: `smoothness`, `side`, and `borderRadius`, to control smooth corners and borders.
33 |
34 | - `smoothness`: Represents the smoothness, ranging from [0, 1.0]. According to Figma's standards, 0.6 is the closest to iOS's rounded corner curve.
35 |
36 | 
37 |
38 | - `side`: Type is `BorderSide`, used to set borders.
39 |
40 | - `borderRadius`: Used to set the corner radius. Note that if the x and y values of the radius are not equal, the smaller one will be chosen.
41 |
42 |
43 |
44 | #### SmoothContainer
45 |
46 | `SmoothContainer` includes all the parameters of `Container`.
47 |
48 | ```dart
49 | SmoothContainer(
50 | width: 200,
51 | height: 200,
52 | smoothness: 0.6,
53 | side: BorderSide(color: Colors.cyan, width: 2),
54 | borderRadius: BorderRadius.circular(40),
55 | child: child,
56 | alignment: Alignment.center,
57 | ),
58 | ```
59 |
60 |
61 |
62 | #### SmoothClipRRect
63 |
64 | To enable images to have borders, `SmoothClipRRect` is provided.
65 | ```dart
66 | SmoothClipRRect(
67 | smoothness: 0.6,
68 | side: BorderSide(color: Colors.deepOrange, width: 4),
69 | borderRadius: BorderRadius.circular(40),
70 | child: Image.network(
71 | url,
72 | fit: BoxFit.cover,
73 | ),
74 | ```
75 |
76 |
77 |
78 | #### SmoothCard
79 |
80 | `SmoothCard` includes all parameters of `Card`.
81 |
82 | ```dart
83 | SmoothCard(
84 | smoothness: 0.6,
85 | borderRadius: BorderRadius.circular(40),
86 | elevation: 6,
87 | child: child,
88 | ),
89 | ```
90 |
91 |
92 |
93 | ### Custom widget
94 |
95 | The smooth corner capabilities of the above widgets are implemented by `SmoothRectangleBorder`. You can use this `ShapeBorder` to freely customize your smooth corner components.
96 |
97 |
98 |
99 | #### ShapeDecoration
100 |
101 | ```dart
102 | Container(
103 | width: 200,
104 | height: 200,
105 | alignment: Alignment.center,
106 | decoration: ShapeDecoration(
107 | shape: SmoothRectangleBorder(
108 | borderRadius: BorderRadius.circular(40),
109 | smoothness: 0.6,
110 | ),
111 | color: Colors.amber,
112 | ),
113 | child: Text(''),
114 | ),
115 | ```
116 |
117 |
118 |
119 | #### ShapeBorderClipper
120 |
121 | ```dart
122 | Container(
123 | width: 200,
124 | height: 200,
125 | child: ClipPath(
126 | clipper: ShapeBorderClipper(
127 | shape: SmoothRectangleBorder(
128 | smoothness: 0.6,
129 | borderRadius:
130 | BorderRadius.circular(40),
131 | ),
132 | ),
133 | child: Image.network(url),
134 | ),
135 | ),
136 | ```
137 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | Language: [English](README.md) | [中文简体](README_CN.md)
2 |
3 | # smooth_corner
4 |
5 | [](https://pub.dev/packages/smooth_corner) 
6 |
7 | ## 项目介绍
8 |
9 | 在 Flutter 中实现 iOS 的平滑圆角,模仿了 Figma 的 「corner smoothing」 功能,算法也来自于 Figma 的blog「[Desperately seeking squircles](https://www.figma.com/blog/desperately-seeking-squircles/)」。
10 |
11 | 原理是用两段贝塞尔曲线和一端圆弧拼接而成,和 Figma 相同,平滑度可变,当参数 smoothness 为 0 时即为正常的圆角矩形,当参数为 1 时,圆角仅由两段贝塞尔曲线组成,接近超椭圆。
12 |
13 | 你可以在 example 工程中查看我写的 Debug 圆角组件和图片示例,调整其平滑度和圆角大小,来查看其中圆角曲线的变化。
14 |
15 |
16 |
17 |
18 |
19 | ## Usage
20 |
21 |
22 |
23 | ### 依赖 package
24 |
25 | ```yaml
26 | dependencies:
27 | smooth_corner: ^1.1.1
28 | ```
29 |
30 |
31 | ### 内置组件
32 |
33 | 该库提供了数个可以调整平滑圆角的常用 Widget。
34 |
35 | 均额外提供了三个参数 `smoothness、side、borderRadius`,用于控制平滑圆角和边框。
36 |
37 | `smoothness` 代表平滑度,范围为 [0, 1.0],按照 Figma 的标准,0.6 最接近 iOS 的圆角曲线。
38 |
39 | 
40 |
41 | `side` 的类型为 `BorderSide`,用于设置边框。
42 |
43 | `borderRadius` 用于设置圆角半径,需要注意的是,radius 的 x 和 y 值如果不相等,会选择最小的那个。
44 |
45 |
46 |
47 | #### SmoothContainer
48 |
49 | `SmoothContainer` 包含 Container 的所有参数
50 |
51 | ```dart
52 | SmoothContainer(
53 | width: 200,
54 | height: 200,
55 | smoothness: 0.6,
56 | side: BorderSide(color: Colors.cyan, width: 2),
57 | borderRadius: BorderRadius.circular(40),
58 | child: child,
59 | alignment: Alignment.center,
60 | ),
61 | ```
62 |
63 |
64 |
65 | #### SmoothClipRRect
66 |
67 | 为了实现图片控件也可以添加边框,提供了`SmoothClipRRect`
68 | ```dart
69 | SmoothClipRRect(
70 | smoothness: 0.6,
71 | side: BorderSide(color: Colors.deepOrange, width: 4),
72 | borderRadius: BorderRadius.circular(40),
73 | child: Image.network(
74 | url,
75 | fit: BoxFit.cover,
76 | ),
77 | ```
78 |
79 |
80 |
81 | #### SmoothCard
82 |
83 | `SmoothCard` 包含 Card 的所有参数
84 |
85 | ```dart
86 | SmoothCard(
87 | smoothness: 0.6,
88 | borderRadius: BorderRadius.circular(40),
89 | elevation: 6,
90 | child: child,
91 | ),
92 | ```
93 |
94 |
95 |
96 | ### 自定义组件
97 |
98 | 上述组件的平滑圆角能力均由 `SmoothRectangleBorder` 实现,你可以使用这个 ShapeBorder 自由定制你的平滑圆角组件
99 |
100 | #### ShapeDecoration
101 |
102 | ```dart
103 | Container(
104 | width: 200,
105 | height: 200,
106 | alignment: Alignment.center,
107 | decoration: ShapeDecoration(
108 | shape: SmoothRectangleBorder(
109 | borderRadius: BorderRadius.circular(40),
110 | smoothness: 0.6,
111 | ),
112 | color: Colors.amber,
113 | ),
114 | child: Text(''),
115 | ),
116 | ```
117 |
118 | #### ShapeBorderClipper
119 |
120 | ```dart
121 | Container(
122 | width: 200,
123 | height: 200,
124 | child: ClipPath(
125 | clipper: ShapeBorderClipper(
126 | shape: SmoothRectangleBorder(
127 | smoothness: 0.6,
128 | borderRadius:
129 | BorderRadius.circular(40),
130 | ),
131 | ),
132 | child: Image.network(url),
133 | ),
134 | ),
135 | ```
136 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android Studio will place build artifacts here
44 | /android/app/debug
45 | /android/app/profile
46 | /android/app/release
47 |
--------------------------------------------------------------------------------
/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: "17025dd88227cd9532c33fa78f5250d548d87e9a"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
17 | base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
18 | - platform: web
19 | create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
20 | base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
21 |
22 | # User provided section
23 |
24 | # List of Local paths (relative to this file) that should be
25 | # ignored by the migrate tool.
26 | #
27 | # Files that are not part of the templates will be ignored by default.
28 | unmanaged_files:
29 | - 'lib/main.dart'
30 | - 'ios/Runner.xcodeproj/project.pbxproj'
31 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at https://dart.dev/lints.
17 | #
18 | # Instead of disabling a lint rule for the entire project in the
19 | # section below, it can also be suppressed for a single line of code
20 | # or a specific dart file by using the `// ignore: name_of_lint` and
21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
22 | # producing the lint.
23 | rules:
24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
26 |
27 | # Additional information about this file can be found at
28 | # https://dart.dev/guides/language/analysis-options
29 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/to/reference-keystore
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5 | id "dev.flutter.flutter-gradle-plugin"
6 | }
7 |
8 | android {
9 | namespace = "com.example.example"
10 | compileSdk = flutter.compileSdkVersion
11 | ndkVersion = flutter.ndkVersion
12 |
13 | compileOptions {
14 | sourceCompatibility = JavaVersion.VERSION_1_8
15 | targetCompatibility = JavaVersion.VERSION_1_8
16 | }
17 |
18 | kotlinOptions {
19 | jvmTarget = JavaVersion.VERSION_1_8
20 | }
21 |
22 | defaultConfig {
23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24 | applicationId = "com.example.example"
25 | // You can update the following values to match your application needs.
26 | // For more information, see: https://flutter.dev/to/review-gradle-config.
27 | minSdk = flutter.minSdkVersion
28 | targetSdk = flutter.targetSdkVersion
29 | versionCode = flutter.versionCode
30 | versionName = flutter.versionName
31 | }
32 |
33 | buildTypes {
34 | release {
35 | // TODO: Add your own signing config for the release build.
36 | // Signing with the debug keys for now, so `flutter run --release` works.
37 | signingConfig = signingConfigs.debug
38 | }
39 | }
40 | }
41 |
42 | flutter {
43 | source = "../.."
44 | }
45 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity()
6 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = "../build"
9 | subprojects {
10 | project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 | project.evaluationDependsOn(":app")
14 | }
15 |
16 | tasks.register("clean", Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
6 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }()
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 | id "com.android.application" version "8.1.0" apply false
22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false
23 | }
24 |
25 | include ":app"
26 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/ephemeral/
22 | Flutter/app.flx
23 | Flutter/app.zip
24 | Flutter/flutter_assets/
25 | Flutter/flutter_export_environment.sh
26 | ServiceDefinitions.json
27 | Runner/GeneratedPluginRegistrant.*
28 |
29 | # Exceptions to above rules.
30 | !default.mode1v3
31 | !default.mode2v3
32 | !default.pbxuser
33 | !default.perspectivev3
34 |
--------------------------------------------------------------------------------
/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 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXCopyFilesBuildPhase section */
19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
20 | isa = PBXCopyFilesBuildPhase;
21 | buildActionMask = 2147483647;
22 | dstPath = "";
23 | dstSubfolderSpec = 10;
24 | files = (
25 | );
26 | name = "Embed Frameworks";
27 | runOnlyForDeploymentPostprocessing = 0;
28 | };
29 | /* End PBXCopyFilesBuildPhase section */
30 |
31 | /* Begin PBXFileReference section */
32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | /* End PBXFileReference section */
46 |
47 | /* Begin PBXFrameworksBuildPhase section */
48 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
49 | isa = PBXFrameworksBuildPhase;
50 | buildActionMask = 2147483647;
51 | files = (
52 | );
53 | runOnlyForDeploymentPostprocessing = 0;
54 | };
55 | /* End PBXFrameworksBuildPhase section */
56 |
57 | /* Begin PBXGroup section */
58 | 9740EEB11CF90186004384FC /* Flutter */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
65 | );
66 | name = Flutter;
67 | sourceTree = "";
68 | };
69 | 97C146E51CF9000F007C117D = {
70 | isa = PBXGroup;
71 | children = (
72 | 9740EEB11CF90186004384FC /* Flutter */,
73 | 97C146F01CF9000F007C117D /* Runner */,
74 | 97C146EF1CF9000F007C117D /* Products */,
75 | );
76 | sourceTree = "";
77 | };
78 | 97C146EF1CF9000F007C117D /* Products */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 97C146EE1CF9000F007C117D /* Runner.app */,
82 | );
83 | name = Products;
84 | sourceTree = "";
85 | };
86 | 97C146F01CF9000F007C117D /* Runner */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
92 | 97C147021CF9000F007C117D /* Info.plist */,
93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
97 | );
98 | path = Runner;
99 | sourceTree = "";
100 | };
101 | /* End PBXGroup section */
102 |
103 | /* Begin PBXNativeTarget section */
104 | 97C146ED1CF9000F007C117D /* Runner */ = {
105 | isa = PBXNativeTarget;
106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
107 | buildPhases = (
108 | 9740EEB61CF901F6004384FC /* Run Script */,
109 | 97C146EA1CF9000F007C117D /* Sources */,
110 | 97C146EB1CF9000F007C117D /* Frameworks */,
111 | 97C146EC1CF9000F007C117D /* Resources */,
112 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
114 | );
115 | buildRules = (
116 | );
117 | dependencies = (
118 | );
119 | name = Runner;
120 | productName = Runner;
121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
122 | productType = "com.apple.product-type.application";
123 | };
124 | /* End PBXNativeTarget section */
125 |
126 | /* Begin PBXProject section */
127 | 97C146E61CF9000F007C117D /* Project object */ = {
128 | isa = PBXProject;
129 | attributes = {
130 | LastUpgradeCheck = 1510;
131 | ORGANIZATIONNAME = "";
132 | TargetAttributes = {
133 | 97C146ED1CF9000F007C117D = {
134 | CreatedOnToolsVersion = 7.3.1;
135 | LastSwiftMigration = 1100;
136 | };
137 | };
138 | };
139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
140 | compatibilityVersion = "Xcode 9.3";
141 | developmentRegion = en;
142 | hasScannedForEncodings = 0;
143 | knownRegions = (
144 | en,
145 | Base,
146 | );
147 | mainGroup = 97C146E51CF9000F007C117D;
148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
149 | projectDirPath = "";
150 | projectRoot = "";
151 | targets = (
152 | 97C146ED1CF9000F007C117D /* Runner */,
153 | );
154 | };
155 | /* End PBXProject section */
156 |
157 | /* Begin PBXResourcesBuildPhase section */
158 | 97C146EC1CF9000F007C117D /* Resources */ = {
159 | isa = PBXResourcesBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
166 | );
167 | runOnlyForDeploymentPostprocessing = 0;
168 | };
169 | /* End PBXResourcesBuildPhase section */
170 |
171 | /* Begin PBXShellScriptBuildPhase section */
172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
173 | isa = PBXShellScriptBuildPhase;
174 | alwaysOutOfDate = 1;
175 | buildActionMask = 2147483647;
176 | files = (
177 | );
178 | inputPaths = (
179 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
180 | );
181 | name = "Thin Binary";
182 | outputPaths = (
183 | );
184 | runOnlyForDeploymentPostprocessing = 0;
185 | shellPath = /bin/sh;
186 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
187 | };
188 | 9740EEB61CF901F6004384FC /* Run Script */ = {
189 | isa = PBXShellScriptBuildPhase;
190 | alwaysOutOfDate = 1;
191 | buildActionMask = 2147483647;
192 | files = (
193 | );
194 | inputPaths = (
195 | );
196 | name = "Run Script";
197 | outputPaths = (
198 | );
199 | runOnlyForDeploymentPostprocessing = 0;
200 | shellPath = /bin/sh;
201 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
202 | };
203 | /* End PBXShellScriptBuildPhase section */
204 |
205 | /* Begin PBXSourcesBuildPhase section */
206 | 97C146EA1CF9000F007C117D /* Sources */ = {
207 | isa = PBXSourcesBuildPhase;
208 | buildActionMask = 2147483647;
209 | files = (
210 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
211 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
212 | );
213 | runOnlyForDeploymentPostprocessing = 0;
214 | };
215 | /* End PBXSourcesBuildPhase section */
216 |
217 | /* Begin PBXVariantGroup section */
218 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
219 | isa = PBXVariantGroup;
220 | children = (
221 | 97C146FB1CF9000F007C117D /* Base */,
222 | );
223 | name = Main.storyboard;
224 | sourceTree = "";
225 | };
226 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
227 | isa = PBXVariantGroup;
228 | children = (
229 | 97C147001CF9000F007C117D /* Base */,
230 | );
231 | name = LaunchScreen.storyboard;
232 | sourceTree = "";
233 | };
234 | /* End PBXVariantGroup section */
235 |
236 | /* Begin XCBuildConfiguration section */
237 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
238 | isa = XCBuildConfiguration;
239 | buildSettings = {
240 | ALWAYS_SEARCH_USER_PATHS = NO;
241 | CLANG_ANALYZER_NONNULL = YES;
242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
243 | CLANG_CXX_LIBRARY = "libc++";
244 | CLANG_ENABLE_MODULES = YES;
245 | CLANG_ENABLE_OBJC_ARC = YES;
246 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
247 | CLANG_WARN_BOOL_CONVERSION = YES;
248 | CLANG_WARN_COMMA = YES;
249 | CLANG_WARN_CONSTANT_CONVERSION = YES;
250 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
252 | CLANG_WARN_EMPTY_BODY = YES;
253 | CLANG_WARN_ENUM_CONVERSION = YES;
254 | CLANG_WARN_INFINITE_RECURSION = YES;
255 | CLANG_WARN_INT_CONVERSION = YES;
256 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
257 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
258 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
259 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
260 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
261 | CLANG_WARN_STRICT_PROTOTYPES = YES;
262 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
263 | CLANG_WARN_UNREACHABLE_CODE = YES;
264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
265 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
266 | COPY_PHASE_STRIP = NO;
267 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
268 | ENABLE_NS_ASSERTIONS = NO;
269 | ENABLE_STRICT_OBJC_MSGSEND = YES;
270 | GCC_C_LANGUAGE_STANDARD = gnu99;
271 | GCC_NO_COMMON_BLOCKS = YES;
272 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
273 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
274 | GCC_WARN_UNDECLARED_SELECTOR = YES;
275 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
276 | GCC_WARN_UNUSED_FUNCTION = YES;
277 | GCC_WARN_UNUSED_VARIABLE = YES;
278 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
279 | MTL_ENABLE_DEBUG_INFO = NO;
280 | SDKROOT = iphoneos;
281 | SUPPORTED_PLATFORMS = iphoneos;
282 | TARGETED_DEVICE_FAMILY = "1,2";
283 | VALIDATE_PRODUCT = YES;
284 | };
285 | name = Profile;
286 | };
287 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
288 | isa = XCBuildConfiguration;
289 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
290 | buildSettings = {
291 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
292 | CLANG_ENABLE_MODULES = YES;
293 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
294 | ENABLE_BITCODE = NO;
295 | INFOPLIST_FILE = Runner/Info.plist;
296 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
297 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
298 | PRODUCT_NAME = "$(TARGET_NAME)";
299 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
300 | SWIFT_VERSION = 5.0;
301 | VERSIONING_SYSTEM = "apple-generic";
302 | };
303 | name = Profile;
304 | };
305 | 97C147031CF9000F007C117D /* Debug */ = {
306 | isa = XCBuildConfiguration;
307 | buildSettings = {
308 | ALWAYS_SEARCH_USER_PATHS = NO;
309 | CLANG_ANALYZER_NONNULL = YES;
310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
311 | CLANG_CXX_LIBRARY = "libc++";
312 | CLANG_ENABLE_MODULES = YES;
313 | CLANG_ENABLE_OBJC_ARC = YES;
314 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
315 | CLANG_WARN_BOOL_CONVERSION = YES;
316 | CLANG_WARN_COMMA = YES;
317 | CLANG_WARN_CONSTANT_CONVERSION = YES;
318 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
320 | CLANG_WARN_EMPTY_BODY = YES;
321 | CLANG_WARN_ENUM_CONVERSION = YES;
322 | CLANG_WARN_INFINITE_RECURSION = YES;
323 | CLANG_WARN_INT_CONVERSION = YES;
324 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
325 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
326 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
328 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
329 | CLANG_WARN_STRICT_PROTOTYPES = YES;
330 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
331 | CLANG_WARN_UNREACHABLE_CODE = YES;
332 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
334 | COPY_PHASE_STRIP = NO;
335 | DEBUG_INFORMATION_FORMAT = dwarf;
336 | ENABLE_STRICT_OBJC_MSGSEND = YES;
337 | ENABLE_TESTABILITY = YES;
338 | GCC_C_LANGUAGE_STANDARD = gnu99;
339 | GCC_DYNAMIC_NO_PIC = NO;
340 | GCC_NO_COMMON_BLOCKS = YES;
341 | GCC_OPTIMIZATION_LEVEL = 0;
342 | GCC_PREPROCESSOR_DEFINITIONS = (
343 | "DEBUG=1",
344 | "$(inherited)",
345 | );
346 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
347 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
348 | GCC_WARN_UNDECLARED_SELECTOR = YES;
349 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
350 | GCC_WARN_UNUSED_FUNCTION = YES;
351 | GCC_WARN_UNUSED_VARIABLE = YES;
352 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
353 | MTL_ENABLE_DEBUG_INFO = YES;
354 | ONLY_ACTIVE_ARCH = YES;
355 | SDKROOT = iphoneos;
356 | TARGETED_DEVICE_FAMILY = "1,2";
357 | };
358 | name = Debug;
359 | };
360 | 97C147041CF9000F007C117D /* Release */ = {
361 | isa = XCBuildConfiguration;
362 | buildSettings = {
363 | ALWAYS_SEARCH_USER_PATHS = NO;
364 | CLANG_ANALYZER_NONNULL = YES;
365 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
366 | CLANG_CXX_LIBRARY = "libc++";
367 | CLANG_ENABLE_MODULES = YES;
368 | CLANG_ENABLE_OBJC_ARC = YES;
369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
370 | CLANG_WARN_BOOL_CONVERSION = YES;
371 | CLANG_WARN_COMMA = YES;
372 | CLANG_WARN_CONSTANT_CONVERSION = YES;
373 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
375 | CLANG_WARN_EMPTY_BODY = YES;
376 | CLANG_WARN_ENUM_CONVERSION = YES;
377 | CLANG_WARN_INFINITE_RECURSION = YES;
378 | CLANG_WARN_INT_CONVERSION = YES;
379 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
380 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
381 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
382 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
383 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
384 | CLANG_WARN_STRICT_PROTOTYPES = YES;
385 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
386 | CLANG_WARN_UNREACHABLE_CODE = YES;
387 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
388 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
389 | COPY_PHASE_STRIP = NO;
390 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
391 | ENABLE_NS_ASSERTIONS = NO;
392 | ENABLE_STRICT_OBJC_MSGSEND = YES;
393 | GCC_C_LANGUAGE_STANDARD = gnu99;
394 | GCC_NO_COMMON_BLOCKS = YES;
395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
396 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
397 | GCC_WARN_UNDECLARED_SELECTOR = YES;
398 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
399 | GCC_WARN_UNUSED_FUNCTION = YES;
400 | GCC_WARN_UNUSED_VARIABLE = YES;
401 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
402 | MTL_ENABLE_DEBUG_INFO = NO;
403 | SDKROOT = iphoneos;
404 | SUPPORTED_PLATFORMS = iphoneos;
405 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
406 | TARGETED_DEVICE_FAMILY = "1,2";
407 | VALIDATE_PRODUCT = YES;
408 | };
409 | name = Release;
410 | };
411 | 97C147061CF9000F007C117D /* Debug */ = {
412 | isa = XCBuildConfiguration;
413 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
414 | buildSettings = {
415 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
416 | CLANG_ENABLE_MODULES = YES;
417 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
418 | ENABLE_BITCODE = NO;
419 | INFOPLIST_FILE = Runner/Info.plist;
420 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
421 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
422 | PRODUCT_NAME = "$(TARGET_NAME)";
423 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
424 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
425 | SWIFT_VERSION = 5.0;
426 | VERSIONING_SYSTEM = "apple-generic";
427 | };
428 | name = Debug;
429 | };
430 | 97C147071CF9000F007C117D /* Release */ = {
431 | isa = XCBuildConfiguration;
432 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
433 | buildSettings = {
434 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
435 | CLANG_ENABLE_MODULES = YES;
436 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
437 | ENABLE_BITCODE = NO;
438 | INFOPLIST_FILE = Runner/Info.plist;
439 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
440 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
441 | PRODUCT_NAME = "$(TARGET_NAME)";
442 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
443 | SWIFT_VERSION = 5.0;
444 | VERSIONING_SYSTEM = "apple-generic";
445 | };
446 | name = Release;
447 | };
448 | /* End XCBuildConfiguration section */
449 |
450 | /* Begin XCConfigurationList section */
451 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
452 | isa = XCConfigurationList;
453 | buildConfigurations = (
454 | 97C147031CF9000F007C117D /* Debug */,
455 | 97C147041CF9000F007C117D /* Release */,
456 | 249021D3217E4FDB00AE95B9 /* Profile */,
457 | );
458 | defaultConfigurationIsVisible = 0;
459 | defaultConfigurationName = Release;
460 | };
461 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
462 | isa = XCConfigurationList;
463 | buildConfigurations = (
464 | 97C147061CF9000F007C117D /* Debug */,
465 | 97C147071CF9000F007C117D /* Release */,
466 | 249021D4217E4FDB00AE95B9 /* Profile */,
467 | );
468 | defaultConfigurationIsVisible = 0;
469 | defaultConfigurationName = Release;
470 | };
471 | /* End XCConfigurationList section */
472 | };
473 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
474 | }
475 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @main
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | 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 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:example/smooth_corner_debug.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:smooth_corner/smooth_corner.dart';
5 |
6 | void main() {
7 | runApp(MyApp());
8 | }
9 |
10 | class MyApp extends StatelessWidget {
11 | // This widget is the root of your application.
12 | @override
13 | Widget build(BuildContext context) {
14 | return MaterialApp(
15 | title: 'Smooth Corner',
16 | theme: ThemeData(
17 | primarySwatch: Colors.blue,
18 | ),
19 | home: MyHomePage(title: 'SMOOTH CORNER'),
20 | );
21 | }
22 | }
23 |
24 | class MyHomePage extends StatefulWidget {
25 | MyHomePage({Key? key, required this.title}) : super(key: key);
26 |
27 | final String title;
28 |
29 | @override
30 | _MyHomePageState createState() => _MyHomePageState();
31 | }
32 |
33 | class _MyHomePageState extends State {
34 | double radius = kIsWeb ? 80 : 40;
35 | double smoothness = 0.6;
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | return Scaffold(
40 | appBar: AppBar(
41 | title: Text(widget.title),
42 | ),
43 | body: Column(
44 | mainAxisAlignment: MainAxisAlignment.center,
45 | children: [
46 | Flexible(
47 | child: Padding(
48 | padding: const EdgeInsets.all(8.0),
49 | child: GridView(
50 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
51 | crossAxisCount: 2,
52 | crossAxisSpacing: 10,
53 | mainAxisSpacing: 10,
54 | ),
55 | children: [
56 | SmoothClipRRect(
57 | smoothness: smoothness,
58 | side: BorderSide(color: Colors.deepOrange, width: 4),
59 | borderRadius: BorderRadius.circular(radius),
60 | child: Image.network(
61 | "https://img1.mydrivers.com/img/20200424/s_cf611107e2d2469fa54b0d8ae2ee5a31.jpg",
62 | fit: BoxFit.cover,
63 | ),
64 | ),
65 | SmoothContainer(
66 | smoothness: smoothness,
67 | side: BorderSide(color: Colors.cyan, width: 2),
68 | borderRadius: BorderRadius.circular(radius),
69 | child: _ExampleText(),
70 | alignment: Alignment.center,
71 | ),
72 | SmoothCard(
73 | smoothness: smoothness,
74 | borderRadius: BorderRadius.circular(radius),
75 | elevation: 6,
76 | child: Center(child: _ExampleText()),
77 | ),
78 | Container(
79 | alignment: Alignment.center,
80 | decoration: ShapeDecoration(
81 | shape: SmoothBorderDebug(
82 | side: BorderSide(color: Colors.blueGrey, width: 4),
83 | borderRadius: BorderRadius.circular(radius),
84 | smoothness: smoothness,
85 | ),
86 | color: Colors.amber,
87 | ),
88 | child: Text(
89 | 'radius:${radius.toInt()} \nsmooth:${smoothness.toStringAsFixed(2)}',
90 | style: kIsWeb
91 | ? Theme.of(context).textTheme.headlineMedium
92 | : Theme.of(context).textTheme.bodyLarge,
93 | ),
94 | ),
95 | ],
96 | ),
97 | ),
98 | ),
99 | Padding(padding: const EdgeInsets.only(top: 40)),
100 | Slider(
101 | min: 0.0,
102 | max: 1.0,
103 | onChanged: (double value) {
104 | setState(() {
105 | smoothness = value;
106 | });
107 | },
108 | value: smoothness,
109 | ),
110 | Slider(
111 | activeColor: Colors.amber,
112 | min: 0,
113 | max: kIsWeb ? 250 : 100,
114 | onChanged: (double value) {
115 | setState(() {
116 | radius = value;
117 | });
118 | },
119 | value: radius,
120 | ),
121 | ],
122 | ),
123 | );
124 | }
125 | }
126 |
127 | class _ExampleText extends StatelessWidget {
128 | const _ExampleText({
129 | Key? key,
130 | }) : super(key: key);
131 |
132 | @override
133 | Widget build(BuildContext context) {
134 | return Text(
135 | 'No one shall be held in slavery or servitude; slavery and the slave trade shall be prohibited in all their forms.');
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/example/lib/smooth_corner_debug.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:smooth_corner/smooth_corner.dart';
5 |
6 | class SmoothBorderDebug extends SmoothRectangleBorder {
7 | SmoothBorderDebug({
8 | double smoothness = 0.0,
9 | BorderSide side = BorderSide.none,
10 | BorderRadiusGeometry borderRadius = BorderRadius.zero,
11 | }) : super(
12 | smoothness: smoothness,
13 | side: side,
14 | borderRadius: borderRadius,
15 | );
16 |
17 | @override
18 | void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
19 | super.paint(canvas, rect);
20 | if (borderRadius == BorderRadius.zero) return;
21 |
22 | var paint = Paint()..color = Colors.redAccent;
23 | var width = rect.width;
24 | var height = rect.height;
25 | var top = rect.top;
26 | var left = rect.left;
27 | var right = rect.right;
28 |
29 | var debugCorner = Corner(
30 | borderRadius.resolve(textDirection).toRRect(rect).deflate(side.width),
31 | CornerLocation.tr,
32 | smoothness);
33 |
34 | var radius = debugCorner.radius;
35 |
36 | var p = debugCorner.p;
37 |
38 | double angleBezier = debugCorner.angleBezier;
39 | double angleCircle = debugCorner.angleCircle;
40 |
41 | var l = sin(angleCircle.toRadian() / 2) * radius * pow(2, 0.5);
42 | var c = debugCorner.c;
43 | var d = debugCorner.d;
44 | var b = debugCorner.b;
45 | var a = debugCorner.a;
46 |
47 | canvas.drawCircle(
48 | Offset(right - radius - side.width, top + radius + side.width),
49 | radius,
50 | Paint()..color = Colors.black12);
51 |
52 | canvas.drawArc(
53 | Rect.fromCircle(
54 | center: Offset(right - radius - side.width, top + radius + side.width),
55 | radius: radius,
56 | ),
57 | (270 + angleBezier).toRadian(),
58 | (90 - 2 * angleBezier).toRadian(),
59 | true,
60 | paint,
61 | );
62 | var pointPaint = Paint()
63 | ..color = Colors.black54
64 | ..style = PaintingStyle.stroke
65 | ..strokeWidth = 1;
66 |
67 | canvas.drawCircle(
68 | Offset(left + max(width / 2, width - p) - side.width, top + side.width),
69 | 5,
70 | pointPaint);
71 |
72 | canvas.drawCircle(
73 | Offset(right - (p - a - b - c) - side.width, top + d + side.width),
74 | 5,
75 | pointPaint);
76 |
77 | canvas.drawCircle(Offset(right - d - side.width, top + d + l + side.width),
78 | 5, pointPaint);
79 |
80 | canvas.drawCircle(
81 | Offset(right - side.width, top + min(height / 2, p) + side.width),
82 | 5,
83 | pointPaint);
84 | }
85 |
86 | @override
87 | SmoothBorderDebug scale(double t) {
88 | return SmoothBorderDebug(borderRadius: borderRadius * t);
89 | }
90 | }
91 |
92 | extension _Math on double {
93 | double toRadian() => this * pi / 180;
94 | }
95 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ^3.6.0
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 | smooth_corner:
27 | path: ../
28 |
29 |
30 | # The following adds the Cupertino Icons font to your application.
31 | # Use with the CupertinoIcons class for iOS style icons.
32 | cupertino_icons: ^1.0.2
33 |
34 | dev_dependencies:
35 | flutter_test:
36 | sdk: flutter
37 |
38 | # For information on the generic Dart part of this file, see the
39 | # following page: https://dart.dev/tools/pub/pubspec
40 |
41 | # The following section is specific to Flutter.
42 | flutter:
43 |
44 | # The following line ensures that the Material Icons font is
45 | # included with your application, so that you can use the icons in
46 | # the material Icons class.
47 | uses-material-design: true
48 |
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 |
--------------------------------------------------------------------------------
/example/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:example/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/example/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/web/favicon.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/howshea/smooth_corner/eb0e01676400cfa012e0a95e97a542467cedd5bd/example/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | example
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/example/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "short_name": "example",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/lib/smooth_corner.dart:
--------------------------------------------------------------------------------
1 | library smooth_corner;
2 |
3 | export 'src/smooth_rectangle_border.dart';
4 | export 'src/smooth_container.dart';
5 | export 'src/smooth_clip_rrect.dart';
6 | export 'src/smooth_card.dart';
7 |
--------------------------------------------------------------------------------
/lib/src/smooth_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:smooth_corner/smooth_corner.dart';
3 |
4 | class SmoothCard extends Card {
5 | /// The radius for each corner.
6 | ///
7 | /// Negative radius values are clamped to 0.0 by [getInnerPath] and
8 | /// [getOuterPath].
9 | ///
10 | /// If radiuses of X and Y from one corner are not equal, the smallest one will be used.
11 | final BorderRadiusGeometry borderRadius;
12 |
13 | /// The smoothness of corners.
14 | ///
15 | /// The concept comes from a feature called "corner smoothing" of Figma.
16 | ///
17 | /// 0.0 - 1.0
18 | final double smoothness;
19 |
20 | /// The border outline's color and weight.
21 | ///
22 | /// If [side] is [BorderSide.none], which is the default, an outline is not drawn.
23 | /// Otherwise the outline is centered over the shape's boundary.
24 | final BorderSide side;
25 |
26 | SmoothCard({
27 | Key? key,
28 | this.smoothness = 0.6,
29 | this.borderRadius = BorderRadius.zero,
30 | this.side = BorderSide.none,
31 | Widget? child,
32 | Color? color,
33 | Color? shadowColor,
34 | double? elevation,
35 | bool borderOnForeground = true,
36 | EdgeInsetsGeometry? margin,
37 | bool semanticContainer = true,
38 | }) : super(
39 | key: key,
40 | color: color,
41 | shadowColor: shadowColor,
42 | elevation: elevation,
43 | borderOnForeground: borderOnForeground,
44 | margin: margin,
45 | semanticContainer: semanticContainer,
46 | clipBehavior: Clip.antiAlias,
47 | shape: SmoothRectangleBorder(
48 | side: side,
49 | borderRadius: borderRadius,
50 | smoothness: smoothness,
51 | ),
52 | child: child,
53 | );
54 | }
55 |
--------------------------------------------------------------------------------
/lib/src/smooth_clip_rrect.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:smooth_corner/smooth_corner.dart';
5 |
6 | class SmoothClipRRect extends StatelessWidget {
7 | /// The radius for each corner.
8 | ///
9 | /// Negative radius values are clamped to 0.0 by [getInnerPath] and
10 | /// [getOuterPath].
11 | ///
12 | /// If radiuses of X and Y from one corner are not equal, the smallest one will be used.
13 | final BorderRadius borderRadius;
14 |
15 | /// The smoothness of corners.
16 | ///
17 | /// The concept comes from a feature called "corner smoothing" of Figma.
18 | ///
19 | /// 0.0 - 1.0
20 | final double smoothness;
21 |
22 | /// The border outline's color and weight.
23 | ///
24 | /// If [side] is [BorderSide.none], which is the default, an outline is not drawn.
25 | /// Otherwise the outline is centered over the shape's boundary.
26 | final BorderSide side;
27 |
28 | final Widget child;
29 |
30 | const SmoothClipRRect({
31 | Key? key,
32 | this.smoothness = 0.6,
33 | this.borderRadius = BorderRadius.zero,
34 | this.side = BorderSide.none,
35 | required this.child,
36 | }) : super(key: key);
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 | var shaper = SmoothRectangleBorder(
41 | smoothness: smoothness,
42 | borderRadius: borderRadius - BorderRadius.circular(side.width),
43 | );
44 | return CustomPaint(
45 | child: Padding(
46 | padding: EdgeInsets.all(max(0.0, side.width - 1)),
47 | child: ClipPath(
48 | clipper: ShapeBorderClipper(
49 | shape: shaper,
50 | ),
51 | child: child,
52 | ),
53 | ),
54 | foregroundPainter: _BorderPainter(side, borderRadius, shaper),
55 | );
56 | }
57 | }
58 |
59 | class _BorderPainter extends CustomPainter {
60 | final BorderSide side;
61 | final BorderRadius borderRadius;
62 | final SmoothRectangleBorder shaper;
63 |
64 | _BorderPainter(this.side, this.borderRadius, this.shaper);
65 | @override
66 | void paint(Canvas canvas, Size size) {
67 | if (side != BorderSide.none &&
68 | side.style == BorderStyle.solid &&
69 | side.width > 0) {
70 | final Path path = shaper.getPath(
71 | borderRadius.toRRect(Offset.zero & size).deflate(side.width / 2),
72 | );
73 | final Paint paint = side.toPaint()..isAntiAlias = true;
74 | canvas.drawPath(path, paint);
75 | }
76 | }
77 |
78 | @override
79 | bool shouldRepaint(covariant _BorderPainter old) {
80 | return old.side != side ||
81 | old.borderRadius != borderRadius ||
82 | old.shaper != shaper;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/src/smooth_container.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:smooth_corner/smooth_corner.dart';
3 |
4 | class SmoothContainer extends Container {
5 | /// The radius for each corner.
6 | ///
7 | /// Negative radius values are clamped to 0.0 by [getInnerPath] and
8 | /// [getOuterPath].
9 | ///
10 | /// If radiuses of X and Y from one corner are not equal, the smallest one will be used.
11 | final BorderRadiusGeometry borderRadius;
12 |
13 | /// The smoothness of corners.
14 | ///
15 | /// The concept comes from a feature called "corner smoothing" of Figma.
16 | ///
17 | /// 0.0 - 1.0
18 | final double smoothness;
19 |
20 | /// The border outline's color and weight.
21 | ///
22 | /// If [side] is [BorderSide.none], which is the default, an outline is not drawn.
23 | /// Otherwise the outline is centered over the shape's boundary.
24 | final BorderSide side;
25 |
26 | SmoothContainer({
27 | Key? key,
28 | this.smoothness = 0.6,
29 | this.borderRadius = BorderRadius.zero,
30 | this.side = BorderSide.none,
31 | Widget? child,
32 | double? width,
33 | double? height,
34 | AlignmentGeometry? alignment,
35 | EdgeInsetsGeometry? padding,
36 | Color? color,
37 | Decoration? foregroundDecoration,
38 | BoxConstraints? constraints,
39 | EdgeInsetsGeometry? margin,
40 | Matrix4? transform,
41 | AlignmentGeometry? transformAlignment,
42 | }) : super(
43 | key: key,
44 | child: child,
45 | width: width,
46 | height: height,
47 | alignment: alignment,
48 | padding: padding ?? EdgeInsets.all(side.width),
49 | foregroundDecoration: foregroundDecoration,
50 | constraints: constraints,
51 | margin: margin,
52 | transform: transform,
53 | transformAlignment: transformAlignment,
54 | decoration: ShapeDecoration(
55 | shape: SmoothRectangleBorder(
56 | side: side,
57 | borderRadius: borderRadius,
58 | smoothness: smoothness,
59 | ),
60 | color: color,
61 | ),
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/lib/src/smooth_rectangle_border.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'dart:ui';
3 | import 'package:flutter/material.dart';
4 |
5 | enum CornerLocation { tl, tr, bl, br }
6 |
7 | /// A rectangular border with variable smoothness transitions between
8 | /// the straight sides and the rounded corners.
9 | class SmoothRectangleBorder extends OutlinedBorder {
10 | SmoothRectangleBorder({
11 | this.smoothness = 0.0,
12 | this.borderRadius = BorderRadius.zero,
13 | BorderSide side = BorderSide.none,
14 | }) : super(side: side);
15 |
16 | /// The radius for each corner.
17 | ///
18 | /// Negative radius values are clamped to 0.0 by [getInnerPath] and
19 | /// [getOuterPath].
20 | ///
21 | /// If radiuses of X and Y from one corner are not equal, the smallest one will be used.
22 | final BorderRadiusGeometry borderRadius;
23 |
24 | /// The smoothness of corners.
25 | ///
26 | /// The concept comes from a feature called "corner smoothing" of Figma.
27 | ///
28 | /// 0.0 - 1.0
29 | final double smoothness;
30 |
31 | @override
32 | EdgeInsetsGeometry get dimensions => EdgeInsets.all(0);
33 |
34 | @override
35 | Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
36 | return getPath(
37 | borderRadius.resolve(textDirection).toRRect(rect).deflate(side.width));
38 | }
39 |
40 | Path getPath(RRect rrect) {
41 | var path = Path();
42 | if (smoothness == 0 || borderRadius == BorderRadius.zero) {
43 | path.addRRect(rrect);
44 | } else {
45 | final width = rrect.width;
46 | final height = rrect.height;
47 | final top = rrect.top;
48 | final left = rrect.left;
49 | final bottom = rrect.bottom;
50 | final right = rrect.right;
51 |
52 | var centerX = width / 2 + left;
53 |
54 | var tl = Corner(rrect, CornerLocation.tl, smoothness);
55 | var tr = Corner(rrect, CornerLocation.tr, smoothness);
56 | var br = Corner(rrect, CornerLocation.br, smoothness);
57 | var bl = Corner(rrect, CornerLocation.bl, smoothness);
58 |
59 | path.moveTo(centerX, top);
60 |
61 | // top right
62 | path
63 | ..lineTo(left + max(width / 2, width - tr.p), top)
64 | ..cubicTo(
65 | right - (tr.p - tr.a),
66 | top,
67 | right - (tr.p - tr.a - tr.b),
68 | top,
69 | right - (tr.p - tr.a - tr.b - tr.c),
70 | top + tr.d,
71 | )
72 | ..arcTo(
73 | Rect.fromCircle(
74 | center: Offset(right - tr.radius, top + tr.radius),
75 | radius: tr.radius,
76 | ),
77 | (270 + tr.angleBezier).toRadian(),
78 | (90 - 2 * tr.angleBezier).toRadian(),
79 | false,
80 | )
81 | ..cubicTo(
82 | right,
83 | top + (tr.p - tr.a - tr.b),
84 | right,
85 | top + (tr.p - tr.a),
86 | right,
87 | top + min(height / 2, tr.p),
88 | );
89 |
90 | //bottom right
91 | path
92 | ..lineTo(
93 | right,
94 | top + max(height / 2, height - br.p),
95 | )
96 | ..cubicTo(
97 | right,
98 | bottom - (br.p - br.a),
99 | right,
100 | bottom - (br.p - br.a - br.b),
101 | right - br.d,
102 | bottom - (br.p - br.a - br.b - br.c),
103 | )
104 | ..arcTo(
105 | Rect.fromCircle(
106 | center: Offset(right - br.radius, bottom - br.radius),
107 | radius: br.radius,
108 | ),
109 | br.angleBezier.toRadian(),
110 | (90 - br.angleBezier * 2).toRadian(),
111 | false,
112 | )
113 | ..cubicTo(
114 | right - (br.p - br.a - br.b),
115 | bottom,
116 | right - (br.p - br.a),
117 | bottom,
118 | left + max(width / 2, width - br.p),
119 | bottom,
120 | );
121 |
122 | //bottom left
123 | path
124 | ..lineTo(left + min(width / 2, bl.p), bottom)
125 | ..cubicTo(
126 | left + (bl.p - bl.a),
127 | bottom,
128 | left + (bl.p - bl.a - bl.b),
129 | bottom,
130 | left + (bl.p - bl.a - bl.b - bl.c),
131 | bottom - bl.d,
132 | )
133 | ..arcTo(
134 | Rect.fromCircle(
135 | center: Offset(left + bl.radius, bottom - bl.radius),
136 | radius: bl.radius),
137 | (90 + bl.angleBezier).toRadian(),
138 | (90 - bl.angleBezier * 2).toRadian(),
139 | false,
140 | )
141 | ..cubicTo(
142 | left,
143 | bottom - (bl.p - bl.a - bl.b),
144 | left,
145 | bottom - (bl.p - bl.a),
146 | left,
147 | top + max(height / 2, height - bl.p),
148 | );
149 |
150 | //top left
151 | path
152 | ..lineTo(left, top + min(height / 2, tl.p))
153 | ..cubicTo(
154 | left,
155 | top + (tl.p - tl.a),
156 | left,
157 | top + (tl.p - tl.a - tl.b),
158 | left + tl.d,
159 | top + (tl.p - tl.a - tl.b - tl.c),
160 | )
161 | ..arcTo(
162 | Rect.fromCircle(
163 | center: Offset(left + tl.radius, top + tl.radius),
164 | radius: tl.radius),
165 | (180 + tl.angleBezier).toRadian(),
166 | (90 - tl.angleBezier * 2).toRadian(),
167 | false,
168 | )
169 | ..cubicTo(
170 | left + (tl.p - tl.a - tl.b),
171 | top,
172 | left + (tl.p - tl.a),
173 | top,
174 | left + min(width / 2, tl.p),
175 | top,
176 | );
177 |
178 | path.close();
179 | }
180 | return path;
181 | }
182 |
183 | @override
184 | Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
185 | return getPath(borderRadius.resolve(textDirection).toRRect(rect));
186 | }
187 |
188 | @override
189 | void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
190 | if (rect.isEmpty) return;
191 | switch (side.style) {
192 | case BorderStyle.none:
193 | break;
194 | case BorderStyle.solid:
195 | final Path path = getPath(borderRadius
196 | .resolve(textDirection)
197 | .toRRect(rect)
198 | .deflate(side.width / 2));
199 | final Paint paint = side.toPaint()..isAntiAlias = true;
200 | canvas.drawPath(path, paint);
201 | break;
202 | }
203 | }
204 |
205 | @override
206 | ShapeBorder scale(double t) {
207 | return SmoothRectangleBorder(
208 | borderRadius: borderRadius * t,
209 | side: side.scale(t),
210 | );
211 | }
212 |
213 | @override
214 | ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
215 | if (a is SmoothRectangleBorder) {
216 | return SmoothRectangleBorder(
217 | side: BorderSide.lerp(a.side, side, t),
218 | borderRadius:
219 | BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
220 | smoothness: lerpDouble(a.smoothness, smoothness, t)!,
221 | );
222 | }
223 | return super.lerpFrom(a, t);
224 | }
225 |
226 | @override
227 | ShapeBorder? lerpTo(ShapeBorder? b, double t) {
228 | if (b is SmoothRectangleBorder) {
229 | return SmoothRectangleBorder(
230 | side: BorderSide.lerp(side, b.side, t),
231 | borderRadius:
232 | BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
233 | smoothness: lerpDouble(smoothness, b.smoothness, t)!,
234 | );
235 | }
236 | return super.lerpTo(b, t);
237 | }
238 |
239 | @override
240 | SmoothRectangleBorder copyWith(
241 | {BorderSide? side,
242 | BorderRadiusGeometry? borderRadius,
243 | double? smoothness}) {
244 | return SmoothRectangleBorder(
245 | borderRadius: borderRadius ?? this.borderRadius,
246 | side: side ?? this.side,
247 | smoothness: smoothness ?? this.smoothness,
248 | );
249 | }
250 |
251 | @override
252 | int get hashCode {
253 | return Object.hash(
254 | smoothness,
255 | borderRadius,
256 | side,
257 | );
258 | }
259 |
260 | @override
261 | bool operator ==(Object other) {
262 | if (identical(this, other)) return true;
263 | if (other.runtimeType != runtimeType) return false;
264 | return other is SmoothRectangleBorder &&
265 | other.smoothness == smoothness &&
266 | other.borderRadius == borderRadius &&
267 | other.side == side;
268 | }
269 | }
270 |
271 | extension _Math on double {
272 | double toRadian() => this * pi / 180;
273 | }
274 |
275 | class Corner {
276 | late double angleBezier;
277 | late double angleCircle;
278 | late double a;
279 | late double b;
280 | late double c;
281 | late double d;
282 | late double p;
283 | late double radius;
284 | late double shortestSide;
285 |
286 | Corner(RRect rrect, CornerLocation location, double smoothness) {
287 | if (smoothness > 1) smoothness = 1;
288 | shortestSide = rrect.shortestSide;
289 |
290 | radius = _getRadius(rrect, location);
291 |
292 | p = min(shortestSide / 2, (1 + smoothness) * radius);
293 |
294 | if (radius > shortestSide / 4) {
295 | var changePercentage = (radius - shortestSide / 4) / (shortestSide / 4);
296 | angleCircle = 90 * (1 - smoothness * (1 - changePercentage));
297 | angleBezier = 45 * smoothness * (1 - changePercentage);
298 | } else {
299 | angleCircle = 90 * (1 - smoothness);
300 | angleBezier = 45 * smoothness;
301 | }
302 |
303 | var dToC = tan(angleBezier.toRadian());
304 | var longest = radius * tan(angleBezier.toRadian() / 2);
305 | var l = sin(angleCircle.toRadian() / 2) * radius * pow(2, 0.5);
306 | c = longest * cos(angleBezier.toRadian());
307 | d = c * dToC;
308 | b = ((p - l) - (1 + dToC) * c) / 3;
309 | a = 2 * b;
310 | }
311 |
312 | double _getRadius(RRect rrect, CornerLocation location) {
313 | double radiusX, radiusY;
314 | switch (location) {
315 | case CornerLocation.tl:
316 | radiusX = rrect.tlRadiusX;
317 | radiusY = rrect.tlRadiusY;
318 | break;
319 | case CornerLocation.tr:
320 | radiusX = rrect.trRadiusX;
321 | radiusY = rrect.trRadiusY;
322 | break;
323 | case CornerLocation.bl:
324 | radiusX = rrect.blRadiusX;
325 | radiusY = rrect.blRadiusY;
326 | break;
327 | case CornerLocation.br:
328 | radiusX = rrect.brRadiusX;
329 | radiusY = rrect.brRadiusY;
330 | break;
331 | }
332 | var radius = max(0.0, min(radiusX, radiusY));
333 | return min(radius, shortestSide / 2);
334 | }
335 | }
336 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: smooth_corner
2 | description: A rectangular border with variable smoothness imitated from Figma.
3 | version: 1.1.1
4 | repository: https://github.com/howshea/smooth_corner
5 |
6 | environment:
7 | sdk: ^3.6.0
8 | flutter: ">=1.17.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://dart.dev/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 |
--------------------------------------------------------------------------------
/test/smooth_corner_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 |
3 | void main() {
4 | test('adds one to input values', () {});
5 | }
6 |
--------------------------------------------------------------------------------