Provider利用時のFlutterのpicker(ドラムロール)の実装方法

状態管理のProviderを利用している際に以下のようなPickerを実装する方法を書き記します

選択前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/be247bf1-3cd6-b0af-bdca-7adc2fab8c6a.png)

↓

選択後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/303edf0c-bd8e-2fcb-3638-943a187cad52.png)


# 実装方法

## フォルダ構成

lib
┗ models
　┗profile_model.dart
┗ pickers
　┗location.dart
┗ providers
　┗profile_provider.dart
┗ screens
　┗my_profile_screen.dart
main.dart


## コード

main.dart
```dart
import 'package:flutter/material.dart';
import 'package:matchingappweb/providers/profile_provider.dart';
import 'package:matchingappweb/screens/my_profile_screen.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => ProfileProvider()),
      ],
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget  {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyProfileScreen(),
      routes: <String, WidgetBuilder>{
        '/my-profile': (BuildContext context) => MyProfileScreen(),
      },
    );
  }
}
```


location_picker.dart
```dart
final Map<String, String> locationPicker = {
  'hokkaido' : '北海道',
  'tohoku' : '東北',
  'kanto' : '関東',
  'hokuriku' : '北陸',
  'chubu' : '中部',
  'chugoku' : '中国',
  'shikoku' : '四国',
  'kyushu' : '九州',
};
```

profile_model.dart
```dart
class ProfileModel {
  late String? location = '';

  ProfileModel({
    this.location,
  });
}
```

profile_provider.dart
```dart
import 'package:flutter/material.dart';
import '../models/profile_model.dart';

class ProfileProvider with ChangeNotifier {
  ProfileModel myProfile = ProfileModel(
      location: null,
  );
}
```

my_profile_screen.dart
```dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:matchingappweb/providers/profile_provider.dart';
import 'package:provider/provider.dart';
import '../pickers/location_picker.dart';


class MyProfileScreen extends StatelessWidget {
  const MyProfileScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('マイプロフィール'),
      ),
      body: Consumer<ProfileProvider>(
        builder: (context, profileProvider, _) {
          return Padding(
              padding: const EdgeInsets.all(32.0),
              child: SingleChildScrollView(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Row(
                      children: [
                        const Text('居住エリア ',),
                        Text(locationPicker[profileProvider.myProfile.location] ?? '', style: const TextStyle(fontWeight: FontWeight.bold)),
                        TextButton(
                          child: const Text('選択'),
                          onPressed: () {
                            showModalBottomSheet(
                              context: context,
                              builder: (BuildContext context) {
                                return Container(
                                  height: MediaQuery.of(context).size.height / 2,
                                  child: Column(
                                    children: [
                                      Row(
                                        crossAxisAlignment: CrossAxisAlignment.end,
                                        children: [
                                          TextButton(
                                            child: const Text('戻る'),
                                            onPressed: () => Navigator.pop(context),
                                          ),
                                          TextButton(
                                            child: const Text('決定'),
                                            onPressed: () {
                                              profileProvider.notifyListeners();
                                              Navigator.pop(context);
                                            },
                                          ),
                                        ],
                                      ),
                                      Container(
                                        height: MediaQuery.of(context).size.height / 3,
                                        child: CupertinoPicker(
                                          itemExtent: 40,
                                          children: [
                                            for (String key in locationPicker.keys) ... {
                                              Text(locationPicker[key] ?? '住所不定')
                                            },
                                          ],
                                          onSelectedItemChanged: (int index) => profileProvider.myProfile.location = locationPicker.keys.elementAt(index),
                                        ),
                                      )
                                    ],
                                  ),
                                );
                              }
                            );
                          },
                        ),
                      ],
                    ),
                  ],
                ),
              ),
          );
        },
      ),
    );
  }
}
```


以上です