LoginSignup
14
10

More than 3 years have passed since last update.

【Flutter】画面下から出てくるピッカー(ドラムロール)を実装する

Last updated at Posted at 2020-02-06

picker.gif

Flutter で画面下から出てくる iOS 風ピッカー(ドラムロール)を実装します。

  • Flutter 1.12.13+hotfix.5
  • Dart 2.7.1

コード

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Modal Picker',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Modal Picker'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                _showModalPicker(context);
              },
              child: const Text('Show Picker'),
            ),
            Text(_selectedItem)
          ],
        ),
      ),
    );
  }

  void _showModalPicker(BuildContext context) {
    showModalBottomSheet<void>(
      context: context,
      builder: (BuildContext context) {
        return Container(
          height: MediaQuery.of(context).size.height / 3,
          child: GestureDetector(
            onTap: () {
              Navigator.pop(context);
            },
            child: CupertinoPicker(
              itemExtent: 40,
              children: _items.map(_pickerItem).toList(),
              onSelectedItemChanged: _onSelectedItemChanged,
            ),
          ),
        );
      },
    );
  }

  String _selectedItem = 'none';

  final List<String> _items = [
    'item1',
    'item2',
    'item3',
    'item4',
    'item5',
    'item6',
  ];

  Widget _pickerItem(String str) {
    return Text(
      str,
      style: const TextStyle(fontSize: 32),
    );
  }

  void _onSelectedItemChanged(int index) {
    setState(() {
      _selectedItem = _items[index];
    });
  }
}

解説

CupertinoPicker を使用するため、 cupertino.dart をインポートします。

import 'package:flutter/cupertino.dart';

ボタンをタップするとモーダル画面出てくるようにします。
モーダルの高さは画面の 3 分の 1 のサイズにしています。
showModalBottomSheet function - material library - Dart API

RaisedButton(
  onPressed: () {
    _showModalPicker(context);
  },
  // ...
),

// ...

void _showModalPicker(BuildContext context) {
    showModalBottomSheet<void>(
      context: context,
      builder: (BuildContext context) {
        return Container(
          height: MediaQuery.of(context).size.height / 3,
          // ...
        );
      },
    );
  }

CupertinoPickerGestureDetector でラップし、ピッカー部分をタップするとモーダルが閉じるようにしています。

GestureDetector(
  onTap: () {
    Navigator.pop(context);
  },
  child: CupertinoPicker(
    // ...
  )
)

itemExtent :アイテムの高さを指定します。
children :表示するアイテムを List<Widget> で渡します。
onSelectedItemChanged :アイテムが選択された際に実行する関数を指定します。

// ...
{
  child: CupertinoPicker(
    itemExtent: 40,
    children: _items.map(_pickerItem).toList(),
    onSelectedItemChanged: _onSelectedItemChanged,
  ),
}
// ...

String _selectedItem = 'none';

final List<String> _items = [
  'item1',
  'item2',
  'item3',
  'item4',
  'item5',
  'item6',
];

Widget _pickerItem(String str) {
  return Text(
    str,
    style: const TextStyle(fontSize: 32),
  );
}

void _onSelectedItemChanged(int index) {
  setState(() {
    _selectedItem = _items[index];
  });
}

参考

14
10
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
14
10