Home > other >  How i can create dropdown like this in flutter
How i can create dropdown like this in flutter

Time:11-04

Hey guys I'm working on some project and need to create a custom dropdown, like this

enter image description here

enter image description here

I am able to make that here is the code, the code is messy but I will refactor it once I make it work. Or if you have some other way how I can accomplish this I'm open to suggestions.

  GlobalKey? actionKey = GlobalKey();

 List<String> picked = [];

  List<IconData> icons = [
    Icons.blur_circular_outlined,
    Icons.sports_basketball,
    Icons.sports_baseball_sharp,
    Icons.sports_tennis_rounded,
    Icons.people,
  ];
  List<String> sports = [
    "Fudbal",
    "Kosarka",
    "Tenis",
    "Stoni tenis",
    "Kuglanje"
  ];
  List<int> ints = [0, 1, 2, 3, 4];

  List<bool> booles = [false, false, false, false, false];
  OverlayEntry? overlayEntry;
  var position;
  double? y;
  double? x;
  void findDropdownData() {
    RenderBox renderBox =
        actionKey!.currentContext!.findRenderObject() as RenderBox;
    position = renderBox.localToGlobal(Offset.zero);
    y = position!.dy;
    x = position!.dx;
  }

  OverlayEntry _overlayEntryBuilder() {
    return OverlayEntry(
      builder: (context) {
        return Positioned(
          // top: position,
          left: 16.w,
          right: 16.w,
          child: Material(
            child: dropdownExpanded(),
          ),
        );
      },
    );
  }

  Widget buildRows(i) {
    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 17.w, vertical: 15.h),
      child: Row(
        children: [
          SizedBox(
            height: 24.h,
            width: 24.w,
            child: Checkbox(
              activeColor: style.purpleMain,
              value: booles[i],
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(4)),
              onChanged: (value) {
                setState(() {
                  booles[i] = value!;
                  booles[i] == true
                      ? picked.add(sports[i])
                      : picked.remove(sports[i]);
                });
              },
            ),
          ),
          SizedBox(
            width: 10.w,
          ),
          Text(
            sports[i],
            style: TextStyle(
              color: booles[i] == true ? style.purpleMain : Colors.grey,
            ),
          ),
          const Spacer(),
          Icon(
            icons[i],
            color: booles[i] == true ? style.purpleMain : Colors.grey,
            size: 15,
          ),
        ],
      ),
    );
  }

  Widget dropdown() {
    return GestureDetector(
      key: actionKey,
      onTap: () {
        setState(() {
          isPressed = !isPressed;
        });
        if (isPressed == false) {
          overlayEntry = _overlayEntryBuilder();
          Overlay.of(context)!.insert(overlayEntry!);
        }
      },
      child: Container(
        width: double.infinity,
        height: 50.h,
        decoration: BoxDecoration(
          border: Border.all(color: style.e8e8e8),
          borderRadius: BorderRadius.circular(8),
        ),
        padding: EdgeInsets.only(left: 16.w, right: 13.w),
        child: Row(
          children: [
            picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
            const Spacer(),
            const Icon(
              Icons.arrow_drop_down,
              color: style.bdbdbd,
            ),
          ],
        ),
      ),
    );
  }

  Widget pickedEmpty() {
    return Text(
      "Možete obeležiti više aktivnosti",
      style: TextStyle(
        fontSize: 16.sp,
        color: style.bdbdbd,
        fontWeight: FontWeight.w400,
      ),
    );
  }

  Widget pickedNotEmpty() {
    List<Widget> list = <Widget>[];
    for (var i = 0; i < picked.length; i  ) {
      list.add(
        Padding(
          padding: EdgeInsets.only(right: 5.w),
          child: Text(
            picked[i],
            style: TextStyle(
              fontSize: 16.sp,
              color: style.bdbdbd,
              fontWeight: FontWeight.w400,
            ),
          ),
        ),
      );
    }
    return Row(children: list);
  }

  Widget dropdownExpanded() {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border.all(color: style.purpleMain),
        borderRadius: BorderRadius.circular(8),
      ),
      child: Column(
        children: [
          GestureDetector(
            onTap: () {
              setState(() {
                isPressed = !isPressed;
              });
              overlayEntry?.remove();
            },
            child: Container(
              width: double.infinity,
              height: 50.h,
              padding: EdgeInsets.only(left: 16.w, right: 13.w),
              child: Row(
                children: [
                  picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
                  const Spacer(),
                  const Icon(
                    Icons.arrow_drop_up,
                    color: style.bdbdbd,
                  ),
                ],
              ),
            ),
          ),
          const Divider(
            height: 0,
            thickness: 1,
            color: style.e8e8e8,
            indent: 17,
            endIndent: 17,
          ),
          Column(
            children: [
              for (int i in ints) buildRows(i),
            ],
          ),
        ],
      ),
    );
  }

Here are results

enter image description here

This is what I want to accomplish

enter image description here

So I just want to move down this expanded dropdown and how to update these booles in the overlay if I don't use overlay it's working as it should but I need to open that dropdown on the top of another content. Thanks for the help.

CodePudding user response:

Use image

CodePudding user response:

Updated Answer

Regarding the UI, it is like an Expansions Tile Widget in flutter. You can implement that dropdown with expansions tile and pass list of items in children, for expand, collapse tile after select each item, you can create a global key and control that in UI.

final GlobalKey<AppExpansionTileState> expansionTile = new GlobalKey();

collapse → expansionTile.currentState.collapse();

ExpansionTile(
  title: Text(
    "Možete obeležiti više aktivnosti",
    style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
  ),
  children: <Widget>[
    // put items here
  ],
),

smaple :

Widget customDropDown() => Container(
      // color: Colors.white,
      padding: const EdgeInsets.all(10),
      child: ListTileTheme(
        dense: true,
        child: ExpansionTile(
          title: const Text(
            "Možete obeležiti više aktivnosti",
            style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
          ),
          children: <Widget>[
            Container(
              width: double.infinity,
              decoration: const BoxDecoration(
                  color: Colors.white,
                  borderRadius:
                      BorderRadius.vertical(bottom: Radius.circular(20))),
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  children: const [
                    ListTile(
                      leading: Icon(Icons.ac_unit),
                      title: Text("something"),
                    ),
                    ListTile(
                      leading: Icon(Icons.ac_unit),
                      title: Text("something"),
                    ),
                    ListTile(
                      leading: Icon(Icons.ac_unit),
                      title: Text("something"),
                    ),
                    ListTile(
                      leading: Icon(Icons.ac_unit),
                      title: Text("something"),
                    )
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: SafeArea(
          child: Stack(
            children: [pageDesign(), customDropDown()],
          ),
        ),
      ),
    );
  }

  fakeWidget(color) => Container(
        height: 100,
        width: double.infinity,
        color: color,
        child: const Center(
          child: Text("widget1"),
        ),
      );

  Widget pageDesign() => Column(
        children: [
          /* you should control this size in diffrent orientation and for big size 
                  device to handle responsive
                  */
          const SizedBox(
            height: 80,
          ),
          fakeWidget(
            Colors.green,
          ),
          fakeWidget(
            Colors.yellow,
          ),
          fakeWidget(
            Colors.orange,
          ),
          fakeWidget(
            Colors.blue,
          ),
        ],
      );
  • Related