본문 바로가기

아카이브/Flutter

[GetX] Obx로 Chip 활용하기

놀이터의 놀이기구들

GetX : https://pub.dev/packages/get

 

get | Flutter Package

Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX.

pub.dev

  • GetX를 통해 상태 관리

하단의 놀이기구를 선택하면, 상단에 추가되어진다.
상단 chip의 x버튼이나 하단의 초록 chip을 누르면 삭제

 

// play_gound.dart
import 'package:flutter/material.dart';
import 'package:frontend/components/custom_appbar.dart';
import 'package:get/get.dart';

class PlayGround extends StatefulWidget {
  @override
  _PlayGroundState createState() => _PlayGroundState();
}

class _PlayGroundState extends State<PlayGround> {
  @override
  Widget build(BuildContext context) {
    RidesController _controller = Get.put(RidesController());
    double defaultSize = 20.0;
    List<String> rides = ["미끄럼틀", "시소", "그네", "정글짐", "철봉", "뻉뺑이", "구름사다리"];

    return Scaffold(
      appBar: PreferredSize(
        preferredSize: Size(double.infinity, 100),
        child: CustomAppbar(
          title: "놀이터",
          goBackButton: true,
        ),
      ),
      body: Container(
        padding: EdgeInsets.symmetric(
          horizontal: defaultSize,
          vertical: defaultSize * .5,
        ),
        child: Column(
          children: [
            Obx(
              () => Wrap(
                children: [
                  for (int i = 0; i < _controller.selectedRides.length; i++)
                    Padding(
                      padding: EdgeInsets.symmetric(
                        horizontal: defaultSize * .5,
                      ),
                      child: SelectedChip(
                        defaultSize: defaultSize,
                        text: _controller.selectedRides[i],
                      ),
                    )
                ],
              ),
            ),
            Spacer(),
            Container(
              height: 200,
              child: GridView.builder(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  childAspectRatio: 2 / 1,
                  crossAxisSpacing: 2,
                  mainAxisSpacing: 2,
                ),
                itemCount: rides.length,
                itemBuilder: (BuildContext ctx, index) {
                  return SelectChip(
                    defaultSize: defaultSize,
                    text: rides[index],
                  );
                },
              ),
            ),
            SizedBox(
              height: 50,
            )
          ],
        ),
      ),
    );
  }
}

// select_chip.dart
class SelectChip extends StatefulWidget {
  const SelectChip({
    Key key,
    @required this.defaultSize,
    this.text,
  }) : super(key: key);

  final double defaultSize;
  final String text;

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

class _SelectChipState extends State<SelectChip> {
  RidesController _controller = Get.find<RidesController>();
  @override
  Widget build(BuildContext context) {
    return Obx(
      () => ActionChip(
        padding: EdgeInsets.symmetric(
          horizontal: widget.defaultSize * .2,
          vertical: widget.defaultSize * .2,
        ),
        elevation: 6.0,
        shadowColor: Colors.purpleAccent[100],
        backgroundColor: _controller.selectedRides.contains(widget.text)
            ? Colors.green[100]
            : Colors.purple[100],
        shape: RoundedRectangleBorder(
            borderRadius:
                BorderRadius.all(Radius.circular(widget.defaultSize))),
        avatar: CircleAvatar(
          // 둥근 아이콘 태두리
          radius: widget.defaultSize,
          backgroundColor: Colors.white70,
          child: Icon(
            Icons.play_arrow,
            color: Colors.red[300],
            size: widget.defaultSize * .9,
          ),
        ),
        onPressed: () {
          _controller.putRide(widget.text);
        },
        label: Text(
          widget.text,
          style: TextStyle(
            color: Colors.blueGrey[900],
            fontSize: widget.defaultSize * .9,
            fontWeight: FontWeight.normal,
          ),
        ),
      ),
    );
  }
}

// selected_chip.dart
class SelectedChip extends StatefulWidget {
  const SelectedChip({
    Key key,
    @required this.defaultSize,
    this.text,
  }) : super(key: key);

  final double defaultSize;
  final String text;

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

class _SelectedChipState extends State<SelectedChip> {
  RidesController _controller = Get.find<RidesController>();
  @override
  Widget build(BuildContext context) {
    return Chip(
      padding: EdgeInsets.symmetric(
        horizontal: widget.defaultSize * .2,
        vertical: widget.defaultSize * .2,
      ),
      elevation: 6.0,
      shadowColor: Colors.purpleAccent[100],
      backgroundColor: Colors.purple[100],
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(Radius.circular(widget.defaultSize))),
      avatar: CircleAvatar(
        // 둥근 아이콘 태두리
        radius: widget.defaultSize,
        backgroundColor: Colors.white70,
        child: Icon(
          Icons.play_arrow,
          color: Colors.red[300],
          size: widget.defaultSize * .9,
        ),
      ),
      onDeleted: () {
        _controller.putRide(widget.text);
      },
      label: Text(
        widget.text,
        style: TextStyle(
          color: Colors.blueGrey[900],
          fontSize: widget.defaultSize * .9,
          fontWeight: FontWeight.normal,
        ),
      ),
    );
  }
}

// rides_controller.dart
class RidesController {
  var selectedRides = [].obs;

  void putRide(String value) {
    if (selectedRides.contains(value)) {
      selectedRides.remove(value);
      selectedRides.sort();
    } else {
      selectedRides.add(value);
      selectedRides.sort();
    }
  }
}