A Flutter widget that can be expanded or collapsed by the user.

Overview

Expandable

A Flutter widget that can be expanded or collapsed by the user.

Introduction

This library helps implement expandable behavior as prescribed by Material Design:

animated image

Expandable should not be confused with ExpansionPanel. ExpansionPanel, which is a part of Flutter material library, is designed to work only within ExpansionPanelList and cannot be used for making other widgets, for example, expandable Card widgets.

Usage

The easiest way to make an expandable widget is to use ExpandablePanel:

class ArticleWidget extends StatelessWidget {
  
  final Article article;
  
  ArticleWidget(this.article);

  @override
  Widget build(BuildContext context) {
    return ExpandablePanel(
      header: Text(article.title),
      collapsed: Text(article.body, softWrap: true, maxLines: 2, overflow: TextOverflow.ellipsis,),
      expanded: Text(article.body, softWrap: true, ),
      tapHeaderToExpand: true,
      hasIcon: true,
    );
  }
}

ExpandablePanel has a number of properties to customize its behavior, but it's restricted by having a title at the top and an expand icon shown as a down arrow (on the right or on the left). If that's not enough, you can implement custom expandable widgets by using a combination of Expandable, ExpandableNotifier, and ExpandableButton:

class EventPhotos extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return ExpandableNotifier(  // <-- Provides ExpandableController to its children
      child: Column(
        children: [
          Expandable(           // <-- Driven by ExpandableController from ExpandableNotifier
            collapsed: ExpandableButton(  // <-- Expands when tapped on the cover photo
              child: buildCoverPhoto(),
            ),
            expanded: Column(  
              children: [
                buildAllPhotos(),
                ExpandableButton(       // <-- Collapses when tapped on
                  child: Text("Back"),
                ),
              ]
            ),
          ),
        ],
      ),
    );
  }
}

Automatic Scrolling

Expandable widgets are often used within a scroll view. When the user expands a widget, be it an ExpandablePanel or an Expandable with a custom control, they expect the expanded widget to fit within the viewable area (if possible). For example, if you show a list of articles with a summary of each article, and the user expands an article to read it, they expect the expanded article to occupy as much screen space as possible. The Expandable package contains a widget to help implement this behavior, ScrollOnExpand. Here's how to use it:

   ExpandableNotifier(      // <-- This is where your controller lives
     //...
     ScrollOnExpand(        // <-- Wraps the widget to scroll
      //...
        ExpandablePanel(    // <-- Your Expandable or ExpandablePanel
          //...
        )
     )
  )

Why a separate widget, you might ask? Because generally you might want to show not just the expanded widget but its container, for example a Card that contains it. See the example app for more details on the usage of ScrollOnExpand.

Themes

Version 4.0 introduced themes to expandable widgets. Themes greatly simplify visual customization and as well as future extensibility. Each expandable widget can get its theme data directly via the constructor or from the nearest ExpandableTheme widget:

  ExpandableTheme(
    data: ExpandableThemeData(
        iconColor: Colors.red, 
        animationDuration: const Duration(milliseconds: 500)
    ),
      // ...
      Expandable(  // 500 milliseconds animation duration
      ),

      // ...
      ExpandablePanel(  // <-- Blue icon color, 500 milliseconds animation duration
        theme: ExpandableThemeData(iconColor: Colors.blue),
  
      ),
  )

ExpandableTheme widgets can be nested, in which case inner definitions override outer definitions. There is a default theme with fallback values defined in ExpandableThemeData.defaults.

Prior to version 4.0, theme parameters were passed to widget constructors directly. These parameters are now deprecated and will be removed in the next release.

Icon Customization

There are several theme properties that help customize the expand/collapse icon:

  • hasIcon - should the icon be shown in the header of [ExpandablePanel];
  • iconSize - icon size;
  • iconColor - icon color;
  • iconPadding - icon padding;
  • iconPlacement - icon placement in the header;
  • iconRotationAngle - the angle to which to rotate the icon;
  • expandIcon - icon face to use in the collapsed state;
  • collapseIcon - icon face to use in the expanded state.

When specifying a custom icon, you have the option to use the same icon for expand/collapse or to use two different icons. If using the same icon, specify the same value for expandIcon and collapseIcon, and that icon will be shown as-is in the collapsed state and upside-down in the expanded state.

Migration

If you have migration issues from a previous version, read the Migration Guide.

Comments
  • Unable to change icon background color.

    Unable to change icon background color.

    Screenshot 2020-08-04 at 13 38 35

    There is no option to change the background of the icon when there is hasIcon: true

    Here's my snippet:

              theme: const ExpandableThemeData(
                tapBodyToCollapse: true,
                iconColor: Colors.black,
                tapHeaderToExpand: true,
                hasIcon: true,
                headerAlignment: ExpandablePanelHeaderAlignment.center,
              ),
              header: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.only(
                      topLeft: const Radius.circular(8.0),
                      topRight: const Radius.circular(8.0),
                      bottomLeft: Radius.circular(animatedContainerBorders),
                      bottomRight: Radius.circular(animatedContainerBorders)),
                  color: isActivated ? mainPink : Colors.white,
                ),
                padding: const EdgeInsets.symmetric(vertical: 25.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Flexible(
                      flex: 5,
                      child: Center(child: Text(widget.text.toUpperCase())),
                    ),
                  ],
                ),
              ),
              expanded: Container(
                padding: const EdgeInsets.symmetric(vertical: 10.0),
                child: Text("Blabla"),
              )
           ),```
    opened by BLKKKBVSIK 4
  • Expandable within expandable content isn't animating/fading in

    Expandable within expandable content isn't animating/fading in

    When placing an expandable within another, we're seeing the sub-expandable header and content blink into existence at the moment the parent slide/fade-in animation is supposed to end. The child expandable animates properly after the parent is already expanded, but when tapping and expanding the parent expandable, the child's header and content aren't shown for the duration of the slide/fade-in animation, then they simply pop into existence.

    opened by kbokarius 4
  • Tap on body of ExpandablePanel does not expand the widget when it is collapsed.

    Tap on body of ExpandablePanel does not expand the widget when it is collapsed.

    Tap on body of ExpandablePanel does not expand the widget when it is collapsed. Tap on body of ExpandablePanel collapse the widget when it is expanded. In version 3.0.1 tap on body behavour was the same as tap on icon behavour. Is it possible to fix this?

    opened by bambinoua 4
  • [Question:] Why does the header loses its collapse-state on setState

    [Question:] Why does the header loses its collapse-state on setState

    Hi, I have the following app in which the default example is wrapped in an expandable-panel. Initially the panel is collapsed but i can expand it by clicking the header. Now everytime i press the increment button, the panel gets collapsed again. How can i prevent that?

    import 'package:flutter/material.dart';
    import 'package:expandable/expandable.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: ExpandablePanel(
                initialExpanded: false,
                header: Text("Header"),
                expanded: Text('You have pushed the button this many times: $_counter')
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    
    opened by ehhc 4
  • tapBodyToCollapse to expand body problem

    tapBodyToCollapse to expand body problem

    Hello, I have a problem with the tapBodyToCollapse property. I can't expand by clicking on the body if I click on any container. To minimize it works normal.

    opened by gbmiranda 3
  • Remove splash/ripple effect on header when tapHeaderToExpand = true

    Remove splash/ripple effect on header when tapHeaderToExpand = true

    In the ExpandableButton class, could you please replace InkWell with GestureDetector, because I don't want the ripple effect, or at least give me the option to disable the ripple effect. Thank you in advance.

    opened by topex-psy 3
  • Nested ExpandablePanels Misbehaving

    Nested ExpandablePanels Misbehaving

    Tried to nest multiple ExpandablePanels inside each other today, and discovered a bit of a hiccup: if you expand the root panel, all of its children are expanded as well. Likewise, if you collapse any of the child panels, the whole tree collapses.

    Is this something I could circumvent with a custom Expandable Widget?

    opened by LuckierDodge 3
  • toggle() doesn't work

    toggle() doesn't work

    When I try to call method toggle on the controller in this way (the controller is null):

    var controller = ExpandableController.of(context);
    controller.toggle();
    

    and in this (the controller isn't null) but the toggle function is not executed:

    expandablePanel.controller.toggle();

    I instantiate the panel in this way:

    ExpandablePanel expandablePanel = ExpandablePanel(
      controller: ExpandableController(),
      expanded: ProductDetailContent(
        product: product,
      )
    );
    
    opened by Franco7Scala 2
  • Splash effect not clippable/cannot be rounded

    Splash effect not clippable/cannot be rounded

    A small cosmetic issue, but it seems that there is no way to round the corners of the splash effect on the header of the expandable panel. Placing a ClipRRect above the expandable panel widget will only clip the content, but the splash effect is not clipped. Setting useInkWell = false in ExpandableThemeData seems to have no effect, with the splash effect still showing.

    image

    opened by andrewjallenuoft 2
  • AndroidManifest.xml could not be found.

    AndroidManifest.xml could not be found.

    Hi, I'm trying to run an example (after git cloning ). Getting following error:

    Launching lib/main.dart on Android SDK built for x86 64 in debug mode... AndroidManifest.xml could not be found. Please check /home/dominik/Flutter_projects/flutter-expandable/example/android/AndroidManifest.xml for errors. No application found for TargetPlatform.android_x64. Is your project missing an android/AndroidManifest.xml? Consider running "flutter create ." to create one.

    How can I run it?

    opened by Dzunior 2
  • Change the position of the icon

    Change the position of the icon

    I wish to change the position of the arrow icon. Currently it comes in the next line of the specified text. Is there any way i can align it in the same line as of text, to the right of it ? I'll give an example! home screen-2 multiple media in one post – 8

    opened by HardikkMadaan 2
  • Remember if the panel was expanded.

    Remember if the panel was expanded.

    Hello,

    I'd like to know how to tell my app when a panel was expanded/collapsed (eg change a variable) so that I can keep track of which were closed/open to reopen them when my app launches next time.

    Thank you for this great package by the way.

    opened by emmggi 1
  • dismiss keyboard when click on expand/collapse icon or header

    dismiss keyboard when click on expand/collapse icon or header

    I have one Textfield with InputDecoration with a listview of expandable panel. After I click to input data in, it displays keyboard and items of expandable panel. i put gesture detector over the scaffold to detect when onTap but it doesnt detect when I click on expand/collapse icon or header.

    I want to dismiss keyboard when I click on expand/collapse icon or header.

    opened by sopheareachte 0
  • Example not compiling

    Example not compiling

    The first, simplest example on https://pub.dev/packages/expandable does not seem to be current. E.g. hasIcon is not an argument of ExpandablePanel anymore.

    And the examples in github do not use the simplest method (ExpandablePanel)

    opened by 2i2i 0
Owner
Alex Ryzhov
I am making contributions to this project in my personal capacity. I am not conveying any rights to any intellectual property of any third parties.
Alex Ryzhov
Create a Flutter User Profile Page UI where you can access and edit your user's information within your Flutter app.

Flutter Tutorial - User Profile Page UI 1/2 Create a Flutter User Profile Page UI where you can access and edit your user's information within your Fl

Johannes Milke 46 Dec 6, 2022
Create a Flutter User Profile Page UI where you can access and edit your user's information within your Flutter app.

Flutter Tutorial - User Profile Page UI #2 Create a Flutter User Profile Page UI where you can access and edit your user's information within your Flu

Johannes Milke 45 Dec 15, 2022
A Flutter widget that checks and displays the version status of application and you can easily guide user to update your app

A most easily usable Flutter widget about application version check! 1. About 1.

Kato Shinya 1 Dec 16, 2021
Academic master is E-learning app where students can share their doubts wiith their peers they can chat and also they can find their notes

Academic Master is E-learning App. Features:- 1) You can post real Post query in Images and video formates. 2) We will Provide notes,books and previou

amit singh 25 Dec 14, 2022
Let's create a complete Flutter User Profile Page with SharedPreferences to persist the user's information in Flutter.

Flutter Tutorial - User Profile & SharedPreferences Let's create a complete Flutter User Profile Page with SharedPreferences to persist the user's inf

Johannes Milke 21 Dec 3, 2022
A Flutter step_tracker plugin is collect information from user and display progress through a sequence of steps. this plugin also have privilege for fully customization from user side. like flipkart, amazon, myntra, meesho.

step_tracker plugin A Flutter step_tracker plugin is collect information from user and display progress through a sequence of steps. this plugin also

Roshan nahak 5 Oct 21, 2022
User auth form - Signup and signin user auth form with ability to stay signed in and have an option to signout.

user_auth_form SIgnup and signin user authentification form Getting Started This project is a starting point for a Flutter application. A few resource

null 0 Jan 6, 2022
Selectable Circle where colors can be customized and a child widget can be defined

selectable_circle A Flutter package for an Circle that can be Selected with animation. How to use SelectableCircle( width: 80.0, onSelected: (

null 11 Sep 29, 2021
Music-App-Flutter - This is a flutter app which has some songs displayed in the form of a list and user can play any of them by clicking on the name of the song.

music_player_app A music player app made by me in flutter About the App This is a music player which i made to play audio files which we have passed i

Harsh Kumar Khatri 3 Apr 1, 2021
The prime objective of this app is to store the real time information of the user using firebase cloud firestore and also can delete, remove and update the customer information

crud_firestore A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started i

Muhammad Zakariya 0 Mar 15, 2022
The classic to-do application where a user can write down all the things he wants to accomplish. Android only.

todo-app The classic to-do application where a user can write down all the things he wants to accomplish. Android only. Table of Contents todo-app Tab

Samuel Marques 9 Sep 23, 2022
Add a fading effect when the user can scroll.

Add a fading effect when the user can scroll. Demo Quickstart Add the dependency to fading_scroll to your pubspec.yaml file. flutter pub add clickup_f

ClickUp 24 Dec 14, 2022
Widget to count the amount of nested widget tree, useful in the dynamic construction of the interface when it is important to know the depth of widget.

widget_tree_depth_counter Widget Tree Depth Counter WidgetTreeDepthCounter is a simple widget to count the amount of nested widget tree, useful in the

Riccardo Cucia 4 Aug 1, 2022
MindInventory 15 Sep 5, 2022
Custom_Empty widget is flutter plugin which is designed to notify user about some event.

Empty Widget Custom_Empty widget is flutter custom widget which is designed to notify user about some event. Screenshots Screenshots Screenshots Scree

Sonu Sharma 66 Nov 17, 2022
My flutter (android, ios) UI design examples 🎈 - user profile UIs, food order ui, splashscreen, mask widget usage, settings page ui

Flutter UI Design Examples ?? This repository contains the flutter ui designs I designed while learning. Doctor Appointment App UI Packages in use: fl

Aleyna Eser 23 Nov 14, 2022
The simple way to show the user some information on your selected widget.

Info Popup The simple way to show the user some information on your selected widget. Features Info holder with dynamic size Fully editable content are

Salih Can 9 Nov 23, 2022