>:NDEBUG>")
47 | endfunction()
48 |
49 | # Flutter library and tool build rules.
50 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
51 | add_subdirectory(${FLUTTER_MANAGED_DIR})
52 |
53 | # System-level dependencies.
54 | find_package(PkgConfig REQUIRED)
55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
56 |
57 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
58 |
59 | # Define the application target. To change its name, change BINARY_NAME above,
60 | # not the value here, or `flutter run` will no longer work.
61 | #
62 | # Any new source files that you add to the application should be added here.
63 | add_executable(${BINARY_NAME}
64 | "main.cc"
65 | "my_application.cc"
66 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
67 | )
68 |
69 | # Apply the standard set of build settings. This can be removed for applications
70 | # that need different build settings.
71 | apply_standard_settings(${BINARY_NAME})
72 |
73 | # Add dependency libraries. Add any application-specific dependencies here.
74 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
75 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
76 |
77 | # Run the Flutter tool portions of the build. This must not be removed.
78 | add_dependencies(${BINARY_NAME} flutter_assemble)
79 |
80 | # Only the install-generated bundle's copy of the executable will launch
81 | # correctly, since the resources must in the right relative locations. To avoid
82 | # people trying to run the unbundled copy, put it in a subdirectory instead of
83 | # the default top-level location.
84 | set_target_properties(${BINARY_NAME}
85 | PROPERTIES
86 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
87 | )
88 |
89 |
90 | # Generated plugin build rules, which manage building the plugins and adding
91 | # them to the application.
92 | include(flutter/generated_plugins.cmake)
93 |
94 |
95 | # === Installation ===
96 | # By default, "installing" just makes a relocatable bundle in the build
97 | # directory.
98 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
99 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
100 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
101 | endif()
102 |
103 | # Start with a clean build bundle directory every time.
104 | install(CODE "
105 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
106 | " COMPONENT Runtime)
107 |
108 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
109 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
110 |
111 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
112 | COMPONENT Runtime)
113 |
114 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
115 | COMPONENT Runtime)
116 |
117 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
118 | COMPONENT Runtime)
119 |
120 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
121 | install(FILES "${bundled_library}"
122 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
123 | COMPONENT Runtime)
124 | endforeach(bundled_library)
125 |
126 | # Fully re-copy the assets directory on each build to avoid having stale files
127 | # from a previous install.
128 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
129 | install(CODE "
130 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
131 | " COMPONENT Runtime)
132 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
133 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
134 |
135 | # Install the AOT library on non-Debug builds only.
136 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
137 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
138 | COMPONENT Runtime)
139 | endif()
140 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## FlutterSnips.♥
2 |
3 | ## HACKTOBERFEST ♥♥ This year we are opening this repo for hacktoberfest contributions.
4 | Have fun contributing . Please read the Conrtibuting.md file.
5 | 
6 |
7 |
8 | ## AIM :
9 | This platform is created , so as to make a huge library of already builded code , that developers can directly use in their flutter project.
10 | - It will decrease the time to build the projects
11 |
12 | - Extensive Code Library: Access a vast collection of pre-built code snippets covering a wide range of Flutter development scenarios and use cases.
13 |
14 | - Save Development Time: Speed up your development process by leveraging ready-to-use code solutions instead of building everything from scratch.
15 |
16 | - Easy Integration: Seamlessly integrate the code snippets into your Flutter projects with clear instructions and guidelines provided.
17 |
18 | - Search and Discover: Find the right code snippet quickly using powerful search functionality. Search by keywords, categories, or tags to locate relevant code for your specific needs.
19 |
20 | - High-Quality Code: Rest assured that all code snippets have undergone thorough testing and review processes to ensure reliability, efficiency, and adherence to best practices.
21 |
22 | - Open-Source: The platform is open-source, allowing developers to collaborate, contribute, and improve the code snippets for the benefit of the entire community.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | 
32 |
33 |
34 | ## [LIVE LINK](https://fluttersnips.vercel.app/)
35 |
36 | 
37 |
38 |
39 | ## 🛠️ Installation Steps + CONTRIBUTION
40 |
41 |
42 | 1. Open Terminal and Clone the Repo
43 |
44 | ```bash
45 | git clone https://github.com/dhruvpatidar359/Fluttersnips.git
46 | ```
47 | 2. Cd Over
48 |
49 | ```bash
50 | cd fluttersnips
51 | ```
52 | 3. Run Pub
53 | ```
54 | Flutter pub get
55 | ```
56 | 4. Creating .env file in root directory
57 | set up your firebase for the flutter web app
58 | ```
59 | GOOGLE_SIGNIN_CLIENT_ID=
60 | ```
61 | 
62 |
63 |
64 |
65 | For getting this you have to connect this app with your firebase flutter webapp :
66 | 1.1) Run the following commands or visit(https://firebase.google.com/docs/flutter/setup?platform=web)
67 | ```
68 | firebase login
69 | ```
70 |
71 | ```
72 | dart pub global activate flutterfire_cli
73 | ```
74 |
75 | ```
76 | flutterfire configure
77 | ```
78 |
79 | Create a project for your firebase
80 |
81 | 1.2) Enable firebase authentication there ( With google authentication )
82 | - There get the web - client - id copy it .
83 |
84 | 
85 |
86 |
87 | - paste , it in the .env file
88 | ```
89 | GOOGLE_SIGNIN_CLIENT_ID=YOUR_CLIENT_ID
90 |
91 | ```
92 | 1.3 ) Enable firebase firestore
93 | 1.4 ) Create two collections there as - recents and users
94 |
95 | 
96 |
97 |
98 |
99 |
100 |
101 | 1.5 ) If you want to enable google login in the webapp , then you have to enable your PEOPLE API from GCP(Google Cloud Platform) .
102 |
103 | 
104 |
105 | Steps : 1 ) Login to Google Cloud platform
106 | 2 ) Select your project
107 | 3 ) Go to API and Services
108 | 4 ) Search for People API
109 | 5 ) Enable It
110 |
111 |
112 | 5. Run App
113 | ```
114 | flutter run
115 | ```
116 |
117 |
118 |
119 |
120 |
121 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | ## For Widget Code Contribution
137 |
138 | 
139 |
140 |
141 | ## Project Maintainers ❤️
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | ## Contributors 💘
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/lib/screens/intro_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fluttersnips/shared/exports.dart';
3 |
4 | class IntroPage extends StatelessWidget {
5 | const IntroPage({super.key});
6 |
7 | @override
8 | Widget build(BuildContext context) {
9 | return SingleChildScrollView(
10 | child: Column(
11 | children: [
12 | Padding(
13 | padding: const EdgeInsets.fromLTRB(40, 110, 40, 30),
14 | child: Row(
15 | children: [
16 | SizedBox(
17 | height: 200,
18 | width: 400,
19 | child: Column(
20 | crossAxisAlignment: CrossAxisAlignment.start,
21 | children: [
22 | Flexible(
23 | child: Text(
24 | 'A comprehensive component library for Flutter.',
25 | style: GoogleFonts.poppins(
26 | color: Colors.white,
27 | fontSize: 16,
28 | fontWeight: FontWeight.w500,
29 | ),
30 | ),
31 | ),
32 | Flexible(
33 | child: Text(
34 | 'Flutter Snips.',
35 | style: GoogleFonts.alfaSlabOne(
36 | color: Colors.white,
37 | fontSize: 48,
38 | fontWeight: FontWeight.w400,
39 | ),
40 | ),
41 | ),
42 | Flexible(
43 | child: Text(
44 | 'By Community For Community',
45 | style: GoogleFonts.poppins(
46 | color: Colors.white,
47 | fontSize: 16,
48 | fontWeight: FontWeight.w500,
49 | ),
50 | ),
51 | ),
52 | ],
53 | ),
54 | ),
55 | const SizedBox(
56 | height: 400,
57 | width: 400,
58 | child: RiveAnimation.asset("assets/birb.riv"),
59 | ),
60 | ],
61 | ),
62 | ),
63 | const SizedBox(height: 30),
64 | Padding(
65 | padding: const EdgeInsets.all(8.0),
66 | child: Row(
67 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
68 | children: [
69 | SizedBox(
70 | width: 300,
71 | height: 400,
72 | child: GlassyCard(
73 | child: Center(
74 | child: Column(
75 | mainAxisAlignment: MainAxisAlignment.center,
76 | children: [
77 | Text(
78 | "How To Use",
79 | style: GoogleFonts.poppins(
80 | fontSize: 25,
81 | fontWeight: FontWeight.w900,
82 | ),
83 | ),
84 | Text(
85 | "👉 Click on SideBar buttons",
86 | style: GoogleFonts.poppins(
87 | fontSize: 15,
88 | fontWeight: FontWeight.w400,
89 | ),
90 | ),
91 | Text(
92 | "👉 Look for your choice",
93 | style: GoogleFonts.poppins(
94 | fontSize: 15,
95 | fontWeight: FontWeight.w400,
96 | ),
97 | ),
98 | Text(
99 | "👉 Copy Code",
100 | style: GoogleFonts.poppins(
101 | fontSize: 15,
102 | fontWeight: FontWeight.w400,
103 | ),
104 | ),
105 | Text(
106 | "👉 Enjoy",
107 | style: GoogleFonts.poppins(
108 | fontSize: 15,
109 | fontWeight: FontWeight.w400,
110 | ),
111 | ),
112 | ],
113 | ))),
114 | ),
115 | SizedBox(
116 | width: 300,
117 | height: 400,
118 | child: GlassyCard(
119 | child: Center(
120 | child: Column(
121 | mainAxisAlignment: MainAxisAlignment.center,
122 | children: [
123 | Text(
124 | "How To Contribute",
125 | style: GoogleFonts.poppins(
126 | fontSize: 25,
127 | fontWeight: FontWeight.w900,
128 | ),
129 | ),
130 | Text(
131 | "👉 Click on Contribute Button",
132 | style: GoogleFonts.poppins(
133 | fontSize: 15,
134 | fontWeight: FontWeight.w400,
135 | ),
136 | ),
137 | Text(
138 | "👉 Select Way to Contribute",
139 | style: GoogleFonts.poppins(
140 | fontSize: 15,
141 | fontWeight: FontWeight.w400,
142 | ),
143 | ),
144 | Text(
145 | "👉 Fluttersnips ,Add Code",
146 | style: GoogleFonts.poppins(
147 | fontSize: 15,
148 | fontWeight: FontWeight.w400,
149 | ),
150 | ),
151 | Text(
152 | "👉 OR Go For Github",
153 | style: GoogleFonts.poppins(
154 | fontSize: 15,
155 | fontWeight: FontWeight.w400,
156 | ),
157 | ),
158 | ],
159 | ))),
160 | ),
161 | ],
162 | ),
163 | )
164 | ],
165 | ),
166 | );
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/lib/widgets/nav_bar/presentation/custom_dialog.dart:
--------------------------------------------------------------------------------
1 | import 'package:awesome_snackbar_content/awesome_snackbar_content.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:fluttersnips/services/auth/auth_repository.dart';
4 | import 'package:fluttersnips/services/datafetch/firebase_repository.dart';
5 |
6 | import '../../../constants/app_colors.dart';
7 |
8 | class MyCustomDialog extends StatefulWidget {
9 | const MyCustomDialog({Key? key}) : super(key: key);
10 |
11 | @override
12 | State createState() => _MyCustomDialogState();
13 | }
14 |
15 | class _MyCustomDialogState extends State {
16 | final TextEditingController _emailController = TextEditingController();
17 | final TextEditingController _widNameController = TextEditingController();
18 | final TextEditingController _codeController = TextEditingController();
19 | String _selectedClass = 'Card';
20 | final List _classOptions = [
21 | 'Container',
22 | 'Row',
23 | 'Column',
24 | 'Text',
25 | 'TextField',
26 | 'Button',
27 | 'TextButton',
28 | 'ElevatedButton',
29 | 'IconButton',
30 | 'AppBar',
31 | 'Image',
32 | 'ListView',
33 | 'GridView',
34 | 'Card',
35 | 'ExpansionPanel',
36 | 'AlertDialog',
37 | 'BottomSheet',
38 | 'Drawer',
39 | 'SnackBar',
40 | 'CircularProgressIndicator',
41 | 'LinearProgressIndicator',
42 | 'Checkbox',
43 | 'Radio',
44 | 'Switch',
45 | 'DropdownButton',
46 | 'Slider',
47 | 'DatePicker',
48 | 'TimePicker',
49 | 'Stack',
50 | 'Positioned',
51 | 'Align',
52 | 'Wrap',
53 | 'Spacer',
54 | 'InkWell',
55 | 'GestureDetector',
56 | 'Opacity',
57 | 'AnimatedContainer',
58 | 'Hero',
59 | 'ClipRRect',
60 | 'IndexedStack',
61 | 'PageView',
62 | 'Tooltip',
63 | 'RichText',
64 | 'DataTable',
65 | 'Stepper',
66 | 'TabBar',
67 | 'SnackBar',
68 | 'WebView',
69 | 'VideoPlayer',
70 | ];
71 | bool _isFormValid = false;
72 |
73 | @override
74 | void dispose() {
75 | _emailController.dispose();
76 | _codeController.dispose();
77 | _widNameController.dispose();
78 | super.dispose();
79 | }
80 |
81 | @override
82 | Widget build(BuildContext context) {
83 | return AlertDialog(
84 | title: const Text('Add Details', style: TextStyle(color: primaryColor)),
85 | content: Column(
86 | mainAxisSize: MainAxisSize.min,
87 | children: [
88 | TextField(
89 | controller: _widNameController,
90 | decoration: const InputDecoration(
91 | labelText: 'Widget Name',
92 | fillColor: primaryColor,
93 | ),
94 | onChanged: (_) => _validateForm(),
95 | ),
96 | const SizedBox(height: 16),
97 | TextField(
98 | controller: _emailController,
99 | decoration: const InputDecoration(
100 | labelText: 'Email',
101 | fillColor: primaryColor,
102 | ),
103 | onChanged: (_) => _validateForm(),
104 | ),
105 | const SizedBox(height: 16),
106 | SizedBox(
107 | height: 200,
108 | width: MediaQuery.of(context).size.width * (3 / 4),
109 | child: SingleChildScrollView(
110 | child: TextField(
111 | controller: _codeController,
112 | decoration: const InputDecoration(
113 | labelText: 'Code',
114 | fillColor: primaryColor,
115 | ),
116 | maxLines: null,
117 | onChanged: (_) => _validateForm(),
118 | ),
119 | ),
120 | ),
121 | const SizedBox(height: 16),
122 | DropdownButtonFormField(
123 | value: _selectedClass,
124 | items: _classOptions.map((String value) {
125 | return DropdownMenuItem(
126 | value: value,
127 | child: Text(value),
128 | );
129 | }).toList(),
130 | onChanged: (String? newValue) {
131 | setState(() {
132 | _selectedClass = newValue!;
133 | _validateForm();
134 | });
135 | },
136 | decoration: const InputDecoration(
137 | labelText: 'Class',
138 | fillColor: primaryColor,
139 | ),
140 | ),
141 | ],
142 | ),
143 | actions: [
144 | TextButton(
145 | onPressed: () {
146 | Navigator.of(context).pop();
147 | },
148 | child: const Text('Cancel', style: TextStyle(color: primaryColor)),
149 | ),
150 | ElevatedButton(
151 | onPressed: _isFormValid ? _submitForm : null,
152 | child: const Text('Submit', style: TextStyle(color: primaryColor)),
153 | ),
154 | ],
155 | // Disable the dialog's close button
156 | // barrierDismissible: false,
157 | );
158 | }
159 |
160 | void _validateForm() {
161 | setState(() {
162 | _isFormValid = _widNameController.text.isNotEmpty &&
163 | _emailController.text.isNotEmpty &&
164 | _codeController.text.isNotEmpty;
165 | });
166 | }
167 |
168 | void _submitForm() async {
169 | final String email = _emailController.text;
170 | final String code = _codeController.text;
171 | final String classT = _selectedClass;
172 | final String widName = _widNameController.text;
173 |
174 | FirebaseRepository().saveCode(widName, email, code, classT);
175 | if (authRepositoryInstance.name != null) {
176 | await authRepositoryInstance
177 | .increaseContriCount(authRepositoryInstance.uid.toString());
178 | }
179 |
180 | final snackBar = SnackBar(
181 | /// need to set following properties for best effect of awesome_snackbar_content
182 | elevation: 0,
183 |
184 | behavior: SnackBarBehavior.fixed,
185 |
186 | backgroundColor: Colors.transparent,
187 | content: AwesomeSnackbarContent(
188 | title: 'YAY,Contributed!',
189 | message: 'You code has been submitted!',
190 | messageFontSize: 15,
191 | titleFontSize: 20,
192 | color: Colors.green.shade700,
193 |
194 | /// change contentType to ContentType.success, ContentType.warning or ContentType.help for variants
195 | contentType: ContentType.success,
196 | ),
197 | );
198 |
199 | if (mounted) {
200 | ScaffoldMessenger.of(context)
201 | ..hideCurrentSnackBar()
202 | ..showSnackBar(snackBar);
203 |
204 | Navigator.of(context).pop();
205 | }
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/lib/widgets/wild_list/shapes/shape_wild_list.dart:
--------------------------------------------------------------------------------
1 | // Square shape using canvas
2 | import 'dart:math' as math;
3 | import 'package:flutter/material.dart';
4 |
5 | class SquareShape extends StatefulWidget {
6 | const SquareShape({super.key});
7 |
8 | @override
9 | State createState() => _SquareShapeState();
10 | }
11 |
12 | class _SquareShapeState extends State {
13 | @override
14 | Widget build(BuildContext context) {
15 | return SizedBox(
16 | width: 400,
17 | height: 400,
18 | child: CustomPaint(
19 | painter: OpenPainter(
20 | rectColor: Colors.yellow, rectSize: const Size(200, 250)),
21 | ),
22 | );
23 | }
24 | }
25 |
26 | class OpenPainter extends CustomPainter {
27 | Color rectColor;
28 | Size rectSize;
29 |
30 | OpenPainter({required this.rectColor, required this.rectSize});
31 |
32 | // ignore: empty_constructor_bodies
33 | @override
34 | void paint(Canvas canvas, Size size) {
35 | var paint1 = Paint()
36 | ..color = rectColor
37 | ..style = PaintingStyle.fill;
38 | canvas.drawRect(const Offset(100, 100) & rectSize, paint1);
39 | }
40 |
41 | @override
42 | bool shouldRepaint(CustomPainter oldDelegate) => true;
43 | }
44 |
45 | // triangle shape using canvas
46 |
47 | class TriangleShape extends StatelessWidget {
48 | const TriangleShape({super.key});
49 |
50 | @override
51 | Widget build(BuildContext context) {
52 | return Center(
53 | child: SizedBox(
54 | width: 200,
55 | height: 200,
56 | child: CustomPaint(size: const Size(200, 200), painter: DrawTriangle()),
57 | ),
58 | );
59 | }
60 | }
61 |
62 | class DrawTriangle extends CustomPainter {
63 | @override
64 | void paint(Canvas canvas, Size size) {
65 | var path = Path();
66 | path.moveTo(size.width / 2, 0);
67 | path.lineTo(0, size.height);
68 | path.lineTo(size.height, size.width);
69 | path.close();
70 | canvas.drawPath(path, Paint()..color = Colors.green);
71 | }
72 |
73 | @override
74 | bool shouldRepaint(CustomPainter oldDelegate) {
75 | return false;
76 | }
77 | }
78 |
79 | // Pentagon shape using Canvas
80 |
81 | class PentagonShape extends StatelessWidget {
82 | const PentagonShape({super.key});
83 |
84 | @override
85 | Widget build(BuildContext context) {
86 | return Center(
87 | child: ClipPath(
88 | clipper: DrawPentagon(),
89 | child: Container(
90 | color: Colors.red,
91 | width: 300,
92 | height: 300,
93 | ),
94 | ),
95 | );
96 | }
97 | }
98 |
99 | class DrawPentagon extends CustomClipper {
100 | @override
101 | Path getClip(Size size) {
102 | Path path = Path();
103 | path.addPolygon([
104 | Offset(0, size.height * 1 / 3),
105 | Offset(size.width / 2, 0),
106 | Offset(size.width, size.height * 1 / 3),
107 | Offset(size.width * 4 / 5, size.height),
108 | Offset(size.width * 1 / 5, size.height),
109 | ], true);
110 | return path;
111 | }
112 |
113 | @override
114 | bool shouldReclip(covariant CustomClipper oldClipper) {
115 | return false;
116 | }
117 | }
118 |
119 | // Hexagon shape using canvas
120 |
121 | class HexagonShape extends StatelessWidget {
122 | const HexagonShape({super.key});
123 |
124 | @override
125 | Widget build(BuildContext context) {
126 | return Center(
127 | child: ClipPath(
128 | clipper: DrawHexagon(),
129 | child: Container(
130 | color: Colors.blue,
131 | width: 300,
132 | height: 300,
133 | ),
134 | ),
135 | );
136 | }
137 | }
138 |
139 | class DrawHexagon extends CustomClipper {
140 | @override
141 | Path getClip(Size size) {
142 | Path path = Path();
143 | path.addPolygon([
144 | Offset(0, size.height / 2),
145 | Offset(size.width * 1 / 3, size.height),
146 | Offset(size.width * 2 / 3, size.height),
147 | Offset(size.width, size.height / 2),
148 | Offset(size.width * 2 / 3, 0),
149 | Offset(size.width * 1 / 3, 0)
150 | ], true);
151 | return path;
152 | }
153 |
154 | @override
155 | bool shouldReclip(covariant CustomClipper oldClipper) {
156 | return false;
157 | }
158 | }
159 |
160 |
161 |
162 | // Star shape using canvas
163 |
164 | class FourPointedStar extends StatelessWidget {
165 | const FourPointedStar({super.key});
166 |
167 | @override
168 | Widget build(BuildContext context) {
169 | return Center(
170 | child: ClipPath(
171 | clipper: StarClipper(5),
172 | child: Container(
173 | width: 300,
174 | height: 300,
175 | color: Colors.green,
176 | ),
177 | ),
178 | );
179 | }
180 | }
181 |
182 | // 6-point star shape using canvas
183 |
184 | class SixPointedStar extends StatelessWidget {
185 | const SixPointedStar({super.key});
186 |
187 | @override
188 | Widget build(BuildContext context) {
189 | return Center(
190 | child: ClipPath(
191 | clipper: StarClipper(6),
192 | child: Container(
193 | width: 300,
194 | height: 300,
195 | color: Colors.white,
196 | ),
197 | ),
198 | );
199 | }
200 | }
201 |
202 | // 10-point star shape using canvas
203 |
204 | class TenPointedStar extends StatelessWidget {
205 | const TenPointedStar({super.key});
206 |
207 | @override
208 | Widget build(BuildContext context) {
209 | return Center(
210 | child: ClipPath(
211 | clipper: StarClipper(10),
212 | child: Container(
213 | width: 300,
214 | height: 300,
215 | color: Colors.red,
216 | ),
217 | ),
218 | );
219 | }
220 | }
221 |
222 | // 20-point star shape using canvas
223 |
224 | class TwentyPointedStar extends StatelessWidget {
225 | const TwentyPointedStar({super.key});
226 |
227 | @override
228 | Widget build(BuildContext context) {
229 | return Center(
230 | child: ClipPath(
231 | clipper: StarClipper(20),
232 | child: Container(
233 | width: 300,
234 | height: 300,
235 | color: Colors.blue,
236 | ),
237 | ),
238 | );
239 | }
240 | }
241 |
242 | class StarClipper extends CustomClipper {
243 | /// The number of points of the star
244 | final int points;
245 | StarClipper(this.points);
246 |
247 | // Degrees to radians conversion
248 | double _degreeToRadian(double deg) => deg * (math.pi / 180.0);
249 |
250 | @override
251 | Path getClip(Size size) {
252 | Path path = Path();
253 | double max = 2 * math.pi;
254 |
255 | double width = size.width;
256 | double halfWidth = width / 2;
257 |
258 | double wingRadius = halfWidth;
259 | double radius = halfWidth / 2;
260 |
261 | double degreesPerStep = _degreeToRadian(360 / points);
262 | double halfDegreesPerStep = degreesPerStep / 2;
263 |
264 | path.moveTo(width, halfWidth);
265 |
266 | for (double step = 0; step < max; step += degreesPerStep) {
267 | path.lineTo(halfWidth + wingRadius * math.cos(step), halfWidth + wingRadius * math.sin(step));
268 | path.lineTo(halfWidth + radius * math.cos(step + halfDegreesPerStep), halfWidth + radius * math.sin(step + halfDegreesPerStep));
269 | }
270 |
271 | path.close();
272 | return path;
273 | }
274 |
275 | @override
276 | bool shouldReclip(CustomClipper oldClipper) {
277 | StarClipper starClipper = oldClipper as StarClipper;
278 | return points != starClipper.points;
279 | }
280 | }
281 |
--------------------------------------------------------------------------------