Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checkbox animation shows a visual toggle but still fails to update state interally #377

Open
mendelg opened this issue Apr 17, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@mendelg
Copy link

mendelg commented Apr 17, 2024

Description

I am developing a Flutter application using Rive animations for checkboxes. While the checkboxes visually toggle correctly when tapped, the programmatic state does not reflect these changes. Specifically, the submittedMissions list does not update correctly—it fails to remove IDs when checkboxes are unchecked, leading to inaccurate state representation in the application logic.

Steps to Reproduce

  1. Tap a checkbox to select it; the internal state list submittedMissions updates to include the mission ID.
  2. Tap the checkbox again to deselect it; the submittedMissions list fails to remove the mission ID.
  3. The UI shows the checkbox as deselected, but the state still considers it selected.

Expected Behavior

When a checkbox is deselected, the corresponding mission ID should be removed from the submittedMissions list, ensuring the internal state matches the visual representation.

Screenshots

Incorrect state representation
State not updating when checkbox is unchecked - it says there are still 2 checkboxes selected

Correct behavior with native Checkbox
Expected behavior using Flutter's native Checkbox.

Code to Reproduce

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive/rive.dart';

void main() {
  runApp(
    MaterialApp(
      home: MissionListScreen(),
      debugShowCheckedModeBanner: false,
    ),
  );
}

class MissionListScreen extends StatefulWidget {
  @override
  _MissionListScreenState createState() => _MissionListScreenState();
}

class _MissionListScreenState extends State<MissionListScreen> {
  List<MissionItem> missions = [
    MissionItem(missionId: '1', missionName: 'Mission 1'),
    MissionItem(missionId: '2', missionName: 'Mission 2'),
    MissionItem(missionId: '3', missionName: 'Mission 3'),
  ];

  List<String> submittedMissions = [];

  @override
  void initState() {
    super.initState();
    loadRiveFiles();
  }

  void loadRiveFiles() async {
    for (var mission in missions) {
      await _loadRiveFile(mission);
    }
    setState(() {});
  }

  Future<void> _loadRiveFile(MissionItem missionItem) async {
    try {
      final data = await rootBundle.load('assets/checkbox.riv');
      final file = RiveFile.import(data);

      final artboard = file.mainArtboard;
      var controller =
          StateMachineController.fromArtboard(artboard, 'State Machine 1');
      if (controller != null) {
        artboard.addController(controller);
        missionItem.checkButtonInput = controller.findInput<bool>('Tap');
        missionItem.checkButtonArtboard = artboard;

        // Set the initial state of the Tap input
        missionItem.checkButtonInput?.value =
            submittedMissions.contains(missionItem.missionId);
      }
    } catch (e) {
      print('Failed to load Rive file: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          //show the total number of missions checked
          Text(
            'There are ${submittedMissions.length} boxes checked.',
            style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
          ),
          SizedBox(height: 20),
          Expanded(
            child: ListView.builder(
              itemCount: missions.length,
              itemBuilder: (context, index) {
                MissionItem missionItem = missions[index];
                return buildMissionListTile(missionItem, index);
              },
            ),
          ),
        ],
      ),
    );
  }

  Widget buildMissionListTile(MissionItem mission, int index) {
    return ListTile(
      title: Text(mission.missionName),
      trailing: GestureDetector(
        onTap: () => toggleMission(mission, index),
        child: SizedBox(
            height: 32,
            width: 32,
            child: Rive(artboard: mission.checkButtonArtboard!)),
        // this code using Checkbox widget DOES work
        // child: Checkbox(
        //   value: mission.checkButtonInput?.value ?? false,
        //   onChanged: (value) => toggleMission(mission, index),
        // )),
      ),
    );
  }

  void toggleMission(MissionItem mission, int index) {
    bool currentState = mission.checkButtonInput?.value ?? false;
    setState(() {
      mission.checkButtonInput?.value = !currentState;
      MissionItem newMission = mission;
      if (currentState) {
        submittedMissions.removeWhere((id) => id == mission.missionId);
      } else {
        if (!submittedMissions.contains(mission.missionId)) {
          submittedMissions.add(mission.missionId);
        }
      }

      missions.removeAt(index);
      missions.insert(index, newMission);
    });
    print("Submitted Missions: $submittedMissions"); // Debugging
  }
}

class MissionItem {
  final String missionId;
  final String missionName;
  SMIInput<bool>? checkButtonInput;
  Artboard? checkButtonArtboard;

  MissionItem({
    required this.missionId,
    required this.missionName,
  });
}

Environment

  • Flutter 3.19.5 • channel stable • https://github.com/flutter/flutter.git
  • Framework • revision 300451adae (3 weeks ago) • 2024-03-27 21:54:07 -0500
  • Engine • revision e76c956498
  • Tools • Dart 3.3.3 • DevTools 2.31.1

Additional Context

Request

Please look into why the Rive animations do not trigger state updates as expected when toggling the state of checkboxes despite the UI changing. Any guidance or workarounds would be greatly appreciated!

@mendelg mendelg added the bug Something isn't working label Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant