Создайте ползунок карусели Flutter с динамической c высотой для каждой страницы - PullRequest
2 голосов
/ 14 апреля 2020

У меня есть Карусельный слайдер с точечным индикатором , как показано на этом изображении

Каждая страница слайдера является виджетом Card с ListView в качестве дочернего элемента .

Если карта не находится внутри виджета Карусель, она расширяется по мере увеличения элементов внутри ListView.

Я бы хотел сохранить это поведение для каждой страницы ползунка, но когда я поместите карточки в ползунок, они больше не меняют размер в зависимости от содержимого , но, кажется, имеют заранее заданную высоту (даже если я не указал ни одной!).

Как Могу ли я динамически обновить высоту карточек внутри ползунка?

Это мой код:

main.dart file

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Slider App',
      home: MyHomePage(),
    );
  }
}

class GeneralEvent {
  final String title;
  final String desc;
  GeneralEvent(this.title, this.desc);
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

final List<GeneralEvent> userEvents = [
  GeneralEvent(
    "List Item 1",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 2",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 3",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 4",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 5",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
];

class _MyHomePageState extends State<MyHomePage> {
  final List<Card> cards = [
    Card(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Text(
              'Card 1',
              style: TextStyle(fontSize: 24),
            ),
          ),
          Container(
            height: 1,
            width: double.infinity,
            color: Color.fromRGBO(0, 0, 0, 0.12),
          ),
          ListView.builder(
            physics: NeverScrollableScrollPhysics(),
            shrinkWrap: true,
            itemBuilder: (ctx, index) {
              return ListTile(
                title: Text(
                  userEvents.sublist(0, 3)[index].title,
                ),
                subtitle: Text(userEvents.sublist(0, 3)[index].desc),
              );
            },
            itemCount: userEvents.sublist(0, 3).length,
          ),
        ],
      ),
    ),
    Card(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Text(
              'Card 2',
              style: TextStyle(fontSize: 24),
            ),
          ),
          Container(
            height: 1,
            width: double.infinity,
            color: Color.fromRGBO(0, 0, 0, 0.12),
          ),
          ListView.builder(
            physics: NeverScrollableScrollPhysics(),
            shrinkWrap: true,
            itemBuilder: (ctx, index) {
              return ListTile(
                title: Text(
                  userEvents.sublist(3)[index].title,
                ),
                subtitle: Text(userEvents.sublist(3)[index].desc),
              );
            },
            itemCount: userEvents.sublist(3).length,
          ),
        ],
      ),
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromRGBO(235, 235, 235, 1),
      appBar: AppBar(title: Text('iWantASliderAPP')),
      body: Padding(
        padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
        child: LayoutBuilder(
          builder: (context, constraints) {
            return ListView(
              children: <Widget>[
                CarouselWithIndicator(cards),
                Padding(
                  padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
                  child: Text(
                    "if the Card is not in the slider it resize properly:",
                  ),
                ),
                cards[0]
              ],
            );
          },
        ),
      ),
    );
  }
} 

и carousel.dart

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

class CarouselWithIndicator extends StatefulWidget {
  final List cards;

  CarouselWithIndicator(this.cards);

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

class _CarouselWithIndicatorState extends State<CarouselWithIndicator> {
  List<T> map<T>(List list, Function handler) {
    List<T> result = [];
    for (var i = 0; i < list.length; i++) {
      result.add(handler(i, list[i]));
    }
    return result;
  }

  int _current = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        CarouselSlider(
          // height: // NO HEIGHT SPECIFIED!
          viewportFraction: 1.0,
          enlargeCenterPage: true,
          enableInfiniteScroll: false,
          onPageChanged: (index) {
            setState(() {
              _current = index;
            });
          },
          items: widget.cards.map((card) {
            return Builder(
              builder: (BuildContext context) {
                return Container(
                  width: MediaQuery.of(context).size.width,
                  child: card,
                );
              },
            );
          }).toList(),
        ),
        SizedBox(
          height: 5,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: map<Widget>(widget.cards, (index, card) {
            return Container(
              width: 10.0,
              height: 10.0,
              margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 3.0),
              decoration: BoxDecoration(
                shape: BoxShape.circle,
                color: _current == index ? Colors.grey : Color.fromRGBO(200, 200, 200, 1),
              ),
            );
          }),
        ),
      ],
    );
  }
}

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

это открытый выпуск библиотеки, но вы все еще можете частично достичь с помощью приведенного ниже кода.
carousel.dart

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

class CarouselWithIndicator extends StatefulWidget {
  final List cards;

  CarouselWithIndicator(this.cards);

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

class _CarouselWithIndicatorState extends State<CarouselWithIndicator> {
  List<T> map<T>(List list, Function handler) {
    List<T> result = [];
    for (var i = 0; i < list.length; i++) {
      result.add(handler(i, list[i]));
    }
    return result;
  }

  int _current = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Wrap(
          children: <Widget>[
            CarouselSlider(
              height: double.maxFinite,
              viewportFraction: 1.0,
              enlargeCenterPage: true,
              enableInfiniteScroll: false,
              onPageChanged: (index) {
                setState(() {
                  _current = index;
                });
              },
              items: widget.cards.map((card) {
                return Builder(
                  builder: (BuildContext context) {
                    return Container(
                      width: MediaQuery.of(context).size.width,
                      child: card,
                    );
                  },
                );
              }).toList(),
            ),
          ],
        ),
        SizedBox(
          height: 5,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: map<Widget>(widget.cards, (index, card) {
            return Container(
              width: 10.0,
              height: 10.0,
              margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 3.0),
              decoration: BoxDecoration(
                shape: BoxShape.circle,
                color: _current == index
                    ? Colors.grey
                    : Color.fromRGBO(200, 200, 200, 1),
              ),
            );
          }),
        ),
      ],
    );
  }
}

файл main.dart

import 'package:flutter/material.dart';

import 'carousel.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Slider App',
      home: MyHomePage(),
    );
  }
}

class GeneralEvent {
  final String title;
  final String desc;
  GeneralEvent(this.title, this.desc);
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

final List<GeneralEvent> userEvents = [
  GeneralEvent(
    "List Item 1",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 2",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 3",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 4",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
  GeneralEvent(
    "List Item 5",
    "Lorem ipsum dolor sit amet, consectetur adipisci elit.",
  ),
];

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> cards = [
    Wrap(
      children: <Widget>[
        Card(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Text(
                  'Card 1',
                  style: TextStyle(fontSize: 24),
                ),
              ),
              Container(
                height: 1,
                width: double.infinity,
                color: Color.fromRGBO(0, 0, 0, 0.12),
              ),
              ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemBuilder: (ctx, index) {
                  return ListTile(
                    title: Text(
                      userEvents.sublist(0, 3)[index].title,
                    ),
                    subtitle: Text(userEvents.sublist(0, 3)[index].desc),
                  );
                },
                itemCount: userEvents.sublist(0, 3).length,
              ),
            ],
          ),
        ),
      ],
    ),
    Wrap(
      children: <Widget>[
        Card(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Text(
                  'Card 2',
                  style: TextStyle(fontSize: 24),
                ),
              ),
              Container(
                height: 1,
                width: double.infinity,
                color: Color.fromRGBO(0, 0, 0, 0.12),
              ),
              ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemBuilder: (ctx, index) {
                  return ListTile(
                    title: Text(
                      userEvents.sublist(3)[index].title,
                    ),
                    subtitle: Text(userEvents.sublist(3)[index].desc),
                  );
                },
                itemCount: userEvents.sublist(3).length,
              ),
            ],
          ),
        ),
      ],
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromRGBO(235, 235, 235, 1),
      appBar: AppBar(title: Text('iWantASliderAPP')),
      body: Padding(
        padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
        child: LayoutBuilder(
          builder: (context, constraints) {
            return ListView(
              children: <Widget>[
                Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    CarouselWithIndicator(cards),
                  ],
                ),
                Padding(
                  padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
                  child: Text(
                    "if the Card is not in the slider it resize properly:",
                  ),
                ),
                cards[0]
              ],
            );
          },
        ),
      ),
    );
  }
}

Надеюсь, это будет вам полезно. :)

1 голос
/ 14 апреля 2020

Это известная проблема в библиотеке. Это ответ от создателя библиотеки lib Currently there is no way to define a dynamic height for each carousel item. But I think it can be done by creating a dynamic height container in the carousel item.

Весь разговор можно посмотреть на вопрос: https://github.com/serenader2014/flutter_carousel_slider/issues/106

...