0

I created a custom class, RectButton, with editable properties of buttonChild, bgColor, and onPress. I was hoping to make this widget further dynamic by creating a new widget that can create a row of these RectButtons based on a variable integer (i.e. 4 buttons on one screen, 3 on another screen, etc) but cant figure out how to continue to have completely editable properties (bgColor isn't depended on index, i.e. bgColor: Colors.red[100 + 100 * index]) in the new widget.

class RectButton extends StatelessWidget {
  RectButton({this.buttonChild, this.bgColor, this.onPress});

  final Widget buttonChild;
  final Color bgColor;
  final Function onPress;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onPress,
      child: Container(
        constraints: BoxConstraints.expand(width: 100, height: 50),
        child: Center(child: buttonChild),
        decoration: BoxDecoration(
            color: bgColor,
            shape: BoxShape.rectangle,
            border: Border.all(width: 1, color: Colors.white)),
        padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
      ),
    );
  }
}

Any thoughts? Any help is much appreciated. Ive been googling everything I can find about for loops and lists with no luck. Also any resources are also appreciated-- kinda new to flutter :)

Edit: Updated Code

import 'package:flutter/material.dart';
import 'rect_button.dart';

enum Options { option0, option1, option2, option3 }

class Screen1 extends StatefulWidget {
  @override
  _Screen1State createState() => _Screen1State();
}

class _Screen1State extends State<Screen1> {
  List<Widget> makeButtons(int num, List<Widget> children, List<Color> colors,
      List<Function> onPresses) {
    List<Widget> buttons = new List();
    for (int i = 0; i < num; i++) {
      buttons.add(RectButton(children[i], colors[i], onPresses[i]));
    }
    return buttons;
  }

  Options selectedOption;

  @override
  Widget build(BuildContext context) {
    int num = 2;
    List<Widget> children = [
      Text("A"),
      Text("B"),
    ];
    List<Color> colors = [
      selectedOption == Options.option0 ? Colors.red : Colors.green,
      selectedOption == Options.option1 ? Colors.red : Colors.green
    ];
    List<Function> onPresses = [
      () {
        setState(() {
          selectedOption = Options.option0;
        });
      },
      () {
        setState(() {
          selectedOption = Options.option1;
        });
      },
    ];
// 3rd method does nothing
    return Scaffold(
      appBar: AppBar(
        title: Text('title'),
      ),
      body: Row(
        children: makeButtons(3, children, colors, onPresses),
      ),
    );
  }
}
  • Do you mean the color IS dependent? – Sidak May 17 '20 at 15:30
  • Yes sorry, Sidak. Good catch! I am hoping that each generated button would be independent of the other. Such that, one could be purple and one could be red if desired. – Peter Moran May 17 '20 at 15:33
  • So you want something like, `makeButtonRow(int num, [Children], [Colors], [onPress])`? – Sidak May 17 '20 at 17:33
  • Yes as long as that would allow me to produce varying numbers of RectButtons based on the int inputed into the makeButtonRow and allow me to change the Children, Colors, and onPress for each RectButton – Peter Moran May 17 '20 at 17:49

1 Answers1

0

If you can create Lists for each child, color, onPress you want, you can use the code below to loop through and create a list of RectButton:

List<Widget> makeButtons(int num, List<Widget> children, List<Color> colors, List<Function> onPresses){
  List<Widget> buttons = new List();
  for(int i = 0; i < num; i ++){
    buttons.add(RectButton(buttonChild: children[i], bgColor: colors[i], onPress: onPresses[i]));
  }
  return buttons;
}

You can use it with a Row like:

Row(
  children: makeButtons(...),
),

You can also modify the makeButtons method to add optional parameters in case you want one color consistently/with a [100+100*i] difference etc.

Edit: Example with build method:

Widget build(BuildContext context) {
    int num = 2;
    List<Widget> children = [Text("A"), Text("B"), Text(_counter.toString())];
    List<Color> colors = [Colors.red, Colors.blue, Colors.green];
    List<Function> onPresses = [_incrementCounter, _decrementCounter, (){}];
// 3rd method does nothing
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Row(
      children: makeButtons(3, children, colors, onPresses),
      ),
    );
  }
Sidak
  • 1,213
  • 6
  • 11
  • thanks so much! Your code has definitely helped me to a lot. I am still running into some trouble though. Currently when I try and call the makeButtons, I keep getting the error "The argument type 'List' can not be assigned to the parameter type 'Widget'. Here is the code I was playing with: `Center( child: makeButtons( 2, [Text('hi'), Text('helo')], [Colors.orange, Colors.red], [print('byeee'), print('eat me')], ), ),` – Peter Moran May 17 '20 at 21:32
  • You need to call `makeButtons` in a `Row` or `Column` or `Stack` like structure where it requires children, not a single child. Alternatively, store the buttons like, `List buttons = makeButtons(...)` and put the child of your container as `buttons[0]` etc. – Sidak May 18 '20 at 08:53
  • Okay after some playing with the code I got it to work without any errors! Now when I run my code, there is nothing that is produced. Do I need to use a Listview.builder? or List.generate? – Peter Moran May 18 '20 at 19:21
  • After some dabbling, I believe the buttons are not displaying secondary to the onPresses. I cant put a normal function (with void) or a future state inside the onPresses list as I get "the expression here has type "void/future" and therefore cant be used." I was able to do ```() { setState(() { selectedOption = Options.option0; }); },``` but it will not display the buttons. – Peter Moran May 18 '20 at 22:29
  • Hey Peter, I just edited the code above to account for the optional arguments. I didn't realise that `RectButton` takes optional args. I've also tried to run the code and it works for me. You can check it out at https://dartpad.dev/b6409e10de32b280b8938aa75364fa7b – Sidak May 19 '20 at 07:49
  • I think that link is just to a normal dart pad. I only see the floating action button and the text that keeps track of number of times pushed :( – Peter Moran May 19 '20 at 14:22
  • Sorry about that, I just edited my answer with the code I used in `build()` – Sidak May 19 '20 at 16:31
  • Sidak, I managed to figured out how to compile the code and remove errors. Unfortunately, I am still only getting an AppBar without the production of buttons. I edited my original post to reflect my full code. Do you see anything I am doing wrong? I did play with the 'num' but even with the corrections, I still had no buttons – Peter Moran May 19 '20 at 17:31
  • Have a look at my `makeButtons` implementation. Your `makeButtons` is using the old implementation which doesnt work – Sidak May 19 '20 at 18:25
  • Thank you sooooo much! I truly appreciate your patience. Thanks again Sidak! – Peter Moran May 19 '20 at 19:19