일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Image Resize typescript
- Flutter
- Babel standalone
- userevent_tracker
- FirebaseAnalytics
- babel
- typescript
- identifierForVender
- Completer
- KakaoMap
- Raycasting
- Three-fiber
- Excel
- jszip
- uint16array
- swagger-typescript-api
- Three js
- node
- RouteObserver
- methodChannel
- code editor
- Redux
- Prism.js
- web track
- uint8array
- Game js
- react
- REST API
- webrtc
- androidId
- Today
- Total
Never give up
Flutter - LayoutBuilder with Text widget width 본문
화면을 구성하다보면 텍스트 길이 혹은 위젯 크기에 따라 유동적으로 변경하고 싶을 때
LayoutBuilder를 쓰면 간단하게 해결할 수 있습니다
먼저 LayoutBuilder의 builder 내부는 BuildContext와 BoxConstraints로 구성되어 있는데
우리가 사용할 부분은 BoxConstraints부분입니다
어떤 역할을 하는지 정말 간단하게 알아 보자면
For boxes, the constraints are BoxConstraints, which, as described herein, consist of four numbers: a minimum width minWidth, a maximum width maxWidth, a minimum height minHeight, and a maximum height maxHeight.
간단하게 위젯의 최소, 최대값 정보를 가지고 있는 녀석(?)입니다
조금 더 자세한 설명은 링크를 참고해주세요
(링크 : https://api.flutter.dev/flutter/rendering/BoxConstraints-class.html)
간단한 예제로 한번 보면서 이해를 해보면 좋을거 같습니다
class _LayoutBuilderExampleState extends State<LayoutBuilderExample> {
final List<String> list1 = List.generate(20, (index) => 'Num - $index');
final List<String> list2 = List.generate(3, (index) => 'Num - $index');
final GlobalKey _paddingKey = GlobalKey();
bool _showMore = false;
@override
Widget build(BuildContext context) {
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
debugPrint('body size : ${_paddingKey.getWidgetSize}');
});
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
key: _paddingKey,
padding: const EdgeInsets.all(10.0),
child: LayoutBuilder(
builder: (_, constraints) {
debugPrint('builder size : ${constraints.biggest}');
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_textListWidgets(
indexList: list1, maxWidth: constraints.maxWidth),
_textListWidgets(
indexList: list2, maxWidth: constraints.maxWidth),
],
);
},
),
),
);
}
Widget _textListWidgets(
{required List<String> indexList, required double maxWidth}) {
int lastIndex = 0;
double textWidth = 0;
bool isOverSize = false;
TextStyle style = TextStyle(fontSize: 14, color: Colors.white);
for (int i = 0; i < indexList.length; i++) {
TextPainter painter = TextPainter();
painter.text = TextSpan(text: indexList[i], style: style);
painter.textDirection = painting.TextDirection.ltr;
painter.layout();
textWidth += painter.width + 32;
//32 = 8 * 2 + 8 * 2 (horizontal padding + margin)
if (textWidth > maxWidth) {
lastIndex = i;
isOverSize = true;
break;
}
}
if (isOverSize && _showMore) {
return Wrap(
children: List.generate(
indexList.length,
(index) => _textWidget(indexList[index], style),
)..add(Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: TextButton(
child: Text('- Hide'),
onPressed: () {
setState(() {
_showMore = !_showMore;
});
},
),
)));
}
return Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [
...List.generate(
isOverSize ? lastIndex : indexList.length,
(index) => _textWidget(indexList[index], style),
),
isOverSize
? Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: TextButton(
child: Text('+ More'),
onPressed: () {
setState(() {
_showMore = !_showMore;
});
},
),
)
: Container()
],
);
}
Widget _textWidget(String text, TextStyle style) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), color: Colors.blue),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Text(
text,
style: style,
),
);
}
}
사용한 extension
extension KeyExtension on GlobalKey {
Size? get getWidgetSize {
RenderObject? renderObject = this.currentContext?.findRenderObject();
return renderObject?.paintBounds.size;
}
}
먼저 LayoutBuilder의 constraints를 이용해서 위젯크기와 비교할 maxWidth를 넘겨줍니다
그리고 text위젯이 그려질 때 width가 얼마나 되는지 계산이 필요한데
여기서 TextPainter를 이용하면 알아낼 수 있고
추가로 Text위젯 주변에 들어가는 padding 혹은 margin값을 계산해서 넣어준 후
maxWidth와 계산된 width값을 비교해줘서 다른 위젯형태로 출력을 해줍니다
추가로 global key를 이용해서 사이즈 값을 가지고 올 수도 있는데
필자는 extension을 이용해서 간단하게 콜을 할 수 있도록 만들어놨습니다
결과값을 확인해보면 패딩 준 20만큼 차이가 나는것을 확인할 수 있습니다
print 결과
I/flutter ( 4224): builder size : Size(372.7, 677.5)
I/flutter ( 4224): body size : Size(392.7, 697.5)
'Flutter' 카테고리의 다른 글
Flutter - When you want to scrol in small widget lists (0) | 2022.01.29 |
---|---|
Flutter - Custom Video player(Feat. Transform) (0) | 2022.01.28 |
Flutter - Easy Overlay (feat. toast) (0) | 2021.08.13 |
Flutter - Scrollable with sliver (0) | 2021.06.26 |
Flutter - WidgetsBindingObserver (0) | 2021.05.22 |