Sean Koh
Sean Koh

Reputation: 13

Center a listview child on selection

I am trying to make all the selected dates to be yellow background and always in the center, how can I achieve that ?

What I have right now :

Here's what I have achieve so far :

Current date selected : https://i.sstatic.net/P2bPp.png
Another date selected : https://i.sstatic.net/oKFXu.png

Example of what I'm trying to achieve :

https://i.sstatic.net/yb6Lx.png
https://i.sstatic.net/G9rZc.png

Please advice. Thanks in advance.

Here is my code :

Date_picker

 return Container(
    height: 85.0,
    margin: EdgeInsets.only(left: 20.0, right: 20.0),
    child: ListView.builder(
      scrollDirection: Axis.horizontal,
      controller: _controller,
      itemCount: daysCount,
      itemBuilder: (context, index) {
        int daysCountBefore = daysCount ~/ 2;
        DateTime today = DateTime.now();

        //get half of the days count before today first then start up total daysCount
        // 2021-01-30 15:31:16.481
        DateTime startDate =
            today.subtract(Duration(days: daysCountBefore));

        //convert to 00:00:00.000 hours
        // 2021-01-30 00:00:00.000
        DateTime _startDate =
            new DateTime(startDate.year, startDate.month, startDate.day);

        // print(_startDate.day);
        // print(daysCountBefore);

        //show days count from start date
        DateTime dates = _startDate.add(Duration(days: index));

        //format to 00:00:00.00 hrs
        //mainly for _compareDates();
        DateTime _dates = new DateTime(dates.year, dates.month, dates.day);

        bool isSelected = _currentDate != null
            ? _compareDates(_dates, _currentDate)
            : false;

        return DateWidget(
          date: dates,
          width: isSelected ? 65.0 : 40.0,
          selectedColor:
              isSelected ? widget.selectedDateColor : Colors.transparent,
          dayNumTextStyle: isSelected
              ? kSelectedDayNumTextStyle
              : kNotSelectedDayNumTextStyle,
          dayMonthTextStyle: isSelected
              ? kSelectedDayMonthTextStyle
              : kNotSelectedDayMonthTextStyle,
          dateTapped: (dateToShow) {
            //change state to the date that is tapped
            setState(() {
              _currentDate = dateToShow;
            });

            //Callback
            widget.onDateChange(dateToShow);
          },
        );
      },
    ));

Date_widget :

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

class DateWidget extends StatelessWidget {
  final DateTime date;
  final TextStyle textStyle;
  final Color selectedColor;
  final TextStyle dayMonthTextStyle;
  final Function(DateTime) dateTapped;
  final double width; //75.0
  final TextStyle dayNumTextStyle;

  DateWidget(
      {@required this.date,
      @required this.dateTapped,
      this.textStyle,
      this.width,
      this.selectedColor,
      this.dayNumTextStyle,
      this.dayMonthTextStyle});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        child: Container(
            margin: EdgeInsets.all(3.0),
            width: width,
            height: 80.0,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(20.0)),
              color: selectedColor,
            ),
            child: Padding(
              padding: EdgeInsets.all(8.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Text(new DateFormat('MMM').format(date).toUpperCase(),
                      style: dayMonthTextStyle),
                  Text(date.day.toString(), style: dayNumTextStyle),
                  Text(
                    new DateFormat('E').format(date).toUpperCase(),
                    // style: TextStyle(fontWeight: FontWeight.bold)
                    style: dayMonthTextStyle,
                  )
                ],
              ),
            )),
        onTap: () {
          dateTapped(date);
        });
  }
}

Upvotes: 0

Views: 408

Answers (2)

Thierry
Thierry

Reputation: 8383

Here is a solution based only on ListView.builder and its ScrollController:

enter image description here

import 'dart:math';

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

void main() {
  runApp(
    MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        body: MyWidget(data: List.generate(100, (index) => index)),
      ),
    ),
  );
}

class MyWidget extends HookWidget {
  final List<int> data;

  const MyWidget({Key key, this.data}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final _scrollController = useScrollController();
    final _selected = useState(0);
    return LayoutBuilder(
      builder: (context, constraints) {
        final double size = constraints.biggest.width / 10;
        return SizedBox(
          height: size,
          child: ListView.builder(
            controller: _scrollController,
            scrollDirection: Axis.horizontal,
            itemExtent: size,
            itemCount: data.length,
            itemBuilder: (context, index) => Padding(
              padding: EdgeInsets.all(size * .05),
              child: GestureDetector(
                onTap: () {
                  _selected.value = index;
                  _scrollController.animateTo(
                    max(index - 4.5, 0) * size,
                    duration: Duration(seconds: 1),
                    curve: Curves.easeInOut,
                  );
                },
                child: Card(
                  color: _selected.value == index
                      ? Colors.amber
                      : Colors.lightGreen.shade100,
                  child: Center(
                    child: Text(data[index].toString()),
                  ),
                ),
              ),
            ),
          ),
        );
      },
    );
  }
}

Upvotes: 1

Sachin Bhankhar
Sachin Bhankhar

Reputation: 900

You can use Carousel Slider

Example -

CarouselSlider(
  options: CarouselOptions(height: 400.0),
  items: [1,2,3,4,5].map((i) {
    return Builder(
      builder: (BuildContext context) {
        return Container(
          width: MediaQuery.of(context).size.width,
          margin: EdgeInsets.symmetric(horizontal: 5.0),
          decoration: BoxDecoration(
            color: Colors.amber
          ),
          child: Text('text $i', style: TextStyle(fontSize: 16.0),)
        );
      },
    );
  }).toList(),
)

Upvotes: 0

Related Questions