Flutter-버튼 그리드를보다 동적으로 표시

Nov 15 2020

저는 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;
                    });
                  },
                ),
            ],
          )
        ],
      ),
    );
  }
}

답변

1 yahyaparvar Nov 15 2020 at 00:47

대신 랩으로 설정할 수 있습니다. 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

allison0002 Nov 15 2020 at 01:41

이전 답변을 통해 알아낼 수 있었다고 생각합니다. 텍스트에 따라 하루 상자 크기를 만들기 위해 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;
                });
              },
            ),
        ],
      ),
    );