0

I have a code:

// New Game route
class NewGameRoute extends StatelessWidget {
  const NewGameRoute({key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'New Game',
      home: ListFromCSV1(),
    );
  }
}

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

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

class _ListFromCSVState1 extends State<ListFromCSV1> {
  List<List<dynamic>> _listData = [
    [""]
  ];
  int _listCount = 0;
  bool _isFirstLoad = true;
  String assetPath = "files/main.jpg";

  @override
  initState() {
    _loadCSV();
  }

  // This function is only triggered at init, so we only load csv once
  void _loadCSV() async {
    String _rawData = await rootBundle.loadString("files/Text.csv");
    _listData = const CsvToListConverter().convert(_rawData);
  }

  // This function is triggered when my button is pressed
  void _nextCSV() {
    setState(() {
      _listData = _listData;
      _listCount < _listData.length - 1
          ? _isFirstLoad ? _isFirstLoad = false
          : _listCount++
          : _listCount;
      // assetPath = _listData[_listCount][1] == "" ? "files/main.jpg" : _listData[_listCount][1];
      assetPath = _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('New Game'),
      ),
      body: Container(
        height: MediaQuery
            .of(context)
            .size
            .height,
        decoration: BoxDecoration(
            image: DecorationImage(
                  image: AssetImage(assetPath), fit: BoxFit.cover)),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            // const SizedBox(height: 30),
            ClipRRect(
              borderRadius: BorderRadius.circular(4),
              child: Stack(
                children: <Widget>[
                  Positioned.fill(
                    child: Container(
                      decoration: const BoxDecoration(
                          image: DecorationImage(
                              image: AssetImage('files/sheet.jpg'),
                              fit: BoxFit.cover)),
                    ),
                  ),
                  Text(
                      _listData[_listCount][0]
                  ),
                ],
              ),
            ),
            // const SizedBox(height: 30),
            ClipRRect(
              borderRadius: BorderRadius.circular(4),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  TextButton(
                    style: TextButton.styleFrom(
                      padding: const EdgeInsets.all(16.0),
                      primary: Colors.white,
                      textStyle: const TextStyle(fontSize: 20),
                    ),
                    // onPressed: () {},
                    onPressed: _nextCSV,

                    child: const Text('OK'),
                  ),
                  TextButton(
                    style: TextButton.styleFrom(
                      padding: const EdgeInsets.all(16.0),
                      primary: Colors.white,
                      textStyle: const TextStyle(fontSize: 20),
                    ),
                    onPressed: () {},
                    // onPressed: _nextCSV,

                    child: const Text('Hide'),
                  ),
                ],
              ),
            ),
            ClipRRect(
              borderRadius: BorderRadius.circular(4),
              child: Stack(
                children: <Widget>[
                  Positioned.fill(
                    child: Container(
                      decoration: const BoxDecoration(
                        gradient: LinearGradient(
                          colors: <Color>[
                            Color(0xFF0D47A1),
                            Color(0xFF1976D2),
                            Color(0xFF42A5F5),
                          ],
                        ),
                      ),
                    ),
                  ),
                  TextButton(
                    style: TextButton.styleFrom(
                      padding: const EdgeInsets.all(16.0),
                      primary: Colors.white,
                      textStyle: const TextStyle(fontSize: 20),
                    ),
                    onPressed: _nextCSV,
                    child: const Text('Show'),
                  ),
                ],
              ),
            ),
            // const SizedBox(height: 30),
          ],
        ),
      ),
    );
  }
}

It looks like this:

enter image description here

I need it to look like this:

enter image description here

  1. How to make the sheet.jpg image used as a background for the OK and Hide buttons? Right now it's a text-only background.

  2. How can I make the OK and Hide buttons have the same style as the Hide button? I understand that I need to use the code:

    borderRadius: BorderRadius.circular(4), child: Stack( children: [ Positioned.fill( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: [ Color(0xFF0D47A1), Color(0xFF1976D2), Color(0xFF42A5F5), ], ), ), ), ),

But I am confused about the children of widgets, which is why the code does not want to be executed at all.

This is just a styling issue, so don't look at classes and functions. Thank you.

Edit1.I want these buttons to have a background from sheet.jpg, while the rest of the screen has a background from main.jpg and what is taken from the csv file later.

But if I use this code:

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

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

class _ListFromCSVState extends State<ListFromCSV> {
  List<List<dynamic>> _listData = [
    [""]
  ];
  int _listCount = 0;
  bool _isFirstLoad = true;
  String assetPath = "assets/files/main.jpeg";

  @override
  void initState() {
    _loadCSV();
  }

  // This function is only triggered at init, so we only load csv once
  void _loadCSV() async {
    String rawData = await rootBundle.loadString("assets/files/Text.csv");
    _listData = const CsvToListConverter().convert(rawData);
    assetPath = _listData[_listCount][1] == "" ? "assets/files/main.jpeg" : _listData[_listCount][1];
  }

  // This function is triggered when my button is pressed
  void _nextCSV() {
    setState(() {
      _listData = _listData;
      _listCount < _listData.length - 1
          ? _isFirstLoad
              ? _isFirstLoad = false
              : _listCount++
          : _listCount;
      assetPath = _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('New Game'),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        decoration: const BoxDecoration(
            image: DecorationImage(
                image: AssetImage("assets/files/sheet.jpeg"), fit: BoxFit.cover)),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Container(
              decoration: BoxDecoration(
                border: Border.all(color: Colors.yellow, width: 3)
              ),
              child: Column(
                children: [
                  ClipRRect(
                    borderRadius: BorderRadius.circular(4),
                    child: Stack(
                      children: <Widget>[
                        Positioned.fill(
                          child: Container(
                            decoration: BoxDecoration(
                                image: DecorationImage(
                                    image: AssetImage(assetPath),
                                    fit: BoxFit.cover)),
                          ),
                        ),
                        Text(_listData[_listCount][0]),
                      ],
                    ),
                  ),
                  ClipRRect(
                    borderRadius: BorderRadius.circular(4),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        TextButton(
                          style: TextButton.styleFrom(
                            side: BorderSide(color: Colors.yellow, width: 3),
                            padding: const EdgeInsets.all(16.0),
                            primary: Colors.white,
                            backgroundColor: Colors.transparent,
                            textStyle: const TextStyle(fontSize: 20),
                          ),
                          // onPressed: () {},
                          onPressed: _nextCSV,
                          child: const Text('OK'),
                        ),
                        TextButton(
                          style: TextButton.styleFrom(
                            side: BorderSide(color: Colors.yellow, width: 3),
                            padding: const EdgeInsets.all(16.0),
                            primary: Colors.white,
                            backgroundColor: Colors.transparent,
                            textStyle: const TextStyle(fontSize: 20),
                          ),
                          onPressed: () {},
                          // onPressed: _nextCSV,
                          child: const Text('Hide'),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            // your other widgets
          ],
        ),
      ),
    );
  }
}

It looks like this:

enter image description here

And I want this:

enter image description here

I understand that I have to wrap the existing buttons in a container with sheet.jpg. But I keep losing punctuation marks, which makes the code not want to run at all.

Edit2. How can I make sheet.jpg the background not only for the OK and Hide buttons, but also for the space between them? I schematically depicted this:

enter image description here

I was trying to just "raise" those buttons into a container. But when I do like this:

child: Container(
  decoration: BoxDecoration(
      image: DecorationImage(
          image: AssetImage('files/sheet.jpg'),
          fit: BoxFit.cover)),
  child:
  Row(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    children: [
      ImageButton(label: 'OK', onButtonTap: _nextCSV),
      ImageButton(label: 'Hide', onButtonTap: () {}),
    ],
  ),
),

I get an error: "A RenderFlex overflowed by 46 pixels on the right"

Texter
  • 95
  • 10
  • can you share full warning? Cos overflow issue might happen in some other place. For me its working perfectly – Prabhakaran Jul 05 '22 at 07:55
  • 1
    Your code works perfect. This error only appears when I start making my changes. But since I plan to change the structure a little later, this problem may not be there by then. So this issue can be considered resolved. Thank you. – Texter Jul 05 '22 at 11:22

3 Answers3

1

Hope this helps you. I created a button-like widget named ImageButton.

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

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

class _ListFromCSVState extends State<ListFromCSV> {
  List<List<dynamic>> _listData = [
    [""]
  ];
  int _listCount = 0;
  bool _isFirstLoad = true;
  String assetPath = "assets/files/main.jpeg";

  @override
  void initState() {
    _loadCSV();
  }

  // This function is only triggered at init, so we only load csv once
  void _loadCSV() async {
    String rawData = await rootBundle.loadString("assets/files/Text.csv");
    _listData = const CsvToListConverter().convert(rawData);
    assetPath = _listData[_listCount][1] == ""
        ? "assets/files/main.jpeg"
        : _listData[_listCount][1];
  }

  // This function is triggered when my button is pressed
  void _nextCSV() {
    setState(() {
      _listData = _listData;
      _listCount < _listData.length - 1
          ? _isFirstLoad
              ? _isFirstLoad = false
              : _listCount++
          : _listCount;
      assetPath =
          _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('New Game'),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        decoration: const BoxDecoration(
            image: DecorationImage(
                image: AssetImage("assets/files/sheet.jpeg"),
                fit: BoxFit.cover)),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Column(
              children: [
                ClipRRect(
                  borderRadius: BorderRadius.circular(4),
                  child: Stack(
                    children: <Widget>[
                      Positioned.fill(
                        child: Container(
                          decoration: BoxDecoration(
                              image: DecorationImage(
                                  image: AssetImage(assetPath),
                                  fit: BoxFit.cover)),
                        ),
                      ),
                      Text(_listData[_listCount][0]),
                    ],
                  ),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ImageButton(label: 'OK', onButtonTap: _nextCSV),
                    ImageButton(label: 'Hide', onButtonTap: () {}),
                  ],
                ),
              ],
            ),
            // your other widgets
          ],
        ),
      ),
    );
  }
}

class ImageButton extends StatelessWidget {
  const ImageButton({Key? key, required this.label, required this.onButtonTap})
      : super(key: key);
  final String label;
  final Function onButtonTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () => onButtonTap(),
      child: Container(
        // customize you button shape and size and design
        margin: const EdgeInsets.all(8),
        padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 32),
        decoration: const BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(2)),
            image: DecorationImage(
                image: AssetImage("assets/files/main.jpeg"), // you can also pass the image dynamically with variable created for the widget.
                fit: BoxFit.cover)),
        child: Center(
          child: Text(
            label,
            style: const TextStyle(
                color: Colors
                    .white, // you can get dominant colour on image and change the text color accordingly or apply shadows to the text
                fontWeight: FontWeight.w500,
                fontSize: 16),
          ),
        ),
      ),
    );
  }
}

You can also create a new dart file and move the ImageButton widget code to that file and import and use it anywhere you want. It will reduce the number of lines of code and also increases code reusability.

Prabhakaran
  • 1,524
  • 2
  • 13
  • 21
  • Wow! It's even better than I wanted. However, I would like to ask the following question. How can I make sheet.jpg the background not only for the OK and Hide buttons, but also for the space between/around them? I schematically depicted this in the figure for Edit2. – Texter Jul 04 '22 at 12:51
0

If I understand correctly you can add an image to your code and later use it for your purpose in this way: See here flutter docs

For the second problem in order to add a border you need to use a container and inside the container box decoration and other stuff, but it depends on the result that you want, checks here Stack refers

  • I am already used an image as a background. The problem is that the image only fills the space where there is text. I want the picture to extend all the way to the OK and Hide buttons (but not Show button). That is, the picture must be limited to the first column only. But how? – Texter Jul 02 '22 at 16:57
  • You need to insert the image on the container that contains all the widgets (Buttons Ok/Hide and the Text). You should do something like that: Container (with image as background) and inside this container the other components, I think that this solution should work but I'm not able to try, so sorry if it doesn't work –  Jul 02 '22 at 17:00
  • Yes, I understand what you are talking about. But as soon as I create a container and start wrapping my buttons there, my code stops working due to the fact that in the process of wrapping I lose brackets and other punctuation marks. – Texter Jul 03 '22 at 10:37
0

You can specify the background as transparent for your buttons like this.

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

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

class _ListFromCSVState extends State<ListFromCSV> {
  List<List<dynamic>> _listData = [
    [""]
  ];
  int _listCount = 0;
  bool _isFirstLoad = true;
  String assetPath = "assets/files/main.jpeg";

  @override
  void initState() {
    _loadCSV();
  }

  // This function is only triggered at init, so we only load csv once
  void _loadCSV() async {
    String rawData = await rootBundle.loadString("assets/files/Text.csv");
    _listData = const CsvToListConverter().convert(rawData);
    assetPath = _listData[_listCount][1] == "" ? "assets/files/main.jpeg" : _listData[_listCount][1];
  }

  // This function is triggered when my button is pressed
  void _nextCSV() {
    setState(() {
      _listData = _listData;
      _listCount < _listData.length - 1
          ? _isFirstLoad
              ? _isFirstLoad = false
              : _listCount++
          : _listCount;
      assetPath = _listData[_listCount][1] == "" ? assetPath : _listData[_listCount][1];
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('New Game'),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        decoration: const BoxDecoration(
            image: DecorationImage(
                image: AssetImage("assets/files/sheet.jpeg"), fit: BoxFit.cover)),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Container(
              decoration: BoxDecoration(
                border: Border.all(color: Colors.yellow, width: 3)
              ),
              child: Column(
                children: [
                  ClipRRect(
                    borderRadius: BorderRadius.circular(4),
                    child: Stack(
                      children: <Widget>[
                        Positioned.fill(
                          child: Container(
                            decoration: BoxDecoration(
                                image: DecorationImage(
                                    image: AssetImage(assetPath),
                                    fit: BoxFit.cover)),
                          ),
                        ),
                        Text(_listData[_listCount][0]),
                      ],
                    ),
                  ),
                  ClipRRect(
                    borderRadius: BorderRadius.circular(4),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        TextButton(
                          style: TextButton.styleFrom(
                            side: BorderSide(color: Colors.yellow, width: 3),
                            padding: const EdgeInsets.all(16.0),
                            primary: Colors.white,
                            backgroundColor: Colors.transparent,
                            textStyle: const TextStyle(fontSize: 20),
                          ),
                          // onPressed: () {},
                          onPressed: _nextCSV,
                          child: const Text('OK'),
                        ),
                        TextButton(
                          style: TextButton.styleFrom(
                            side: BorderSide(color: Colors.yellow, width: 3),
                            padding: const EdgeInsets.all(16.0),
                            primary: Colors.white,
                            backgroundColor: Colors.transparent,
                            textStyle: const TextStyle(fontSize: 20),
                          ),
                          onPressed: () {},
                          // onPressed: _nextCSV,
                          child: const Text('Hide'),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            // your other widgets
          ],
        ),
      ),
    );
  }
}
Prabhakaran
  • 1,524
  • 2
  • 13
  • 21
  • Thanks, but I want two buttons to have a background from sheet.jpg while the rest of the screen has a background from main.jpg. I am attaching a picture to Edit 1. – Texter Jul 03 '22 at 07:05