Reputation: 13
I'm using the vertical type stepper, where I have multiple steps (over 20), I want the step with the isActive property to appear at the beginning, but I can still scroll up to see the previous ones.
Stepper(
key: key_1,
physics: ClampingScrollPhysics(),
onStepTapped: (step) => goTo(step),
currentStep: currentStep,
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue,
VoidCallback onStepCancel}) {
return Row(
children: <Widget>[
Container(
child: null,
),
Container(
child: null,
),
],
);
},
steps: steps)
Example: if step 2 is active, I want it to appear at the beginning and that step 1 when scrolling above can see it, but visually the one that is at the beginning is step 2 enter image description here
Upvotes: 1
Views: 2854
Reputation: 76
In my case what I did was a modification in the Stepper
widget.
Declare the scrollController
variable, as follows:
const Stepper({
Key key,
@required this.steps,
this.physics,
this.scrollController, //Declarate ScrollController
this.type = StepperType.vertical,
this.currentStep = 0,
this.onStepTapped,
this.onStepContinue,
this.onStepCancel,
this.controlsBuilder,
}) : assert(steps != null),
assert(type != null),
assert(currentStep != null),
assert(0 <= currentStep && currentStep < steps.length),
super(key: key);
final ScrollController scrollController;
Once the variable is declared, in the ListView you proceed to add the scrollController as follows:
Widget _buildVertical() {
return ListView(
shrinkWrap: true,
physics: widget.physics,
controller: widget.scrollController,//Add ScrollController here
children: <Widget>[
for (int i = 0; i < widget.steps.length; i += 1)
Column(
key: _keys[i],
children: <Widget>[
InkWell(
onTap: widget.steps[i].state != StepState.disabled
? () {
// In the vertical case we need to scroll to the newly tapped
// step.
Scrollable.ensureVisible(
_keys[i].currentContext,
curve: Curves.fastOutSlowIn,
duration: kThemeAnimationDuration,
);
if (widget.onStepTapped != null) widget.onStepTapped(i);
}
: null,
canRequestFocus: widget.steps[i].state != StepState.disabled,
child: _buildVerticalHeader(i),
),
_buildVerticalBody(i),
],
),
],
);
}
Once that is done, you will have control in the Stepper class, just declare a final variable as scrollController in your document, like this:
final _controller = new ScrollController();
Attach the controller to the Stepper.
When you press onStepContinue, move the animation to the position you want in the controller. I leave you my detailed example below:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class MyStepper extends StatefulWidget {
@override
_MyStepperState createState() => _MyStepperState();
}
class _MyStepperState extends State<MyStepper> {
int _currentStape = 0;
final _controller = new ScrollController();
@override
Widget build(BuildContext context) {
return Material(
child: Container(
width: double.infinity,
height: double.infinity,
child: Stepper(
currentStep: _currentStape,
scrollController: _controller,
physics: ClampingScrollPhysics(),
onStepContinue: () {
_currentStape++;
_controller.animateTo(
0,
duration: Duration(milliseconds: 100),
curve: Curves.bounceIn,
);
setState(() {});
},
onStepTapped: (value) {
_currentStape = value;
},
steps: [
Step(
title: FaIcon(
FontAwesomeIcons.dog,
),
subtitle: Text('Ingresa la información de tu mascota'),
content: Container(
height: 500,
),
),
Step(
title: FaIcon(
FontAwesomeIcons.userAlt,
),
subtitle: Text('Ingresa tú información personal'),
content: Container(
height: 500,
),
),
Step(
title: FaIcon(
FontAwesomeIcons.image,
),
subtitle: Text('Agrega algunas imágenes'),
content: Text('Contenido'),
),
],
),
),
);
}
}
I'm use Flutter 1.17.3
Upvotes: 3