Joel Broström
Joel Broström

Reputation: 4090

Flutter Expandable leaves empty area after being collapsed

I have a long text in a CustomScrollView that I have wrapped in an Expandable widget.
When the text is collapsed I show the first 7 rows, and when it's expanded I show the entire text which can be long.
After I expand the text and then collapse it again I get a long area of nothing under the collapsed view.

Here is a screenshot of the expanded and collapsed text:
enter image description here enter image description here

as you can see the Feature text widget is no longer directly beneath the text widget.

Here is the widget:

import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';
import 'package:My_ui/My_ui.dart';
import 'package:listing_detail_page/generated/l10n.dart';
import 'package:listing_detail_page/network/models/listing_detail.dart';

import '../../../generic_components/bottom_fade.dart';

class DescriptionView extends StatelessWidget {
  const DescriptionView({
    Key? key,
    required this.details,
    required this.expandableController,
  }) : super(key: key);

  final ListingDetails details;
  final ExpandableController expandableController;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(
        left: Spacing.x2,
        right: Spacing.x2,
        top: Spacing.x3,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Text(
            S.of(context).descriptionView_title_description,
            style: Theme.of(context).textTheme.headlineMedium?.copyWith(
                  fontWeight: FontWeight.w600,
                  color: MyColors.grey25,
                ),
          ),
          const SizedBox(height: Spacing.x1),
          ExpandableNotifier(
            controller: expandableController,
            child: ScrollOnExpand(
              child: Expandable(
                collapsed: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    BottomFade(
                      height: 80,
                      child: Text(
                        details.description ?? '',
                        maxLines: 7,
                        overflow: TextOverflow.fade,
                        style: Theme.of(context)
                            .textTheme
                            .bodyLarge
                            ?.copyWith(height: 1.5),
                      ),
                    ),
                    const SizedBox(height: Spacing.x1),
                    ExpandableButton(
                      child: Row(
                        children: [
                          const Icon(
                            Icons.add,
                            color: MyColors.blue,
                            size: 22,
                          ),
                          const SizedBox(width: Spacing.x1),
                          Text(
                            S
                                .of(context)
                                .descriptionView_button_readTheFullDescription,
                            textAlign: TextAlign.start,
                            style:
                                Theme.of(context).textTheme.bodyLarge?.copyWith(
                                      color: MyColors.blue,
                                      height: 1.5,
                                    ),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
                expanded: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Text(
                      details.description ?? '',
                      style: Theme.of(context)
                          .textTheme
                          .bodyLarge
                          ?.copyWith(height: 1.5),
                    ),
                    const SizedBox(height: Spacing.x1),
                    ExpandableButton(
                      child: Row(
                        children: [
                          const Icon(
                            Icons.remove,
                            color: MyColors.blue,
                            size: 22,
                          ),
                          const SizedBox(width: Spacing.x1),
                          Text(
                            S.of(context).descriptionView_button_showLess,
                            textAlign: TextAlign.start,
                            style:
                                Theme.of(context).textTheme.bodyLarge?.copyWith(
                                      color: MyColors.blue,
                                      height: 1.5,
                                    ),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

And here is how it is being used:

import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';
import 'package:My_ui/My_ui.dart';
import 'package:listing_detail_page/network/models/feature_section.dart';
import 'package:listing_detail_page/network/models/listing_detail.dart';
import 'package:listing_detail_page/ui/generic_components/My_sliver_app_bar.dart';
import 'package:listing_detail_page/ui/screens/listing_detail/components/address_section.dart';
import 'package:listing_detail_page/ui/screens/listing_detail/components/description_view.dart';
import 'package:listing_detail_page/ui/screens/listing_detail/components/price_tile.dart';

class ListingDetailBody extends StatefulWidget {
  const ListingDetailBody({
    Key? key,
    required this.details,
    required this.listingId,
    required this.sections,
  }) : super(key: key);

  final ListingDetails details;
  final String listingId;
  final List<FeatureSection> sections;

  @override
  State<ListingDetailBody> createState() => _ListingDetailBodyState();
}

class _ListingDetailBodyState extends State<ListingDetailBody> {
  final ExpandableController _descriptionExpandableController =
      ExpandableController();

  @override
  void dispose() {
    _descriptionExpandableController.dispose();
    super.dispose();
  }

  Widget? _buildDescriptionView(BuildContext context) {
    final description = widget.details.description;
    if (description != null && description.isNotEmpty) {
      return DescriptionView(
        details: widget.details,
        expandableController: _descriptionExpandableController,
      );
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      physics: const BouncingScrollPhysics(),
      slivers: [
        MySliverAppBar(
          details: widget.details,
          listingId: widget.listingId,
        ),
        SliverList(
          delegate: SliverChildListDelegate(
            [
              ...
              const SizedBox(height: Spacing.x3),
              AddressSection(details: widget.details),
              PriceTile(details: widget.details),
              _buildDescriptionView(context),
             ...
            ].whereType<Widget>().toList(),
          ),
        ),
      ],
    );
  }
}

Upvotes: 1

Views: 238

Answers (0)

Related Questions