LoginSignup
3
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-03-05

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

選択前
image.png

選択後
image.png

実装方法

フォルダ構成

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

コード

main.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

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

profile_model.dart

class ProfileModel {
  late String? location = '';

  ProfileModel({
    this.location,
  });
}

profile_provider.dart

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

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

my_profile_screen.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),
                                        ),
                                      )
                                    ],
                                  ),
                                );
                              }
                            );
                          },
                        ),
                      ],
                    ),
                  ],
                ),
              ),
          );
        },
      ),
    );
  }
}

以上です

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2