'How to add image to ExpantionTile in flutter

I've been working on an app in which I want to add an image in the ExpansionTile function but the catch is that flutter don't allow us to add image in that.

For the reference, this is what I'm trying to implement, this exact same UI has also been implemented on Myntra app.

Check out Myntra UI here: https://vimeo.com/707250315

enter image description here

I've tried searching for some alternatives for this and I found expandable package which does the same thing but is not exactly what I want to achieve. I managed to implement this for now:

enter image description here

If anyone of you have implemented this UI before, I would love to see how it's implemented.



Solution 1:[1]

enter image description here

In my research for a solution to this, I concluded AnimatedContainer() would be the best suited for the primary tile. This first snippet is the general widget. At the very end, I have modeled a List of Map<String, dynamic> that represents a possible JSON response

import 'package:flutter/material.dart';

import '/widgets/category_item.dart';

class CategoriesPage extends StatefulWidget {
  const CategoriesPage({Key? key}) : super(key: key);

  @override
  State<CategoriesPage> createState() => _CategoriesPageState();
}

class _CategoriesPageState extends State<CategoriesPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: _products.length,
        itemBuilder: (ctx, index) => CategoryItem(product: _products[index]),
      ),
    );
  }
}

List<Map<String, dynamic>> _products = [
  {
    'categoryTitle': 'Summer Shop',
    'categoryDescription': 'Turn up the heat in style',
    'categoryImage':
        'https://images.unsplash.com/photo-1600566752355-35792bedcfea?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Nnx8YmF0aHJvb218ZW58MHx8MHx8&auto=format&fit=crop&w=500&q=60',
    'subCategory': [
      {'categ': 'Top Brands'},
      {'categ': 'Men'},
      {'categ': 'Women'},
      {'categ': 'Kids'},
      {'categ': 'Footware'},
      {'categ': 'Accessories'},
      {'categ': 'Jewellery'},
      {'categ': 'Beauty'},
    ],
  },
  {
    'categoryTitle': 'Men',
    'categoryDescription': 'T-shorts, Shirts,Jeans,Accessories',
    'categoryImage':
        'https://images.unsplash.com/photo-1603825491103-bd638b1873b0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8OXx8YmF0aHJvb218ZW58MHx8MHx8&auto=format&fit=crop&w=500&q=60',
    'subCategory': [
      {'categ': 'Top Brands'},
      {'categ': 'Men'},
      {'categ': 'Women'},
      {'categ': 'Kids'},
      {'categ': 'Footware'},
      {'categ': 'Accessories'},
      {'categ': 'Jewellery'},
      {'categ': 'Beauty'},
    ],
  },
  {
    'categoryTitle': 'Women',
    'categoryDescription': 'T-shorts, Shirts,Jeans,Accessories',
    'categoryImage':
        'https://images.unsplash.com/photo-1603825491103-bd638b1873b0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8OXx8YmF0aHJvb218ZW58MHx8MHx8&auto=format&fit=crop&w=500&q=60',
    'subCategory': [
      {'categ': 'Top Brands'},
      {'categ': 'Men'},
      {'categ': 'Women'},
      {'categ': 'Kids'},
      {'categ': 'Footware'},
      {'categ': 'Accessories'},
      {'categ': 'Jewellery'},
      {'categ': 'Beauty'},
    ],
  },
  {
    'categoryTitle': 'Kids',
    'categoryDescription': 'T-shorts, Shirts,Jeans,Accessories',
    'categoryImage':
        'https://images.unsplash.com/photo-1603825491103-bd638b1873b0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8OXx8YmF0aHJvb218ZW58MHx8MHx8&auto=format&fit=crop&w=500&q=60',
    'subCategory': [
      {'categ': 'Top Brands'},
      {'categ': 'Men'},
      {'categ': 'Women'},
      {'categ': 'Kids'},
      {'categ': 'Footware'},
      {'categ': 'Accessories'},
      {'categ': 'Jewellery'},
      {'categ': 'Beauty'},
    ],
  },
];

This is the builder part. Update with Expandable packge

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

class CategoryItem extends StatefulWidget {
  final Map<String, dynamic> product;
  const CategoryItem({required this.product, Key? key}) : super(key: key);

  @override
  State<CategoryItem> createState() => _CategoryItemState();
}

class _CategoryItemState extends State<CategoryItem> {
  final _controller = ExpandableController();

  @override
  Widget build(BuildContext context) {
    final deviceSize = MediaQuery.of(context).size;

    return ExpandablePanel(
      controller: _controller,
      theme: const ExpandableThemeData(hasIcon: false),
      header: Container(
        height: deviceSize.height * .13,
        decoration: BoxDecoration(
          image: DecorationImage(
            fit: BoxFit.cover,
            image: NetworkImage(widget.product['categoryImage']),
          ),
        ),
      ),
      collapsed: const SizedBox(height: 0),
      expanded: ListView.builder(
        shrinkWrap: true,
        physics: const BouncingScrollPhysics(),
        itemCount: widget.product['subCategory'].length,
        itemBuilder: (ctx, index) => ExpansionTile(
          childrenPadding: const EdgeInsets.symmetric(vertical: 5),
          title: Text(widget.product['subCategory'][index]['categ']),
          children: List<Widget>.generate(
            widget.product['subCategory'].length,
            (index) => Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Text(widget.product['subCategory'][index]['categ']),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 littleironical