USER9561
USER9561

Reputation: 1084

How to show all dates in a horizontal scroll view

I want to have all the dates of a month in a horizontal scroll view. The current week 7 days should be displayed first and on scrolling right the previous dates should be shown. later on scrolling left the later weeks dates should be displayed an don tap of a date i should get the date in return. How to do this? I have tried using the below. It displays dates and scrolls horizontally as well but it displays only multiple of 7 and all the exact dates of a month. Also on tapping the date it does not return the position form listview builder as 0 and i returns the index.

Widget displaydates(int week) {
return ListView.builder(
    itemCount: 5,
    itemBuilder: (BuildContext context, int position) {
      return Row(
        children: <Widget>[
          for (int i = 1; i < 8; i++)
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: GestureDetector(
                onTap: () {
                  print(position);
                },
                child: Text(
                  ((week * 7) + i).toString() + " ",
                  style: TextStyle(),
                ),
              ),
            ),
        ],
      );
    });
  }

I am calling this like:

displaydates(0),
displaydates(1),
displaydates(2),
displaydates(3),
displaydates(4),

Upvotes: 0

Views: 2807

Answers (2)

Blasanka
Blasanka

Reputation: 22437

I have created a widget that let me select date from a list and it is scrollable(along time ago). There lot of code but you can use the selected date under any widget which parent wrapped from InheritedWidget.

Here is the code(Note that I also created a package for this, if you dont like to write this much code for this):

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class MyInheritedWidget extends InheritedWidget {

  final DateTime date;
  final int selectedDay;
  final int monthDateCount;
  final bool isDateHolderActive;
  final Map<int, bool> dayAvailabilityMap;
  final ValueChanged<bool> toggleDateHolderActive;
  final ValueChanged<int> setSelectedDay;

  MyInheritedWidget({
    Key key,
    this.date,
    this.selectedDay,
    this.monthDateCount,
    this.isDateHolderActive,
    this.dayAvailabilityMap,
    this.toggleDateHolderActive,
    this.setSelectedDay,
    Widget child,
  }) : super(key: key, child: child);

  @override
  bool updateShouldNotify(MyInheritedWidget oldWidget) {
    return oldWidget.selectedDay != selectedDay ||
        oldWidget.toggleDateHolderActive != toggleDateHolderActive;
  }
}

class DateIndicatorPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: SafeArea(
        child: Column(
          children: <Widget>[
            DateIndicator(),
            Expanded(
              child: Container(),
            ),
          ],
        ),
      ),
    );
  }
}


class DateIndicator extends StatefulWidget {
  static MyInheritedWidget of(BuildContext context) => context.dependOnInheritedWidgetOfExactType();

  @override
  _DateIndicatorState createState() => _DateIndicatorState();
}

class _DateIndicatorState extends State<DateIndicator> {
  DateTime date = DateTime.now();
  int selectedDay = 1;
  int monthDateCount = 1;
  bool isDateHolderActive = false;
  Map<int, bool> dayAvailabilityMap = {};

  void toggleDateHolderActive(bool flag) {
    setState(() {
      isDateHolderActive = flag;
    });
  }

  void setSelectedDay(int index) {
    setState(() {
      selectedDay = index;
    });
  }

  @override
  void initState() {
    final DateTime dateForValues = new DateTime(date.year, date.month + 1, 0);
    monthDateCount = dateForValues.day;

    // Just to show how to activate when something exist for this day(from network response or something)
    dayAvailabilityMap[1] = true;
    dayAvailabilityMap[2] = true;
    dayAvailabilityMap[3] = true;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      height: 68.0,
      padding:
      const EdgeInsets.only(left: 7.0, right: 3.0, top: 2.0, bottom: 2.0),
      decoration: BoxDecoration(
        color: Theme.of(context).secondaryHeaderColor,
        boxShadow: [
          BoxShadow(
              color: Colors.blueAccent.withOpacity(.7),
              offset: Offset(0.0, .5),
              blurRadius: 3.0,
              spreadRadius: 0.3),
        ],
      ),
      child: ListView.builder(
          scrollDirection: Axis.horizontal,
          itemCount: monthDateCount, // to avoid showing zero
          itemBuilder: (BuildContext context, int index) {
            return MyInheritedWidget(
                date: date,
                selectedDay: selectedDay,
                monthDateCount: monthDateCount,
                isDateHolderActive: isDateHolderActive,
                dayAvailabilityMap: dayAvailabilityMap,
                toggleDateHolderActive: toggleDateHolderActive,
                setSelectedDay: setSelectedDay,
                child: DateHolder(index));
          }),
    );
  }
}

class DateHolder extends StatelessWidget {
  DateHolder(this.index);

  final int index;

  final Widget activeBubble = Container(
    width: 15.0,
    height: 15.0,
    decoration: BoxDecoration(
      shape: BoxShape.circle,
      color: Colors.deepOrangeAccent,
    ),
  );

  @override
  Widget build(BuildContext context) {

    final appState = DateIndicator.of(context);

    return InkWell(
      onTap: () {
        appState.toggleDateHolderActive(true);
        appState.setSelectedDay(index);
        print("Date ${index} selected!");
      },
      child: Stack(
        children: <Widget>[
          Column(
            children: <Widget>[
              Container(
                  margin: const EdgeInsets.only(right: 5.0),
                  child: Text(
                    "${DateFormat('EEEE').format(DateTime(appState.date.year, appState.date.month, index)).substring(0, 1)}",
                    style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 12.0),
                  )),
              Container(
                width: 45.0,
                height: 45.0,
                margin: const EdgeInsets.only(right: 5.0),
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: Colors.white,
                  border: (index == (appState.selectedDay) &&
                      appState.isDateHolderActive == true)
                      ? Border.all(width: 2.0, color: Theme.of(context).primaryColor)
                      : Border.all(color: Colors.transparent),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Center(
                    child: Text(
                      "${index + 1}", // to avoid showing zero
                      style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 16.0),
                    ),
                  ),
                ),
              ),
            ],
          ),
          (appState.dayAvailabilityMap[index] ?? false)
              ? Positioned(right: 8.0, bottom: 5.0, child: activeBubble)
              : Container(),
        ],
      ),
    );
  }
}

Upvotes: 1

Parth Patel
Parth Patel

Reputation: 6788

UPDATE:

You can get last day of month using below code :

DateTime(year,month + 1).subtract(Duration(days: 1)).day;

You should use ModalBottomSheet for the same and then pop that on selection with the Navigator.of(context).pop(result);

showModalBottomSheet(
  context: context,
  builder: (BuildContext context) {
      return ListView.builder(
        itemCount: 5,
        itemBuilder: (BuildContext context, int position) {
          return Row(
            children: <Widget>[
              for (int i = 1; i < 8; i++)
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GestureDetector(
                    onTap: () {
                      Navigator.of(context).pop(position);
                    },
                    child: Text(
                      ((week * 7) + i).toString() + " ",
                      style: TextStyle(),
                    ),
                  ),
                ),
            ],
          );
      }
    );
  }
);

Upvotes: 1

Related Questions