Home > other >  Is there a way to get the index of a widget in a List
Is there a way to get the index of a widget in a List

Time:02-15

Hi im trying to get the index of a particular widget in a list

static const List<Widget> _widgetOptions = <Widget>[
     Index(),
     Achievements(),
];

so get it when to get a certain widget

_widgetOptions.elementAt(_selectedIndex)

but I am having a hard time getting the index of a widget.

I tried int index = _widgetOptions.indexOf(Index()); but it is returning a value of -1 which translate to not found.

CodePudding user response:

I don't know what type of widgets are in your list but it would be better to use you list in ListView.builder and if the widgets are wrapped in something like gestureDetector or button just create an int variable index = - 1 and when one widget is clicked or pressed use a setSate(() => index = i) . (I call i the index in your ListView.builder.

CodePudding user response:

So let's talk about List<T> in Dart!

If you look at the source code for indexOf you'll see this documentation:

  /// The first index of [element] in this list.
  ///
  /// Searches the list from index [start] to the end of the list.
  /// The first time an object `o` is encountered so that `o == element`,
  /// the index of `o` is returned.

Pay special attention to the o == element meaning that the item that you're trying to find has to implement the == operator. If you look deeper into the source code for Flutter you will see that StatelessWidget implements DiagnosticableTree and that itself implements the == operator:

  /// Compare two widgets for equality.
  ///
  /// When a widget is rebuilt with another that compares equal according
  /// to `operator ==`, it is assumed that the update is redundant and the
  /// work to update that branch of the tree is skipped.

You can prove that it all works by writing this code:

final widget1 = const MyText();
final widget2 = const MyText();
final List<dynamic> texts = [widget1, widget2];
final i1 = texts.indexOf(widget1);
final i2 = texts.indexOf(widget2);
assert(i1 == 0);
assert(i2 == 1);

And you'll see that Flutter is indeed able to find those elements at the right index. So that's the first point.

However, after more than 2 years of Flutter development I've never had to do this which tells me what you're doing can be achieved in many other ways, such as using a ListView.builder() that creates a widget for all the itemCount that you provide to it.

CodePudding user response:

When you call '_widgetOptions.indexOf(Index())' to find Widget index,
the two 'Index()' Widget instance will be made.

So the 'Index()' instance is different between '_widgetOptions' and 'Index()'.

Below is example code and result.
enter image description here

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // the text entered by the user
  Widget? indexWidget;
  Widget? achievements;
  
  
   Widget Index() {
    return Container();
  }
  
   Widget Achievements() {
    return Column(
      children: [
        Container(),
      ]
    );
  }
  
    @override
  void initState() {
    super.initState();
    indexWidget = Index();
    achievements = Achievements();
    
    List<Widget?> _widgetOptions = <Widget?> [
       Index(),
       Achievements(),
    ];
    
    List<Widget?> _widgetOptions2 = <Widget?> [
       indexWidget,
       achievements,
    ];
    
    print(_widgetOptions.indexOf(Index()));
    
    print(_widgetOptions2.indexOf(indexWidget));
    print(_widgetOptions2.indexOf(Index()));
  }
  


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Remove the debug banner
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: Container(),
        ),
      ),
    );
  }
}
  • Related