From 728ce748b289976002c450667940d6ab3ca88f31 Mon Sep 17 00:00:00 2001 From: "nikbel2004@outlook.com" Date: Sun, 29 Sep 2024 16:49:32 +0400 Subject: [PATCH] laboratory_4 --- lib/details_page/details_page.dart | 51 +++++++++++++ lib/home_page/card.dart | 112 +++++++++++++++++++++++++++++ lib/home_page/home_page.dart | 68 ++++++++++++++++++ lib/main.dart | 103 +------------------------- lib/models/card_data.dart | 9 +++ 5 files changed, 243 insertions(+), 100 deletions(-) create mode 100644 lib/details_page/details_page.dart create mode 100644 lib/home_page/card.dart create mode 100644 lib/home_page/home_page.dart create mode 100644 lib/models/card_data.dart diff --git a/lib/details_page/details_page.dart b/lib/details_page/details_page.dart new file mode 100644 index 0000000..303d6b2 --- /dev/null +++ b/lib/details_page/details_page.dart @@ -0,0 +1,51 @@ +import 'package:pmd/models/card_data.dart'; +import 'package:flutter/material.dart'; + +class DetailsPage extends StatelessWidget { + final CardData data; + + const DetailsPage({super.key, required this.data}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('House ${data.name}'), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(30), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: ClipRRect( + borderRadius: BorderRadius.circular(20.0), + child: Image.network( + "https://cdn0.youla.io/files/images/780_780/63/29/6329d9f543eedb62b7695786-1.jpg", + height: 250, + width: 250, + ), + ), + ), + const SizedBox(height: 20), + Text( + "Название ${data.name}", + style: const TextStyle(fontSize: 20, color: Colors.blue), + ), + Text( + "Описание: ${data.location}.", + style: TextStyle(fontSize: 18), + ), + Text( + "Описание: ${data.description}.", + style: TextStyle(fontSize: 18), + ), + Text("Цена: ${data.price} Рублей/сутки", + style: TextStyle(fontSize: 24, color: Colors.orange) + ) + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/home_page/card.dart b/lib/home_page/card.dart new file mode 100644 index 0000000..c712498 --- /dev/null +++ b/lib/home_page/card.dart @@ -0,0 +1,112 @@ +part of "home_page.dart"; + +typedef OnLikeFunction = void Function(String text); + +class _Card extends StatefulWidget { + final String name; + final String location; + final double price; + final String description; + + final OnLikeFunction? onLike; + final VoidCallback? onTap; + + const _Card( + {required this.name, required this.location, required this.price, required this.description, required this.onLike, required this.onTap}); + + factory _Card.fromData(CardData data, OnLikeFunction? onLike, + VoidCallback? onTap) => + _Card( + name: data.name, + location: data.location, + price: data.price, + description: data.description, + onLike: onLike, + onTap: onTap); + + @override + State createState() => _CardState(); +} + +class _CardState extends State<_Card> { + bool _isFavourite = false; + + void toggleIsFavourite() { + setState(() { + _isFavourite = !_isFavourite; + }); + + widget.onLike?.call(_isFavourite + ? "Property liked me" + : "Property has been removed from the likes"); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: widget.onTap, + child: Container( + width: double.infinity, + padding: + const EdgeInsets.only(top: 15, bottom: 15, left: 30, right: 30), + decoration: BoxDecoration( + border: Border.all(color: Colors.black12, width: 2), + color: Colors.blue, + borderRadius: BorderRadius.circular(20)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, // Выравниваем по левому краю + children: [ + GestureDetector( + onTap: toggleIsFavourite, + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 200), + child: _isFavourite + ? const Icon( + Icons.favorite, + color: Colors.red, + key: ValueKey(0), + ) + : const Icon( + Icons.favorite_border, + color: Colors.red, + key: ValueKey(1), + ), + ), + ) + ], + ), + const SizedBox(height: 20), + Center( + child: ClipRRect( + borderRadius: BorderRadius.circular(20.0), + // Радиус скругления + child: Image.network( + "https://cdn0.youla.io/files/images/780_780/63/29/6329d9f543eedb62b7695786-1.jpg", + width: 280, // Ширина изображения + height: 350, // Высота изображения + fit: BoxFit.cover + )// Позволяет изображению подстраиваться под рамки), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 50), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.name, style: TextStyle(fontSize: 17)), + Text("Местоположение: ${widget.location}", + style: TextStyle(fontSize: 15)), + Text("Цена: ${widget.price} Рублей/сутки", + style: TextStyle(fontSize: 17, color: Colors.orange)) + ], + ), + ) + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/home_page/home_page.dart b/lib/home_page/home_page.dart new file mode 100644 index 0000000..5b45ff7 --- /dev/null +++ b/lib/home_page/home_page.dart @@ -0,0 +1,68 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:pmd/models/card_data.dart'; +import 'package:pmd/details_page/details_page.dart'; + +part 'card.dart'; + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + void _showSnackBar(BuildContext context, String text) { + WidgetsBinding.instance.addPostFrameCallback((_) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(text), + duration: const Duration(seconds: 2), + backgroundColor: Colors.black54, + )); + }); + } + + void _navigateToDetailsPage(BuildContext context, CardData data) { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => DetailsPage(data: data)), + ); + } + + final cards = [ + CardData(name: "house 0", location: "Moscow", price: 1100.0, description: "null"), + CardData(name: "house 1", location: "Samara", price: 2200.0, description: "Very good house"), + CardData(name: "house 2", location: "Samara", price: 2300.0, description: "House in Samarus") + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: Text(widget.title), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(30), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: cards.map((cardData) { + return Column( + children: [ + _Card.fromData( + cardData, + (String text) => _showSnackBar(context, text), // передаем функцию onLike + () => _navigateToDetailsPage(context, cardData), // передаем функцию onTap + ), + const SizedBox(height: 20) + ], + ); + }).toList(), + ), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 5035444..5aba5c7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:pmd/home_page/home_page.dart'; void main() { runApp(const MyApp()); @@ -13,108 +14,10 @@ class MyApp extends StatelessWidget { title: 'Flutter Demo', debugShowCheckedModeBanner: false, theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange), + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), - home: const MyHomePage(title: 'Laboratory 3: Cards'), - ); - } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme - .of(context) - .colorScheme - .inversePrimary, - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(30), - child: ListView.separated( - itemBuilder: (context, index) => - Card(name: "House $index", location: "Moscow", price: 1100.0), - separatorBuilder: (context, index) => const SizedBox(height: 20), - itemCount: 5, - ))); - } -} - -class Card extends StatefulWidget { - const Card({super.key, required this.name, required this.price, required this.location}); - - final String name; - final double price; - final String location; - - @override - State createState() => _CardState(); -} - -class _CardState extends State { - bool _isFavorite = false; - - void toggleIsFavorite() { - setState(() { - _isFavorite = !_isFavorite; - }); - } - - @override - Widget build(BuildContext context) { - return Stack( - children: [ - Container( - padding: - const EdgeInsets.only(top: 50, bottom: 15, left: 40, right: 40), - decoration: BoxDecoration( - border: Border.all(color: Colors.black12, width: 2), - borderRadius: BorderRadius.circular(20)), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Image.network( - "https://cdn0.youla.io/files/images/780_780/63/29/6329d9f543eedb62b7695786-1.jpg"), - ), - Padding( - padding: EdgeInsets.only(top: 50), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.name, style: TextStyle(fontSize: 17)), - Text("Местоположение: ${widget.location}", style: TextStyle(fontSize: 15)), - Text("${widget.price} Рублей/сутки", - style: TextStyle( - fontSize: 17, color: Colors.orange)) - ], - ), - ) - ], - ), - ), - - Positioned( - right: 300, - top: 10, - child: IconButton( - icon: Icon(_isFavorite ? Icons.favorite : Icons.favorite_border), - color: Colors.red, - onPressed: toggleIsFavorite, - )) - ], + home: const MyHomePage(title: 'Laboratory 4: Likes on Cards'), ); } } diff --git a/lib/models/card_data.dart b/lib/models/card_data.dart new file mode 100644 index 0000000..28b54ef --- /dev/null +++ b/lib/models/card_data.dart @@ -0,0 +1,9 @@ +class CardData { + final String name; + final String location; + final double price; + final String description; + + const CardData({required this.name, required this.location, + required this.price, required this.description}); +} \ No newline at end of file