Flutter-버튼 그리드를보다 동적으로 표시
저는 Flutter를 처음 사용하고 UI 작업을 처음 사용합니다. 요일에 대한 라디오 버튼 세트를 표시하려고하는데 텍스트를 축소하지 않고 매일 포함 된 상자를 텍스트 길이에 맞추고 싶습니다. 그런 다음 한 세트에있는 모든 상자를 보여주고 싶지만 잘 맞 춥니 다. 다음은 내가 지금 가지고있는 것과 내가 갖고 싶은 것입니다.


두 번째 그림의 상자는 다른 날짜를 가져야하며 일부는 다른 날짜보다 더 넓을 수 있지만 이것이 제가 대략적으로 시각화 한 것입니다.
나는 개별 상자에 대해 크기, 맞춤 및 제한된 상자의 다른 조합을 시도해 왔으며 상자 세트를 표시하기 위해 두 개의 행이있는 열과 gridview를 비교했습니다.
현재 내가 가지고있는 코드는 다음과 같습니다. Flutter 레이아웃 작업에 대해 누구든지 가질 수있는 통찰력이나 설명에 감사드립니다.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class TimeRadioModel {
bool isSelected;
String timeText;
TimeRadioModel(this.isSelected, this.timeText);
}
class TimeRadioItem extends StatelessWidget {
final TimeRadioModel item;
TimeRadioItem(this.item);
@override
Widget build(BuildContext context) {
return LimitedBox(
child: Container(
child: Text(
item.timeText,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.center,
),
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.amber,
border: item.isSelected ? Border.all(width: 0.1) : null,
boxShadow: item.isSelected
? [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(1, 1.5),
),
]
: null,
borderRadius: BorderRadius.all(Radius.circular(7)),
),
),
);
}
}
class CustomTimeRadio extends StatefulWidget {
@override
_CustomTimeRadioState createState() => _CustomTimeRadioState();
}
class _CustomTimeRadioState extends State<CustomTimeRadio> {
List<TimeRadioModel> timeChoices = new List<TimeRadioModel>();
final currTime = DateTime.now().weekday;
// m = 1, t = 2, w = 3, th = 4, f = 5, s = 6, su = 7
@override
void initState() {
super.initState();
if (currTime == 1) {
timeChoices.add(TimeRadioModel(false, 'Today'));
timeChoices.add(TimeRadioModel(false, 'Tomorrow'));
timeChoices.add(TimeRadioModel(false, 'Wednesday'));
timeChoices.add(TimeRadioModel(false, 'Thursday'));
timeChoices.add(TimeRadioModel(false, 'Friday'));
timeChoices.add(TimeRadioModel(false, 'Saturday'));
timeChoices.add(TimeRadioModel(false, 'Sunday'));
} else if (currTime == 2) {
timeChoices.add(TimeRadioModel(false, 'Today'));
timeChoices.add(TimeRadioModel(false, 'Tomorrow'));
timeChoices.add(TimeRadioModel(false, 'Thursday'));
timeChoices.add(TimeRadioModel(false, 'Friday'));
timeChoices.add(TimeRadioModel(false, 'Saturday'));
timeChoices.add(TimeRadioModel(false, 'Sunday'));
timeChoices.add(TimeRadioModel(false, 'Monday'));
} else if (currTime == 3) {
timeChoices.add(TimeRadioModel(false, 'Today'));
timeChoices.add(TimeRadioModel(false, 'Tomorrow'));
timeChoices.add(TimeRadioModel(false, 'Friday'));
timeChoices.add(TimeRadioModel(false, 'Saturday'));
timeChoices.add(TimeRadioModel(false, 'Sunday'));
timeChoices.add(TimeRadioModel(false, 'Monday'));
timeChoices.add(TimeRadioModel(false, 'Tuesday'));
} else if (currTime == 4) {
timeChoices.add(TimeRadioModel(false, 'Today'));
timeChoices.add(TimeRadioModel(false, 'Tomorrow'));
timeChoices.add(TimeRadioModel(false, 'Saturday'));
timeChoices.add(TimeRadioModel(false, 'Sunday'));
timeChoices.add(TimeRadioModel(false, 'Monday'));
timeChoices.add(TimeRadioModel(false, 'Tuesday'));
timeChoices.add(TimeRadioModel(false, 'Wednesday'));
} else if (currTime == 5) {
timeChoices.add(TimeRadioModel(false, 'Today'));
timeChoices.add(TimeRadioModel(false, 'Tomorrow'));
timeChoices.add(TimeRadioModel(false, 'Sunday'));
timeChoices.add(TimeRadioModel(false, 'Monday'));
timeChoices.add(TimeRadioModel(false, 'Tuesday'));
timeChoices.add(TimeRadioModel(false, 'Wednesday'));
timeChoices.add(TimeRadioModel(false, 'Thursday'));
} else if (currTime == 6) {
timeChoices.add(TimeRadioModel(false, 'Today'));
timeChoices.add(TimeRadioModel(false, 'Tomorrow'));
timeChoices.add(TimeRadioModel(false, 'Monday'));
timeChoices.add(TimeRadioModel(false, 'Tuesday'));
timeChoices.add(TimeRadioModel(false, 'Wednesday'));
timeChoices.add(TimeRadioModel(false, 'Thursday'));
timeChoices.add(TimeRadioModel(false, 'Friday'));
} else {
timeChoices.add(TimeRadioModel(false, 'Today'));
timeChoices.add(TimeRadioModel(false, 'Tomorrow'));
timeChoices.add(TimeRadioModel(false, 'Tuesday'));
timeChoices.add(TimeRadioModel(false, 'Wednesday'));
timeChoices.add(TimeRadioModel(false, 'Thursday'));
timeChoices.add(TimeRadioModel(false, 'Friday'));
timeChoices.add(TimeRadioModel(false, 'Saturday'));
}
timeChoices.add(TimeRadioModel(false, 'Anytime'));
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: 100,
width: 200,
child: Column(
children: [
Row(
children: [
for (int i = 0; i < timeChoices.length - 4; i++)
IconButton(
padding: EdgeInsets.fromLTRB(2, 1, 2, 1),
icon: new TimeRadioItem(timeChoices[i]),
onPressed: () {
setState(() {
timeChoices.forEach((element) {
element.isSelected = false;
});
timeChoices[i].isSelected = true;
});
},
),
],
),
Row(
children: [
for (int i = 4; i < timeChoices.length; i++)
IconButton(
padding: EdgeInsets.fromLTRB(2, 1, 2, 1),
icon: new TimeRadioItem(timeChoices[i]),
onPressed: () {
setState(() {
timeChoices.forEach((element) {
element.isSelected = false;
});
timeChoices[i].isSelected = true;
});
},
),
],
)
],
),
);
}
}
답변
대신 랩으로 설정할 수 있습니다. row
Wrap(
children: [
for (int i = 4; i < timeChoices.length; i++)
IconButton(
padding: EdgeInsets.fromLTRB(2, 1, 2, 1),
icon: new TimeRadioItem(timeChoices[i]),
onPressed: () {
setState(() {
timeChoices.forEach((element) {
element.isSelected = false;
});
timeChoices[i].isSelected = true;
});
},
),
],
)
여기에서 랩 위젯에 대해 자세히 알아보세요. https://medium.com/flutter-community/flutter-wrap-widget-e1ee0b005b16
이전 답변을 통해 알아낼 수 있었다고 생각합니다. 텍스트에 따라 하루 상자 크기를 만들기 위해 TimeRadioItem 위젯에서 텍스트 길이에서 너비를 계산하는 크기가 지정된 상자를 사용했습니다.
return SizedBox(
width: item.timeText.length * 9.0,
child: Container(
child: Text(
item.timeText,
style: TextStyle(fontSize: 12),
textAlign: TextAlign.center,
),
padding: EdgeInsets.fromLTRB(0, 4, 0, 4),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.amber,
border: item.isSelected ? Border.all(width: 0.1) : null,
boxShadow: item.isSelected
? [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(1, 1.5),
),
]
: null,
borderRadius: BorderRadius.all(Radius.circular(7)),
),
),
);
그런 다음 IconButton 대신 Wrap 및 GestureDetector를 사용하여 CustomTimeRadio 위젯의 집합으로 날짜를 올바르게 표시 할 수있었습니다.
return SizedBox(
width: 250,
child: Wrap(
children: [
for (int i = 0; i < timeChoices.length; i++)
GestureDetector(
child: Container(
padding: EdgeInsets.fromLTRB(2, 1, 2, 1),
child: new TimeRadioItem(timeChoices[i]),
),
onTap: () {
setState(() {
timeChoices.forEach((element) {
element.isSelected = false;
});
timeChoices[i].isSelected = true;
});
},
),
],
),
);