feat : button , outlined button
fab button , fab outlined button , input , pagination widget's
8
assets/icons/add.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="vuesax/outline/add">
|
||||||
|
<g id="add">
|
||||||
|
<path id="Vector" d="M30 21.25H10C9.31667 21.25 8.75 20.6833 8.75 20C8.75 19.3167 9.31667 18.75 10 18.75H30C30.6833 18.75 31.25 19.3167 31.25 20C31.25 20.6833 30.6833 21.25 30 21.25Z" fill="white"/>
|
||||||
|
<path id="Vector_2" d="M20 31.25C19.3167 31.25 18.75 30.6833 18.75 30V10C18.75 9.31667 19.3167 8.75 20 8.75C20.6833 8.75 21.25 9.31667 21.25 10V30C21.25 30.6833 20.6833 31.25 20 31.25Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 554 B |
7
assets/icons/arrow_left.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Arrow - Right">
|
||||||
|
<g id="Arrow - Right 2">
|
||||||
|
<path id="Stroke 1" d="M21.8999 26.8L12.0999 17L21.8999 7.19998" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 307 B |
7
assets/icons/arrow_right.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Arrow - Right">
|
||||||
|
<g id="Arrow - Right 2">
|
||||||
|
<path id="Stroke 1" d="M8.5 5L15.5 12L8.5 19" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 288 B |
10
assets/icons/download.svg
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="vuesax/outline/document-download">
|
||||||
|
<g id="document-download">
|
||||||
|
<path id="Vector" d="M9 17.75C8.9 17.75 8.81 17.73 8.71 17.69C8.43 17.58 8.25 17.3 8.25 17V11C8.25 10.59 8.59 10.25 9 10.25C9.41 10.25 9.75 10.59 9.75 11V15.19L10.47 14.47C10.76 14.18 11.24 14.18 11.53 14.47C11.82 14.76 11.82 15.24 11.53 15.53L9.53 17.53C9.39 17.67 9.19 17.75 9 17.75Z" fill="white"/>
|
||||||
|
<path id="Vector_2" d="M8.99994 17.75C8.80994 17.75 8.61994 17.68 8.46994 17.53L6.46994 15.53C6.17994 15.24 6.17994 14.76 6.46994 14.47C6.75994 14.18 7.23994 14.18 7.52994 14.47L9.52994 16.47C9.81994 16.76 9.81994 17.24 9.52994 17.53C9.37994 17.68 9.18994 17.75 8.99994 17.75Z" fill="white"/>
|
||||||
|
<path id="Vector_3" d="M15 22.75H9C3.57 22.75 1.25 20.43 1.25 15V9C1.25 3.57 3.57 1.25 9 1.25H14C14.41 1.25 14.75 1.59 14.75 2C14.75 2.41 14.41 2.75 14 2.75H9C4.39 2.75 2.75 4.39 2.75 9V15C2.75 19.61 4.39 21.25 9 21.25H15C19.61 21.25 21.25 19.61 21.25 15V10C21.25 9.59 21.59 9.25 22 9.25C22.41 9.25 22.75 9.59 22.75 10V15C22.75 20.43 20.43 22.75 15 22.75Z" fill="white"/>
|
||||||
|
<path id="Vector_4" d="M22 10.75H18C14.58 10.75 13.25 9.41999 13.25 5.99999V1.99999C13.25 1.69999 13.43 1.41999 13.71 1.30999C13.99 1.18999 14.31 1.25999 14.53 1.46999L22.53 9.46999C22.74 9.67999 22.81 10.01 22.69 10.29C22.57 10.57 22.3 10.75 22 10.75ZM14.75 3.80999V5.99999C14.75 8.57999 15.42 9.24999 18 9.24999H20.19L14.75 3.80999Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
9
assets/icons/edit.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="vuesax/outline/edit-2">
|
||||||
|
<g id="edit-2">
|
||||||
|
<path id="Vector" d="M5.53999 19.52C4.92999 19.52 4.35999 19.31 3.94999 18.92C3.42999 18.43 3.17999 17.69 3.26999 16.89L3.63999 13.65C3.70999 13.04 4.07999 12.23 4.50999 11.79L12.72 3.09999C14.77 0.929988 16.91 0.869988 19.08 2.91999C21.25 4.96999 21.31 7.10999 19.26 9.27999L11.05 17.97C10.63 18.42 9.84999 18.84 9.23999 18.94L6.01999 19.49C5.84999 19.5 5.69999 19.52 5.53999 19.52ZM15.93 2.90999C15.16 2.90999 14.49 3.38999 13.81 4.10999L5.59999 12.81C5.39999 13.02 5.16999 13.52 5.12999 13.81L4.75999 17.05C4.71999 17.38 4.79999 17.65 4.97999 17.82C5.15999 17.99 5.42999 18.05 5.75999 18L8.97999 17.45C9.26999 17.4 9.74999 17.14 9.94999 16.93L18.16 8.23999C19.4 6.91999 19.85 5.69999 18.04 3.99999C17.24 3.22999 16.55 2.90999 15.93 2.90999Z" fill="white"/>
|
||||||
|
<path id="Vector_2" d="M17.3404 10.95C17.3204 10.95 17.2904 10.95 17.2704 10.95C14.1504 10.64 11.6404 8.26997 11.1604 5.16997C11.1004 4.75997 11.3804 4.37997 11.7904 4.30997C12.2004 4.24997 12.5804 4.52997 12.6504 4.93997C13.0304 7.35997 14.9904 9.21997 17.4304 9.45997C17.8404 9.49997 18.1404 9.86997 18.1004 10.28C18.0504 10.66 17.7204 10.95 17.3404 10.95Z" fill="white"/>
|
||||||
|
<path id="Vector_3" d="M21 22.75H3C2.59 22.75 2.25 22.41 2.25 22C2.25 21.59 2.59 21.25 3 21.25H21C21.41 21.25 21.75 21.59 21.75 22C21.75 22.41 21.41 22.75 21 22.75Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
8
assets/icons/filter.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="vuesax/outline/filter">
|
||||||
|
<g id="filter">
|
||||||
|
<path id="Vector" d="M10.9399 22.65C10.4599 22.65 9.9899 22.53 9.5499 22.29C8.6699 21.8 8.1399 20.91 8.1399 19.91V14.61C8.1399 14.11 7.8099 13.36 7.4999 12.98L3.7599 9.02001C3.1299 8.39001 2.6499 7.31001 2.6499 6.50001V4.20001C2.6499 2.60001 3.8599 1.35001 5.3999 1.35001H18.5999C20.1199 1.35001 21.3499 2.58001 21.3499 4.10001V6.30001C21.3499 7.35001 20.7199 8.54001 20.1299 9.13001L15.7999 12.96C15.3799 13.31 15.0499 14.08 15.0499 14.7V19C15.0499 19.89 14.4899 20.92 13.7899 21.34L12.4099 22.23C11.9599 22.51 11.4499 22.65 10.9399 22.65ZM5.3999 2.85001C4.6999 2.85001 4.1499 3.44001 4.1499 4.20001V6.50001C4.1499 6.87001 4.4499 7.59001 4.8299 7.97001L8.6399 11.98C9.1499 12.61 9.6499 13.66 9.6499 14.6V19.9C9.6499 20.55 10.0999 20.87 10.2899 20.97C10.7099 21.2 11.2199 21.2 11.6099 20.96L12.9999 20.07C13.2799 19.9 13.5599 19.36 13.5599 19V14.7C13.5599 13.63 14.0799 12.45 14.8299 11.82L19.1099 8.03001C19.4499 7.69001 19.8599 6.88001 19.8599 6.29001V4.10001C19.8599 3.41001 19.2999 2.85001 18.6099 2.85001H5.3999Z" fill="white"/>
|
||||||
|
<path id="Vector_2" d="M6.00017 10.75C5.86017 10.75 5.73017 10.71 5.60017 10.64C5.25017 10.42 5.14017 9.94999 5.36017 9.59999L10.2902 1.69999C10.5102 1.34999 10.9702 1.23999 11.3202 1.45999C11.6702 1.67999 11.7802 2.13999 11.5602 2.48999L6.63017 10.39C6.49017 10.62 6.25017 10.75 6.00017 10.75Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
14
assets/icons/scan.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="vuesax/outline/scan-barcode">
|
||||||
|
<g id="scan-barcode">
|
||||||
|
<path id="Vector" d="M2 9.75C1.59 9.75 1.25 9.41 1.25 9V6.5C1.25 3.6 3.61 1.25 6.5 1.25H9C9.41 1.25 9.75 1.59 9.75 2C9.75 2.41 9.41 2.75 9 2.75H6.5C4.43 2.75 2.75 4.43 2.75 6.5V9C2.75 9.41 2.41 9.75 2 9.75Z" fill="white"/>
|
||||||
|
<path id="Vector_2" d="M22 9.75C21.59 9.75 21.25 9.41 21.25 9V6.5C21.25 4.43 19.57 2.75 17.5 2.75H15C14.59 2.75 14.25 2.41 14.25 2C14.25 1.59 14.59 1.25 15 1.25H17.5C20.39 1.25 22.75 3.6 22.75 6.5V9C22.75 9.41 22.41 9.75 22 9.75Z" fill="white"/>
|
||||||
|
<path id="Vector_3" d="M17.5 22.75H16C15.59 22.75 15.25 22.41 15.25 22C15.25 21.59 15.59 21.25 16 21.25H17.5C19.57 21.25 21.25 19.57 21.25 17.5V16C21.25 15.59 21.59 15.25 22 15.25C22.41 15.25 22.75 15.59 22.75 16V17.5C22.75 20.4 20.39 22.75 17.5 22.75Z" fill="white"/>
|
||||||
|
<path id="Vector_4" d="M9 22.75H6.5C3.61 22.75 1.25 20.4 1.25 17.5V15C1.25 14.59 1.59 14.25 2 14.25C2.41 14.25 2.75 14.59 2.75 15V17.5C2.75 19.57 4.43 21.25 6.5 21.25H9C9.41 21.25 9.75 21.59 9.75 22C9.75 22.41 9.41 22.75 9 22.75Z" fill="white"/>
|
||||||
|
<path id="Vector_5" d="M9 11.25H7C5.59 11.25 4.75 10.41 4.75 9V7C4.75 5.59 5.59 4.75 7 4.75H9C10.41 4.75 11.25 5.59 11.25 7V9C11.25 10.41 10.41 11.25 9 11.25ZM7 6.25C6.41 6.25 6.25 6.41 6.25 7V9C6.25 9.59 6.41 9.75 7 9.75H9C9.59 9.75 9.75 9.59 9.75 9V7C9.75 6.41 9.59 6.25 9 6.25H7Z" fill="white"/>
|
||||||
|
<path id="Vector_6" d="M17 11.25H15C13.59 11.25 12.75 10.41 12.75 9V7C12.75 5.59 13.59 4.75 15 4.75H17C18.41 4.75 19.25 5.59 19.25 7V9C19.25 10.41 18.41 11.25 17 11.25ZM15 6.25C14.41 6.25 14.25 6.41 14.25 7V9C14.25 9.59 14.41 9.75 15 9.75H17C17.59 9.75 17.75 9.59 17.75 9V7C17.75 6.41 17.59 6.25 17 6.25H15Z" fill="white"/>
|
||||||
|
<path id="Vector_7" d="M9 19.25H7C5.59 19.25 4.75 18.41 4.75 17V15C4.75 13.59 5.59 12.75 7 12.75H9C10.41 12.75 11.25 13.59 11.25 15V17C11.25 18.41 10.41 19.25 9 19.25ZM7 14.25C6.41 14.25 6.25 14.41 6.25 15V17C6.25 17.59 6.41 17.75 7 17.75H9C9.59 17.75 9.75 17.59 9.75 17V15C9.75 14.41 9.59 14.25 9 14.25H7Z" fill="white"/>
|
||||||
|
<path id="Vector_8" d="M17 19.25H15C13.59 19.25 12.75 18.41 12.75 17V15C12.75 13.59 13.59 12.75 15 12.75H17C18.41 12.75 19.25 13.59 19.25 15V17C19.25 18.41 18.41 19.25 17 19.25ZM15 14.25C14.41 14.25 14.25 14.41 14.25 15V17C14.25 17.59 14.41 17.75 15 17.75H17C17.59 17.75 17.75 17.59 17.75 17V15C17.75 14.41 17.59 14.25 17 14.25H15Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
11
assets/icons/trash.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="vuesax/outline/trash">
|
||||||
|
<g id="trash">
|
||||||
|
<path id="Vector" d="M20.9997 6.72998C20.9797 6.72998 20.9497 6.72998 20.9197 6.72998C15.6297 6.19998 10.3497 5.99998 5.11967 6.52998L3.07967 6.72998C2.65967 6.76998 2.28967 6.46998 2.24967 6.04998C2.20967 5.62998 2.50967 5.26998 2.91967 5.22998L4.95967 5.02998C10.2797 4.48998 15.6697 4.69998 21.0697 5.22998C21.4797 5.26998 21.7797 5.63998 21.7397 6.04998C21.7097 6.43998 21.3797 6.72998 20.9997 6.72998Z" fill="white"/>
|
||||||
|
<path id="Vector_2" d="M8.49977 5.72C8.45977 5.72 8.41977 5.72 8.36977 5.71C7.96977 5.64 7.68977 5.25 7.75977 4.85L7.97977 3.54C8.13977 2.58 8.35977 1.25 10.6898 1.25H13.3098C15.6498 1.25 15.8698 2.63 16.0198 3.55L16.2398 4.85C16.3098 5.26 16.0298 5.65 15.6298 5.71C15.2198 5.78 14.8298 5.5 14.7698 5.1L14.5498 3.8C14.4098 2.93 14.3798 2.76 13.3198 2.76H10.6998C9.63977 2.76 9.61977 2.9 9.46977 3.79L9.23977 5.09C9.17977 5.46 8.85977 5.72 8.49977 5.72Z" fill="white"/>
|
||||||
|
<path id="Vector_3" d="M15.2104 22.75H8.79039C5.30039 22.75 5.16039 20.82 5.05039 19.26L4.40039 9.19001C4.37039 8.78001 4.69039 8.42001 5.10039 8.39001C5.52039 8.37001 5.87039 8.68001 5.90039 9.09001L6.55039 19.16C6.66039 20.68 6.70039 21.25 8.79039 21.25H15.2104C17.3104 21.25 17.3504 20.68 17.4504 19.16L18.1004 9.09001C18.1304 8.68001 18.4904 8.37001 18.9004 8.39001C19.3104 8.42001 19.6304 8.77001 19.6004 9.19001L18.9504 19.26C18.8404 20.82 18.7004 22.75 15.2104 22.75Z" fill="white"/>
|
||||||
|
<path id="Vector_4" d="M13.6601 17.25H10.3301C9.92008 17.25 9.58008 16.91 9.58008 16.5C9.58008 16.09 9.92008 15.75 10.3301 15.75H13.6601C14.0701 15.75 14.4101 16.09 14.4101 16.5C14.4101 16.91 14.0701 17.25 13.6601 17.25Z" fill="white"/>
|
||||||
|
<path id="Vector_5" d="M14.5 13.25H9.5C9.09 13.25 8.75 12.91 8.75 12.5C8.75 12.09 9.09 11.75 9.5 11.75H14.5C14.91 11.75 15.25 12.09 15.25 12.5C15.25 12.91 14.91 13.25 14.5 13.25Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/vec/add.svg.vec
Normal file
BIN
assets/vec/arrow_left.svg.vec
Normal file
BIN
assets/vec/arrow_right.svg.vec
Normal file
BIN
assets/vec/download.svg.vec
Normal file
BIN
assets/vec/edit.svg.vec
Normal file
BIN
assets/vec/filter.svg.vec
Normal file
BIN
assets/vec/scan.svg.vec
Normal file
BIN
assets/vec/trash.svg.vec
Normal file
BIN
fonts/iranyekanregularfanum.ttf
Normal file
267
lib/main.dart
@@ -1,7 +1,20 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/utils/color_utils.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/buttons/elevated.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/buttons/fab_outlined.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/buttons/outline_elevated.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/buttons/text_button.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/inputs/r_input.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/pagination/pagination_from_until.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/pagination/show_more.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/tabs/tab.dart';
|
||||||
|
|
||||||
|
import 'presentation/widget/buttons/fab.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@@ -14,7 +27,259 @@ class MyApp extends StatelessWidget {
|
|||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||||
),
|
),
|
||||||
|
home: Home(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Home extends StatefulWidget {
|
||||||
|
const Home({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<Home> createState() => _HomeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HomeState extends State<Home> {
|
||||||
|
List<bool> _isOpen = [false, false, false, false, false, false];
|
||||||
|
|
||||||
|
void _handleAdd() {
|
||||||
|
print("Add FAB pressed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleEdit() {
|
||||||
|
print("Edit FAB pressed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleDelete() {
|
||||||
|
print("Delete FAB pressed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text("System design"), centerTitle: true),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: ExpansionPanelList(
|
||||||
|
expansionCallback: (panelIndex, isExpanded) {
|
||||||
|
setState(() {
|
||||||
|
_isOpen[panelIndex] = isExpanded;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
buttonWidget(),
|
||||||
|
fabWidget(),
|
||||||
|
outlinedFabWidget(),
|
||||||
|
paginationWidget(),
|
||||||
|
tabWidget(),
|
||||||
|
inputsWidget(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpansionPanel inputsWidget() {
|
||||||
|
return ExpansionPanel(
|
||||||
|
isExpanded: _isOpen[5],
|
||||||
|
headerBuilder: (context, isExpanded) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"inputs",
|
||||||
|
style: AppFonts.yekan20Regular.copyWith(color: Colors.red),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
spacing: 14,
|
||||||
|
children: [
|
||||||
|
RTextField(
|
||||||
|
hintText: 'حجم کشتار را در روز به قطعه وارد کنید',
|
||||||
|
hintStyle: AppFonts.yekan13Regular,
|
||||||
|
),
|
||||||
|
RTextField(
|
||||||
|
label: 'تلفن مرغداری',
|
||||||
|
labelStyle: AppFonts.yekan10Regular,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpansionPanel tabWidget() {
|
||||||
|
return ExpansionPanel(
|
||||||
|
isExpanded: _isOpen[4],
|
||||||
|
headerBuilder: (context, isExpanded) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"tab",
|
||||||
|
style: AppFonts.yekan20Regular.copyWith(color: Colors.red),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
body: Column(
|
||||||
|
spacing: 14,
|
||||||
|
children: [
|
||||||
|
CupertinoSegmentedControlDemo(),
|
||||||
|
CupertinoSegmentedControlDemo2(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpansionPanel paginationWidget() {
|
||||||
|
return ExpansionPanel(
|
||||||
|
isExpanded: _isOpen[3],
|
||||||
|
headerBuilder: (context, isExpanded) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"پیجینیشن",
|
||||||
|
style: AppFonts.yekan20Regular.copyWith(color: Colors.red),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
body: Column(spacing: 14, children: [RShowMore(), PaginationFromUntil()]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpansionPanel outlinedFabWidget() {
|
||||||
|
return ExpansionPanel(
|
||||||
|
isExpanded: _isOpen[2],
|
||||||
|
headerBuilder: (context, isExpanded) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"Outlined Fab ",
|
||||||
|
style: AppFonts.yekan20Regular.copyWith(color: Colors.green),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
body: Column(
|
||||||
|
spacing: 14,
|
||||||
|
children: [
|
||||||
|
Row(),
|
||||||
|
|
||||||
|
RFabOutlined.smallAdd(onPressed: () {}),
|
||||||
|
RFabOutlined.smallAdd(onPressed: null),
|
||||||
|
|
||||||
|
RFabOutlined.smallAddNoBorder(onPressed: () {}),
|
||||||
|
RFabOutlined.smallAddNoBorder(onPressed: null),
|
||||||
|
|
||||||
|
RFabOutlined.add(onPressed: () {}),
|
||||||
|
RFabOutlined.add(onPressed: null),
|
||||||
|
|
||||||
|
RFabOutlined.addNoBorder(onPressed: () {}),
|
||||||
|
RFabOutlined.addNoBorder(onPressed: null),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpansionPanel fabWidget() {
|
||||||
|
return ExpansionPanel(
|
||||||
|
isExpanded: _isOpen[1],
|
||||||
|
headerBuilder: (context, isExpanded) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"Fab",
|
||||||
|
style: AppFonts.yekan20Regular.copyWith(color: Colors.green),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
body: Column(
|
||||||
|
spacing: 14,
|
||||||
|
children: [
|
||||||
|
Row(),
|
||||||
|
|
||||||
|
RFab.smallAdd(onPressed: () {}),
|
||||||
|
RFab.smallAdd(onPressed: null),
|
||||||
|
|
||||||
|
RFab.add(onPressed: () {}),
|
||||||
|
RFab.add(onPressed: null),
|
||||||
|
|
||||||
|
RFab.smallEdit(onPressed: null),
|
||||||
|
RFab.smallEdit(onPressed: () {}),
|
||||||
|
|
||||||
|
RFab.edit(onPressed: () {}),
|
||||||
|
RFab.edit(onPressed: null),
|
||||||
|
|
||||||
|
RFab.smallDelete(onPressed: () {}),
|
||||||
|
RFab.smallDelete(onPressed: null),
|
||||||
|
|
||||||
|
RFab.delete(onPressed: () {}),
|
||||||
|
RFab.delete(onPressed: null),
|
||||||
|
|
||||||
|
RFab.smallAction(onPressed: () {}),
|
||||||
|
RFab.smallAction(onPressed: null),
|
||||||
|
|
||||||
|
RFab.action(onPressed: () {}),
|
||||||
|
RFab.action(onPressed: null),
|
||||||
|
|
||||||
|
RFab.smallFilter(onPressed: () {}),
|
||||||
|
RFab.smallFilter(onPressed: null),
|
||||||
|
|
||||||
|
RFab.filter(onPressed: () {}),
|
||||||
|
RFab.filter(onPressed: null),
|
||||||
|
|
||||||
|
RFab.smallDownload(onPressed: () {}),
|
||||||
|
RFab.smallDownload(onPressed: null),
|
||||||
|
|
||||||
|
RFab.download(onPressed: () {}),
|
||||||
|
RFab.download(onPressed: null),
|
||||||
|
|
||||||
|
RFab.smallExcel(onPressed: () {}),
|
||||||
|
RFab.smallExcel(onPressed: null),
|
||||||
|
|
||||||
|
RFab.excel(onPressed: () {}),
|
||||||
|
RFab.excel(onPressed: null),
|
||||||
|
|
||||||
|
RFab.smallBack(onPressed: () {}),
|
||||||
|
RFab.smallBack(onPressed: null),
|
||||||
|
|
||||||
|
RFab.back(onPressed: () {}),
|
||||||
|
RFab.back(onPressed: null),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpansionPanel buttonWidget() {
|
||||||
|
return ExpansionPanel(
|
||||||
|
isExpanded: _isOpen[0],
|
||||||
|
headerBuilder: (context, isExpanded) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"دکمه ها",
|
||||||
|
style: AppFonts.yekan20Regular.copyWith(color: Colors.green),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
body: Column(
|
||||||
|
spacing: 14,
|
||||||
|
children: [
|
||||||
|
Row(),
|
||||||
|
|
||||||
|
RElevated(text: 'ثبت', onPressed: () {}),
|
||||||
|
|
||||||
|
RElevated(text: 'ثبت', onPressed: null),
|
||||||
|
|
||||||
|
ROutlinedElevated(text: 'ثبت', onPressed: () {}),
|
||||||
|
ROutlinedElevated(
|
||||||
|
text: 'ثبتwwww',
|
||||||
|
onPressed: () {},
|
||||||
|
backgroundColor: AppColor.blueNormal.disabledColor,
|
||||||
|
pressedBackgroundColor: AppColor.blueNormal,
|
||||||
|
),
|
||||||
|
ROutlinedElevated(text: 'ثبت', onPressed: null),
|
||||||
|
|
||||||
|
RTextButton(text: 'ثبت', onPressed: () {}),
|
||||||
|
RTextButton(text: 'ثبت', onPressed: null),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
155
lib/presentation/common/app_fonts.dart
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AppFonts {
|
||||||
|
AppFonts._(); // Private constructor to prevent instantiation
|
||||||
|
|
||||||
|
// --- Font Families ---
|
||||||
|
static const String yekan = 'yekan';
|
||||||
|
|
||||||
|
// --- Font Weights ---
|
||||||
|
static const FontWeight regular = FontWeight.w400;
|
||||||
|
static const FontWeight bold = FontWeight.w600;
|
||||||
|
static const double _height = 1.20;
|
||||||
|
|
||||||
|
static const TextStyle yekan61Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 61,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan49Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 48,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan39Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 39,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan31Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 31,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan25Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 25,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan24Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 24,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan20Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 20,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan16Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 16,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan13Regular = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 13,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan10Regular = TextStyle(
|
||||||
|
// Rounded from 10.24
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: regular,
|
||||||
|
fontSize: 10,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan61Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 61,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan49Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 48,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan39Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 39,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan31Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 31,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan25Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 25,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan24Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 24,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan20Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 20,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan16Bold = TextStyle(
|
||||||
|
// Base size bold
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 16,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan13Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 13,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const TextStyle yekan10Bold = TextStyle(
|
||||||
|
fontFamily: yekan,
|
||||||
|
fontWeight: bold, // Use bold weight
|
||||||
|
fontSize: 10,
|
||||||
|
height: _height,
|
||||||
|
);
|
||||||
|
}
|
||||||
24
lib/presentation/common/assets.dart
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
///This file is automatically generated. DO NOT EDIT, all your changes would be lost.
|
||||||
|
class Assets {
|
||||||
|
Assets._();
|
||||||
|
|
||||||
|
static const String iconsAdd = 'assets/icons/add.svg';
|
||||||
|
static const String iconsArrowLeft = 'assets/icons/arrow_left.svg';
|
||||||
|
static const String iconsArrowRight = 'assets/icons/arrow_right.svg';
|
||||||
|
static const String iconsDownload = 'assets/icons/download.svg';
|
||||||
|
static const String iconsEdit = 'assets/icons/edit.svg';
|
||||||
|
static const String iconsFilter = 'assets/icons/filter.svg';
|
||||||
|
static const String iconsScan = 'assets/icons/scan.svg';
|
||||||
|
static const String iconsTrash = 'assets/icons/trash.svg';
|
||||||
|
static const String imagesInnerSplash = 'assets/images/inner_splash.webp';
|
||||||
|
static const String imagesOutterSplash = 'assets/images/outter_splash.webp';
|
||||||
|
static const String vecAddSvg = 'assets/vec/add.svg.vec';
|
||||||
|
static const String vecArrowLeftSvg = 'assets/vec/arrow_left.svg.vec';
|
||||||
|
static const String vecArrowRightSvg = 'assets/vec/arrow_right.svg.vec';
|
||||||
|
static const String vecDownloadSvg = 'assets/vec/download.svg.vec';
|
||||||
|
static const String vecEditSvg = 'assets/vec/edit.svg.vec';
|
||||||
|
static const String vecFilterSvg = 'assets/vec/filter.svg.vec';
|
||||||
|
static const String vecScanSvg = 'assets/vec/scan.svg.vec';
|
||||||
|
static const String vecTrashSvg = 'assets/vec/trash.svg.vec';
|
||||||
|
|
||||||
|
}
|
||||||
24
lib/presentation/utils/color_utils.dart
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
extension ColorUtils on Color {
|
||||||
|
Color _darken([double amount = 0.1]) {
|
||||||
|
assert(amount >= 0 && amount <= 1, 'مقدار تیرگی باید بین 0 و 1 باشد');
|
||||||
|
final hslColor = HSLColor.fromColor(this);
|
||||||
|
final newLightness = (hslColor.lightness - amount).clamp(0.0, 1.0);
|
||||||
|
final hslDarkerColor = hslColor.withLightness(newLightness);
|
||||||
|
return hslDarkerColor.toColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabledColor{
|
||||||
|
return withAlpha(38);
|
||||||
|
}
|
||||||
|
|
||||||
|
get hoverColor{
|
||||||
|
return _darken(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
get pressedColor{
|
||||||
|
return _darken(0.10);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
58
lib/presentation/widget/buttons/elevated.dart
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||||
|
|
||||||
|
class RElevated extends StatefulWidget {
|
||||||
|
RElevated({
|
||||||
|
super.key,
|
||||||
|
required this.text,
|
||||||
|
required this.onPressed,
|
||||||
|
foregroundColor,
|
||||||
|
backgroundColor,
|
||||||
|
disabledBackgroundColor,
|
||||||
|
disabledForegroundColor,
|
||||||
|
radius,
|
||||||
|
textStyle,
|
||||||
|
this.width = 150.0,
|
||||||
|
this.height = 56.0,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
Color? foregroundColor;
|
||||||
|
Color? backgroundColor;
|
||||||
|
Color? disabledForegroundColor;
|
||||||
|
Color? disabledBackgroundColor;
|
||||||
|
double? radius;
|
||||||
|
TextStyle? textStyle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RElevated> createState() => _RElevatedState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RElevatedState extends State<RElevated> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: widget.backgroundColor ?? AppColor.blueNormal,
|
||||||
|
foregroundColor: widget.foregroundColor ?? Colors.white,
|
||||||
|
disabledBackgroundColor:
|
||||||
|
widget.disabledBackgroundColor ?? AppColor.blueNormal.withAlpha(38),
|
||||||
|
disabledForegroundColor: widget.disabledForegroundColor ?? Colors.white,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(widget.radius ?? 8),
|
||||||
|
),
|
||||||
|
fixedSize: Size(widget.width, widget.height),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
textStyle: widget.textStyle ?? AppFonts.yekan24Regular,
|
||||||
|
),
|
||||||
|
child: Text(widget.text),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
232
lib/presentation/widget/buttons/fab.dart
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/assets.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/utils/color_utils.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/vec_widget.dart';
|
||||||
|
|
||||||
|
class RFab extends StatefulWidget {
|
||||||
|
|
||||||
|
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
Color? foregroundColor;
|
||||||
|
Color? backgroundColor;
|
||||||
|
Color? disabledForegroundColor;
|
||||||
|
Color? disabledBackgroundColor;
|
||||||
|
double? radius;
|
||||||
|
ShapeBorder? shapeBorder;
|
||||||
|
Widget? icon;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RFab> createState() => _RFabState();
|
||||||
|
|
||||||
|
//region Add
|
||||||
|
RFab.smallAdd({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecAddSvg),
|
||||||
|
backgroundColor: AppColor.greenNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.add({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecAddSvg),
|
||||||
|
backgroundColor: AppColor.greenNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Edit
|
||||||
|
RFab.smallEdit({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecEditSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.edit({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecEditSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region delete
|
||||||
|
RFab.smallDelete({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecTrashSvg),
|
||||||
|
backgroundColor: AppColor.redNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.delete({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecTrashSvg),
|
||||||
|
backgroundColor: AppColor.redNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region action
|
||||||
|
RFab.smallAction({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecScanSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.action({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecScanSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region filter
|
||||||
|
RFab.smallFilter({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecFilterSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.filter({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecFilterSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region download
|
||||||
|
RFab.smallDownload({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecDownloadSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.download({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecDownloadSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Excel
|
||||||
|
RFab.smallExcel({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecDownloadSvg),
|
||||||
|
backgroundColor: AppColor.greenDark,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.excel({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecDownloadSvg),
|
||||||
|
backgroundColor: AppColor.greenDark,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Back
|
||||||
|
RFab.smallBack({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecArrowLeftSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
RFab.back({required VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: vecWidget(Assets.vecArrowLeftSvg),
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
key: key,
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region General
|
||||||
|
RFab.small({
|
||||||
|
required this.onPressed,
|
||||||
|
required this.icon,
|
||||||
|
required this.backgroundColor,
|
||||||
|
super.key,
|
||||||
|
}) : radius = 40.0,
|
||||||
|
foregroundColor = Colors.white;
|
||||||
|
|
||||||
|
RFab({
|
||||||
|
required this.onPressed,
|
||||||
|
required this.icon,
|
||||||
|
required this.backgroundColor,
|
||||||
|
super.key,
|
||||||
|
}) : radius = 56.0,
|
||||||
|
foregroundColor = Colors.white;
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RFabState extends State<RFab> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ElevatedButton(
|
||||||
|
onPressed: widget.onPressed,
|
||||||
|
style: ButtonStyle(
|
||||||
|
side: WidgetStateProperty.all(BorderSide.none),
|
||||||
|
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return widget.backgroundColor?.pressedColor ??
|
||||||
|
AppColor.blueNormalActive;
|
||||||
|
} else if (states.contains(WidgetState.hovered)) {
|
||||||
|
return widget.backgroundColor?.hoverColor ??
|
||||||
|
AppColor.blueNormalHover;
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return widget.backgroundColor?.disabledColor ??
|
||||||
|
AppColor.blueNormal.disabledColor;
|
||||||
|
}
|
||||||
|
return widget.backgroundColor ?? AppColor.blueNormal;
|
||||||
|
}),
|
||||||
|
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.disabled)) {
|
||||||
|
return widget.foregroundColor?.disabledColor;
|
||||||
|
}
|
||||||
|
return widget.foregroundColor;
|
||||||
|
}),
|
||||||
|
|
||||||
|
shape: WidgetStatePropertyAll(
|
||||||
|
CircleBorder(side: BorderSide(width: 1, color: Colors.transparent)),
|
||||||
|
),
|
||||||
|
fixedSize: WidgetStatePropertyAll(
|
||||||
|
Size(widget.radius ?? 56, widget.radius ?? 56),
|
||||||
|
),
|
||||||
|
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||||
|
),
|
||||||
|
child: widget.icon,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
605
lib/presentation/widget/buttons/fab_outlined.dart
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/assets.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/utils/color_utils.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/widget/vec_widget.dart';
|
||||||
|
|
||||||
|
class RFabOutlined extends StatefulWidget {
|
||||||
|
final Widget icon;
|
||||||
|
VoidCallback? onPressed;
|
||||||
|
final Color backgroundColor;
|
||||||
|
final Color? borderColor;
|
||||||
|
final double? radius;
|
||||||
|
OutlinedBorder? shapeBorder;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RFabOutlined> createState() => _RFabOutlinedState();
|
||||||
|
|
||||||
|
//region General
|
||||||
|
RFabOutlined({
|
||||||
|
required this.icon,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.backgroundColor,
|
||||||
|
required this.borderColor,
|
||||||
|
this.radius = 56.0,
|
||||||
|
super.key,
|
||||||
|
}) : shapeBorder = CircleBorder(
|
||||||
|
side: BorderSide(color: borderColor ?? Colors.transparent),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.noBorder({
|
||||||
|
required this.icon,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.backgroundColor,
|
||||||
|
super.key,
|
||||||
|
}) : borderColor = Colors.transparent,
|
||||||
|
radius = 56.0,
|
||||||
|
shapeBorder = CircleBorder(
|
||||||
|
side: BorderSide(color: Colors.transparent, width: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.small({
|
||||||
|
required this.icon,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.backgroundColor,
|
||||||
|
required this.borderColor,
|
||||||
|
super.key,
|
||||||
|
}) : radius = 40.0,
|
||||||
|
shapeBorder = CircleBorder(
|
||||||
|
side: BorderSide(color: borderColor ?? Colors.transparent, width: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallNoBorder({
|
||||||
|
required this.icon,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.backgroundColor,
|
||||||
|
super.key,
|
||||||
|
}) : borderColor = Colors.transparent,
|
||||||
|
radius = 40.0,
|
||||||
|
shapeBorder = CircleBorder(
|
||||||
|
side: BorderSide(color: Colors.transparent, width: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Add
|
||||||
|
RFabOutlined.smallAdd({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenNormal,
|
||||||
|
borderColor: AppColor.greenNormal,
|
||||||
|
icon: vecWidget2(
|
||||||
|
Assets.vecAddSvg,
|
||||||
|
|
||||||
|
color: AppColor.greenNormal,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallAddNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.smallNoBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecAddSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenNormal
|
||||||
|
: AppColor.greenNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.add({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenNormal,
|
||||||
|
borderColor: AppColor.greenNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecAddSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenNormal
|
||||||
|
: AppColor.greenNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.addNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecAddSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenNormal
|
||||||
|
: AppColor.greenNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Edit
|
||||||
|
RFabOutlined.smallEdit({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecEditSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallEditNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.smallNoBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecEditSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.edit({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecEditSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.editNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecEditSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Delete
|
||||||
|
RFabOutlined.smallDelete({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.redNormal,
|
||||||
|
borderColor: AppColor.redNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecTrashSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.redNormal
|
||||||
|
: AppColor.redNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallDeleteNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.smallNoBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.redNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecTrashSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.redNormal
|
||||||
|
: AppColor.redNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.delete({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.redNormal,
|
||||||
|
borderColor: AppColor.redNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecTrashSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.redNormal
|
||||||
|
: AppColor.redNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.deleteNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.redNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecTrashSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.redNormal
|
||||||
|
: AppColor.redNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Action
|
||||||
|
RFabOutlined.smallAction({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecScanSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallActionNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.smallNoBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecScanSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.action({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecScanSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.actionNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecScanSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Filter
|
||||||
|
RFabOutlined.smallFilter({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecFilterSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallFilterNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.smallNoBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecFilterSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.filter({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecFilterSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.filterNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecFilterSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Download
|
||||||
|
RFabOutlined.smallDownload({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallDownloadNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.smallNoBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.download({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.downloadNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Excel
|
||||||
|
RFabOutlined.smallExcel({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenDark,
|
||||||
|
borderColor: AppColor.greenDark,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallExcelNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenDark,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.excel({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenDark,
|
||||||
|
borderColor: AppColor.greenDark,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.excelNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.greenDark,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecDownloadSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.greenDark
|
||||||
|
: AppColor.greenDark.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Back
|
||||||
|
RFabOutlined.smallBack({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.small(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecArrowLeftSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.smallBackNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.smallNoBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecArrowLeftSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.back({VoidCallback? onPressed, Key? key})
|
||||||
|
: this(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
borderColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecArrowLeftSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
RFabOutlined.backNoBorder({VoidCallback? onPressed, Key? key})
|
||||||
|
: this.noBorder(
|
||||||
|
key: key,
|
||||||
|
onPressed: onPressed,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
icon: vecWidget(
|
||||||
|
Assets.vecArrowLeftSvg,
|
||||||
|
color:
|
||||||
|
onPressed != null
|
||||||
|
? AppColor.blueNormal
|
||||||
|
: AppColor.blueNormal.disabledColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RFabOutlinedState extends State<RFabOutlined> {
|
||||||
|
bool isOnPressed =false;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return OutlinedButton(
|
||||||
|
onPressed:widget.onPressed ,
|
||||||
|
style: ButtonStyle(
|
||||||
|
side: WidgetStateProperty.resolveWith<BorderSide?>((states) {
|
||||||
|
if (states.contains(WidgetState.disabled)) {
|
||||||
|
return BorderSide(
|
||||||
|
color:
|
||||||
|
widget.borderColor?.disabledColor ??
|
||||||
|
AppColor.blueNormal.disabledColor,
|
||||||
|
width: 2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return BorderSide(
|
||||||
|
color: widget.borderColor ?? AppColor.blueNormal,
|
||||||
|
width: 2,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return widget.backgroundColor;
|
||||||
|
} else if (states.contains(WidgetState.hovered)) {
|
||||||
|
return widget.backgroundColor.hoverColor ??
|
||||||
|
AppColor.blueNormal.hoverColor;
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return widget.backgroundColor.disabledColor ??
|
||||||
|
AppColor.blueNormal.disabledColor;
|
||||||
|
}
|
||||||
|
return Colors.transparent;
|
||||||
|
}),
|
||||||
|
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return Colors.white;
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return widget.backgroundColor.disabledColor ??
|
||||||
|
AppColor.blueNormal.disabledColor;
|
||||||
|
}
|
||||||
|
return widget.backgroundColor;
|
||||||
|
}),
|
||||||
|
|
||||||
|
shape: WidgetStatePropertyAll(widget.shapeBorder),
|
||||||
|
fixedSize: WidgetStatePropertyAll(
|
||||||
|
Size(widget.radius ?? 56, widget.radius ?? 56),
|
||||||
|
),
|
||||||
|
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||||
|
),
|
||||||
|
child: widget.icon
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
101
lib/presentation/widget/buttons/outline_elevated.dart
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/utils/color_utils.dart';
|
||||||
|
|
||||||
|
class ROutlinedElevated extends StatefulWidget {
|
||||||
|
ROutlinedElevated({
|
||||||
|
super.key,
|
||||||
|
required this.text,
|
||||||
|
required this.onPressed,
|
||||||
|
this.foregroundColor,
|
||||||
|
this.backgroundColor,
|
||||||
|
this.borderColor,
|
||||||
|
this.disabledBackgroundColor,
|
||||||
|
this.pressedBackgroundColor,
|
||||||
|
this.radius,
|
||||||
|
this.textStyle,
|
||||||
|
this.width = 150.0,
|
||||||
|
this.height = 56.0,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
Color? foregroundColor;
|
||||||
|
Color? backgroundColor;
|
||||||
|
|
||||||
|
Color? borderColor;
|
||||||
|
|
||||||
|
Color? disabledBackgroundColor;
|
||||||
|
Color? pressedBackgroundColor;
|
||||||
|
double? radius;
|
||||||
|
TextStyle? textStyle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ROutlinedElevated> createState() => _ROutlinedElevatedState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ROutlinedElevatedState extends State<ROutlinedElevated> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return OutlinedButton(
|
||||||
|
onPressed: widget.onPressed,
|
||||||
|
style: ButtonStyle(
|
||||||
|
side: WidgetStateProperty.resolveWith<BorderSide?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return BorderSide(
|
||||||
|
color: widget.borderColor ?? AppColor.blueNormal,
|
||||||
|
width: 2,
|
||||||
|
);
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return BorderSide(
|
||||||
|
color: widget.borderColor ?? AppColor.blueNormal.withAlpha(38),
|
||||||
|
width: 2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return BorderSide(
|
||||||
|
color: widget.borderColor ?? AppColor.blueNormal,
|
||||||
|
width: 2,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
if (widget.pressedBackgroundColor != null) {
|
||||||
|
return widget.pressedBackgroundColor;
|
||||||
|
}
|
||||||
|
return widget.backgroundColor?.pressedColor ?? AppColor.blueNormal;
|
||||||
|
} else if (states.contains(WidgetState.hovered)) {
|
||||||
|
return widget.backgroundColor?.hoverColor ??
|
||||||
|
AppColor.blueNormal.hoverColor;
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return widget.backgroundColor?.disabledColor ?? Colors.transparent;
|
||||||
|
}
|
||||||
|
return widget.backgroundColor;
|
||||||
|
}),
|
||||||
|
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return Colors.white;
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return AppColor.blueNormal.withAlpha(38);
|
||||||
|
}
|
||||||
|
return AppColor.blueNormal;
|
||||||
|
}),
|
||||||
|
|
||||||
|
shape: WidgetStatePropertyAll(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(widget.radius ?? 8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
fixedSize: WidgetStatePropertyAll(Size(widget.width, widget.height)),
|
||||||
|
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||||
|
textStyle: WidgetStatePropertyAll(
|
||||||
|
widget.textStyle ??
|
||||||
|
AppFonts.yekan24Regular.copyWith(color: AppColor.blueNormal),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(widget.text),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
77
lib/presentation/widget/buttons/text_button.dart
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||||
|
|
||||||
|
class RTextButton extends StatefulWidget {
|
||||||
|
RTextButton({
|
||||||
|
super.key,
|
||||||
|
required this.text,
|
||||||
|
required this.onPressed,
|
||||||
|
foregroundColor,
|
||||||
|
backgroundColor,
|
||||||
|
borderColor,
|
||||||
|
disabledBackgroundColor,
|
||||||
|
radius,
|
||||||
|
textStyle,
|
||||||
|
this.width = 150.0,
|
||||||
|
this.height = 56.0,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
Color? foregroundColor;
|
||||||
|
Color? backgroundColor;
|
||||||
|
Color? borderColor;
|
||||||
|
|
||||||
|
Color? disabledBackgroundColor;
|
||||||
|
double? radius;
|
||||||
|
TextStyle? textStyle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RTextButton> createState() => _RTextButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RTextButtonState extends State<RTextButton> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TextButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
side: WidgetStatePropertyAll(BorderSide.none),
|
||||||
|
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return widget.backgroundColor ?? AppColor.blueNormal;
|
||||||
|
} else if (states.contains(WidgetState.hovered)) {
|
||||||
|
return widget.backgroundColor?.withAlpha(38) ?? AppColor.blueNormal.withAlpha(38);
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return widget.disabledBackgroundColor ?? Colors.transparent;
|
||||||
|
}
|
||||||
|
return Colors.transparent;
|
||||||
|
}),
|
||||||
|
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return Colors.white;
|
||||||
|
} else if (states.contains(WidgetState.disabled)) {
|
||||||
|
return AppColor.blueNormal.withAlpha(38);
|
||||||
|
}
|
||||||
|
return AppColor.blueNormal;
|
||||||
|
}),
|
||||||
|
|
||||||
|
shape: WidgetStatePropertyAll(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(widget.radius ?? 8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
fixedSize: WidgetStatePropertyAll(Size(widget.width, widget.height)),
|
||||||
|
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||||
|
textStyle: WidgetStatePropertyAll(
|
||||||
|
widget.textStyle ??
|
||||||
|
AppFonts.yekan24Regular.copyWith(color: AppColor.blueNormal),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed:widget.onPressed,
|
||||||
|
child: Text(widget.text),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
216
lib/presentation/widget/inputs/r_input.dart
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class RTextField extends StatefulWidget {
|
||||||
|
RTextField(
|
||||||
|
{super.key,
|
||||||
|
this.maxLines,
|
||||||
|
this.maxLength,
|
||||||
|
this.hintText,
|
||||||
|
this.padding,
|
||||||
|
this.onChanged,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.keyboardType,
|
||||||
|
this.showCounter = false,
|
||||||
|
this.isDense,
|
||||||
|
this.initText,
|
||||||
|
this.isForNumber = false,
|
||||||
|
this.style,
|
||||||
|
this.hintStyle,
|
||||||
|
this.suffixIcon,
|
||||||
|
this.prefixIcon,
|
||||||
|
this.validator,
|
||||||
|
this.readonly = false,
|
||||||
|
this.boxConstraints,
|
||||||
|
this.minLines,
|
||||||
|
this.radius,
|
||||||
|
this.filled,
|
||||||
|
this.enabled,
|
||||||
|
this.errorStyle,
|
||||||
|
this.labelStyle,
|
||||||
|
this.label}) {
|
||||||
|
filled = filled ?? false;
|
||||||
|
obscure = false;
|
||||||
|
_inputBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.grey.shade300),
|
||||||
|
borderRadius: BorderRadius.circular(radius ?? 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
RTextField.noBorder(
|
||||||
|
{super.key,
|
||||||
|
this.maxLines,
|
||||||
|
this.maxLength,
|
||||||
|
this.hintText,
|
||||||
|
this.padding,
|
||||||
|
this.onChanged,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.keyboardType,
|
||||||
|
this.showCounter = false,
|
||||||
|
this.isDense,
|
||||||
|
this.initText,
|
||||||
|
this.style,
|
||||||
|
this.hintStyle,
|
||||||
|
this.suffixIcon,
|
||||||
|
this.radius,
|
||||||
|
this.validator,
|
||||||
|
this.boxConstraints,
|
||||||
|
this.minLines,
|
||||||
|
this.isForNumber = false,
|
||||||
|
this.readonly = false,
|
||||||
|
this.label,
|
||||||
|
this.filled,
|
||||||
|
this.errorStyle,
|
||||||
|
this.labelStyle,
|
||||||
|
this.enabled}) {
|
||||||
|
_inputBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
borderRadius: BorderRadius.circular(radius ?? 16));
|
||||||
|
obscure = false;
|
||||||
|
filled = filled ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTextField.password(
|
||||||
|
{super.key,
|
||||||
|
this.maxLines = 1,
|
||||||
|
this.maxLength,
|
||||||
|
this.hintText,
|
||||||
|
this.padding,
|
||||||
|
this.onChanged,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.keyboardType,
|
||||||
|
this.showCounter = false,
|
||||||
|
this.isDense,
|
||||||
|
this.initText,
|
||||||
|
this.style,
|
||||||
|
this.hintStyle,
|
||||||
|
this.suffixIcon,
|
||||||
|
this.prefixIcon,
|
||||||
|
this.radius,
|
||||||
|
this.validator,
|
||||||
|
this.boxConstraints,
|
||||||
|
this.minLines,
|
||||||
|
this.isForNumber = false,
|
||||||
|
this.readonly = false,
|
||||||
|
this.label,
|
||||||
|
this.filled,
|
||||||
|
this.errorStyle,
|
||||||
|
this.labelStyle,
|
||||||
|
this.enabled}) {
|
||||||
|
_inputBorder = OutlineInputBorder(
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
borderRadius: BorderRadius.circular(radius ?? 16));
|
||||||
|
filled = filled ?? true;
|
||||||
|
obscure = true;
|
||||||
|
_isPassword = true;
|
||||||
|
prefixIcon = prefixIcon ?? const Icon(CupertinoIcons.person);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int? maxLines;
|
||||||
|
final int? minLines;
|
||||||
|
final int? maxLength;
|
||||||
|
final String? hintText;
|
||||||
|
final String? label;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
final TextStyle? style;
|
||||||
|
final TextStyle? errorStyle;
|
||||||
|
final TextStyle? hintStyle;
|
||||||
|
final TextStyle? labelStyle;
|
||||||
|
final bool showCounter;
|
||||||
|
final bool? isDense;
|
||||||
|
final bool? isForNumber;
|
||||||
|
final bool readonly;
|
||||||
|
bool? obscure;
|
||||||
|
final bool? enabled;
|
||||||
|
final double? radius;
|
||||||
|
final TextInputType? keyboardType;
|
||||||
|
final Function(String)? onChanged;
|
||||||
|
final Function(String)? onSubmitted;
|
||||||
|
final FormFieldValidator? validator;
|
||||||
|
final String? initText;
|
||||||
|
Widget? suffixIcon;
|
||||||
|
Widget? prefixIcon;
|
||||||
|
bool? filled;
|
||||||
|
bool _isPassword = false;
|
||||||
|
|
||||||
|
final BoxConstraints? boxConstraints;
|
||||||
|
late final InputBorder? _inputBorder;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RTextField> createState() => _RTextFieldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RTextFieldState extends State<RTextField> {
|
||||||
|
final TextEditingController _controller = TextEditingController();
|
||||||
|
bool? obscure;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.initText != null) {
|
||||||
|
_controller.text = widget.initText!;
|
||||||
|
}
|
||||||
|
obscure = widget.obscure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant RTextField oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (widget.initText != oldWidget.initText) {
|
||||||
|
_controller.text = widget.initText ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: widget.padding ?? const EdgeInsets.symmetric(vertical: 6.0),
|
||||||
|
child: TextFormField(
|
||||||
|
controller: _controller,
|
||||||
|
readOnly: widget.readonly,
|
||||||
|
minLines: widget.minLines,
|
||||||
|
maxLines: widget.maxLines,
|
||||||
|
onChanged: widget.onChanged,
|
||||||
|
validator: widget.validator,
|
||||||
|
enabled: widget.enabled,
|
||||||
|
obscureText: obscure ?? false,
|
||||||
|
onTapOutside: (event) {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
},
|
||||||
|
onFieldSubmitted: widget.onSubmitted,
|
||||||
|
maxLength: widget.maxLength,
|
||||||
|
textDirection: TextDirection.rtl,
|
||||||
|
style: widget.style ,
|
||||||
|
keyboardType: widget.keyboardType,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
errorStyle: widget.errorStyle,
|
||||||
|
errorMaxLines: 1,
|
||||||
|
isDense: widget.isDense,
|
||||||
|
suffixIcon: widget.suffixIcon ??
|
||||||
|
(widget._isPassword
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
obscure = !obscure!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: Icon(!obscure!
|
||||||
|
? CupertinoIcons.eye_slash
|
||||||
|
: CupertinoIcons.eye))
|
||||||
|
: null),
|
||||||
|
suffixIconConstraints: widget.boxConstraints,
|
||||||
|
prefixIcon: widget.prefixIcon,
|
||||||
|
prefixIconConstraints: widget.boxConstraints,
|
||||||
|
hintText: widget.hintText,
|
||||||
|
labelText: widget.label,
|
||||||
|
labelStyle: widget.labelStyle,
|
||||||
|
filled: widget.filled,
|
||||||
|
counter: widget.showCounter ? null : const SizedBox(),
|
||||||
|
hintStyle: widget.hintStyle,
|
||||||
|
enabledBorder: widget._inputBorder,
|
||||||
|
focusedBorder: widget._inputBorder,
|
||||||
|
border: widget._inputBorder),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
255
lib/presentation/widget/pagination/pagination_from_until.dart
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||||
|
|
||||||
|
class PaginationFromUntil extends StatefulWidget {
|
||||||
|
const PaginationFromUntil({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PaginationFromUntil> createState() => _PaginationFromUntilState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaginationFromUntilState extends State<PaginationFromUntil> {
|
||||||
|
int current = 1;
|
||||||
|
int total = 10;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: 164,
|
||||||
|
height: 47,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
decoration: ShapeDecoration(
|
||||||
|
color: const Color(0xFFEAEFFF),
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
FloatingActionButton.small(
|
||||||
|
onPressed: () {
|
||||||
|
if(current>1){
|
||||||
|
setState(() {
|
||||||
|
current--;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
shape: CircleBorder(),
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
child: Icon(CupertinoIcons.arrow_left, color: AppColor.blueNormal),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'$current از $total',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
textDirection: TextDirection.rtl,
|
||||||
|
style: AppFonts.yekan16Regular.copyWith(
|
||||||
|
color: AppColor.blueNormal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FloatingActionButton.small(
|
||||||
|
|
||||||
|
onPressed:() {
|
||||||
|
if (current < total) {
|
||||||
|
setState(() {
|
||||||
|
current++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shape: CircleBorder(),
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: AppColor.blueNormal,
|
||||||
|
child: Icon(CupertinoIcons.arrow_right, color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack buildStack() {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 4,
|
||||||
|
top: 4,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 40,
|
||||||
|
top: 40,
|
||||||
|
child: Container(
|
||||||
|
transform:
|
||||||
|
Matrix4.identity()
|
||||||
|
..translate(0.0, 0.0)
|
||||||
|
..rotateZ(-3.14),
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
decoration: ShapeDecoration(
|
||||||
|
color:
|
||||||
|
Colors.white /* Secondary */,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: BorderSide(
|
||||||
|
width: 1,
|
||||||
|
color:
|
||||||
|
Colors
|
||||||
|
.white /* Secondary */,
|
||||||
|
),
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Stack(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 8,
|
||||||
|
top: 8,
|
||||||
|
child: Container(width: 24, height: 24, child: Stack()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 120,
|
||||||
|
top: 3,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 40,
|
||||||
|
top: 40,
|
||||||
|
child: Container(
|
||||||
|
transform:
|
||||||
|
Matrix4.identity()
|
||||||
|
..translate(0.0, 0.0)
|
||||||
|
..rotateZ(-3.14),
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
decoration: ShapeDecoration(
|
||||||
|
color: const Color(
|
||||||
|
0xFF2D5FFF,
|
||||||
|
) /* Primary */,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: BorderSide(
|
||||||
|
width: 1,
|
||||||
|
color: const Color(
|
||||||
|
0xFF2D5FFF,
|
||||||
|
) /* Primary */,
|
||||||
|
),
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Stack(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 8,
|
||||||
|
top: 8,
|
||||||
|
child: Container(width: 24, height: 24, child: Stack()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 63,
|
||||||
|
top: 9,
|
||||||
|
child: Text(
|
||||||
|
'1 از 17',
|
||||||
|
style: TextStyle(
|
||||||
|
color: const Color(0xFF2D5FFF) /* Primary */,
|
||||||
|
fontSize: 16,
|
||||||
|
fontFamily: 'IRANYekanFN',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
height: 1.75,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
78
lib/presentation/widget/pagination/show_more.dart
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||||
|
|
||||||
|
class RShowMore extends StatefulWidget {
|
||||||
|
const RShowMore({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RShowMore> createState() => _RShowMoreState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RShowMoreState extends State<RShowMore>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
bool _toggled = false;
|
||||||
|
late final AnimationController _controller;
|
||||||
|
late final Animation<double> _iconRotation;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_controller = AnimationController(
|
||||||
|
vsync: this,
|
||||||
|
duration: const Duration(milliseconds: 500),
|
||||||
|
);
|
||||||
|
_iconRotation = Tween<double>(
|
||||||
|
begin: 0,
|
||||||
|
end: 0.50,
|
||||||
|
) // 90 degrees (quarter turn)
|
||||||
|
.animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggle() {
|
||||||
|
setState(() => _toggled = !_toggled);
|
||||||
|
_toggled ? _controller.forward() : _controller.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: _toggle,
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
RotationTransition(
|
||||||
|
turns: _iconRotation,
|
||||||
|
child: const Icon(CupertinoIcons.chevron_down, size: 12,color:AppColor.blueNormal ,),
|
||||||
|
),
|
||||||
|
|
||||||
|
AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 500),
|
||||||
|
transitionBuilder:
|
||||||
|
(child, animation) =>
|
||||||
|
FadeTransition(opacity: animation, child: child),
|
||||||
|
child: Text(
|
||||||
|
_toggled ? 'کمتر' : 'مشاهده بیشتر',
|
||||||
|
key: ValueKey(_toggled),
|
||||||
|
style: AppFonts.yekan10Regular.copyWith(color: AppColor.blueNormal),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 50,)
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
784
lib/presentation/widget/tabs/new_tab.dart
Normal file
@@ -0,0 +1,784 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
/// @docImport 'switch.dart';
|
||||||
|
library;
|
||||||
|
|
||||||
|
import 'dart:collection';
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/rendering.dart';
|
||||||
|
|
||||||
|
// Minimum padding from edges of the segmented control to edges of
|
||||||
|
// encompassing widget.
|
||||||
|
const EdgeInsetsGeometry _kHorizontalItemPadding = EdgeInsets.symmetric(
|
||||||
|
horizontal: 16.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Minimum height of the segmented control.
|
||||||
|
const double _kMinSegmentedControlHeight = 28.0;
|
||||||
|
|
||||||
|
// The default color used for the text of the disabled segment.
|
||||||
|
const Color _kDisableTextColor = Color.fromARGB(115, 122, 122, 122);
|
||||||
|
|
||||||
|
// The duration of the fade animation used to transition when a new widget
|
||||||
|
// is selected.
|
||||||
|
const Duration _kFadeDuration = Duration(milliseconds: 165);
|
||||||
|
|
||||||
|
class NewCupertinoSegmentedControl<T extends Object> extends StatefulWidget {
|
||||||
|
/// Creates an iOS-style segmented control bar.
|
||||||
|
///
|
||||||
|
/// The [children] argument must be an ordered [Map] such as a
|
||||||
|
/// [LinkedHashMap]. Further, the length of the [children] list must be
|
||||||
|
/// greater than one.
|
||||||
|
///
|
||||||
|
/// Each widget value in the map of [children] must have an associated key
|
||||||
|
/// that uniquely identifies this widget. This key is what will be returned
|
||||||
|
/// in the [onValueChanged] callback when a new value from the [children] map
|
||||||
|
/// is selected.
|
||||||
|
///
|
||||||
|
/// The [groupValue] is the currently selected value for the segmented control.
|
||||||
|
/// If no [groupValue] is provided, or the [groupValue] is null, no widget will
|
||||||
|
/// appear as selected. The [groupValue] must be either null or one of the keys
|
||||||
|
/// in the [children] map.
|
||||||
|
NewCupertinoSegmentedControl({
|
||||||
|
super.key,
|
||||||
|
required this.children,
|
||||||
|
required this.onValueChanged,
|
||||||
|
this.groupValue,
|
||||||
|
this.unselectedColor,
|
||||||
|
this.selectedColor,
|
||||||
|
this.borderColor,
|
||||||
|
this.pressedColor,
|
||||||
|
this.disabledColor,
|
||||||
|
this.disabledTextColor,
|
||||||
|
this.padding,
|
||||||
|
this.disabledChildren = const <Never>{},
|
||||||
|
}) : assert(children.length >= 2),
|
||||||
|
assert(
|
||||||
|
groupValue == null ||
|
||||||
|
children.keys.any((T child) => child == groupValue),
|
||||||
|
'The groupValue must be either null or one of the keys in the children map.',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// The identifying keys and corresponding widget values in the
|
||||||
|
/// segmented control.
|
||||||
|
///
|
||||||
|
/// The map must have more than one entry.
|
||||||
|
/// This attribute must be an ordered [Map] such as a [LinkedHashMap].
|
||||||
|
final Map<T, Widget> children;
|
||||||
|
|
||||||
|
/// The identifier of the widget that is currently selected.
|
||||||
|
///
|
||||||
|
/// This must be one of the keys in the [Map] of [children].
|
||||||
|
/// If this attribute is null, no widget will be initially selected.
|
||||||
|
final T? groupValue;
|
||||||
|
|
||||||
|
/// The callback that is called when a new option is tapped.
|
||||||
|
///
|
||||||
|
/// The segmented control passes the newly selected widget's associated key
|
||||||
|
/// to the callback but does not actually change state until the parent
|
||||||
|
/// widget rebuilds the segmented control with the new [groupValue].
|
||||||
|
final ValueChanged<T> onValueChanged;
|
||||||
|
|
||||||
|
/// The color used to fill the backgrounds of unselected widgets and as the
|
||||||
|
/// text color of the selected widget.
|
||||||
|
///
|
||||||
|
/// Defaults to [CupertinoTheme]'s `primaryContrastingColor` if null.
|
||||||
|
final Color? unselectedColor;
|
||||||
|
|
||||||
|
/// The color used to fill the background of the selected widget and as the text
|
||||||
|
/// color of unselected widgets.
|
||||||
|
///
|
||||||
|
/// Defaults to [CupertinoTheme]'s `primaryColor` if null.
|
||||||
|
final Color? selectedColor;
|
||||||
|
|
||||||
|
/// The color used as the border around each widget.
|
||||||
|
///
|
||||||
|
/// Defaults to [CupertinoTheme]'s `primaryColor` if null.
|
||||||
|
final Color? borderColor;
|
||||||
|
|
||||||
|
/// The color used to fill the background of the widget the user is
|
||||||
|
/// temporarily interacting with through a long press or drag.
|
||||||
|
///
|
||||||
|
/// Defaults to the selectedColor at 20% opacity if null.
|
||||||
|
final Color? pressedColor;
|
||||||
|
|
||||||
|
/// The color used to fill the background of the segment when it is disabled.
|
||||||
|
///
|
||||||
|
/// If null, this color will be 50% opacity of the [selectedColor] when
|
||||||
|
/// the segment is selected. If the segment is unselected, this color will be
|
||||||
|
/// set to [unselectedColor].
|
||||||
|
final Color? disabledColor;
|
||||||
|
|
||||||
|
/// The color used for the text of the segment when it is disabled.
|
||||||
|
final Color? disabledTextColor;
|
||||||
|
|
||||||
|
/// The CupertinoSegmentedControl will be placed inside this padding.
|
||||||
|
///
|
||||||
|
/// Defaults to EdgeInsets.symmetric(horizontal: 16.0)
|
||||||
|
final EdgeInsetsGeometry? padding;
|
||||||
|
|
||||||
|
/// The set of identifying keys that correspond to the segments that should be disabled.
|
||||||
|
///
|
||||||
|
/// All segments are enabled by default.
|
||||||
|
final Set<T> disabledChildren;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<NewCupertinoSegmentedControl<T>> createState() =>
|
||||||
|
_SegmentedControlState<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SegmentedControlState<T extends Object>
|
||||||
|
extends State<NewCupertinoSegmentedControl<T>>
|
||||||
|
with TickerProviderStateMixin<NewCupertinoSegmentedControl<T>> {
|
||||||
|
T? _pressedKey;
|
||||||
|
|
||||||
|
final List<AnimationController> _selectionControllers =
|
||||||
|
<AnimationController>[];
|
||||||
|
final List<ColorTween> _childTweens = <ColorTween>[];
|
||||||
|
|
||||||
|
late ColorTween _forwardBackgroundColorTween;
|
||||||
|
late ColorTween _reverseBackgroundColorTween;
|
||||||
|
late ColorTween _textColorTween;
|
||||||
|
|
||||||
|
Color? _selectedColor;
|
||||||
|
Color? _unselectedColor;
|
||||||
|
Color? _borderColor;
|
||||||
|
Color? _pressedColor;
|
||||||
|
Color? _selectedDisabledColor;
|
||||||
|
Color? _unselectedDisabledColor;
|
||||||
|
Color? _disabledTextColor;
|
||||||
|
|
||||||
|
AnimationController createAnimationController() {
|
||||||
|
return AnimationController(duration: _kFadeDuration, vsync: this)
|
||||||
|
..addListener(() {
|
||||||
|
setState(() {
|
||||||
|
// State of background/text colors has changed
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _updateColors() {
|
||||||
|
assert(mounted, 'This should only be called after didUpdateDependencies');
|
||||||
|
bool changed = false;
|
||||||
|
final Color disabledTextColor =
|
||||||
|
widget.disabledTextColor ?? _kDisableTextColor;
|
||||||
|
if (_disabledTextColor != disabledTextColor) {
|
||||||
|
changed = true;
|
||||||
|
_disabledTextColor = disabledTextColor;
|
||||||
|
}
|
||||||
|
final Color selectedColor =
|
||||||
|
widget.selectedColor ?? CupertinoTheme.of(context).primaryColor;
|
||||||
|
if (_selectedColor != selectedColor) {
|
||||||
|
changed = true;
|
||||||
|
_selectedColor = selectedColor;
|
||||||
|
}
|
||||||
|
final Color unselectedColor =
|
||||||
|
widget.unselectedColor ??
|
||||||
|
CupertinoTheme.of(context).primaryContrastingColor;
|
||||||
|
if (_unselectedColor != unselectedColor) {
|
||||||
|
changed = true;
|
||||||
|
_unselectedColor = unselectedColor;
|
||||||
|
}
|
||||||
|
final Color selectedDisabledColor =
|
||||||
|
widget.disabledColor ?? selectedColor.withOpacity(0.5);
|
||||||
|
final Color unselectedDisabledColor =
|
||||||
|
widget.disabledColor ?? unselectedColor;
|
||||||
|
if (_selectedDisabledColor != selectedDisabledColor ||
|
||||||
|
_unselectedDisabledColor != unselectedDisabledColor) {
|
||||||
|
changed = true;
|
||||||
|
_selectedDisabledColor = selectedDisabledColor;
|
||||||
|
_unselectedDisabledColor = unselectedDisabledColor;
|
||||||
|
}
|
||||||
|
final Color borderColor =
|
||||||
|
widget.borderColor ?? CupertinoTheme.of(context).primaryColor;
|
||||||
|
if (_borderColor != borderColor) {
|
||||||
|
changed = true;
|
||||||
|
_borderColor = borderColor;
|
||||||
|
}
|
||||||
|
final Color pressedColor =
|
||||||
|
widget.pressedColor ??
|
||||||
|
CupertinoTheme.of(context).primaryColor.withOpacity(0.2);
|
||||||
|
if (_pressedColor != pressedColor) {
|
||||||
|
changed = true;
|
||||||
|
_pressedColor = pressedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
_forwardBackgroundColorTween = ColorTween(
|
||||||
|
begin: _pressedColor,
|
||||||
|
end: _selectedColor,
|
||||||
|
);
|
||||||
|
_reverseBackgroundColorTween = ColorTween(
|
||||||
|
begin: _unselectedColor,
|
||||||
|
end: _selectedColor,
|
||||||
|
);
|
||||||
|
_textColorTween = ColorTween(begin: _selectedColor, end: _unselectedColor);
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateAnimationControllers() {
|
||||||
|
assert(mounted, 'This should only be called after didUpdateDependencies');
|
||||||
|
for (final AnimationController controller in _selectionControllers) {
|
||||||
|
controller.dispose();
|
||||||
|
}
|
||||||
|
_selectionControllers.clear();
|
||||||
|
_childTweens.clear();
|
||||||
|
|
||||||
|
for (final T key in widget.children.keys) {
|
||||||
|
final AnimationController animationController =
|
||||||
|
createAnimationController();
|
||||||
|
if (widget.groupValue == key) {
|
||||||
|
_childTweens.add(_reverseBackgroundColorTween);
|
||||||
|
animationController.value = 1.0;
|
||||||
|
} else {
|
||||||
|
_childTweens.add(_forwardBackgroundColorTween);
|
||||||
|
}
|
||||||
|
_selectionControllers.add(animationController);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
|
||||||
|
if (_updateColors()) {
|
||||||
|
_updateAnimationControllers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(NewCupertinoSegmentedControl<T> oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
|
if (_updateColors() ||
|
||||||
|
oldWidget.children.length != widget.children.length) {
|
||||||
|
_updateAnimationControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldWidget.groupValue != widget.groupValue) {
|
||||||
|
int index = 0;
|
||||||
|
for (final T key in widget.children.keys) {
|
||||||
|
if (widget.groupValue == key) {
|
||||||
|
_childTweens[index] = _forwardBackgroundColorTween;
|
||||||
|
_selectionControllers[index].forward();
|
||||||
|
} else {
|
||||||
|
_childTweens[index] = _reverseBackgroundColorTween;
|
||||||
|
_selectionControllers[index].reverse();
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
for (final AnimationController animationController
|
||||||
|
in _selectionControllers) {
|
||||||
|
animationController.dispose();
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTapDown(T currentKey) {
|
||||||
|
if (_pressedKey == null && currentKey != widget.groupValue) {
|
||||||
|
setState(() {
|
||||||
|
_pressedKey = currentKey;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTapCancel() {
|
||||||
|
setState(() {
|
||||||
|
_pressedKey = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTap(T currentKey) {
|
||||||
|
if (currentKey != _pressedKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!widget.disabledChildren.contains(currentKey)) {
|
||||||
|
if (currentKey != widget.groupValue) {
|
||||||
|
widget.onValueChanged(currentKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pressedKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color? getTextColor(int index, T currentKey) {
|
||||||
|
if (widget.disabledChildren.contains(currentKey)) {
|
||||||
|
return _disabledTextColor;
|
||||||
|
}
|
||||||
|
if (_selectionControllers[index].isAnimating) {
|
||||||
|
return _textColorTween.evaluate(_selectionControllers[index]);
|
||||||
|
}
|
||||||
|
if (widget.groupValue == currentKey) {
|
||||||
|
return _unselectedColor;
|
||||||
|
}
|
||||||
|
return _selectedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color? getBackgroundColor(int index, T currentKey) {
|
||||||
|
if (widget.disabledChildren.contains(currentKey)) {
|
||||||
|
return widget.groupValue == currentKey
|
||||||
|
? _selectedDisabledColor
|
||||||
|
: _unselectedDisabledColor;
|
||||||
|
}
|
||||||
|
if (_selectionControllers[index].isAnimating) {
|
||||||
|
return _childTweens[index].evaluate(_selectionControllers[index]);
|
||||||
|
}
|
||||||
|
if (widget.groupValue == currentKey) {
|
||||||
|
return _selectedColor;
|
||||||
|
}
|
||||||
|
if (_pressedKey == currentKey) {
|
||||||
|
return _pressedColor;
|
||||||
|
}
|
||||||
|
return _unselectedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final List<Widget> gestureChildren = <Widget>[];
|
||||||
|
final List<Color> backgroundColors = <Color>[];
|
||||||
|
int index = 0;
|
||||||
|
int? selectedIndex;
|
||||||
|
int? pressedIndex;
|
||||||
|
for (final T currentKey in widget.children.keys) {
|
||||||
|
selectedIndex = (widget.groupValue == currentKey) ? index : selectedIndex;
|
||||||
|
pressedIndex = (_pressedKey == currentKey) ? index : pressedIndex;
|
||||||
|
|
||||||
|
final TextStyle textStyle = DefaultTextStyle.of(
|
||||||
|
context,
|
||||||
|
).style.copyWith(color: getTextColor(index, currentKey));
|
||||||
|
final IconThemeData iconTheme = IconThemeData(
|
||||||
|
color: getTextColor(index, currentKey),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget child = Center(child: widget.children[currentKey]);
|
||||||
|
|
||||||
|
child = MouseRegion(
|
||||||
|
cursor: kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
|
||||||
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTapDown:
|
||||||
|
widget.disabledChildren.contains(currentKey)
|
||||||
|
? null
|
||||||
|
: (TapDownDetails event) {
|
||||||
|
_onTapDown(currentKey);
|
||||||
|
},
|
||||||
|
onTapCancel:
|
||||||
|
widget.disabledChildren.contains(currentKey)
|
||||||
|
? null
|
||||||
|
: _onTapCancel,
|
||||||
|
onTap: () {
|
||||||
|
_onTap(currentKey);
|
||||||
|
},
|
||||||
|
child: IconTheme(
|
||||||
|
data: iconTheme,
|
||||||
|
child: DefaultTextStyle(
|
||||||
|
style: textStyle,
|
||||||
|
child: Semantics(
|
||||||
|
button: true,
|
||||||
|
inMutuallyExclusiveGroup: true,
|
||||||
|
selected: widget.groupValue == currentKey,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
backgroundColors.add(getBackgroundColor(index, currentKey)!);
|
||||||
|
gestureChildren.add(child);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Widget box = _SegmentedControlRenderWidget<T>(
|
||||||
|
selectedIndex: selectedIndex,
|
||||||
|
pressedIndex: pressedIndex,
|
||||||
|
backgroundColors: backgroundColors,
|
||||||
|
borderColor: _borderColor!,
|
||||||
|
children: gestureChildren,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: widget.padding ?? _kHorizontalItemPadding,
|
||||||
|
child: UnconstrainedBox(constrainedAxis: Axis.horizontal, child: box),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
|
||||||
|
const _SegmentedControlRenderWidget({
|
||||||
|
super.key,
|
||||||
|
super.children,
|
||||||
|
required this.selectedIndex,
|
||||||
|
required this.pressedIndex,
|
||||||
|
required this.backgroundColors,
|
||||||
|
required this.borderColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
final int? selectedIndex;
|
||||||
|
final int? pressedIndex;
|
||||||
|
final List<Color> backgroundColors;
|
||||||
|
final Color borderColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
RenderObject createRenderObject(BuildContext context) {
|
||||||
|
return _RenderSegmentedControl<T>(
|
||||||
|
textDirection: Directionality.of(context),
|
||||||
|
selectedIndex: selectedIndex,
|
||||||
|
pressedIndex: pressedIndex,
|
||||||
|
backgroundColors: backgroundColors,
|
||||||
|
borderColor: borderColor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void updateRenderObject(
|
||||||
|
BuildContext context,
|
||||||
|
_RenderSegmentedControl<T> renderObject,
|
||||||
|
) {
|
||||||
|
renderObject
|
||||||
|
..textDirection = Directionality.of(context)
|
||||||
|
..selectedIndex = selectedIndex
|
||||||
|
..pressedIndex = pressedIndex
|
||||||
|
..backgroundColors = backgroundColors
|
||||||
|
..borderColor = borderColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SegmentedControlContainerBoxParentData
|
||||||
|
extends ContainerBoxParentData<RenderBox> {
|
||||||
|
RRect? surroundingRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef _NextChild = RenderBox? Function(RenderBox child);
|
||||||
|
|
||||||
|
class _RenderSegmentedControl<T> extends RenderBox
|
||||||
|
with
|
||||||
|
ContainerRenderObjectMixin<
|
||||||
|
RenderBox,
|
||||||
|
ContainerBoxParentData<RenderBox>
|
||||||
|
>,
|
||||||
|
RenderBoxContainerDefaultsMixin<
|
||||||
|
RenderBox,
|
||||||
|
ContainerBoxParentData<RenderBox>
|
||||||
|
> {
|
||||||
|
_RenderSegmentedControl({
|
||||||
|
required int? selectedIndex,
|
||||||
|
required int? pressedIndex,
|
||||||
|
required TextDirection textDirection,
|
||||||
|
required List<Color> backgroundColors,
|
||||||
|
required Color borderColor,
|
||||||
|
}) : _textDirection = textDirection,
|
||||||
|
_selectedIndex = selectedIndex,
|
||||||
|
_pressedIndex = pressedIndex,
|
||||||
|
_backgroundColors = backgroundColors,
|
||||||
|
_borderColor = borderColor;
|
||||||
|
|
||||||
|
int? get selectedIndex => _selectedIndex;
|
||||||
|
int? _selectedIndex;
|
||||||
|
|
||||||
|
set selectedIndex(int? value) {
|
||||||
|
if (_selectedIndex == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_selectedIndex = value;
|
||||||
|
markNeedsPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
int? get pressedIndex => _pressedIndex;
|
||||||
|
int? _pressedIndex;
|
||||||
|
|
||||||
|
set pressedIndex(int? value) {
|
||||||
|
if (_pressedIndex == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_pressedIndex = value;
|
||||||
|
markNeedsPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextDirection get textDirection => _textDirection;
|
||||||
|
TextDirection _textDirection;
|
||||||
|
|
||||||
|
set textDirection(TextDirection value) {
|
||||||
|
if (_textDirection == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_textDirection = value;
|
||||||
|
markNeedsLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Color> get backgroundColors => _backgroundColors;
|
||||||
|
List<Color> _backgroundColors;
|
||||||
|
|
||||||
|
set backgroundColors(List<Color> value) {
|
||||||
|
if (_backgroundColors == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_backgroundColors = value;
|
||||||
|
markNeedsPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color get borderColor => _borderColor;
|
||||||
|
Color _borderColor;
|
||||||
|
|
||||||
|
set borderColor(Color value) {
|
||||||
|
if (_borderColor == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_borderColor = value;
|
||||||
|
markNeedsPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double computeMinIntrinsicWidth(double height) {
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
double minWidth = 0.0;
|
||||||
|
while (child != null) {
|
||||||
|
final _SegmentedControlContainerBoxParentData childParentData =
|
||||||
|
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||||
|
final double childWidth = child.getMinIntrinsicWidth(height);
|
||||||
|
minWidth = math.max(minWidth, childWidth);
|
||||||
|
child = childParentData.nextSibling;
|
||||||
|
}
|
||||||
|
return minWidth * childCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double computeMaxIntrinsicWidth(double height) {
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
double maxWidth = 0.0;
|
||||||
|
while (child != null) {
|
||||||
|
final _SegmentedControlContainerBoxParentData childParentData =
|
||||||
|
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||||
|
final double childWidth = child.getMaxIntrinsicWidth(height);
|
||||||
|
maxWidth = math.max(maxWidth, childWidth);
|
||||||
|
child = childParentData.nextSibling;
|
||||||
|
}
|
||||||
|
return maxWidth * childCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double computeMinIntrinsicHeight(double width) {
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
double minHeight = 0.0;
|
||||||
|
while (child != null) {
|
||||||
|
final _SegmentedControlContainerBoxParentData childParentData =
|
||||||
|
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||||
|
final double childHeight = child.getMinIntrinsicHeight(width);
|
||||||
|
minHeight = math.max(minHeight, childHeight);
|
||||||
|
child = childParentData.nextSibling;
|
||||||
|
}
|
||||||
|
return minHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double computeMaxIntrinsicHeight(double width) {
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
double maxHeight = 0.0;
|
||||||
|
while (child != null) {
|
||||||
|
final _SegmentedControlContainerBoxParentData childParentData =
|
||||||
|
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||||
|
final double childHeight = child.getMaxIntrinsicHeight(width);
|
||||||
|
maxHeight = math.max(maxHeight, childHeight);
|
||||||
|
child = childParentData.nextSibling;
|
||||||
|
}
|
||||||
|
return maxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||||
|
return defaultComputeDistanceToHighestActualBaseline(baseline);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setupParentData(RenderBox child) {
|
||||||
|
if (child.parentData is! _SegmentedControlContainerBoxParentData) {
|
||||||
|
child.parentData = _SegmentedControlContainerBoxParentData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _layoutRects(
|
||||||
|
_NextChild nextChild,
|
||||||
|
RenderBox? leftChild,
|
||||||
|
RenderBox? rightChild,
|
||||||
|
) {
|
||||||
|
RenderBox? child = leftChild;
|
||||||
|
double start = 0.0;
|
||||||
|
while (child != null) {
|
||||||
|
final _SegmentedControlContainerBoxParentData childParentData =
|
||||||
|
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||||
|
final Offset childOffset = Offset(start, 0.0);
|
||||||
|
childParentData.offset = childOffset;
|
||||||
|
final Rect childRect = Rect.fromLTWH(
|
||||||
|
start,
|
||||||
|
0.0,
|
||||||
|
child.size.width,
|
||||||
|
child.size.height,
|
||||||
|
);
|
||||||
|
final RRect rChildRect;
|
||||||
|
if (child == leftChild) {
|
||||||
|
rChildRect = RRect.fromRectAndCorners(
|
||||||
|
childRect,
|
||||||
|
topLeft: const Radius.circular(10.0),
|
||||||
|
bottomLeft: const Radius.circular(10.0),
|
||||||
|
);
|
||||||
|
} else if (child == rightChild) {
|
||||||
|
rChildRect = RRect.fromRectAndCorners(
|
||||||
|
childRect,
|
||||||
|
topRight: const Radius.circular(10.0),
|
||||||
|
bottomRight: const Radius.circular(10.0),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
rChildRect = RRect.fromRectAndCorners(childRect);
|
||||||
|
}
|
||||||
|
childParentData.surroundingRect = rChildRect;
|
||||||
|
start += child.size.width;
|
||||||
|
child = nextChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Size _calculateChildSize(BoxConstraints constraints) {
|
||||||
|
double maxHeight = _kMinSegmentedControlHeight;
|
||||||
|
double childWidth = constraints.minWidth / childCount;
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
while (child != null) {
|
||||||
|
childWidth = math.max(
|
||||||
|
childWidth,
|
||||||
|
child.getMaxIntrinsicWidth(double.infinity),
|
||||||
|
);
|
||||||
|
child = childAfter(child);
|
||||||
|
}
|
||||||
|
childWidth = math.min(childWidth, constraints.maxWidth / childCount);
|
||||||
|
child = firstChild;
|
||||||
|
while (child != null) {
|
||||||
|
final double boxHeight = child.getMaxIntrinsicHeight(childWidth);
|
||||||
|
maxHeight = math.max(maxHeight, boxHeight);
|
||||||
|
child = childAfter(child);
|
||||||
|
}
|
||||||
|
return Size(childWidth, maxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size _computeOverallSizeFromChildSize(Size childSize) {
|
||||||
|
return constraints.constrain(
|
||||||
|
Size(childSize.width * childCount, childSize.height),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double? computeDryBaseline(
|
||||||
|
covariant BoxConstraints constraints,
|
||||||
|
TextBaseline baseline,
|
||||||
|
) {
|
||||||
|
final Size childSize = _calculateChildSize(constraints);
|
||||||
|
final BoxConstraints childConstraints = BoxConstraints.tight(childSize);
|
||||||
|
|
||||||
|
BaselineOffset baselineOffset = BaselineOffset.noBaseline;
|
||||||
|
for (
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
child != null;
|
||||||
|
child = childAfter(child)
|
||||||
|
) {
|
||||||
|
baselineOffset = baselineOffset.minOf(
|
||||||
|
BaselineOffset(child.getDryBaseline(childConstraints, baseline)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return baselineOffset.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size computeDryLayout(BoxConstraints constraints) {
|
||||||
|
final Size childSize = _calculateChildSize(constraints);
|
||||||
|
return _computeOverallSizeFromChildSize(childSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void performLayout() {
|
||||||
|
final BoxConstraints constraints = this.constraints;
|
||||||
|
final Size childSize = _calculateChildSize(constraints);
|
||||||
|
|
||||||
|
final BoxConstraints childConstraints = BoxConstraints.tightFor(
|
||||||
|
width: childSize.width,
|
||||||
|
height: childSize.height,
|
||||||
|
);
|
||||||
|
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
while (child != null) {
|
||||||
|
child.layout(childConstraints, parentUsesSize: true);
|
||||||
|
child = childAfter(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (textDirection) {
|
||||||
|
case TextDirection.rtl:
|
||||||
|
_layoutRects(childBefore, lastChild, firstChild);
|
||||||
|
case TextDirection.ltr:
|
||||||
|
_layoutRects(childAfter, firstChild, lastChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
size = _computeOverallSizeFromChildSize(childSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(PaintingContext context, Offset offset) {
|
||||||
|
RenderBox? child = firstChild;
|
||||||
|
int index = 0;
|
||||||
|
while (child != null) {
|
||||||
|
_paintChild(context, offset, child, index);
|
||||||
|
child = childAfter(child);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _paintChild(
|
||||||
|
PaintingContext context,
|
||||||
|
Offset offset,
|
||||||
|
RenderBox child,
|
||||||
|
int childIndex,
|
||||||
|
) {
|
||||||
|
final _SegmentedControlContainerBoxParentData childParentData =
|
||||||
|
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||||
|
|
||||||
|
context.canvas.drawRRect(
|
||||||
|
childParentData.surroundingRect!.shift(offset),
|
||||||
|
Paint()
|
||||||
|
..color = backgroundColors[childIndex]
|
||||||
|
..style = PaintingStyle.fill,
|
||||||
|
);
|
||||||
|
context.canvas.drawRRect(
|
||||||
|
childParentData.surroundingRect!.shift(offset),
|
||||||
|
Paint()
|
||||||
|
..color = borderColor
|
||||||
|
..strokeWidth = 1.0
|
||||||
|
..style = PaintingStyle.stroke,
|
||||||
|
);
|
||||||
|
|
||||||
|
context.paintChild(child, childParentData.offset + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
|
||||||
|
RenderBox? child = lastChild;
|
||||||
|
while (child != null) {
|
||||||
|
final _SegmentedControlContainerBoxParentData childParentData =
|
||||||
|
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||||
|
if (childParentData.surroundingRect!.contains(position)) {
|
||||||
|
return result.addWithPaintOffset(
|
||||||
|
offset: childParentData.offset,
|
||||||
|
position: position,
|
||||||
|
hitTest: (BoxHitTestResult result, Offset localOffset) {
|
||||||
|
assert(localOffset == position - childParentData.offset);
|
||||||
|
return child!.hitTest(result, position: localOffset);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
child = childParentData.previousSibling;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
115
lib/presentation/widget/tabs/tab.dart
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||||
|
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||||
|
|
||||||
|
import 'new_tab.dart';
|
||||||
|
|
||||||
|
class CupertinoSegmentedControlDemo extends StatefulWidget {
|
||||||
|
const CupertinoSegmentedControlDemo({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CupertinoSegmentedControlDemo> createState() =>
|
||||||
|
_CupertinoSegmentedControlDemoState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CupertinoSegmentedControlDemoState
|
||||||
|
extends State<CupertinoSegmentedControlDemo> {
|
||||||
|
int _selectedSegment = 0;
|
||||||
|
|
||||||
|
// The data for the segments
|
||||||
|
final Map<int, Widget> _segments = const {
|
||||||
|
0: Text('Segment 1'),
|
||||||
|
1: Text('Segment 2'),
|
||||||
|
2: Text('Segment 3'),
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SafeArea(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
CupertinoSlidingSegmentedControl<int>(
|
||||||
|
children: _segments,
|
||||||
|
groupValue: _selectedSegment,
|
||||||
|
|
||||||
|
onValueChanged: (int? value) {
|
||||||
|
setState(() {
|
||||||
|
_selectedSegment = value!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
'Selected Segment: ${_selectedSegment + 1}',
|
||||||
|
style: const TextStyle(fontSize: 24),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CupertinoSegmentedControlDemo2 extends StatefulWidget {
|
||||||
|
const CupertinoSegmentedControlDemo2({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CupertinoSegmentedControlDemo2> createState() =>
|
||||||
|
_CupertinoSegmentedControlDemoState2();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CupertinoSegmentedControlDemoState2
|
||||||
|
extends State<CupertinoSegmentedControlDemo2> {
|
||||||
|
int _selectedSegment = 0;
|
||||||
|
|
||||||
|
// The data for the segments
|
||||||
|
final Map<int, Widget> _segments = {
|
||||||
|
0:Container(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(50)
|
||||||
|
),
|
||||||
|
child: Text('لاشه', style: AppFonts.yekan13Regular),
|
||||||
|
),
|
||||||
|
1: Container(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(50)
|
||||||
|
),
|
||||||
|
child: Text('زنده', style: AppFonts.yekan13Regular),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SafeArea(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
NewCupertinoSegmentedControl<int>(
|
||||||
|
padding: EdgeInsetsDirectional.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
children: _segments,
|
||||||
|
groupValue: _selectedSegment,
|
||||||
|
selectedColor: AppColor.blueNormal,
|
||||||
|
unselectedColor: Colors.white,
|
||||||
|
borderColor: Colors.grey.shade300,
|
||||||
|
onValueChanged: (int value) {
|
||||||
|
setState(() {
|
||||||
|
_selectedSegment = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
'Selected Segment: ${_selectedSegment + 1}',
|
||||||
|
style: const TextStyle(fontSize: 24),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
47
lib/presentation/widget/vec_widget.dart
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:vector_graphics/vector_graphics.dart';
|
||||||
|
|
||||||
|
SvgPicture vecWidget(
|
||||||
|
String assets, {
|
||||||
|
double? width,
|
||||||
|
double? height,
|
||||||
|
BoxFit? fit,
|
||||||
|
Color? color,
|
||||||
|
}) {
|
||||||
|
return SvgPicture(
|
||||||
|
AssetBytesLoader(assets),
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit ?? BoxFit.contain,
|
||||||
|
colorFilter:
|
||||||
|
color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Widget vecWidget2(
|
||||||
|
String assets, {
|
||||||
|
double? width,
|
||||||
|
double? height,
|
||||||
|
BoxFit? fit,
|
||||||
|
Color? color,
|
||||||
|
}) {
|
||||||
|
final resolvedColor = WidgetStateProperty.resolveWith<Color?>((states) {
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return Colors.white;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}).resolve({}); // You can pass actual states if needed
|
||||||
|
|
||||||
|
return IconTheme(
|
||||||
|
data: IconThemeData(color: resolvedColor),
|
||||||
|
child: SvgPicture(
|
||||||
|
AssetBytesLoader(assets),
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit ?? BoxFit.contain,
|
||||||
|
colorFilter: resolvedColor != null
|
||||||
|
? ColorFilter.mode(resolvedColor, BlendMode.srcIn)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
32
pubspec.yaml
@@ -58,34 +58,14 @@ dev_dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
|
||||||
assets:
|
assets:
|
||||||
- assets/icons/
|
- assets/icons/
|
||||||
- assets/images/
|
- assets/images/
|
||||||
- assets/logos/
|
- assets/logos/
|
||||||
|
- assets/vec/
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
fonts:
|
||||||
# https://flutter.dev/to/resolution-aware-images
|
- family: yekan
|
||||||
|
fonts:
|
||||||
# For details regarding adding assets from package dependencies, see
|
- asset: fonts/iranyekanregularfanum.ttf
|
||||||
# https://flutter.dev/to/asset-from-package
|
|
||||||
|
|
||||||
# To add custom fonts to your application, add a fonts section here,
|
|
||||||
# in this "flutter" section. Each entry in this list should have a
|
|
||||||
# "family" key with the font family name, and a "fonts" key with a
|
|
||||||
# list giving the asset and other descriptors for the font. For
|
|
||||||
# example:
|
|
||||||
# fonts:
|
|
||||||
# - family: Schyler
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/Schyler-Regular.ttf
|
|
||||||
# - asset: fonts/Schyler-Italic.ttf
|
|
||||||
# style: italic
|
|
||||||
# - family: Trajan Pro
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/TrajanPro.ttf
|
|
||||||
# - asset: fonts/TrajanPro_Bold.ttf
|
|
||||||
# weight: 700
|
|
||||||
#
|
|
||||||
# For details regarding fonts from package dependencies,
|
|
||||||
# see https://flutter.dev/to/font-from-package
|
|
||||||
|
|||||||
33
vecGeneratoe.sh
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Directory to read files from
|
||||||
|
sourcePath="assets/icons"
|
||||||
|
targetPath="assets/vec"
|
||||||
|
|
||||||
|
|
||||||
|
if [ ! -e "$targetPath" ]; then
|
||||||
|
echo "📁 Directory does not exist. Creating: $targetPath"
|
||||||
|
mkdir -p "$targetPath"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Loop and delete old vec file
|
||||||
|
for file in "$targetPath"/*
|
||||||
|
do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
|
||||||
|
echo "Delete old ===> $file"
|
||||||
|
rm "$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# Loop through all files in the directory
|
||||||
|
for file in "$sourcePath"/*
|
||||||
|
do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
echo "Generate Vec file ===> $file"
|
||||||
|
fileName=$(basename -- "$file")
|
||||||
|
echo "Generate Vec file ===> $fileName"
|
||||||
|
dart run vector_graphics_compiler -i "$file" -o "$targetPath/$fileName.vec"
|
||||||
|
git add .
|
||||||
|
fi
|
||||||
|
done
|
||||||