Add decomposition to lec4

This commit is contained in:
Aleksey Filippov 2024-10-04 11:59:55 +04:00
parent 58a81e14eb
commit 62b87de295
5 changed files with 155 additions and 103 deletions

View File

@ -1,8 +1,13 @@
part of 'home_page.dart';
import 'package:flutter/material.dart';
import 'package:test_app/domain/card.dart';
part 'card_image.dart';
part 'card_like.dart';
part 'card_text.dart';
typedef OnLikeCallback = void Function(String title, bool isLiked)?;
class _Card extends StatefulWidget {
class HomeCard extends StatelessWidget {
final String text;
final String descriptionText;
final IconData icon;
@ -10,21 +15,22 @@ class _Card extends StatefulWidget {
final OnLikeCallback onLike;
final VoidCallback? onTap;
const _Card(
const HomeCard(
this.text, {
this.icon = Icons.ac_unit_outlined,
required this.descriptionText,
this.imageUrl,
this.onLike,
this.onTap,
super.key,
});
factory _Card.fromData(
factory HomeCard.fromData(
CardData data, {
OnLikeCallback? onLike,
VoidCallback? onTap,
}) =>
_Card(
HomeCard(
data.text,
descriptionText: data.descriptionText,
icon: data.icon,
@ -33,17 +39,10 @@ class _Card extends StatefulWidget {
onTap: onTap,
);
@override
State<_Card> createState() => _CardState();
}
class _CardState extends State<_Card> {
bool _isLiked = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onTap,
onTap: onTap,
child: Container(
margin: const EdgeInsets.only(top: 8, bottom: 8),
constraints: const BoxConstraints(minHeight: 140),
@ -63,94 +62,14 @@ class _CardState extends State<_Card> {
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
topLeft: Radius.circular(20),
),
child: SizedBox(
height: double.infinity,
width: 115,
child: Stack(
children: [
Positioned.fill(
child: Image.network(
widget.imageUrl ?? '',
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const Placeholder(),
),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
decoration: const BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
),
),
padding: const EdgeInsets.fromLTRB(8, 2, 8, 2),
child: Text(
'скидка 20%',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(color: Colors.black),
),
),
)
],
),
),
_CardImage(imageUrl ?? ''),
_CardText(
text,
descriptionText: descriptionText,
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.text,
style: Theme.of(context).textTheme.headlineLarge,
),
Text(
widget.descriptionText,
style: Theme.of(context).textTheme.bodyLarge,
)
],
),
),
),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(
left: 8,
right: 16,
bottom: 16,
),
child: GestureDetector(
onTap: () {
setState(() {
_isLiked = !_isLiked;
});
widget.onLike?.call(widget.text, _isLiked);
},
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: _isLiked
? const Icon(
Icons.favorite,
color: Colors.redAccent,
key: ValueKey(0),
)
: const Icon(
Icons.favorite_border,
key: ValueKey(1),
),
),
),
),
_CardLike(
onLike,
text: text,
)
],
),

View File

@ -0,0 +1,51 @@
part of 'card.dart';
class _CardImage extends StatelessWidget {
final String imageUrl;
const _CardImage(this.imageUrl);
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
topLeft: Radius.circular(20),
),
child: SizedBox(
height: double.infinity,
width: 115,
child: Stack(
children: [
Positioned.fill(
child: Image.network(
imageUrl,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const Placeholder(),
),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
decoration: const BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
),
),
padding: const EdgeInsets.fromLTRB(8, 2, 8, 2),
child: Text(
'скидка 20%',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(color: Colors.black),
),
),
)
],
),
),
);
}
}

View File

@ -0,0 +1,50 @@
part of 'card.dart';
class _CardLike extends StatefulWidget {
final OnLikeCallback onLike;
final String text;
const _CardLike(this.onLike, {required this.text});
@override
State<_CardLike> createState() => _CardLikeState();
}
class _CardLikeState extends State<_CardLike> {
bool _isLiked = false;
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(
left: 8,
right: 16,
bottom: 16,
),
child: GestureDetector(
onTap: () {
setState(() {
_isLiked = !_isLiked;
});
widget.onLike?.call(widget.text, _isLiked);
},
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: _isLiked
? const Icon(
Icons.favorite,
color: Colors.redAccent,
key: ValueKey(0),
)
: const Icon(
Icons.favorite_border,
key: ValueKey(1),
),
),
),
),
);
}
}

View File

@ -0,0 +1,33 @@
part of 'card.dart';
class _CardText extends StatelessWidget {
final String text;
final String descriptionText;
const _CardText(
this.text, {
required this.descriptionText,
});
@override
Widget build(BuildContext context) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
text,
style: Theme.of(context).textTheme.headlineLarge,
),
Text(
descriptionText,
style: Theme.of(context).textTheme.bodyLarge,
)
],
),
),
);
}
}

View File

@ -1,8 +1,7 @@
import 'package:flutter/material.dart';
import 'package:test_app/domain/card.dart';
import 'package:test_app/view/details_page/details_page.dart';
part 'card.dart';
import 'package:test_app/view/home_page/card.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
@ -62,7 +61,7 @@ class Body extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: data
.map((data) => _Card.fromData(
.map((data) => HomeCard.fromData(
data,
onLike: (String title, bool isLiked) =>
_showSnackBar(context, title, isLiked),