تصميم ui باستخدام Flutter لصفحة عرض تفاصيل المنتج مع Animation
في هذا المقال سوف نتعرف على CustomScrollView وكيف تقوم بعمل scroll للعناصر الخاصه بك مع انميشن لطيف اثناء النزول للاسفل او حتى الصعود للاعلى كما هو موضح بالصورة الخاصه بالمقاله , بكل بساطة ما سوف تحتاج اليه هو استخدام خاصية CustomScrollView وهيا التي تساعدك في تخصيص عمل scroll وذلك يكون عن طريق sliver الذي يتم فصل فيه ال appbar عن ال body يمكنك نسخ الكود التالي واستخدامه في تطبيقك فهو يقدم لك SliverAppBar و SliverList .
هناك العديد من الجوانب الحاسمة لتطوير تطبيقات الويب التي يجب التفكير فيها. الأداء المتسق هو أحد هذه العناصر. هذا يستدعي تقديم المعلومات بأسرع ما يمكن على موقع الويب أو التطبيق الخاص بك. سيترك المستخدمون موقعك وينتقلون إلى موقع آخر إذا استغرق تحميل الصفحة وقتًا طويلاً. الاتساق هو أحد أهم العناصر في العمل. يحتاج العملاء إلى أن يكونوا واثقين من أنه يمكنهم الاعتماد عليك لتقديم نفس مستوى الخدمة أو الجودة في كل مرة يتعاملون معك فيها. قد يكون بناء قاعدة مستهلكين متينة أمرًا صعبًا إذا كان أداؤك غير متسق.
Design ui page to show all details product
SliverList هو عباره عن body او الجزء الذي يتم فيه كتابة الكود ويظهر في التطبيق ويكون هذا الجزء اسفل ال SliverAppBar والذي يعبر عن شريط يظهر بالاعلى او يمكنك اعتباره الجزء العلوي وهنا قمنا بعمل بداخله صورة بسيطه وتمكين المستخدم من عمل scroll ويختفي الجزء العلوي ولكن مع انميشن تمويه في الاعلى كما هو ملاحظ وهذا التصميم يعبر عن صفحة لعرض تفاصيل منتج في احد التطبيقات يمكنك نسخ الاكواد والتعامل معها في تطبيقك وفي اي تصميم ترغب به .
ui.dart
class ProductViewPage extends StatefulWidget {
final String img;
final String hero;
const ProductViewPage({ Key? key, required this.img , required this.hero }) : super(key: key);
@override
_ProductViewPageState createState(
) => _ProductViewPageState();
}
class _ProductViewPageState extends State<ProductViewPage> {
List<dynamic> productList = [];
List<String> size = [
"S",
"M",
"L",
"XL",
];
List<Color> colors = [
Colors.black,
Colors.purple,
Colors.orange.shade200,
Colors.blueGrey,
const Color(0xFFFFC1D9),
];
int _selectedColor = 0;
int _selectedSize = 1;
@override
void initState() {
print(widget.hero);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: MediaQuery.of(context).size.height * 0.65,
elevation: 0,
snap: true,
floating: true,
stretch: true,
backgroundColor: Colors.grey.shade50,
flexibleSpace: FlexibleSpaceBar(
stretchModes: [
StretchMode.zoomBackground,
],
background: Hero(
tag: widget.hero,
transitionOnUserGestures: true,
child: Image.asset(widget.img, fit: BoxFit.cover,))
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(45),
child: Transform.translate(
offset: const Offset(0, 1),
child: Container(
height: 45,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Center(
child: Container(
width: 50,
height: 8,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(10),
),
)
),
),
)
),
),
SliverList(
delegate: SliverChildListDelegate([
Container(
height: MediaQuery.of(context).size.height * 0.80,
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Test data',
style: TextStyle(color: Colors.black, fontSize: 22, fontWeight: FontWeight.bold,),
),
const SizedBox(height: 5,),
Text('developer', style: TextStyle(color: Colors.orange.shade400, fontSize: 14,),),
],
),
const Text("\$ " + "150" + '.00',
style: TextStyle(color: Colors.black, fontSize: 16),
),
],
),
const SizedBox(height: 20,),
Text("Take a break from jeans with the parker long straight pant. These lightweight, pleat front pants feature a flattering high waist and loose, straight legs.",
style: TextStyle(height: 1.5, color: Colors.grey.shade800, fontSize: 15,),
),
const SizedBox(height: 30,),
Text("Color", style: TextStyle(color: Colors.grey.shade400, fontSize: 18),),
const SizedBox(height: 10,),
Container(
height: 60,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: colors.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
_selectedColor = index;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.only(right: 10),
decoration: BoxDecoration(
color: _selectedColor == index ? colors[index] : colors[index].withOpacity(0.5),
shape: BoxShape.circle
),
width: 40,
height: 40,
child: Center(
child: _selectedColor == index ? const Icon(Icons.check, color: Colors.white,) : Container(),
),
),
);
},
),
),
const SizedBox(height: 20,),
Text('Size', style: TextStyle(color: Colors.grey.shade400, fontSize: 18),),
const SizedBox(height: 10,),
Container(
height: 60,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: size.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
_selectedSize = index;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
margin: const EdgeInsets.only(right: 10),
decoration: BoxDecoration(
color: _selectedSize == index ? Colors.yellow[800] : Colors.grey.shade200,
shape: BoxShape.circle
),
width: 40,
height: 40,
child: Center(
child: Text(size[index], style: TextStyle(color: _selectedSize == index ? Colors.white : Colors.black, fontSize: 15),),
),
),
);
},
),
),
const SizedBox(height: 20,),
MaterialButton(
onPressed: () {
Navigator.pop(context);
},
height: 50,
elevation: 0,
splashColor: Colors.yellow[700],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
color: Colors.yellow[800],
child: const Center(
child: Text("Add to Cart", style: TextStyle(color: Colors.white, fontSize: 18),),
),
)
],
)
)
])
),
]
),
);
}
}