Never give up

Flutter 2.0 - typedef callback with ScaffoldMessenger Widget, global key 본문

Flutter

Flutter 2.0 - typedef callback with ScaffoldMessenger Widget, global key

대기만성 개발자 2021. 5. 8. 19:08
반응형

이번 예제는 overlay entry 실험하면서 typedef 콜백을 사용해 본적이 있었는데

 

상황에 따라서는 유용하지만 조금 귀찮은 점도 있어서

 

일반적으로 Function()형태로 넘기는 형태를 선호했었는데

 

상황에 따라 필요하기도 하고, 안쓰다보니 까먹기도 해서 기록으로 남겨두려고 포스트를 결정했습니다

 

그리고 Flutter 2.0으로 넘어오면서 global key를 이용한 Snackbar 호출을 하는 방법이 없을까 해서 찾아보던 중

 

방법을 찾아내서 필요하신분들을 위해 예제를 만들어봤습니다

(제 블로그 보시는분들 거의 없겠지만 말이죠..)

import 'package:flutter/material.dart';

typedef ButtonClicked = void Function(String text);
typedef ButtonClickedWithIndex = void Function(int index);

extension SnackBarWithKey on GlobalKey<ScaffoldMessengerState>{
  ScaffoldFeatureController<SnackBar, SnackBarClosedReason> show(String text){
    return this.currentState!.showSnackBar(SnackBar(content: Text(text)));
  }
}

class CallbackExample2 extends StatelessWidget {
  CallbackExample2({Key? key, required this.title}) : super(key: key);

  final String title;
  final GlobalKey<ScaffoldMessengerState> _messengerKey =
      GlobalKey<ScaffoldMessengerState>();

  @override
  Widget build(BuildContext context) {
    return ScaffoldMessenger(
        key: _messengerKey,
        child: Scaffold(
            appBar: AppBar(title: Text(title)),
            body: Center(
              child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  ExampleWidget(buttonClicked: _buttonClicked),
                  SizedBox(height: 20),
                  ExampleWidget2(buttonClickedWithIndex: _buttonClickedWithIndex)
                ],
              ),
            )));
  }

  void _buttonClicked(String text) {
    _messengerKey.show(text);
  }

  void _buttonClickedWithIndex(int index) {
    _messengerKey.show('Current index is - $index');
  }
}

class ExampleWidget extends StatelessWidget {
  const ExampleWidget({Key? key, required this.buttonClicked})
      : super(key: key);
  final ButtonClicked buttonClicked;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
        onPressed: () {
          buttonClicked('This is example');
        },
        child: Text('Click'));
  }
}

class ExampleWidget2 extends StatelessWidget {
  const ExampleWidget2({Key? key, required this.buttonClickedWithIndex}) : super(key: key);
  final ButtonClickedWithIndex buttonClickedWithIndex;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 40,
      child: ListView.builder(
          itemCount: 3,
          scrollDirection: Axis.horizontal,
          shrinkWrap: true,
          itemBuilder: (_,index){
            return Container(
              width: 100,
              margin: const EdgeInsets.symmetric(horizontal: 10),
              child: ElevatedButton(onPressed: (){
                buttonClickedWithIndex(index);
              }, child: Text('Button - $index')),
            );
          }),
    );
  }

typedef로 사용하는 콜백의 이름과 데이터 타입을 정해주고

 

콜백이 필요한 위젯에서 정의를 해줍니다

 

그리고 이벤트가 발생할 때 사용할 메소드를 정의해주고 기능을 만들어주시면 됩니다

(해당 예제에서는 _buttonClicked와 _buttonClickedWithIndex)

 

상황에 따라서는 여러개의 버튼을 만들어놓고 각각 index값을 넣어주고

 

클릭된 버튼에 따라 index값이 들어오게 할수도 있습니다

 

Example Widget2와 ButtonClickedWithIndex처럼 말이죠

 

(필자는 해당 방식을 OverlayEntry에 적용시켜봤는데 아주 만족스러웠습니다)

 

그리고 key로 snackbar를 호출하는 부분을 말씀드리자면

 

먼저 Scaffold widget 상위에 ScaffoldMessenger를 wrap 해주고 key값을 넣어줍니다

 

여기서 주의할점은 이전 GlobalKey값의 Generic은 ScaffoldState였지만

 

ScaffoldMessenger에서는 ScaffoldMessengerState라는부분입니다

 

그리고 만들어놓으면 편하니 extension으로 작업을 해놨으니

 

필요하신분은 그대로 가져다 쓰시면 될거 같습니다

(혹시 extension에 대한 예제를 보고싶으신분은 해당 예제를 참고해주세요 : devmemory.tistory.com/44)

반응형
Comments