2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
अधुना एव अहं क्रॉस्-टर्मिनल्-अनुकूलतायै Flutter-लेखने व्यस्तः अभवम्, श्रम-रक्षण-व्ययस्य न्यूनीकरणाय एण्ड्रॉयड्, iOS, HarmonyOS-इत्यस्य च सामान्य-समुच्चयं सम्पन्नवान् Android native यदा पाठस्य एकः खण्डः अधिकतमं रेखानां संख्यां अतिक्रमयति , अन्ते truncate and splice expand/collapse. अहं प्रथमं तया परिचितः नासीत्, अतः अहं प्रथमं Stack इत्यस्य उपयोगं कृत्वा maxLines तथा overflow इत्यस्य नियन्त्रणं गतिशीलरूपेण कृतवान्, तथा च तत् प्राप्तुं अधः दक्षिणकोणे मास्कं पाठं च स्थापितवान् पश्चात् मया ज्ञातं यत् केषुचित् स्क्रीन-फोनेषु लज्जाजनकं स्थितिः भविष्यति यत्र भागः of the text is covered and half of the word leaks out , अद्य मम अन्ततः कार्यान्वयनयोजनायाः अनुकूलनार्थं समयः अस्ति।
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 घटकानां उपयोगं कुर्वन्तु ।
यदा पाठः अधिकतमपङ्क्तयः अतिक्रमति तदा पाठस्य गणनां कृत्वा अवरुद्ध्य पाठः संकुचिते अवस्थायां सम्यक् प्रदर्शितः इति सुनिश्चितं कुर्वन्तु, "विस्तार" इति लिङ्कं योजयन्तु
"expand" तथा "collapse" कार्याणि कार्यान्वितुं 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 इत्यस्य उपयोगं कुर्वन् सुनिश्चितं कुर्वन्तु यत् भवान् पर्याप्तं सन्दर्भविस्तारं प्रदाति येन पाठस्य तन्तुबिन्दुः सम्यक् गण्यते ।
उत्तमं दृश्यप्रभावं प्राप्तुं वास्तविक-आवश्यकतानुसारं कस्टम्-शैली-मापदण्डान् समायोजितव्यम् ।