Dropdown Using RenderObject In Flutter

Dropdown Using RenderObject In Flutter :

Screenshot 1 :

Dropdown Using RenderObject In Flutter

Screenshot 2 :

Dropdown Using RenderObject In Flutter

custom_dropdown.dart

import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutterapp/screen_adapter.dart';

class CustomDropDown<T> extends StatefulWidget {
  final String keyName;
  final ValueChanged<T> onChanged;
  final List<String> items;
  final int showItemNum;

  const CustomDropDown(
      {Key key,
      @required this.keyName,
      @required this.onChanged,
      @required this.items,
      this.showItemNum = 2})
      : super(key: key);

  @override
  _CustomDropDownState createState() => _CustomDropDownState();
}

class _CustomDropDownState extends State<CustomDropDown> {
  GlobalKey actionKey;
  double width, height, xPosition, yPosition;
  bool isDropDownOpened = false;
  OverlayEntry floatingDropdown;
  OverlayEntry middleLayer;
  String content;

  @override
  void initState() {
    actionKey = LabeledGlobalKey(widget.keyName);
    super.initState();
  }

  void findDropDownData() {
    RenderBox renderBox = actionKey.currentContext.findRenderObject();
    width = renderBox.size.width;
    height = renderBox.size.height;
    Offset offset = renderBox.localToGlobal(Offset.zero);
    xPosition = offset.dx;
    yPosition = offset.dy;
  }

  OverlayEntry _createFloatingDropdown() {
    return OverlayEntry(builder: (context) {
      return Positioned(
          left: xPosition + ScreenAdapter.width(10),
          width: width - 2 * ScreenAdapter.width(10),
          top: yPosition + height,
          height: widget.showItemNum * height + 2 * ScreenAdapter.height(10),
          child: dropDownWidget());
    });
  }

  OverlayEntry _createMiddleLayer() {
    return OverlayEntry(builder: (context) {
      return Positioned(
          left: 0,
          top: 0,
          child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                setState(() {
                  floatingDropdown.remove();
                  middleLayer.remove();
                  isDropDownOpened = !isDropDownOpened;
                });
              },
              child: Container(
                  width: ScreenAdapter.getScreenWidth(),
                  height: ScreenAdapter.getScreenHeight())));
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        key: actionKey,
        onTap: () {
          setState(() {
            if (isDropDownOpened) {
              floatingDropdown.remove();
              middleLayer.remove();
            } else {
              middleLayer = _createMiddleLayer();
              Overlay.of(context).insert(middleLayer);
              findDropDownData();
              floatingDropdown = _createFloatingDropdown();
              Overlay.of(context).insert(floatingDropdown);
            }

            isDropDownOpened = !isDropDownOpened;
          });
        },
        child: Container(
            width: ScreenAdapter.getScreenWidth(),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(ScreenAdapter.width(8)),
              border:
                  Border.all(color: Colors.grey, width: ScreenAdapter.width(1)),
            ),
            padding: EdgeInsets.symmetric(
                horizontal: ScreenAdapter.width(20),
                vertical: ScreenAdapter.height(20)),
            child: Row(children: <Widget>[
              Spacer(),
              Text(content ?? widget.keyName,
                  style: TextStyle(fontSize: ScreenAdapter.size(30))),
              Spacer(),
              Icon(Icons.arrow_drop_down, size: ScreenAdapter.width(40))
            ])));
  }

  Widget dropDownWidget() {
    return MediaQuery.removePadding(
        removeTop: true,
        context: context,
        child: Container(
            height: widget.showItemNum * height + 2 * ScreenAdapter.height(20),
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(ScreenAdapter.width(16))),
            child: ScrollConfiguration(
                behavior: MyBehavior(),
                child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: widget.items.length,
                    itemBuilder: (_, index) {
                      if (index == widget.items.length - 1) {
                        return DropDownItem.last(
                            text: widget.items[index],
                            onPress: (value) {
                              setState(() {
                                content = value;
                              });
                              widget.onChanged(value);
                              floatingDropdown.remove();
                              middleLayer.remove();
                              isDropDownOpened = !isDropDownOpened;
                            });
                      } else {
                        return DropDownItem(
                            text: widget.items[index],
                            onPress: (value) {
                              setState(() {
                                content = value;
                              });
                              widget.onChanged(value);
                              floatingDropdown.remove();
                              middleLayer.remove();
                              isDropDownOpened = !isDropDownOpened;
                            });
                      }
                    }))));
  }
}

class DropDownItem extends StatelessWidget {
  final String text;

  final bool isFirstItem;

  final bool isLastItem;

  final Function(String) onPress;

  const DropDownItem(
      {Key key,
      this.text,
      this.isFirstItem = false,
      this.isLastItem = false,
      this.onPress})
      : super(key: key);

  factory DropDownItem.last({String text, Function(String) onPress}) {
    return DropDownItem(text: text, onPress: onPress, isLastItem: true);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: () {
          onPress(text);
        },
        child: Container(
            alignment: Alignment.center,
            width: ScreenAdapter.width(100),
            decoration: BoxDecoration(
                border: Border.all(
                    color: Colors.grey, width: ScreenAdapter.width(0.5)),
                borderRadius: BorderRadius.vertical(
                    top: isFirstItem
                        ? Radius.circular(ScreenAdapter.width(16))
                        : Radius.zero,
                    bottom: isLastItem
                        ? Radius.circular(ScreenAdapter.width(16))
                        : Radius.zero),
                color: Colors.white),
            padding: EdgeInsets.symmetric(
                horizontal: ScreenAdapter.width(20),
                vertical: ScreenAdapter.height(20)),
            child: Text(text,
                style: TextStyle(
                    fontWeight: FontWeight.normal,
                    decoration: TextDecoration.none,
                    color: Colors.black,
                    fontSize: ScreenAdapter.size(30)))));
  }
}

class MyBehavior extends ScrollBehavior {
  @override
  Widget buildViewportChrome(
      BuildContext context, Widget child, AxisDirection axisDirection) {
    if (Platform.isAndroid || Platform.isFuchsia) {
      return child;
    } else {
      return super.buildViewportChrome(context, child, axisDirection);
    }
  }
}

screen_adapter.dart

import 'package:flutter_screenutil/flutter_screenutil.dart';

class ScreenAdapter {
  static init(context) {
    //ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
    ScreenUtil.init(context, width: 750, height: 1334,allowFontScaling: false);
  }

  static height(double value) {
    return ScreenUtil().setHeight(value.toDouble());
  }

  static width(double value) {
    return ScreenUtil().setWidth(value.toDouble());
  }

  static getScreenHeight() {
    return ScreenUtil.screenHeightDp;
  }

  static getPixelRatio(){
    return ScreenUtil.pixelRatio;
  }

  static getScreenWidth() {
    return ScreenUtil.screenWidthDp;
  }

  static getScreenPxHeight() {
    return ScreenUtil.screenHeight;
  }

  static getScreenPxWidth() {
    return ScreenUtil.screenWidth;
  }

  static size(double value){
   return ScreenUtil().setSp(value.toDouble());  
  }

  static instance()=> ScreenUtil;
}

main.dart

import 'package:flutter/material.dart';
import 'custom_dropdown.dart';
import 'screen_adapter.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(visualDensity: VisualDensity.adaptivePlatformDensity),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    ScreenAdapter.init(context);

    return Scaffold(
        appBar: AppBar(
          title: Text('Dropdown using RenderObject'),
        ),
        body: CustomDropDown(
            keyName: "Gender",
            items: ["Male", "Female", "None"],
            showItemNum: 20,
            onChanged: (value) {}));
  }
}

pubspec.yaml

name: flutterapp
description: A new Flutter application.

publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.3
  flutter_screenutil:

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

The flutter tutorial  is a website that bring you the latest and amazing resources of code. All the languages codes are included in this website. The languages like flutter, android, java,kotlin etc.with the help of this languages any user can develop the beautiful application .

For more information about Flutter. visit www.fluttertutorial.in