Flutter

[Fluttet] 플러터 앱 예제 가게 이름 선택하기 예제 (하) (삼항연산자)

성영욱 2022. 1. 1. 14:20
728x90

안녕하세요! 이전에 했던 예제를 이어서 진행해보겠습니다. price와 title은 가져와보셨나요? 

Stack(
  children: [
    ClipRRect(
        borderRadius: BorderRadius.circular(60),
        child: Container(
            width: 80,
            height: 80,
            child: Image.network(
              foodList[index]["image"],
              fit: BoxFit.cover,
            ))),
    Padding(
      padding: EdgeInsets.only(left: 110.0),
      child: Text(
        foodList[index]["title"],
        style: TextStyle(
            fontWeight: FontWeight.bold, fontSize: 21),
      ),
    ),
    Padding(
      padding: EdgeInsets.only(left: 110.0, top: 50),
      child: Text(
        "최소주문 ${foodList[index]["price"]}원".toString(),
        style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 16,
            color: Colors.grey[500]),
      ),
    ),
    Padding(
      padding: EdgeInsets.only(left: 265.0, top: 20),
      child:  Text(
        "${foodList[index]["thx"]}",
        style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 16,
            color: Colors.grey[500]),
      ),
    )
  ],
)

저는 이렇게 작성했답니다! 위치는 padding 값을 줘서 조정했습니다.  다음으로 저희는 해당 Container를 클릭했을 때 변화를 줘야 하기 때문에 selectIndex라는 int 변수를 하나 지정해주겠습니다. 값은 0으로 해주시면 됩니다.

class _Practice2State extends State<Practice2> {
  int selectIndex = 0;

해당 ui는 Widget을 onTap 했을 경우 Container를 둘러싼 border 색상이 변경되고 반갑습니다 라는 텍스트가 정성껏 모시겠습니다 로 변경이 되는 것을 확인하실 수 있습니다. 근데 내가 어떻게 Widget을 tap 했다는 걸 보여줄 수 있을까요? 그때 사용하는 Widget은 여러 가지가 있겠지만 지금은 그중에서 GestureDetector라는 Widget을 사용해보겠습니다. GestureDetector은 onTap이라는 함수를 꼭 가져야 하는데요. 이 함수를 통해 몇 번째 index를 tap 했는지 알려주겠습니다. Stack Widget을 GestureDetector로 감싸주시고요. ontap함수를 불러 selectIndex에 index를 넣어주겠습니다.

GestureDetector(
onTap: (){
  setState(() {
    selectIndex = index;
    print(selectIndex);
  });

가게 클릭시 변화하는 INDEX

setState함수는 화면이 변화하는걸 즉시 반영해주는 걸로 알고 계시면 좋을 것 같습니다. 다음 Container를 둘러싼 border에 색상과 애니메이션을 추가하기 위해 기존 Container에 Animated를 붙여주고 아래와 같이 작성해줍니다.

AnimatedContainer(
    padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
  margin: EdgeInsets.only(bottom: 10),
  duration: Duration(milliseconds: 500),
    decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(8),
border: Border.all(
color: selectIndex == index ? Colors.pink[200] : Colors.white,
width: 2,)),

color부분을 보시면 삼항 연산자를 사용했는데요. 풀어서보면 selectIndex가 index가 일치할 경우에만 Colors.pink를 보여주고 일치하지 않을경우 Colors.white를 보여준다는 뜻입니다. ?는 해당 조건에 참, : 해당조건에 거짓 이라고 이해하시면 되겠습니다. 마지막으로 반갑습니다라는 text를 index가 일치할경우 정성껏 모시겠습니다로 변경해보는 작업을 진행해보겠습니다. 

Padding(
  padding: EdgeInsets.only(left: 265.0, top: 20),
  child: selectIndex != index ? Text(
    "${foodList[index]["thx"]}",
    style: TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 16,
        color: Colors.grey[500]),
  ): Text("정성껏\n모시겠습니다.",style: TextStyle(fontWeight: FontWeight.bold),),
)

위와 마찬가지로 삼항연산자를 사용했습니다 selectIndex와 index가 일치하지 않을 경우에 반갑습니다라는 text를 보여주고 일치할 경우 정성껏 모시겠습니다.라는 text가 나오도록 설계를 해봤습니다. 

import 'package:flutter/material.dart';

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

  @override
  State<Practice2> createState() => _Practice2State();
}

class _Practice2State extends State<Practice2> {
  int selectIndex = 0;
  List foodList = [
    {
      "title": "군침이 마카롱",
      "price": 3900,
      "image":
          "https://t1.daumcdn.net/cfile/tistory/99758C355F7F04AA25",
      "thx": "반갑습니다."
    },
    {
      "title": "햄깅이 가게",
      "price": 1900,
      "image":
          "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRYxaq4udWruQnbE2t4mcoeZTP6h4PYsjMO9g&usqp=CAU",
    "thx": "반갑습니다."
    },
    {
      "title": "루시우 가게",
      "price": 7900,
      "image": "https://t1.daumcdn.net/cfile/tistory/267ACB4E57ADC00536",
      "thx": "반갑습니다."
    }
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text(
          "가게 이름",
          style: TextStyle(color: Colors.black),
        ),
        centerTitle: true,
        backgroundColor: Colors.white,
        elevation: 3.0,
      ),
      body: Center(
        child: Container(
          width: 400,
          height: 400,
          child: ListView.separated(
              separatorBuilder: (context, index) => SizedBox(
                    height: 30,
                  ),
              itemCount: foodList.length,
              itemBuilder: (BuildContext context, int index) {
                return
                  GestureDetector(
                  onTap: (){
                    setState(() {
                      selectIndex = index;
                      print(selectIndex);
                    });
                   // Navigator.push(context, MaterialPageRoute(builder: (context)=>Pick(index: index,title: foodList[index]["title"],)));
                  },
                  child: AnimatedContainer(
                      padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
                    margin: EdgeInsets.only(bottom: 10),
                    duration: Duration(milliseconds: 500),
                      decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(8),
                  border: Border.all(
                  color: selectIndex == index ? Colors.pink[200] : Colors.white,
                  width: 2,)),
                      child: Stack(
                        children: [
                          ClipRRect(
                              borderRadius: BorderRadius.circular(60),
                              child: Container(
                                  width: 80,
                                  height: 80,
                                  child: Image.network(
                                    foodList[index]["image"],
                                    fit: BoxFit.cover,
                                  ))),
                          Padding(
                            padding: EdgeInsets.only(left: 110.0),
                            child: Text(
                              foodList[index]["title"],
                              style: TextStyle(
                                  fontWeight: FontWeight.bold, fontSize: 21),
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.only(left: 110.0, top: 50),
                            child: Text(
                              "최소주문 ${foodList[index]["price"]}원".toString(),
                              style: TextStyle(
                                  fontWeight: FontWeight.bold,
                                  fontSize: 16,
                                  color: Colors.grey[500]),
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.only(left: 265.0, top: 20),
                            child: selectIndex != index ? Text(
                              "${foodList[index]["thx"]}",
                              style: TextStyle(
                                  fontWeight: FontWeight.bold,
                                  fontSize: 16,
                                  color: Colors.grey[500]),
                            ): Text("정성껏\n모시겠습니다.",style: TextStyle(fontWeight: FontWeight.bold),),
                          )
                        ],
                      )),
                );
              }),
        ),
      ),
    );
  }  

 좀 더 심화학습으로 원하는 가게를 하나 더 만들어서 추가해보는 것도 도움이 될 것 같습니다. 글로 설명을 하려니 빠진 부분과 제가 아직 많이 부족하다는 생각도 느끼네요. 부족한 설명을 들어주셔서 감사합니다. 도움이 되셨다면 하트 한 번씩 눌러주시면 감사하겠습니다. 

728x90