├── .gitignore ├── .vscode └── launch.json ├── CHANGELOG.md ├── LICENSE ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── flutter_cupertino_settings_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── lib │ └── main.dart ├── pubspec.yaml └── test │ └── widget_test.dart ├── flutter_cupertino_settings.iml ├── lib ├── flutter_cupertino_settings.dart └── widgets │ ├── button.dart │ ├── control.dart │ ├── description.dart │ ├── header.dart │ ├── link.dart │ ├── secret.dart │ ├── selection.dart │ ├── spacer.dart │ └── widget.dart ├── pubspec.yaml ├── readme.md └── screenshots └── scr1.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .idea 4 | .packages 5 | .pub/ 6 | .dart_tool 7 | .vscode 8 | packages 9 | ios/ 10 | pubspec.lock -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Flutter", 9 | "type": "dart", 10 | "request": "launch", 11 | "program": "example/lib/main.dart" 12 | } 13 | 14 | ] 15 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.5.0] 2 | * NULL safety 3 | * Allow a scroll controller to be specified 4 | * Support subtitle for selection lists 5 | 6 | ## [0.4.0] 7 | * Allow to use library in web #26 8 | * Update cupertino_icons to 1.0.0 #24 9 | * Remove state from CSSelection widget #22 10 | 11 | ## [0.3.0] - iOS 13 Support 12 | 13 | * added support for the different types of CSLink based on UITableViewCell 14 | * use CupertinoDynamicColors to match the official DynamicColors added with iOS13 15 | * use CupertinoColors and CupertinoIcons instead of Material one 16 | * added HapticFeedback to CSSelection 17 | * updated example 18 | * bump Flutter Version to 1.12.13-hotfix.5 19 | 20 | ## [0.2.0] - Smaller changes and fixes 21 | 22 | ## [0.1.0] - Dark Mode Support 23 | 24 | * Dark Mode Support 25 | * Support for different font sizes 26 | * Added Example App 27 | * Added Optional Shrink Wrap 28 | * Includes SafeArea Wrapper 29 | 30 | ## [0.0.9] - Dart 2.1.0 Support 31 | 32 | * Dart 2.1.0 Support Added 33 | 34 | ## [0.0.1] - TODO: Add release date. 35 | 36 | * TODO: Describe initial release. 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Matthias Rupp 2 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 3 | 4 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # Visual Studio Code related 19 | .vscode/ 20 | 21 | # Flutter/Dart/Pub related 22 | **/doc/api/ 23 | .dart_tool/ 24 | .flutter-plugins 25 | .packages 26 | .pub-cache/ 27 | .pub/ 28 | /build/ 29 | 30 | # Android related 31 | **/android/**/gradle-wrapper.jar 32 | **/android/.gradle 33 | **/android/captures/ 34 | **/android/gradlew 35 | **/android/gradlew.bat 36 | **/android/local.properties 37 | **/android/**/GeneratedPluginRegistrant.java 38 | 39 | # iOS/XCode related 40 | **/ios/**/*.mode1v3 41 | **/ios/**/*.mode2v3 42 | **/ios/**/*.moved-aside 43 | **/ios/**/*.pbxuser 44 | **/ios/**/*.perspectivev3 45 | **/ios/**/*sync/ 46 | **/ios/**/.sconsign.dblite 47 | **/ios/**/.tags* 48 | **/ios/**/.vagrant/ 49 | **/ios/**/DerivedData/ 50 | **/ios/**/Icon? 51 | **/ios/**/Pods/ 52 | **/ios/**/.symlinks/ 53 | **/ios/**/profile 54 | **/ios/**/xcuserdata 55 | **/ios/.generated/ 56 | **/ios/Flutter/App.framework 57 | **/ios/Flutter/Flutter.framework 58 | **/ios/Flutter/Generated.xcconfig 59 | **/ios/Flutter/app.flx 60 | **/ios/Flutter/app.zip 61 | **/ios/Flutter/flutter_assets/ 62 | **/ios/ServiceDefinitions.json 63 | **/ios/Runner/GeneratedPluginRegistrant.* 64 | 65 | # Exceptions to above rules. 66 | !**/ios/**/default.mode1v3 67 | !**/ios/**/default.mode2v3 68 | !**/ios/**/default.pbxuser 69 | !**/ios/**/default.perspectivev3 70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 71 | -------------------------------------------------------------------------------- /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: 035e0765cc575c3b455689c2402cce073d564fce 8 | channel: master 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_cupertino_settings_example 2 | 3 | Demonstrates how to use the flutter_cupertino_settings plugin. 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.io/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.io/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 28 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.flutter_cupertino_settings_example" 42 | minSdkVersion 16 43 | targetSdkVersion 28 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | testImplementation 'junit:junit:4.12' 65 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 66 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 67 | } 68 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 13 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/flutter_cupertino_settings_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.flutter_cupertino_settings_example 2 | 3 | import android.os.Bundle 4 | 5 | import io.flutter.app.FlutterActivity 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | GeneratedPluginRegistrant.registerWith(this) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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/matthinc/flutter_cupertino_settings/5edb0476d73ecfbc1857d6f9f9eddaf507344f5e/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/matthinc/flutter_cupertino_settings/5edb0476d73ecfbc1857d6f9f9eddaf507344f5e/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/matthinc/flutter_cupertino_settings/5edb0476d73ecfbc1857d6f9f9eddaf507344f5e/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/matthinc/flutter_cupertino_settings/5edb0476d73ecfbc1857d6f9f9eddaf507344f5e/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/matthinc/flutter_cupertino_settings/5edb0476d73ecfbc1857d6f9f9eddaf507344f5e/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.2.71' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.2.1' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 4 | import 'package:flutter_cupertino_settings/flutter_cupertino_settings.dart'; 5 | 6 | void main() => runApp(MyApp()); 7 | 8 | class MyApp extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | return CupertinoApp( 12 | theme: const CupertinoThemeData( 13 | brightness: Brightness.light, 14 | ), 15 | home: HomeScreen(), 16 | ); 17 | } 18 | } 19 | 20 | class HomeScreen extends StatefulWidget { 21 | @override 22 | _HomeScreenState createState() => _HomeScreenState(); 23 | } 24 | 25 | class _HomeScreenState extends State { 26 | double _slider = 0.5; 27 | bool _switch = false; 28 | int _index = 0; 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return CupertinoPageScaffold( 33 | navigationBar: const CupertinoNavigationBar( 34 | middle: Text('Cupertino Settings'), 35 | ), 36 | child: CupertinoSettings( 37 | items: [ 38 | const CSHeader('Brightness'), 39 | CSWidget( 40 | CupertinoSlider( 41 | value: _slider, 42 | onChanged: (double value) => setState(() => _slider = value), 43 | ), 44 | style: CSWidgetStyle( 45 | icon: Icon(FontAwesomeIcons.sun), 46 | ), 47 | addPaddingToBorder: true, 48 | ), 49 | CSControl( 50 | nameWidget: Text('Auto brightness'), 51 | contentWidget: CupertinoSwitch( 52 | value: _switch, 53 | onChanged: (bool value) => setState(() => _switch = value), 54 | ), 55 | style: CSWidgetStyle( 56 | icon: Icon(FontAwesomeIcons.sun), 57 | ), 58 | addPaddingToBorder: false, 59 | ), 60 | const CSHeader('Selection'), 61 | CSSelection( 62 | items: const >[ 63 | CSSelectionItem(text: 'Day mode', value: 0), 64 | CSSelectionItem(text: 'Night mode', value: 1, subtitle: 'Subtitle'), 65 | ], 66 | onSelected: (value) => setState(() => _index = value), 67 | currentSelection: _index, 68 | ), 69 | const CSDescription( 70 | 'Using Night mode extends battery life on devices with OLED display', 71 | ), 72 | const CSHeader(""), 73 | CSControl( 74 | nameWidget: Text('Loading...'), 75 | contentWidget: const CupertinoActivityIndicator(), 76 | ), 77 | CSButton(CSButtonType.DEFAULT, "Licenses", () { 78 | print("It works!"); 79 | }), 80 | const CSHeader(""), 81 | CSSecret("Your Password", "Hello World"), 82 | CSButton(CSButtonType.DESTRUCTIVE, "Delete all data", () {}), 83 | ], 84 | ), 85 | ); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_cupertino_settings_example 2 | description: Demonstrates how to use the flutter_cupertino_settings plugin. 3 | publish_to: 'none' 4 | 5 | environment: 6 | sdk: ">=2.12.0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | 12 | # The following adds the Cupertino Icons font to your application. 13 | # Use with the CupertinoIcons class for iOS style icons. 14 | cupertino_icons: ^1.0.0 15 | # cupertino_icons: 16 | # git: 17 | # url: https://github.com/flutter/cupertino_icons.git 18 | font_awesome_flutter: ^9.0.0 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter 23 | 24 | flutter_cupertino_settings: 25 | path: ../ 26 | 27 | # For information on the generic Dart part of this file, see the 28 | # following page: https://www.dartlang.org/tools/pub/pubspec 29 | 30 | # The following section is specific to Flutter. 31 | flutter: 32 | 33 | # The following line ensures that the Material Icons font is 34 | # included with your application, so that you can use the icons in 35 | # the material Icons class. 36 | uses-material-design: true 37 | 38 | # To add assets to your application, add an assets section, like this: 39 | # assets: 40 | # - images/a_dot_burr.jpeg 41 | # - images/a_dot_ham.jpeg 42 | 43 | # An image asset can refer to one or more resolution-specific "variants", see 44 | # https://flutter.io/assets-and-images/#resolution-aware. 45 | 46 | # For details regarding adding assets from package dependencies, see 47 | # https://flutter.io/assets-and-images/#from-packages 48 | 49 | # To add custom fonts to your application, add a fonts section here, 50 | # in this "flutter" section. Each entry in this list should have a 51 | # "family" key with the font family name, and a "fonts" key with a 52 | # list giving the asset and other descriptors for the font. For 53 | # example: 54 | # fonts: 55 | # - family: Schyler 56 | # fonts: 57 | # - asset: fonts/Schyler-Regular.ttf 58 | # - asset: fonts/Schyler-Italic.ttf 59 | # style: italic 60 | # - family: Trajan Pro 61 | # fonts: 62 | # - asset: fonts/TrajanPro.ttf 63 | # - asset: fonts/TrajanPro_Bold.ttf 64 | # weight: 700 65 | # 66 | # For details regarding fonts from package dependencies, 67 | # see https://flutter.io/custom-fonts/#from-packages 68 | -------------------------------------------------------------------------------- /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:flutter_cupertino_settings_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && 22 | widget.data.startsWith('Running on:'), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /flutter_cupertino_settings.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /lib/flutter_cupertino_settings.dart: -------------------------------------------------------------------------------- 1 | library flutter_cupertino_settings; 2 | 3 | import 'dart:io'; 4 | 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:flutter/material.dart' show Theme; 7 | import 'package:flutter/cupertino.dart'; 8 | import 'package:flutter/rendering.dart'; 9 | import 'package:flutter/services.dart'; 10 | 11 | part 'widgets/button.dart'; 12 | part 'widgets/control.dart'; 13 | part 'widgets/description.dart'; 14 | part 'widgets/header.dart'; 15 | part 'widgets/link.dart'; 16 | part 'widgets/secret.dart'; 17 | part 'widgets/selection.dart'; 18 | part 'widgets/spacer.dart'; 19 | part 'widgets/widget.dart'; 20 | 21 | const double CS_ITEM_HEIGHT = 50.0; 22 | const EdgeInsets CS_ITEM_PADDING = 23 | EdgeInsets.symmetric(horizontal: 10, vertical: 1); 24 | const double CS_TITLE_FONT_SIZE = 16.0; 25 | const double CS_SUBTITLE_FONT_SIZE = 11.0; 26 | const double CS_HEADER_FONT_SIZE = 14.0; 27 | const double CS_DESCRIPTION_FONT_SIZE = 13.0; 28 | const double CS_ITEM_NAME_SIZE = 15.0; 29 | const EdgeInsets CS_ICON_PADDING = EdgeInsets.only( 30 | right: 10.0, 31 | left: 4.0, 32 | ); 33 | const CSWidgetStyle CS_DEFAULT_STYLE = CSWidgetStyle(); 34 | const double CS_CHECK_SIZE = 20.0; 35 | const double CS_CHEVRON_SIZE = 17.0; 36 | 37 | /// Event for [CSSelection] 38 | typedef void SelectionCallback(int selected); 39 | 40 | TextStyle basicTextStyle(BuildContext context) => 41 | (kIsWeb 42 | ? Theme.of(context).textTheme.subtitle2 43 | : Platform.isIOS 44 | ? CupertinoTheme.of(context).textTheme.textStyle 45 | : Theme.of(context).textTheme.subtitle2) ?? 46 | TextStyle(); 47 | 48 | class CupertinoSettings extends StatelessWidget { 49 | final List items; 50 | final bool shrinkWrap; 51 | final ScrollController? scrollController; 52 | 53 | const CupertinoSettings({ 54 | required this.items, 55 | this.scrollController, 56 | this.shrinkWrap = false, 57 | }); 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | return Container( 62 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 63 | child: SafeArea( 64 | bottom: false, 65 | child: shrinkWrap 66 | ? ListView.builder( 67 | shrinkWrap: shrinkWrap, 68 | itemCount: items.length, 69 | controller: scrollController, 70 | itemBuilder: (BuildContext context, int index) => items[index], 71 | ) 72 | : Column( 73 | children: [ 74 | Expanded( 75 | child: ListView.builder( 76 | shrinkWrap: shrinkWrap, 77 | itemCount: items.length, 78 | controller: scrollController, 79 | itemBuilder: (BuildContext context, int index) => 80 | items[index], 81 | ), 82 | ), 83 | ], 84 | ), 85 | ), 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lib/widgets/button.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// A button-cell inside [CupertinoSettings] 4 | /// 3 different types are available (they only affect the design): 5 | /// [CSButtonType.DESTRUCTIVE] Red and centered 6 | /// [CSButtonType.DEFAULT] Blue and left aligned 7 | /// [CSButtonType.DEFAULT_CENTER] Blue and centered 8 | /// Provides the correct paddings and text properties 9 | /// 10 | /// It is quite complex: 11 | /// 12 | /// -- Widget 13 | /// |- Flex 14 | /// |- Expand 15 | /// |- CupertinoButton 16 | /// |- Container (<--- For text-alignment) 17 | /// |- Text 18 | /// 19 | /// This "hack" is mandatory to archive that... 20 | /// 1) The button can be aligned 21 | /// 2) The entire row is touch-sensitive 22 | class CSButton extends CSWidget { 23 | final CSButtonType buttonType; 24 | final String text; 25 | final VoidCallback pressed; 26 | final double fontSize; 27 | 28 | CSButton( 29 | this.buttonType, 30 | this.text, 31 | this.pressed, { 32 | CSWidgetStyle style = CS_DEFAULT_STYLE, 33 | this.fontSize = CS_TITLE_FONT_SIZE, 34 | }) : super( 35 | Flex( 36 | direction: Axis.horizontal, 37 | children: [ 38 | Expanded( 39 | child: CupertinoButton( 40 | padding: EdgeInsets.zero, 41 | onPressed: pressed, 42 | child: Container( 43 | alignment: buttonType.alignment, 44 | child: Text( 45 | text, 46 | style: TextStyle( 47 | color: buttonType.color, 48 | fontSize: fontSize, 49 | ), 50 | ), 51 | ), 52 | ), 53 | ), 54 | ], 55 | ), 56 | style: style, 57 | ); 58 | } 59 | 60 | /// Defines different types for [CSButton] 61 | /// Specifies color and alignment 62 | class CSButtonType { 63 | static const CSButtonType DESTRUCTIVE = CSButtonType( 64 | CupertinoColors.destructiveRed, 65 | AlignmentDirectional.center, 66 | ); 67 | static const CSButtonType DEFAULT = CSButtonType( 68 | CupertinoColors.systemBlue, 69 | AlignmentDirectional.centerStart, 70 | ); 71 | static const CSButtonType DEFAULT_CENTER = CSButtonType( 72 | CupertinoColors.systemBlue, 73 | AlignmentDirectional.center, 74 | ); 75 | 76 | final Color color; 77 | final AlignmentGeometry alignment; 78 | 79 | const CSButtonType(this.color, this.alignment); 80 | } 81 | -------------------------------------------------------------------------------- /lib/widgets/control.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// A title [name] in combination with any widget [contentWidget] 4 | /// extends [CSWidget] 5 | /// Provides the correct paddings and text properties 6 | class CSControl extends CSWidget { 7 | final Widget? nameWidget; 8 | final Widget? contentWidget; 9 | final double fontSize; 10 | 11 | CSControl({ 12 | this.nameWidget, 13 | this.contentWidget, 14 | CSWidgetStyle style = CS_DEFAULT_STYLE, 15 | this.fontSize = CS_TITLE_FONT_SIZE, 16 | bool addPaddingToBorder = true, 17 | }) : super( 18 | _ControlWidget( 19 | fontSize: fontSize, 20 | contentWidget: contentWidget, 21 | nameWidget: nameWidget, 22 | ), 23 | style: style, 24 | addPaddingToBorder: addPaddingToBorder, 25 | ); 26 | } 27 | 28 | class _ControlWidget extends StatelessWidget { 29 | final Widget? nameWidget; 30 | final Widget? contentWidget; 31 | final double? fontSize; 32 | 33 | const _ControlWidget({ 34 | Key? key, 35 | this.fontSize, 36 | this.contentWidget, 37 | this.nameWidget, 38 | }) : super(key: key); 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return DefaultTextStyle( 43 | style: basicTextStyle(context).copyWith( 44 | color: CupertinoColors.label.resolveFrom(context), 45 | fontSize: fontSize, 46 | ), 47 | child: Row( 48 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 49 | children: [ 50 | if (nameWidget != null) nameWidget!, 51 | if (contentWidget != null) contentWidget!, 52 | ], 53 | ), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/widgets/description.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | class CSDescription extends StatelessWidget { 4 | final String description; 5 | 6 | const CSDescription(this.description); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Container( 11 | padding: const EdgeInsets.fromLTRB(10, 7.5, 5, 5), 12 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 13 | child: Text( 14 | description, 15 | style: basicTextStyle(context).copyWith( 16 | color: CupertinoColors.secondaryLabel.resolveFrom(context), 17 | fontSize: CS_DESCRIPTION_FONT_SIZE, 18 | height: 1.1, 19 | ), 20 | ), 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/widgets/header.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// This widgets is used as a grouping separator. 4 | /// The [title] attribute is optional. 5 | class CSHeader extends StatelessWidget { 6 | final String title; 7 | 8 | const CSHeader(this.title); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return Container( 13 | padding: const EdgeInsets.only(left: 10.0, top: 30.0, bottom: 5.0), 14 | decoration: BoxDecoration( 15 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 16 | border: Border( 17 | bottom: BorderSide( 18 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 19 | ), 20 | ), 21 | ), 22 | child: Text( 23 | title.toUpperCase(), 24 | style: basicTextStyle(context).copyWith( 25 | color: CupertinoColors.secondaryLabel.resolveFrom(context), 26 | fontSize: CS_HEADER_FONT_SIZE, 27 | ), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/widgets/link.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// Provides a button for navigation 4 | class CSLink extends StatelessWidget { 5 | final String title; 6 | final String? subtitle; 7 | final String? detail; 8 | final VoidCallback? onPressed; 9 | final double titleFontSize; 10 | final double subTitleFontSize; 11 | final CSWidgetStyle style; 12 | final bool addPaddingToBorder; 13 | final bool showTopBorder; 14 | final Widget? trailing; 15 | final CellType cellType; 16 | 17 | const CSLink({ 18 | required this.title, 19 | this.onPressed, 20 | this.subtitle, 21 | this.detail, 22 | this.style = CS_DEFAULT_STYLE, 23 | this.titleFontSize = CS_TITLE_FONT_SIZE, 24 | this.subTitleFontSize = CS_SUBTITLE_FONT_SIZE, 25 | this.addPaddingToBorder = true, 26 | this.showTopBorder = false, 27 | this.trailing, 28 | this.cellType = CellType.defaultStyle, 29 | }); 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | final showSubtitle = (cellType == CellType.subtitleDetailStyle || 34 | cellType == CellType.subtitleStyle) && 35 | subtitle != null && 36 | subtitle!.isNotEmpty; 37 | final showDetail = (cellType == CellType.subtitleDetailStyle || 38 | cellType == CellType.detailRightStyle) && 39 | detail != null && 40 | detail!.isNotEmpty; 41 | 42 | return CSWidget( 43 | CupertinoButton( 44 | padding: EdgeInsets.zero, 45 | onPressed: onPressed, 46 | child: Row( 47 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 48 | crossAxisAlignment: CrossAxisAlignment.center, 49 | children: [ 50 | Expanded( 51 | child: Column( 52 | crossAxisAlignment: CrossAxisAlignment.start, 53 | mainAxisAlignment: MainAxisAlignment.center, 54 | mainAxisSize: MainAxisSize.min, 55 | children: [ 56 | Text( 57 | title, 58 | style: basicTextStyle(context).copyWith( 59 | color: CupertinoColors.label.resolveFrom(context), 60 | fontSize: titleFontSize, 61 | ), 62 | maxLines: 2, 63 | overflow: TextOverflow.ellipsis, 64 | ), 65 | if (showSubtitle) const SizedBox(height: 2), 66 | if (showSubtitle) 67 | Text( 68 | subtitle!, 69 | style: basicTextStyle(context).copyWith( 70 | color: 71 | CupertinoColors.secondaryLabel.resolveFrom(context), 72 | fontSize: subTitleFontSize, 73 | fontWeight: FontWeight.w400, 74 | ), 75 | maxLines: 1, 76 | overflow: TextOverflow.clip, 77 | ), 78 | ], 79 | ), 80 | ), 81 | if (showDetail) ...[ 82 | Text( 83 | detail!, 84 | style: basicTextStyle(context).copyWith( 85 | color: CupertinoColors.secondaryLabel.resolveFrom(context), 86 | fontSize: titleFontSize, 87 | ), 88 | maxLines: 1, 89 | overflow: TextOverflow.clip, 90 | ), 91 | const SizedBox(width: 4), 92 | ], 93 | Padding( 94 | padding: const EdgeInsets.only(left: 1.0, right: 2.0), 95 | child: trailing ?? 96 | Icon( 97 | CupertinoIcons.right_chevron, 98 | color: CupertinoColors.secondaryLabel 99 | .resolveFrom(context) 100 | .withOpacity(0.4), 101 | size: CS_CHEVRON_SIZE, 102 | ), 103 | ), 104 | ], 105 | ), 106 | ), 107 | style: style, 108 | addPaddingToBorder: addPaddingToBorder, 109 | showTopBorder: showTopBorder, 110 | ); 111 | } 112 | } 113 | 114 | enum CellType { 115 | /// Default Style with optional widget on left side and left-aligned title 116 | defaultStyle, 117 | 118 | /// Left-aligned title and left-aligned subtitle below 119 | subtitleStyle, 120 | 121 | /// Left-aligned title, left-aligned subtitle below and right-aligned detail 122 | subtitleDetailStyle, 123 | 124 | /// Left-aligned title and right-aligned detail 125 | detailRightStyle, 126 | 127 | /// right-aligned title and left-aligned detail 128 | detailLeftStyle, 129 | } 130 | -------------------------------------------------------------------------------- /lib/widgets/secret.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// Provides a button for navigation 4 | class CSSecret extends StatefulWidget { 5 | final String text; 6 | final String secret; 7 | final double fontSize; 8 | final CSWidgetStyle style; 9 | final bool addPaddingToBorder; 10 | final String obscuringCharacter; 11 | 12 | CSSecret( 13 | this.text, 14 | this.secret, { 15 | this.style = CS_DEFAULT_STYLE, 16 | this.fontSize = CS_TITLE_FONT_SIZE, 17 | this.addPaddingToBorder = true, 18 | this.obscuringCharacter = '•', 19 | }); 20 | 21 | @override 22 | _CSSecretState createState() => _CSSecretState(); 23 | } 24 | 25 | class _CSSecretState extends State { 26 | bool _show = false; 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return CSWidget( 31 | DefaultTextStyle( 32 | style: basicTextStyle(context).copyWith( 33 | color: CupertinoColors.label.resolveFrom(context), 34 | fontSize: widget.fontSize, 35 | ), 36 | child: Row( 37 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 38 | children: [ 39 | Text(widget.text), 40 | Row( 41 | children: [ 42 | Text( 43 | _show ? widget.secret : widget.obscuringCharacter * widget.secret.length, 44 | ), 45 | CupertinoButton( 46 | child: Icon( 47 | CupertinoIcons.eye_solid, 48 | size: CS_CHECK_SIZE, 49 | ), 50 | onPressed: () => setState(() => _show = !_show), 51 | ), 52 | ], 53 | ), 54 | ], 55 | ), 56 | ), 57 | style: widget.style, 58 | addPaddingToBorder: widget.addPaddingToBorder, 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/widgets/selection.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// A selection view 4 | /// Allows to select between multiple items 5 | /// Every item is represented by a String 6 | /// 7 | /// If an item is selected, onSelected is called with its index 8 | /// 9 | /// eg: 10 | /// items = ["hello","world","flutter"] 11 | /// select "world" 12 | /// 13 | /// onSelected(1) 14 | 15 | class CSSelection extends StatelessWidget { 16 | final List> items; 17 | final void Function(T selected) onSelected; 18 | final T? currentSelection; 19 | final double fontSize; 20 | 21 | const CSSelection({ 22 | required this.items, 23 | required this.onSelected, 24 | this.currentSelection, 25 | this.fontSize = CS_TITLE_FONT_SIZE, 26 | }); 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Column( 31 | children: items.map((item) => createItem(context, item)).toList(), 32 | ); 33 | } 34 | 35 | Widget createItem(BuildContext context, CSSelectionItem item) { 36 | final text = Text(item.text, 37 | style: TextStyle( 38 | color: CupertinoColors.label.resolveFrom(context), 39 | fontSize: fontSize, 40 | )); 41 | final textWidget = item.subtitle == null 42 | ? text 43 | : Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ 44 | text, 45 | SizedBox(height: 2), 46 | Text(item.subtitle!, 47 | style: basicTextStyle(context).copyWith( 48 | color: CupertinoColors.secondaryLabel.resolveFrom(context), 49 | fontSize: CS_HEADER_FONT_SIZE)) 50 | ]); 51 | return CSWidget( 52 | CupertinoButton( 53 | onPressed: () { 54 | HapticFeedback.selectionClick(); 55 | onSelected(item.value); 56 | }, 57 | pressedOpacity: 1.0, 58 | padding: const EdgeInsets.fromLTRB(4, 8, 2, 8), 59 | child: Row( 60 | crossAxisAlignment: CrossAxisAlignment.center, 61 | children: [ 62 | Expanded(child: textWidget), 63 | Padding( 64 | padding: const EdgeInsets.only(right: 5.0), 65 | child: Icon( 66 | CupertinoIcons.check_mark, 67 | color: item.value == currentSelection 68 | ? CupertinoColors.activeBlue 69 | : const Color(0x00000000), 70 | size: CS_CHECK_SIZE, 71 | ), 72 | ), 73 | ], 74 | ), 75 | ), 76 | addPaddingToBorder: items.last != item, 77 | showTopBorder: item.showTopBorder, 78 | ); 79 | } 80 | } 81 | 82 | class CSSelectionItem { 83 | final T value; 84 | final String text; 85 | final String? subtitle; 86 | final bool showTopBorder; 87 | 88 | const CSSelectionItem({ 89 | required this.value, 90 | required this.text, 91 | this.subtitle, 92 | this.showTopBorder = false, 93 | }); 94 | } 95 | -------------------------------------------------------------------------------- /lib/widgets/spacer.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | class CSSpacer extends StatelessWidget { 4 | final bool showBorder; 5 | 6 | const CSSpacer({ 7 | Key? key, 8 | this.showBorder = true, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Container( 14 | padding: const EdgeInsets.only(left: 10.0, top: 20.0, bottom: 5.0), 15 | decoration: BoxDecoration( 16 | color: CupertinoColors.systemGroupedBackground.resolveFrom(context), 17 | border: Border( 18 | bottom: showBorder 19 | ? BorderSide( 20 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 21 | ) 22 | : BorderSide.none, 23 | ), 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/widgets/widget.dart: -------------------------------------------------------------------------------- 1 | part of flutter_cupertino_settings; 2 | 3 | /// Used to display a widget of any kind in [CupertinoSettings] 4 | /// It provices the correct height, color and border to create the intended look 5 | /// The optional [alignment] attribute allows to specify the aligment inside the container 6 | /// The optional [style] attribute allows to specify a style (e.g. an Icon) 7 | class CSWidget extends StatelessWidget { 8 | final Widget widget; 9 | final AlignmentGeometry? alignment; 10 | final double height; 11 | final CSWidgetStyle style; 12 | final bool addPaddingToBorder; 13 | final bool showTopBorder; 14 | 15 | const CSWidget( 16 | this.widget, { 17 | this.alignment, 18 | this.height = CS_ITEM_HEIGHT, 19 | this.style = CS_DEFAULT_STYLE, 20 | this.addPaddingToBorder = false, 21 | this.showTopBorder = false, 22 | }); 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | Widget child; 27 | EdgeInsets padding; 28 | 29 | //style.icon 30 | if (style.icon != null) { 31 | padding = CS_ICON_PADDING; 32 | child = Row( 33 | children: [ 34 | Container( 35 | padding: CS_ICON_PADDING, 36 | child: style.icon, 37 | ), 38 | Expanded(child: widget) 39 | ], 40 | ); 41 | } else { 42 | child = widget; 43 | padding = CS_ITEM_PADDING; 44 | } 45 | 46 | return Container( 47 | alignment: alignment, 48 | decoration: BoxDecoration( 49 | color: CupertinoColors.secondarySystemGroupedBackground 50 | .resolveFrom(context), 51 | border: Border( 52 | top: showTopBorder 53 | ? BorderSide( 54 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 55 | ) 56 | : BorderSide.none, 57 | ), 58 | ), 59 | constraints: const BoxConstraints(minHeight: 42), 60 | // height: height, 61 | padding: EdgeInsets.only( 62 | left: addPaddingToBorder ? padding.left : 0, 63 | ), 64 | child: Container( 65 | padding: padding.copyWith( 66 | left: addPaddingToBorder ? 2 : padding.left + 2, 67 | ), 68 | decoration: BoxDecoration( 69 | border: Border( 70 | bottom: BorderSide( 71 | color: CupertinoColors.opaqueSeparator.resolveFrom(context), 72 | ), 73 | ), 74 | ), 75 | child: child, 76 | ), 77 | ); 78 | } 79 | } 80 | 81 | /// Defines style attributes that can be applied to every [CSWidget] 82 | class CSWidgetStyle { 83 | final Icon? icon; 84 | 85 | const CSWidgetStyle({this.icon}); 86 | } 87 | 88 | enum ItemType { single, list, listLast } 89 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_cupertino_settings 2 | description: Flutter widget to create an iOS settings-table (static TableView). 3 | version: 0.5.0 4 | homepage: https://github.com/matthinc/flutter_cupertino_settings 5 | 6 | environment: 7 | sdk: ">=2.12.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | cupertino_icons: ^1.0.0 13 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # flutter_cupertino_settings 2 | 3 | [![Pub badge](https://img.shields.io/pub/v/flutter_cupertino_settings.svg)](https://pub.dartlang.org/packages/flutter_cupertino_settings) ![](https://img.shields.io/github/license/matthinc/flutter_cupertino_settings.svg) 4 | 5 | A Flutter widget to create an iOS settings-table (static TableView). 6 | 7 | ```dart 8 | 9 | import 'package:flutter_cupertino_settings/flutter_cupertino_settings.dart'; 10 | 11 | CSWidgetStyle brightnessStyle = const CSWidgetStyle( 12 | icon: const Icon(Icons.brightness_medium, color: Colors.black54) 13 | ); 14 | 15 | CupertinoSettings( 16 | items: [ 17 | const CSHeader('Brightness'), 18 | CSWidget(CupertinoSlider(value: 0.5), style: brightnessStyle), 19 | CSControl( 20 | nameWidget: Text('Auto brightness'), 21 | contentWidget: CupertinoSwitch(value: true), 22 | style: brightnessStyle, 23 | ), 24 | CSHeader('Selection'), 25 | CSSelection( 26 | items: const >[ 27 | CSSelectionItem(text: 'Day mode', value: 0), 28 | CSSelectionItem(text: 'Night mode', value: 1), 29 | ], 30 | onSelected: (index) {print(index);}, 31 | currentSelection: 0, 32 | ), 33 | CSDescription('Using Night mode extends battery life on devices with OLED display',), 34 | const CSHeader(''), 35 | CSControl( 36 | nameWidget: Text('Loading...'), 37 | contentWidget: CupertinoActivityIndicator(), 38 | ), 39 | CSButton(CSButtonType.DEFAULT, "Licenses", (){ print("It works!"); }), 40 | const CSHeader(''), 41 | CSButton(CSButtonType.DESTRUCTIVE, "Delete all data", (){}) 42 | ] 43 | ); 44 | ``` 45 | 46 | ![](screenshots/scr1.png) 47 | 48 | ### Contributors 49 | - Dark theme & example by [AppleEducate](https://github.com/appleeducate) 50 | - CSSecret by [SimonIT](https://github.com/SimonIT) 51 | - iOS 13 support by [Tim Bierbaum](https://github.com/bierbaumtim) 52 | -------------------------------------------------------------------------------- /screenshots/scr1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matthinc/flutter_cupertino_settings/5edb0476d73ecfbc1857d6f9f9eddaf507344f5e/screenshots/scr1.png --------------------------------------------------------------------------------