简体   繁体   中英

How to change times one by one in ListView using TimePicker Flutter?

I'm trying to allow users to choose their working hours for a week for that I've done a List of days of the week and used a ListView.builder to display all days as shown below.

在此处输入图像描述

Now I would like to allow users to change start hour and end hour for each day. For that I call a TimePicker on click but when I change a start hour, all start hours are changed.

My question is, is that a good idea to use a ListView to generate the days and if yes how to modiify hours one by one for each day without modify the others at the same time.

Here is the code:

Utils

static String displayCorrectTimeOfDay(int hour, int minute) {
    final hours = hour.toString().padLeft(2, '0');
    final minutes = minute.toString().padLeft(2, '0');

    return "${hours}h$minutes";
}

Text

const String monday = "Mon.";
const String tuesday = "Tue.";
const String wednesday = "Wed";
const String thursday = "Thu.";
const String friday = "Fri.";
const String saturday = "Sat.";
const String sunday = "Sun.";

WeeklyScheduleScreen

class WeeklyScheduleScreen extends StatefulWidget {
  const WeeklyScheduleScreen({Key? key}) : super(key: key);

  @override
  State<WeeklyScheduleScreen> createState() => _WeeklyScheduleScreenState();
}

class _WeeklyScheduleScreenState extends State<WeeklyScheduleScreen> {
  TimeOfDay from = const TimeOfDay(hour: 7, minute: 00);
  TimeOfDay to = const TimeOfDay(hour: 23, minute: 00);
  List<String> week = [monday, tuesday, wednesday, thursday, friday, saturday, sunday];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: const CloseButton(
          color: white,
        ),
        title: const Text(
          myWeek,
          style: TextStyle(
            color: white,
          ),
        ),
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SizedBox(height: 15,),
            buildSubTitle(),
            const SizedBox(height: 25,),
            buildWeek(),
            //buildFrom(),
          ],
        ),
      ),
    );
  }

  Widget buildSubTitle() => const Text(
    myWeekSubTitle,
    style: TextStyle(
      fontSize: 20,
      fontWeight: FontWeight.bold,
    ),
  );

  Widget buildWeek() => ListView.builder(
    itemCount: week.length,
    itemBuilder: (_, i) => buildSelectHour(week[i]),
    shrinkWrap: true,
    physics: const BouncingScrollPhysics(),
  );

  Widget buildSelectHour(String day) => Row(
    children: [
      Text(
        day,
        style: const TextStyle(
          fontSize: 18,
          fontWeight: FontWeight.bold,
        ),
      ),
      Expanded(
        flex: 3,
        child: buildDropDownField(
          text: Utils.displayCorrectTimeOfDay(from.hour, from.minute),
          onClicked: () => pickFromTime(),
        ),
      ),
      Expanded(
        flex: 3,
        child: buildDropDownField(
          text: Utils.displayCorrectTimeOfDay(to.hour, to.minute),
          onClicked: () => pickToTime(),
        ),
      ),
      Expanded(
        flex: 1,
        child: IconButton(
            onPressed: () { print( "Done clicked"); },
            icon: const Icon(
              Icons.check_circle,
              color: phoneButtonColor,
            ),
        ),
      ),
      Expanded(
        flex: 1,
        child: IconButton(
          onPressed: () { print( "Cancel clicked"); },
          icon: const Icon(
            Icons.cancel,
            color: red,
          ),
        ),
      ),
    ],
  );

  Widget buildDropDownField({required String text, required VoidCallback onClicked}) =>
      ListTile(
        title: Text(text),
        trailing: const Icon(Icons.arrow_drop_down),
        onTap: onClicked,
      );

  Future pickFromTime() async {
    TimeOfDay? timePicked = await showTimePicker(
      context: context,
      initialTime: from,
    );

    if(timePicked == null) return;

    setState(() => from = timePicked);
  }

  Future pickToTime() async {
    TimeOfDay? timePicked = await showTimePicker(
      context: context,
      initialTime: to,
    );

    if(timePicked == null) return;

    setState(() => to = timePicked);
  }
}

Thanks in advance

You just created one TimeOfDay that you applied to all items.

Just create a List with all TimeOfDay's so you can easily access them through the builders index, for example:

...
List<TimeOfDay> froms = [const TimeOfDay(hour: 7, minute: 00),...];
<TimeOfDay> tos = [const TimeOfDay(hour: 23, minute: 00),...];
...

Widget buildSelectHour(String day, int index) => Row(
    children: [
      Text(
        day,
        style: const TextStyle(
          fontSize: 18,
          fontWeight: FontWeight.bold,
        ),
      ),
      Expanded(
        flex: 3,
        child: buildDropDownField(
          text: Utils.displayCorrectTimeOfDay(froms[index].hour, froms[index].minute),
          onClicked: () => pickFromTime(),
        ),
      ),
      Expanded(
        flex: 3,
        child: buildDropDownField(
          text: Utils.displayCorrectTimeOfDay(tos[index].hour, tos[index].minute),
          onClicked: () => pickToTime(),
        ),
      ),
      Expanded(
        flex: 1,
        child: IconButton(
            onPressed: () { print( "Done clicked"); },
            icon: const Icon(
              Icons.check_circle,
              color: phoneButtonColor,
            ),
        ),
      ),
      Expanded(
        flex: 1,
        child: IconButton(
          onPressed: () { print( "Cancel clicked"); },
          icon: const Icon(
            Icons.cancel,
            color: red,
          ),
        ),
      ),
    ],
  );

Future pickFromTime(int index) async {
    TimeOfDay? timePicked = await showTimePicker(
      context: context,
      initialTime: from,
    );

    if(timePicked == null) return;

    setState(() => froms[index] = timePicked);
  }

  Future pickToTime(int index) async {
    TimeOfDay? timePicked = await showTimePicker(
      context: context,
      initialTime: to,
    );

    if(timePicked == null) return;

    setState(() => tos[index] = timePicked);
  }

try to make WeekDays model class

void main() {
  List<WeekDays> week = [
    WeekDays(days: "Mon."),
    WeekDays(days: "Tue."),
    WeekDays(days: "Wed."),
    WeekDays(days: "Thu."),
    WeekDays(days: "Fri."),
    WeekDays(days: "Sat."),
    WeekDays(days: "Sun."),
  ];

  week.forEach((day) {
    print("${day.days} ${day.startHour} ${day.endHour}");
  });
}

class WeekDays {
  final String days;
  double startHour;
  double endHour;

  WeekDays({
    required this.days,
    this.startHour = 7.0,
    this.endHour = 24.0,
  });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM