Kel
Kel

Reputation: 463

Flutter: How to insert Icon/Action based on X Y percent position of image

I want to insert a Icon/Action based on X Y percent position of image as follows:

enter image description here

This is Json file:

[
  {
    "seasonName": "Spring",
    "isDaySelected": true,
    "listButton": "Sky",
    "pointXPercent": 66.0,
    "pointYPercent": 12.0,
    "pointName": "Bird",
    "pointDialog": "this is a bird"
  },
  {
    "seasonName": "Spring",
    "isDaySelected": true,
    "listButton": "Sky",
    "pointXPercent": 53.6,
    "pointYPercent": 27.4,
    "pointName": "Cloud",
    "pointDialog": "this is a cloud"
  },
  {
    "seasonName": "Spring",
    "isDaySelected": true,
    "listButton": "Land",
    "pointXPercent": 38.5,
    "pointYPercent": 78.3,
    "pointName": "Flower",
    "pointDialog": "this is a flower"
  },
  {
    "seasonName": "Spring",
    "isDaySelected": false,
    "listButton": "Land",
    "pointXPercent": 55.3,
    "pointYPercent": 79.8,
    "pointName": "Meadow",
    "pointDialog": "this is a meadow"
  },
  {
    "seasonName": "Summer",
    "isDaySelected": true,
    "listButton": "Sky",
    "pointXPercent": 38.9,
    "pointYPercent": 23.5,
    "pointName": "Sun",
    "pointDialog": "this is the sun"
  }
]

I want that when click on the TogglesButton "Sky" => get data from Json:

  1. Get values seasonName = "Spring" (because TabBar is being selected as "Spring")

  2. Get values that satisfy (1) and have isDaySelected = "true" (because the TogglesButton isDaySelected is being selected as true)

  3. Get values that satisfy (1) and (2) and listButton = "Sky"

  4. Show the pointName values that satisfy (1) (2) (3) on image based on X Y percent. Ex:

So pls help me, this is main file:

import 'package:ask/model/season_model.dart';
import 'package:ask/services/season_service.dart';
import 'package:flutter/material.dart';

class SeasonPage extends StatefulWidget {
  SeasonPage() : super();
  @override
  _SeasonPageState createState() => _SeasonPageState();
}

class _SeasonPageState extends State<SeasonPage> {
  List<Season> _season = [];
  List<bool> isDaySelected = [true, false];
  List<bool> listButton = [false, false, false];

  final String springDay = 'https://i.imgur.com/MUuCuYI.png';
  final String springNight = 'https://i.imgur.com/QxbAg8Y.png';
  final String summerDay = 'https://i.imgur.com/9Qi6oLm.png';
  final String summerNight = 'https://i.imgur.com/jrFGHvn.png';
  final String autumnDay = 'https://i.imgur.com/yo0RWi6.png';
  final String autumnNight = 'https://i.imgur.com/iPW4r2g.png';
  final String winterDay = 'https://i.imgur.com/CnFDmEJ.png';
  final String winterNight = 'https://i.imgur.com/lFNdvDe.png';

  @override
  void initState() {
    super.initState();
    SeasonServices.getSeason().then((seasons) {
      setState(() {
        _season = seasons;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: DefaultTabController(
            length: 4,
            child: Scaffold(
                appBar: AppBar(
                  title: Text('Season'),
                  bottom: TabBar(tabs: [
                    Tab(child: Text('Spring')),
                    Tab(child: Text('Summer')),
                    Tab(child: Text('Autumn')),
                    Tab(child: Text('Winter')),
                  ]),
                ),
                body: Column(children: [
                  Center(
                      child: ToggleButtons(
                          children: [Text('Day'), Text('Night')],
                          onPressed: (int index) {
                            setState(() {
                              for (int buttonIndex = 0; buttonIndex < isDaySelected.length; buttonIndex++) {
                                if (buttonIndex == index) {
                                  isDaySelected[buttonIndex] = true;
                                } else {
                                  isDaySelected[buttonIndex] = false;
                                }
                              }
                            });
                          },
                          isSelected: isDaySelected)),
                  SizedBox(height: 5),
                  Center(
                      child: ToggleButtons(
                          children: [Text('Sky'), Text('Mountain'), Text('Land')],
                          onPressed: (int index) {
                            setState(() {
                              for (int buttonIndex = 0; buttonIndex < listButton.length; buttonIndex++) {
                                if (buttonIndex == index) {
                                  listButton[buttonIndex] = !listButton[buttonIndex];
                                } else {
                                  listButton[buttonIndex] = false;
                                }
                              }
                            });
                          },
                          isSelected: listButton)),
                  Expanded(
                    child: TabBarView(children: [
                      isDaySelected[0] ? Image.network(springDay) : Image.network(springNight),
                      isDaySelected[0] ? Image.network(summerDay) : Image.network(summerNight),
                      isDaySelected[0] ? Image.network(autumnDay) : Image.network(autumnNight),
                      isDaySelected[0] ? Image.network(winterDay) : Image.network(winterNight),
                    ]),
                  )
                ]))));
  }
}

Upvotes: 2

Views: 1724

Answers (2)

Sergey Salnikov
Sergey Salnikov

Reputation: 1791

There are several ways to achive result

Use Stack and wrap it in IntrinsicHeight to set it height as you image height

      Column(
        children: <Widget>[
          IntrinsicHeight(
            child: Stack(
              children: <Widget>[
                Image.network('https://i.imgur.com/MUuCuYI.png'),
                Align(
                  alignment: Alignment(.66 * 2 - 1, .12 * 2 - 1),
                  child: Text('bird'),
                ),
                Align(
                  alignment: Alignment(.536 * 2 - 1, .274 * 2 - 1),
                  child: Text('cloud'),
                ),
              ],
            ),
          ),
        ],
      ),

This will be sized to Stack children max height and until network image loaded(finally you know size) it will be tall as max of bird or cloud heigh

Note that IntrinsicHeight is relatively expensive. Avoid using it where possible.

For more complex cases you can use LayoutBuilder

        body: Column(
        children: <Widget>[
          Expanded(
            child: LayoutBuilder(
              builder: (context, constraints) {
                return Stack(
                  children: <Widget>[
                    Positioned(
                      top: .12 * constraints.biggest.height,
                      left: .66 * constraints.biggest.width,
                      child: Text('bird'),
                    ),
                    Positioned(
                      top: .274 * constraints.biggest.height,
                      left: .536 * constraints.biggest.width,
                      child: Text('cloud'),
                    ),
                  ],
                );
              },
            ),
          ),
        ],
      ),

PS Here we laying out by left&top of our bird&cloud If you need to layout by center of birs&cloud - you have to know their sizes and do a little bit more math

Upvotes: 2

MSpeed
MSpeed

Reputation: 8290

You can use Align to choose the position in a stack like this:

Stack(children: [
    child: Align(
        alignment: Alignment(-.40, -.90),
        child: MyPictureWidget()
    ),
]);

Nicer because you don't need to get the constraints. :) Alignment(0, 0) would be at the center

enter image description here

Upvotes: 0

Related Questions