τα στοιχεία επικοινωνίας μου
Ταχυδρομείο[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Πρόσφατα, ήμουν απασχολημένος με το γράψιμο του Flutter για προσαρμογή σε cross-terminals, συμπληρώνοντας ένα κοινό σύνολο κωδικών για Android, iOS και HarmonyOS για να μειώσω το κόστος συντήρησης εργασίας Στο έργο, αντιμετώπισα την ανάγκη να εφαρμόσω το ίδιο πράγμα με το προηγούμενο Εγγενές Android όταν ένα κομμάτι κειμένου υπερβαίνει τον μέγιστο αριθμό γραμμών , περικόπτεται στο τέλος και συνδέετε την ανάπτυξη/σύμπτυξη. Δεν το γνώριζα στην αρχή, οπότε χρησιμοποίησα το Stack για να ελέγξω δυναμικά τα maxLines και την υπερχείλιση και έβαλα μια μάσκα και κείμενο στην κάτω δεξιά γωνία για να το πετύχω του κειμένου καλύπτεται και η μισή λέξη διαρρέει, σήμερα έχω επιτέλους χρόνο να βελτιστοποιήσω το σχέδιο υλοποίησης.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class ExpandableText extends StatefulWidget {
final String text;
final int maxLines;
final TextStyle textStyle;
final String linkTextExpand;
final String linkTextCollapse;
final Color linkTextColor;
const ExpandableText(
{super.key,
required this.text,
this.maxLines = 2,
this.textStyle = const TextStyle(color: Colors.black),
this.linkTextColor = Colors.blue,
this.linkTextExpand = " 展开",
this.linkTextCollapse = " 收起"});
State<StatefulWidget> createState() => _ExpandableTextState();
}
class _ExpandableTextState extends State<ExpandableText> {
bool isExpanded = false;
late TextSpan expandSpan;
late TextSpan linkTextSpan;
void initState() {
super.initState();
expandSpan = TextSpan(
text: widget.linkTextExpand,
style: TextStyle(color: widget.linkTextColor),
recognizer: TapGestureRecognizer()
..onTap = () {
setState(() {
isExpanded = !isExpanded;
});
},
);
linkTextSpan = TextSpan(
text: '...',
style: widget.textStyle,
children: [expandSpan],
);
}
/// 检查文本是否溢出
bool checkOverflow(double width) {
final textPainter = TextPainter(
text: TextSpan(text: widget.text, style: widget.textStyle),
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: width);
return textPainter.height > widget.maxLines * textPainter.preferredLineHeight;
}
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final maxWidth = constraints.maxWidth;
final textSpan = TextSpan(
text: widget.text,
style: widget.textStyle,
);
final textPainter = TextPainter(
text: textSpan,
maxLines: isExpanded ? null : widget.maxLines,
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: maxWidth);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
isExpanded ? _buildExpandedText() : _buildCollapsedText(textPainter, maxWidth),
],
);
},
);
}
/// 构建折叠状态下的文本
Widget _buildCollapsedText(TextPainter textPainter, double maxWidth) {
var truncatedText = widget.text;
if (checkOverflow(maxWidth)) {
// 文本的长度超过了最大行数,需要截取然后拼接展开部分的逻辑
final linkPainter = TextPainter(
text: linkTextSpan,
textDirection: TextDirection.ltr,
);
linkPainter.layout(maxWidth: maxWidth);
final position = textPainter.getPositionForOffset(Offset(maxWidth - linkPainter.width, textPainter.height));
final endOffset = textPainter.getOffsetBefore(position.offset) ?? position.offset;
truncatedText = widget.text.substring(0, endOffset);
}
return RichText(
text: TextSpan(
text: truncatedText,
style: widget.textStyle,
children: widget.text.length == truncatedText.length ? [] : [linkTextSpan],
),
maxLines: widget.maxLines,
overflow: TextOverflow.ellipsis,
);
}
/// 构建展开状态下的文本
Widget _buildExpandedText() {
final collapseSpan = TextSpan(
text: widget.linkTextCollapse,
style: TextStyle(color: widget.linkTextColor),
recognizer: TapGestureRecognizer()
..onTap = () {
setState(() {
isExpanded = !isExpanded;
});
},
);
return RichText(
text: TextSpan(
text: widget.text,
style: widget.textStyle,
children: [collapseSpan],
),
);
}
}
Το ExpandableText είναι ένα προσαρμοσμένο γραφικό στοιχείο Flutter που χρησιμοποιείται για την εμφάνιση μεγάλου περιεχομένου κειμένου. Όταν το μήκος του κειμένου υπερβαίνει τον προκαθορισμένο μέγιστο αριθμό γραμμών, το κείμενο θα συμπτύσσεται και θα εμφανιστεί ένας σύνδεσμος "ανάπτυξη" Κάντε κλικ για πλήρη επέκταση του κειμένου και κάντε κλικ ξανά για σύμπτυξη του κειμένου.
Χρησιμοποιήστε το StatefulWidget και το _ExpandableTextState για να διαχειριστείτε την κατάσταση ανεπτυγμένου/συμπτυγμένου κειμένου.
Η μεταβλητή isExpanded ελέγχει την κατάσταση εμφάνισης του κειμένου.
Χρησιμοποιήστε τα στοιχεία TextPainter και RichText για μέτρηση και απόδοση κειμένου.
Όταν το κείμενο υπερβαίνει τον μέγιστο αριθμό γραμμών, υπολογίζοντας και αποκλείοντας το κείμενο, βεβαιωθείτε ότι το κείμενο εμφανίζεται σωστά σε συμπτυγμένη κατάσταση και προσθέστε έναν σύνδεσμο "ανάπτυξη".
Προσθέστε παρακολούθηση συμβάντων κλικ μέσω του TapGestureRecognizer για να εφαρμόσετε τις λειτουργίες "ανάπτυξη" και "σύμπτυξη".
Η μέθοδος setState χρησιμοποιείται για την ενημέρωση της κατάστασης εμφάνισης του κειμένου.
Χρησιμοποιήστε το LayoutBuilder για να αποκτήσετε διαθέσιμα πλάτη για να προσαρμόσετε διαφορετικά μεγέθη οθόνης και περιβάλλοντα διάταξης.
Η μέθοδος checkOverflow χρησιμοποιείται για να προσδιοριστεί εάν το κείμενο υπερβαίνει τον καθορισμένο μέγιστο αριθμό γραμμών.
Παρέχει πολλαπλές παραμέτρους με δυνατότητα διαμόρφωσης, όπως maxLines, textStyle, linkTextExpand, linkTextCollapse, linkTextColor, επιτρέποντας στους χρήστες να προσαρμόσουν την εμφάνιση και τη συμπεριφορά του κειμένου.
ExpandableText(
text: "这是一段很长的文本,它将被折叠起来,只有在点击'展开'链接后才会完全显示。",
maxLines: 2,
textStyle: TextStyle(fontSize: 16, color: Colors.black),
linkTextExpand: " 展开",
linkTextCollapse: " 收起",
linkTextColor: Colors.blue,
);
Βεβαιωθείτε ότι όταν χρησιμοποιείτε το ExpandableText παρέχετε επαρκές πλάτος περιβάλλοντος, ώστε το σημείο αναδίπλωσης του κειμένου να υπολογίζεται σωστά.
Οι παράμετροι προσαρμοσμένου στυλ θα πρέπει να προσαρμόζονται σύμφωνα με τις πραγματικές ανάγκες για να επιτευχθεί το καλύτερο οπτικό αποτέλεσμα.