【问题标题】:Horizontal Stepper in FlutterFlutter 中的水平步进器
【发布时间】:2020-04-16 11:16:11
【问题描述】:

我想创建一个水平步进器,我知道这很容易,但是这一次,步数应该很大。

举个例子,这就是我在垂直领域所做的,

import 'package:flutter/material.dart';


void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new HomePage(),
    );
  }
}

class HomePage extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body:  Container(
          margin: EdgeInsets.symmetric(vertical: 20.0),
          child: new ListView(
        children: <Widget>[
          new Text("Helllo "),
          new Text( " Welcome"),
          new Text (" Yaaa0"),
          new SimpleWidget(),
        ],
      ), ),
    );
  }
}





class SimpleWidget extends StatefulWidget {
  @override
  SimpleWidgetState createState() => new SimpleWidgetState();
}

class SimpleWidgetState extends State<SimpleWidget> {
  int stepCounter = 0;


  List<Step> steps = [];

   @override
  void initState() {
    prepareState();
    super.initState();
  }
  void prepareState(){
    for (var i= 0; i<100; i++){
      var stepVal = new Step(
      title:new Text("Step $i"),
      content: new Text("This is the child of $i step"),
      isActive: true,
    );
      steps.add(stepVal);

    }
  }
  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new Stepper(
        type: StepperType.vertical,
        physics : ClampingScrollPhysics(),
        currentStep: this.stepCounter,
        steps: steps,
        onStepTapped: (step) {
          setState(() {
            stepCounter = step;
          });
        },
        onStepCancel: () {
          setState(() {
            stepCounter > 0 ? stepCounter -= 1 : stepCounter = 0;
          });
        },
        onStepContinue: () {
          setState(() {
            stepCounter < steps.length - 1 ? stepCounter += 1 : stepCounter = 0;
          });
        },
      ),
    );
  }
}

当我尝试在水平模式下重新创建它时,它什么也没有显示。我试图使listView 水平,我试图使步进器水平,无论是单独的还是一起的。没有工作。您可以在 dartpad 中尝试。

我的问题: 1.如何制作水平模式下可滚动的Stepper。 2. Stepper 的内容是可滚动的,我可以看到。可以关掉吗?

【问题讨论】:

    标签: android ios flutter stepper


    【解决方案1】:

    试试这个example,例如:conf pubspec file: fa_stepper: ^0.0.2,然后是flutter packages get,之后:使用FAStepper 构造函数,定义如下:

    Widget w1(BuildContext context) {
        return Scaffold(      
          // Body
          body: Container(
              child: FAStepper(
            // physics: ClampingScrollPhysics(),
            // Using a variable here for handling the currentStep
            currentStep: this.currentStep,
            // List the steps you would like to have
            titleHeight: 120,
            steps: mySteps,
            // Define the type of Stepper style
            // StepperType.horizontal :  Horizontal Style
            // StepperType.vertical   :  Vertical Style
            type: FAStepperType.horizontal,
            titleIconArrange: FAStepperTitleIconArrange.column,
            stepNumberColor: Colors.pinkAccent,
            // Know the step that is tapped
            onStepTapped: (step) {
              // On hitting step itself, change the state and jump to that step
              setState(() {
                // update the variable handling the current step value
                // jump to the tapped step
                currentStep = step;
              });
              // Log function call
              print("onStepTapped : " + step.toString());
            },
            onStepCancel: () {
              // On hitting cancel button, change the state
              setState(() {
                // update the variable handling the current step value
                // going back one step i.e subtracting 1, until its 0
                if (currentStep > 0) {
                  currentStep = currentStep - 1;
                } else {
                  currentStep = 0;
                }
              });
              // Log function call
              print("onStepCancel : " + currentStep.toString());
            },
            // On hitting continue button, change the state
            onStepContinue: () {
              setState(() {
                // update the variable handling the current step value
                // going back one step i.e adding 1, until its the length of the step
                if (currentStep < mySteps.length - 1) {
                  currentStep = currentStep + 1;
                } else {
                  currentStep = 0;
                }
              });
              // Log function call
              print("onStepContinue : " + currentStep.toString());
            },
          )),
        );
      }
    

    【讨论】:

      【解决方案2】:

      ConstrainedBox 包裹步进器并将其高度设置为常数,并将StepperType 设为horizontal。您可以在 dartpad 中查看。

              return ConstrainedBox(
                constraints: BoxConstraints.tightFor(height: 500.0),
                child: Stepper(
                    type: StepperType.horizontal,
                  ),
              );
      

      【讨论】:

      • 我这样做了,只是它给出了同样的错误。布局期间引发了以下断言: RenderFlex 在右侧溢出了 7688 像素。小部件创建跟踪当前已禁用。启用它可以改进错误消息。
      【解决方案3】:

      您可以在 Flutter 中创建 Horizo​​ntal Stepper 而无需任何外部包,也可以通过以下方式 这将正常工作并使用 StatefulWidget 将此代码放入其中(StatefulWidget)。

          int _currentStep = 0;
          Widget build(BuildContext context) {
          return Container(
                child: Column(
                  children: [
                    Expanded(
                      child: Stepper(
                        type: StepperType.horizontal,
                        physics: ScrollPhysics(),
                        currentStep: _currentStep,
                        onStepTapped: (step) => tapped(step),
                        onStepContinue:  continued,
                        onStepCancel: cancel,
                        steps: <Step>[
                           Step(
                            title: new Text(''),
                            content: Column(
                              children: <Widget>[
                                TextFormField(
                                  decoration: InputDecoration(labelText: 'Email Address'),
                                ),
                                TextFormField(
                                  decoration: InputDecoration(labelText: 'Password'),
                                ),
                              ],
                            ),
                            isActive: _currentStep >= 0,
                            state: _currentStep >= 0 ?
                            StepState.complete : StepState.disabled,
                          ),
                           Step(
                            title: new Text(''),
                            content: Column(
                              children: <Widget>[
                                TextFormField(
                                  decoration: InputDecoration(labelText: 'Home Address'),
                                ),
                                TextFormField(
                                  decoration: InputDecoration(labelText: 'Postcode'),
                                ),
                              ],
                            ),
                            isActive: _currentStep >= 0,
                            state: _currentStep >= 1 ?
                            StepState.complete : StepState.disabled,
                          ),
                           Step(
                            title: new Text(''),
                            content: Column(
                              children: <Widget>[
                                TextFormField(
                                  decoration: InputDecoration(labelText: 'Mobile Number'),
                                ),
                              ],
                            ),
                            isActive:_currentStep >= 0,
                            state: _currentStep >= 2 ?
                            StepState.complete : StepState.disabled,
                          ),
                          Step(
                            title: new Text(''),
                            content: Column(
                              children: <Widget>[
                                TextFormField(
                                  decoration: InputDecoration(labelText: 'Mobile Number'),
                                ),
                              ],
                            ),
                            isActive:_currentStep >= 0,
                            state: _currentStep >= 3 ?
                            StepState.complete : StepState.disabled,
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              );
              
      
        
        }
        
      
        tapped(int step){
          setState(() => _currentStep = step);
        }
      
        continued(){
          _currentStep < 3 ?
              setState(() => _currentStep += 1): null;
        }
        cancel(){
          _currentStep > 0 ?
              setState(() => _currentStep -= 1) : null;
        }
      

      【讨论】:

        【解决方案4】:

        github上有一个关于这个的问题https://github.com/flutter/flutter/issues/40601

        但是

        这就是我现在使用的

        output image

        import 'package:flutter/material.dart';
        
        void main() {
          runApp(MyApp());
        }
        
        class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              theme:ThemeData(
              primarySwatch:Colors.amber
              ),
              debugShowCheckedModeBanner: false,
              home: Scaffold(
                body: Center(
                  child: MyWidget(),
                ),
              ),
            );
          }
        }
        
        
        
        
        class CustomStep {
          final String title;
          final Widget page;
          CustomStep(
              {@required this.title, @required this.page});
        }
        
        
          class MyWidget extends StatefulWidget {
          const MyWidget({ Key key }) : super(key: key);
        
          @override
          _MyWidgetState createState() => _MyWidgetState();
        }
        
        class _MyWidgetState extends State<MyWidget> {
          ScrollController _scrollController = new ScrollController();
          static const double STEP_WIDTH = 90;
          PageController pageController = PageController();
          List<CustomStep> stepsList;
          int currentPage=0;
         @override
          void initState() {
            super.initState();
            stepsList = [
              CustomStep(
                title: 'ddddd',
                page: Placeholder(
                  color: Colors.pink,
                ),
              ),
              CustomStep(
                title: 'zzzzzzzz',
                page: Placeholder(
                  color: Colors.deepPurple,
                ),
              ),
            ];
          }
        
          SizedBox buildStepDivider(int index) {
            return SizedBox(
              height: 90,
              child: Container(
                alignment: Alignment.topCenter,
                child: Transform.translate(
                  offset: Offset(0, 16),
                  child: Container(
                    color: index < currentPage
                        ? Theme.of(context).primaryColor
                        : Colors.grey,
                    width: 30,
                    height: 3,
                    padding: EdgeInsets.symmetric(horizontal: 10),
                  ),
                ),
              ),
            );
          }
        
        
          buildStep(int index) {
            return Padding(
              padding: const EdgeInsets.symmetric(horizontal: 5),
              child: SizedBox(
                height: 90,
                width: STEP_WIDTH,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Container(
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: index <= currentPage
                            ? Theme.of(context).primaryColor
                            : Colors.grey[300],
                      ),
                      padding: EdgeInsets.all(10),
                      child: Text((index + 1).toString()),
                    ),
                    Expanded(
                        child: Text(
                      stepsList[index].title,
                      textAlign: TextAlign.center,
                    ))
                  ],
                ),
              ),
            );
          }
        
          _buildStepper(int currentStep) {
            Future.delayed(
                Duration(milliseconds: 100),
                () => _scrollController.animateTo((STEP_WIDTH * currentStep).toDouble(),
                    duration: const Duration(milliseconds: 300),
                    curve: Curves.easeOut));
            return Center(
              child: SizedBox(
                height: 110,
                child: ListView.builder(
                    controller: _scrollController,
                    shrinkWrap: true,
                    scrollDirection: Axis.horizontal,
                    itemCount: stepsList.length,
                    itemBuilder: (ctx, index) => index < stepsList.length - 1
                        ? Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              buildStep(index),
                              buildStepDivider(index)
                            ],
                          )
                        :Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              buildStep(index)]) ),
              ),
            );
          }
        
        
        
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              appBar: AppBar(title: Text('hello'), centerTitle: true),
              body: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  _buildStepper(currentPage),
                  Expanded(
                      child: PageView.builder(
                    controller: pageController,
                    physics: NeverScrollableScrollPhysics(),
                    onPageChanged: (index) {
                      setState(() {
                        currentPage = index;
                      });
                    },
                    itemCount: stepsList.length,
                    itemBuilder: (ctx, index) => 
                             stepsList[index].page,
                  )),
                ],
              ),
            );
          }
        
        }
        

        【讨论】:

          【解决方案5】:

          我相信您已经得到了答案,但也许这适用于正在寻找包而不是创建自定义包的人。这是我觉得不错的东西,请检查一下,看看它是否适合您的用例。

          https://pub.dev/packages/im_stepper

          【讨论】:

            【解决方案6】:

            创建数字步进器的一个非常简单的步骤是

             Container(
                                margin: const EdgeInsets.only(top: 4, right: 6),
                                padding: const EdgeInsets.all(3.0),
                                decoration: BoxDecoration(
                                  border: Border.all(color: Colors.red, width: 2),
                                  borderRadius: BorderRadius.circular(2),
                                ),
                                child: Row(
                                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                  children: [
                                    InkWell(
                                      child: Icon(Icons.remove, color: Colors.red),
                                      onTap: _dicrement,
                                    ),
                                    Container(
                                      margin: EdgeInsets.only(right: 8, left: 8),
                                      child: Text(
                                        _currentCount.toString(),
                                        style: TextStyle(fontWeight: FontWeight.bold),
                                      ),
                                    ),
                                    InkWell(
                                      child: Icon(Icons.add, color: Colors.red),
                                      onTap: _increment,
                                    ),
                                  ],
                                ),
                              ),
            

            【讨论】:

              猜你喜欢
              • 2021-08-05
              • 2021-02-06
              • 1970-01-01
              • 1970-01-01
              • 2018-12-22
              • 2019-06-16
              • 1970-01-01
              • 2012-01-05
              • 2021-03-28
              相关资源
              最近更新 更多