I have implemented a TabBar in my Flutter application in which each individual tab represents a day that the user wants to work out and the tab’s text is the title of the day. Days are stored in a list. My problem is changing a day’s title in the list, changes other tabs’ texts as well. Take a look at my code.
This is my WorkoutDay class.
class WorkoutDay {
List<Exercise>? exercises;
String title = 'Workout Day';
WorkoutDay.newEmptyDay();
WorkoutDay(this.title, this.exercises);
}
I have a list of workout days.
List<WorkoutDays> workoutDays;
And I have a TabBar which tabs are the title of workout days. I generate the tabs this way.
tabs: List.generate(workoutDays.length, (index) => Tab(text: workoutDays[index].title))
The problem is that workoutDays[0].title = 'new title';
applies to all the other tabs as well.
What is the problem?!
I will share the whole dart file below. Thanks.
import 'package:extrain/ui/views/add_exercise_tab_view.dart';
import 'package:extrain/utilities/enums/purposes.dart';
import 'package:extrain/utilities/models/exercise.dart';
import 'package:extrain/utilities/models/workout_day.dart';
import 'package:flutter/material.dart';
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
import 'package:provider/provider.dart';
import 'dart:developer';
class NewManualWorkout extends StatefulWidget {
const NewManualWorkout({Key? key}) : super(key: key);
@override
State<NewManualWorkout> createState() => _NewManualWorkoutState();
}
class _NewManualWorkoutState extends State<NewManualWorkout>
with TickerProviderStateMixin {
late TabController _tabController;
String _dropdownValue = Purpose.values.first.text;
double _currentSliderValue = 1;
bool _restWarningVisibility = false;
late List<WorkoutDay> workoutDays;
@override
void initState() {
super.initState();
workoutDays = [WorkoutDay.newEmptyDay()];
_tabController = TabController(length: workoutDays.length, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/** Assigning new name here for example **/
ElevatedButton(
onPressed: () {
setState(() {
workoutDays[0].title = 'New Name';
});
}, child: const Text('Assign new name')),
Slider(
value: _currentSliderValue,
max: 7,
min: 1,
divisions: 6,
label: _currentSliderValue.round() == 1
? '${_currentSliderValue.round().toString()} day in a week'
: '${_currentSliderValue.round().toString()} days in a week',
onChanged: (double value) {
setState(() {
_currentSliderValue = value;
workoutDays = List<WorkoutDay>.filled(
_currentSliderValue.round(),
WorkoutDay.newEmptyDay());
_tabController = TabController(
length: workoutDays.length, vsync: this);
});
},
),
],
),
),
Card(
semanticContainer: true,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
child: Column(
children: [
Material(
color: Colors.blue,
child: SizedBox(
width: double.infinity,
child: Align(
alignment: Alignment.center,
child: TabBar(
controller: _tabController,
isScrollable: true,
tabs: List.generate(
workoutDays.length,
(index) => Tab(
text: workoutDays[index].title,
))),
),
),
),
SizedBox(
height: 300,
child: TabBarView(
controller: _tabController,
children: List.generate(
workoutDays.length,
(currentDay) => const Center(
child: AddExerciseTabView(),
))),
),
],
),
)
],
),
)),
);
}
}
2
Answers
its because of the way you instantiate the
workoutDays
in your
Slider
onChanged
.Your general approach for the
and the
is totally fine.
just move the handling of the list to outside the build method
(currently you reset your list every build with
workoutDays = List<WorkoutDay>.filled(...
).You could try like this