flutter 将具有setState的小部件传递到另一个没有有状态/无状态小部件的页面

yizd12fk  于 2023-01-31  发布在  Flutter
关注(0)|答案(5)|浏览(207)

如何将一个小部件函数传递到另一个没有任何无状态/有状态的页面?该文件只包括小部件,如文本字段,按钮等。我尽量不聚集在一个页面中的每个字段。任何帮助/想法将不胜感激!
Main.dart

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<Main Page> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
// bool for toggling password
  bool isSecuredPasswordField = true;
  @override
  Widget build(BuildContext context) {
    return Container();
  }
// widget function that I need to pass on widget_fields.dart
 Widget togglePassword() {
    return IconButton(
      onPressed: () {
        setState(() {
          isSecuredPasswordField = !isSecuredPasswordField;
        });
      },
      icon: isSecuredPasswordField
          ? const Icon(Icons.visibility)
          : const Icon(Icons.visibility_off),
    );
  }
}

窗口小部件_字段.dart

Widget userPasswordField(_passwordUserCtrlr) {
  return Padding(
    padding: const EdgeInsets.symmetric(horizontal: 25.0),
    child: TextFormField(
      obscureText: true,
      controller: _passwordUserCtrlr,
      keyboardType: TextInputType.visiblePassword,
      decoration: InputDecoration(
        isDense: true,
        suffixIcon: togglePassword(), //<-- I wanna call that function here
        prefixIcon: const Icon(Icons.lock),
        enabledBorder: OutlineInputBorder(
          borderSide: const BorderSide(color: Color(0xFFCECECE)),
          borderRadius: BorderRadius.circular(12),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: const BorderSide(color: Color(0xFFCECECE)),
        ),
        hintText: 'Password',
        hintStyle: const TextStyle(
          fontFamily: 'Poppins',
          fontSize: 14,
        ),
        fillColor: const Color(0xFFFEFEFE),
        filled: true,
      ),
      validator: (value) {
        if (value!.isEmpty) {
          return "Please enter your password.";
        } else if (value.length < 8) {
          return "Password should be min. 8 characters.";
        } else {
          return null;
        }
      },
    ),
  );
}
yhxst69z

yhxst69z1#

你可以像传递其他变量一样传递函数。我做了一个完整的工作示例,它与你的示例不同,只是为了展示一个更小的示例,但是你可以在代码中应用相同的逻辑

  • 主省道 *
import 'package:flutter/material.dart';

import 'column.dart';

void main() {
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

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

class MyAppState extends State<MyApp> {
  Widget returnSomeText() {
    return const Text("test");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: createColumn(returnSomeText));
  }
}
  • 纵列.省道 *
import 'package:flutter/material.dart';

Widget createColumn(Function widgetFunction) {
  return Column(
    children: [widgetFunction(), widgetFunction()],
  );
}

正如你所看到的,你的代码中的togglePassword对应于我的代码中的returnSomeText,而userPasswordField类似于createColumn,但必须指出的是,这里不推荐使用createColumn这样的辅助函数,而是将其转换为StatelessWidget,例如:

import 'package:flutter/material.dart';

class CreateColumn extends StatelessWidget {
  final Function widgetFunction;
  const CreateColumn({Key? key, required this.widgetFunction}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [widgetFunction(), widgetFunction()],
    );
  }
}

然后在main.dart中:

return Scaffold(body: CreateColumn(widgetFunction: returnSomeText));

另请参阅此YouTube视频:Widgets vs helper methods

tvokkenx

tvokkenx2#

这是如何在另一个类中调用Widget的示例:

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

  @override
  State<MainApge> createState() => _MainApgeState();
}

class _MainApgeState extends State<MainApge> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ContainerTextFields.customsTextField(
          "User Name",
          'enter name',
          userNameController,
        ),
      ],
    );
  }
}

这是自定义小部件类:

class ContainerTextFields {
      static Widget customsTextField(
          String label, String cusHintText, TextEditingController _controller) {
        return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Padding(
              padding: EdgeInsets.only(
                  left: SizeConfig.screenHeight! * 0.05,
                  top: SizeConfig.screenHeight! * 0.03),
              child: Text(
                label,
                style: AppStyle.kUnSyncedDialogeText.copyWith(
                    color: AppColors.kTextFieldLabelColorGrey,
                    fontWeight: FontWeight.bold),
              )),
          Padding(
            padding: EdgeInsets.only(
                top: SizeConfig.screenHeight! * 0.02,
                left: SizeConfig.screenHeight! * 0.042,
                right: SizeConfig.screenWidth! * 0.042),
            child: SingleChildScrollView(
              child: Container(
                height: SizeConfig.screenHeight! * 0.065,
                child: TextFormField(
                  controller: _controller,
                  decoration: InputDecoration(
                    hintText: cusHintText,
                    hintStyle: TextStyle(
                      color: AppColors.kLoginPopUpColor,
                    ),
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10),
                    ),
                  ),
                ),
              ),
            ),
          )
        ]);
      }
    }
nkoocmlb

nkoocmlb3#

您可以将小部件作为参数传递给子小部件:

class MyTextField extends StatelessWidget {
  const MyTextField({Key? key,
    this.togglePassword,
    this.passwordUserCtrlr
  })
      : super(key: key);

  final Widget? togglePassword;
  final TextEditingController? passwordUserCtrlr;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 25.0),
      child: TextFormField(
        obscureText: true,
        controller: passwordUserCtrlr,
        keyboardType: TextInputType.visiblePassword,
        decoration: InputDecoration(
          isDense: true,
          suffixIcon: togglePassword, //<-- I wanna call that function here
          prefixIcon: const Icon(Icons.lock),
          enabledBorder: OutlineInputBorder(
            borderSide: const BorderSide(color: Color(0xFFCECECE)),
            borderRadius: BorderRadius.circular(12),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(12),
            borderSide: const BorderSide(color: Color(0xFFCECECE)),
          ),
          hintText: 'Password',
          hintStyle: const TextStyle(
            fontFamily: 'Poppins',
            fontSize: 14,
          ),
          fillColor: const Color(0xFFFEFEFE),
          filled: true,
        ),
        validator: (value) {
          if (value!.isEmpty) {
            return "Please enter your password.";
          } else if (value.length < 8) {
            return "Password should be min. 8 characters.";
          } else {
            return null;
          }
        },
      ),
    );
  }
}

并且可以轻松地从主控件调用:

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
// bool for toggling password
  bool isSecuredPasswordField = true;
  TextEditingController? passwordUserCtrlr = TextEditingController();
  @override
  Widget build(BuildContext context) {
    return MyTextField(
      togglePassword: togglePassword(),
      passwordUserCtrlr: passwordUserCtrlr,
    );
  }
// widget function that I need to pass on widget_fields.dart
  Widget togglePassword() {
    return IconButton(
      onPressed: () {
        setState(() {
          isSecuredPasswordField = !isSecuredPasswordField;
        });
      },
      icon: isSecuredPasswordField
          ? const Icon(Icons.visibility)
          : const Icon(Icons.visibility_off),
    );
  }
}
vyu0f0g1

vyu0f0g14#

您可以创建类似GlobalWidget的类,例如:

class GlobalWidget {

 // widget function that I need to pass on widget_fields.dart
 Widget togglePassword(Function()? onPressed, bool value) {
    return IconButton(
      onPressed: onPressed,
      icon: value
          ? const Icon(Icons.visibility)
          : const Icon(Icons.visibility_off),
    );
  }

}

您可以这样调用小部件:

GlobalWidget().togglePassword(() => setState(() {
    isSecuredPasswordField = !isSecuredPasswordField;
  }), isSecuredPasswordField)
dkqlctbz

dkqlctbz5#

您所尝试的操作在Flutter框架中是不可能的,您不能调用属于其他小部件的方法
此外,不鼓励使用函数返回小部件,因为这会影响框架优化构建过程的能力。
一种可能的解决方案是将完整的密码输入打包到一组自定义(statefull)小部件中。如果愿意,可以将这些小部件收集到一个源文件中。确保为每个小部件创建一个类。

相关问题