forked from eatvio/eatvio_app
124 lines
3.8 KiB
Dart
124 lines
3.8 KiB
Dart
import 'dart:math' as math;
|
|
|
|
import 'package:eatvio_app/generated/l10n.dart';
|
|
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
|
|
class ExpandableText extends StatefulWidget {
|
|
final String text;
|
|
final int maxLines;
|
|
|
|
const ExpandableText({
|
|
super.key,
|
|
required this.text,
|
|
this.maxLines = 5, // по умолчанию 5 строк
|
|
});
|
|
|
|
@override
|
|
State<ExpandableText> createState() => _ExpandableTextState();
|
|
}
|
|
|
|
class _ExpandableTextState extends State<ExpandableText> {
|
|
bool isExpanded = false;
|
|
bool showExpandButton = false;
|
|
|
|
final GlobalKey _textKey = GlobalKey();
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) => _checkTextOverflow());
|
|
}
|
|
|
|
void _checkTextOverflow() {
|
|
final textRenderObject = _textKey.currentContext?.findRenderObject();
|
|
if (textRenderObject is RenderBox) {
|
|
final maxLinesHeight = widget.maxLines * TextStyles.textMMediumAuto.fontSize! * 1.2;
|
|
final actualHeight = textRenderObject.size.height;
|
|
|
|
if (actualHeight > maxLinesHeight && !showExpandButton) {
|
|
setState(() {
|
|
showExpandButton = true;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void toggleExpansion() {
|
|
setState(() {
|
|
isExpanded = !isExpanded;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final s = S.of(context);
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: AnimatedSize(
|
|
duration: const Duration(milliseconds: 200),
|
|
curve: Curves.easeInOut,
|
|
child: Stack(
|
|
children: [
|
|
Text(
|
|
widget.text,
|
|
key: _textKey,
|
|
style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black),
|
|
maxLines: isExpanded ? null : widget.maxLines,
|
|
overflow: TextOverflow.clip,
|
|
),
|
|
if (!isExpanded && showExpandButton)
|
|
Positioned.fill(
|
|
child: Align(
|
|
alignment: Alignment.bottomCenter,
|
|
child: Container(
|
|
height: 35,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Colors.white.withAlpha(0),
|
|
Colors.white.withAlpha((255 * 0.6).toInt()),
|
|
Colors.white,
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (showExpandButton)
|
|
Align(
|
|
alignment: Alignment.bottomCenter,
|
|
child: GestureDetector(
|
|
onTap: toggleExpansion,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
isExpanded ? s.hide : s.expand,
|
|
style: TextStyles.textMMedium.copyWith(color: appTheme.blueA400),
|
|
),
|
|
const SizedBox(width: 4),
|
|
Transform.rotate(
|
|
angle: isExpanded ? math.pi : 0,
|
|
child: SvgPicture.asset('assets/icons/arrow_down.svg', width: 12, height: 12),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|