创建自定义 Flutter DropDown 按钮作为单独的小部件

时间:2021-02-18 07:11:57

标签: flutter dropdown

我正在做一个 Flutter 项目,它在不同的页面上有多个下拉按钮。我创建了一个自定义下拉按钮,它工作正常。但是当我尝试在有一些错误的文件中使它成为一个单独的小部件(在其他页面中使用)时。下面是我试过的代码。

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  List<Activities> _activities = [
    Activities(id: 1, icon: Icons.place, title: 'Travel'),
    Activities(id: 2, icon: Icons.food_bank, title: 'Eat'),
  ];
  List<DropdownMenuItem<Activities>> activityListDropDownItems = [];
  Activities selectedActivity;
  int selectedActivityId = 0;
  String selectedActivityTitle = '';
  IconData selectedActivityIcon = Icons.addchart;

  List<DropdownMenuItem<Activities>> buildActivityList(List activities) {
    List<DropdownMenuItem<Activities>> items = [];
    for (Activities activity in activities) {
      items.add(
        DropdownMenuItem(
          value: activity,
          child: Row(
            children: [
              Text(
                '${activity.title}',
                style: TextStyle(
                  color: Colors.red,
                ),
              ),
            ],
          ),
        ),
      );
    }
    return items;
  }

  onChangeActivityListDropDownItem(Activities selected) {
    setState(() {
      selectedActivity = selected;
      selectedActivityId = selected.id;
      selectedActivityTitle = selected.title;
      selectedActivityIcon = selected.icon;
    });
  }

  @override
  void initState() {
    activityListDropDownItems = buildActivityList(_activities);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Custom DropDown'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$selectedActivityTitle'),
            SizedBox(height: 10.0),
            Container(
              padding: EdgeInsets.symmetric(horizontal: 10.0),
              decoration: BoxDecoration(
                color: Colors.white,
                border: Border.all(
                  color: Colors.grey,
                  width: 0.3,
                ),
                borderRadius: BorderRadius.all(
                  Radius.circular(
                    30.0,
                  ),
                ),
              ),
              child: Row(
                children: [
                  SizedBox(width: 10.0),
                  Icon(
                    selectedActivityIcon,
                    color: Colors.red.withOpacity(0.7),
                  ),
                  SizedBox(width: 10.0),
                  Expanded(
                    child: DropdownButton(
                      hint: Text(
                        'Activity',
                        style: TextStyle(),
                      ),
                      isExpanded: true,
                      value: selectedActivity,
                      items: activityListDropDownItems,
                      onChanged: onChangeActivityListDropDownItem,
                      underline: Container(),
                    ),
                  )
                ],
              ),
            ),
            SizedBox(height: 20.0),
            //MyDropDown(
            //  value: selectedActivity,
            //  items: activityListDropDownItems,
            //  onChanged: onChangeActivityListDropDownItem,
            //),
          ],
        ),
      ),
    );
  }
}

class MyDropDown extends StatelessWidget {
  final List<DropdownMenuItem> items;
  final IconData icon;
  final dynamic value;
  final String hintText;
  final ValueChanged onChanged;

  const MyDropDown(
      {Key key,
      @required this.items,
      this.icon,
      this.value,
      this.hintText,
      this.onChanged})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 10.0),
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border.all(
          color: Colors.grey,
          width: 0.3,
        ),
        borderRadius: BorderRadius.all(
          Radius.circular(
            30.0,
          ),
        ),
      ),
      child: Row(
        children: [
          SizedBox(width: 10.0),
          Icon(
            icon,
            color: Colors.red.withOpacity(0.7),
          ),
          SizedBox(width: 10.0),
          Expanded(
            child: DropdownButton(
              hint: Text(
                hintText,
                style: TextStyle(),
              ),
              isExpanded: true,
              value: value,
              items: items,
              onChanged: onChanged,
              underline: Container(),
            ),
          )
        ],
      ),
    );
  }
}

class Activities {
  final int id;
  final IconData icon;
  final String title;

  Activities({@required this.id, @required this.icon, @required this.title});
}

Working

当我使用 MyDropDown 时显示错误。如何将 valueonChanged 传递给 DropdownButton

    MyDropDown(
      value: selectedActivity,
      items: activityListDropDownItems,
      onChanged: onChangeActivityListDropDownItem,
    ),

Error

1 个答案:

答案 0 :(得分:2)

当您传递活动时,您的值需要动态日期类型

class MyDropDown<T> extends StatelessWidget {
  final T value;

  const MyDropDown({Key key, this.value}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

声明对象类型

MyDropDown<Activies>(
  value: selectedActivity,
  items: activityListDropDownItems,
  onChanged: onChangeActivityListDropDownItem,
),