laboratory_4

This commit is contained in:
nikbel2004@outlook.com 2024-09-29 16:49:32 +04:00
parent a0f7bb995e
commit 728ce748b2
5 changed files with 243 additions and 100 deletions

View File

@ -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)
)
],
),
),
);
}
}

112
lib/home_page/card.dart Normal file
View File

@ -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<StatefulWidget> 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<int>(0),
)
: const Icon(
Icons.favorite_border,
color: Colors.red,
key: ValueKey<int>(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))
],
),
)
],
),
),
);
}
}

View File

@ -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<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
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(),
),
),
);
}
}

View File

@ -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<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@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<StatefulWidget> createState() => _CardState();
}
class _CardState extends State<Card> {
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'),
);
}
}

View File

@ -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});
}