如何在Flutter中自定义步进器并通过内容中的小部件进行控制?

时间:2019-05-17 10:47:24

标签: flutter

我在自己的视图中创建了一系列步骤,希望使用Flutter中的Stepper Widget来实现。但是我希望这些步骤由内容中的小部件而不是“继续”和“取消”触发。我尝试使用controlsBuilder,但是为每个步骤创建了相同的控件小部件。根据我的要求,我希望使用不同的小部件来触发流程。我的第一步是肯定的问题。下一步应通过视图中是否有图像等来控制。 我该如何实现?

有没有一种方法可以创建自定义步进器栏并完全避免使用Stepper类?

这是我想用stepper实现的流程:

https://ibb.co/KzJYGdQ

https://ibb.co/BsHZbHd

我尝试了以下代码:

import 'package:flutter/material.dart';

class StepperView extends StatefulWidget{
  @override
  _stepperViewState createState() => _stepperViewState();
}

class _stepperViewState extends State<StepperView> {

  //bool itemBought = false;

  int _currentstep = 0;
  void _movetonext() {
    setState(() {
      if(_currentstep< steps.length-1){
        _currentstep++;
      }
    });
  }

  void _movetostart() {
    setState(() {
      _currentstep = 0;
    });
  }


  List<Step> steps = [
    Step(
      title: Text("Item bought?"),
      content: Column(
  children: <Widget> [
  Row(
  children: <Widget>[

  GestureDetector(
  //onTap: _movetonext,
    // (GIVES ERROR: only static members can accessed in initializers )
  child: Container(decoration: BoxDecoration(border: Border.all(color: Colors.red, width: 1.0), borderRadius: BorderRadius.circular(20.0)),child: Center(
  child: Padding(
  padding: const EdgeInsets.only(top: 6.0, bottom: 6.0, left: 20.0, right: 20.0),
  child: Text('NO', style: TextStyle(color: Colors.red, fontSize: 9.0)),
  ),
  )),
  ),
  SizedBox(width: 10.0),

  GestureDetector(
 //onTap: _movetostart,
    // (GIVES ERROR: only static members can accessed in initializers )
  child: Container(decoration: BoxDecoration(color: Colors.red,border: Border.all(color: Colors.red, width: 1.0),borderRadius: BorderRadius.circular(20.0)),child: Center(
  child: Padding(
  padding: const EdgeInsets.only(top: 6.0, bottom: 6.0, left: 20.0, right: 20.0),
  child: Text('YES', style: TextStyle(color: Colors.white, fontSize: 9.0)),
  ),
  )),
  ),

  ])]),
      isActive: true,
    ),

    Step(
      title: Text("Step 2"),
      content: Text("this is the second step"),
      isActive: true,
    ),
  ];


  @override
  Widget build(BuildContext context) {

    return Stepper(
      controlsBuilder:
          (BuildContext context, {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
        /*return Row(
          children: <Widget>[
            FlatButton(
              onPressed: onStepContinue,
              child: const Text('CONTINUE'),
            ),
            FlatButton(
              onPressed: onStepCancel,
              child: const Text('CANCEL'),
            ),
          ],
        ); */
      },
      currentStep: this._currentstep,
      type: StepperType.vertical,
      steps: steps,
      onStepTapped: (step){
          setState(() {
            _currentstep = step;
          });
        },
        onStepCancel: _movetostart,
        onStepContinue: _movetonext
      ,
    );
  }

}


1 个答案:

答案 0 :(得分:0)

虽然您的用例似乎对 Stepper 有非常规的设计,但可以修改现有的 Stepper 小部件。您只需复制现有的 Stepper 小部件类并添加将覆盖“下一步”和“取消”按钮上设置的文本的参数。

在 Step 类上添加所需的参数。为简单起见,省略了一些未更改的行。

class CustomStep {
  /// Creates a step for a [CustomStepper].
  ///
  /// The [title], [content], and [state] arguments must not be null.
  const CustomStep({
  required this.title,
  this.subtitle,
  required this.content,
  this.state = StepState.indexed,
  this.isActive = false,
  this.continueButtonLabel, // String for 'Next' button
  this.cancelButtonLabel,   // String for 'Cancel' button
  }) : assert(title != null),
  assert(content != null),
  assert(state != null);

  ...

  /// Set a different text on Stepper Continue Button
  final String? continueButtonLabel;

  /// Set a different text on Stepper Cancel Button
  final String? cancelButtonLabel;
}

然后在 _CustomStepperState 类中,为 index 添加一个 Widget _buildVerticalControls() 参数。找到“下一步”和“取消”按钮的 TextButton 并修改它们以处理您设置的参数。

Widget _buildVerticalControls(int index) {

  ...

  // If continueButtonLabel is empty, display default text
  Text((widget.steps[index].continueButtonLabel !=null) ? widget.steps[index].continueButtonLabel! : localizations.continueButtonLabel)
  
  ...

  // If cancelButtonLabel is empty, display default text
  Text((widget.steps[index].cancelButtonLabel !=null) ? widget.steps[index].cancelButtonLabel! : localizations.cancelButtonLabel),
}

使用这种方法,还可以更改按钮的外观。如果您想尝试一下,这里是 complete custom_stepper.dart

在您的屏幕上,您只需添加参数 continueButtonLabelcancelButtonLabel 即可运行。

int _index = 0;
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
    ),
    body: Center(
      child: CustomStepper(
        currentStep: _index,
        onStepCancel: () {
          if (_index > 0) {
            setState(() {
               _index -= 1;
            });
          }
        },
        onStepContinue: () {
          if (_index <= 0) {
            setState(() {
              _index += 1;
            });
          }
        },
        onStepTapped: (int index) {
          setState(() {
            _index = index;
          });
        },
        steps: <CustomStep>[
          CustomStep(
            title: const Text('Step 1 title'),
            content: Container(
              alignment: Alignment.centerLeft,
              child: const Text('Content for Step 1'),
            ),
            // Set custom label for the 'Next' button
            continueButtonLabel: 'Next',
            // Set custom label for the 'Cancel' button
            cancelButtonLabel: 'Back',
          ),
          const CustomStep(
            title: Text('Step 2 title'),
            content: Text('Content for Step 2'),
          ),
        ],
      ),
    ),
  );
}

Demo