Flutter Question: How to select/highlight widget based on widget key or unique key properties upon tap

384 Views Asked by At

Im trying to build dynamically generated widgets, each of them need to be selected/highlighted when I tap on them.

here is code borrowed by another solution on stackoverflow, reference code below is DartPad friendly to paste and play.

this is perfect solution for me except, I don't want hard coded integer to identify which widget is tapped on ( I don't have finite number of widget), instead need to check against key or unique key property of myContainer instance

import 'package:flutter/material.dart';


void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(),
      debugShowCheckedModeBanner: false,
      home:  HomeScreen(),
    );
  }
}


class MyContainer extends StatelessWidget {
  final VoidCallback ontap;
  bool isSelected;
  Key myKey = UniqueKey();
  MyContainer({
    required this.ontap,
    this.isSelected = false,
  });

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10),
      child: GestureDetector(
        onTap: ontap,
        child: Container(
          decoration: BoxDecoration(
            color: Colors.grey.shade300,
            borderRadius: BorderRadius.circular(20),
            border: isSelected == true
                ? Border.all(width: 2, color: Colors.blue)
                : null,
          ),
        ),
      ),
    );
  }
}

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  int? selectedIndex;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
              child: Row(
            children: [
              Expanded(
                child: MyContainer(
                  isSelected: selectedIndex == 1,
                  ontap: () {
                    selectedIndex = 1;
                    setState(() {});
                  },
                ),
              ),
              Expanded(
                child: MyContainer(
                  isSelected: selectedIndex == 2,
                  ontap: () {
                    selectedIndex = 2;
                    setState(() {});
                  },
                ),
              )
            ],
          )),
          Expanded(
            child: MyContainer(
              isSelected: selectedIndex == 3,
              ontap: () {
                selectedIndex = 3;
                setState(() {});
              },
            ),
          ),
        ],
      ),
    );
  }
} ```
1

There are 1 best solutions below

1
On

you can use the spread operator ... to generate widgets dynamically based on your needs elements length, and use the index for each one :

inside the Column children:

Column(
children: <Widget>[
 ...List.generate(100, (index) =>
     Expanded(
            child: MyContainer(
              isSelected: selectedIndex == index,
              ontap: () {
                selectedIndex = index;
                setState(() {});
              },
            ),
          )
        ],
      )),),],),

this will basically generate 100 widgets, each of them having an index from 0-99. if you have an already List of your data, you can use its length instead of hardcoded 100, so it will be dynamic.