Open7

Flutter開発を楽にするコピペで完結スクラップ🚀

ピン留めされたアイテム
mcz9mmmcz9mm

このスクラップについて

なるべくコピペだけですぐに使えるものをメモとして残すスクラップになります。
新規プロジェクトを始めるときに使えそうなものをピックアップできれば。

mcz9mmmcz9mm

BlurButton

Widget _submitButton() {
    return Container(
      width: MediaQuery.of(context).size.width,
      padding: EdgeInsets.symmetric(vertical: 15),
      alignment: Alignment.center,
      decoration: BoxDecoration(
          borderRadius: BorderRadius.all(Radius.circular(5)),
          boxShadow: <BoxShadow>[
            BoxShadow(
                color: Colors.grey.shade200,
                offset: Offset(2, 4),
                blurRadius: 5,
                spreadRadius: 2)
          ],
          gradient: LinearGradient(
              begin: Alignment.centerLeft,
              end: Alignment.centerRight,
              colors: [Color(0xfffbb448), Color(0xfff7892b)])),
      child: Text(
        'Login',
        style: TextStyle(fontSize: 20, color: Colors.white),
      ),
    );
  }

mcz9mmmcz9mm

BottomNavigationでRebuildを発生させない

final List<Widget> _widgetOptions = <Widget>[
    OnePage(),
    TwoPage(),
    ThreePage(),
    FourPage(),
];


Widget build(BuildContext context) {
  debugPrint('RootPage build');
  var brightness = MediaQuery.of(context).platformBrightness;
  return Scaffold(
    body: _widgetOptions.elementAt(_selectedIndex),
    bottomNavigationBar: BottomNavigationBar(
      items: const <BottomNavigationBarItem>[...],
      currentIndex: _selectedIndex,
      onTap: _onItemTapped,
    ),
  );
}

// body: _widgetOptions.elementAt(_selectedIndex),
// bodyをIndexedStackに変更
body: IndexedStack(
  index: _selectedIndex,
  children: _widgetOptions,
),
mcz9mmmcz9mm

バリデーションつきTextForm コピペ用

FormTextField

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

class FormTextField extends StatelessWidget {

  FormTextField({
    this.hintText,
    this.maxLength,
    this.validator,
    this.formKey,
    this.textInputAction,
    this.onFieldSubmitted,
    this.focusNode,
    this.isAutoFocus = false,
    this.controller,
     this.title,
     this.initValue,
     this.isNumberOnly,
     this.callback});

  final String title;
  final String initValue;
  final String hintText;
  final int maxLength;
  final bool isNumberOnly;
  final Function(String) validator;
  final Function(String) callback;
  final Function(String) onFieldSubmitted;
  final GlobalKey<FormState> formKey;
  final TextInputAction textInputAction;
  final FocusNode focusNode;
  final bool isAutoFocus;
  final TextEditingController controller;

  Widget _entryField(BuildContext context) {
    var brightness = MediaQuery.of(context).platformBrightness;

    return Container(
      margin: EdgeInsets.symmetric(vertical: 4),
      child: Form(
        key: formKey,
        child: TextFormField(
          initialValue: initValue,
          maxLength: maxLength,
          controller: controller,
          autofocus: isAutoFocus,
          focusNode: focusNode,
          style: Theme.of(context).textTheme.headline5,
          keyboardType: isNumberOnly ? TextInputType.number : TextInputType.text,
          textInputAction: textInputAction,
          inputFormatters: isNumberOnly ? [
            // WhitelistingTextInputFormatter.digitsOnly,
            FilteringTextInputFormatter.digitsOnly,
          ] : null,
          decoration: InputDecoration(
              contentPadding: EdgeInsets.symmetric(vertical: 0.0, horizontal: 16),
              counterStyle: Theme.of(context).textTheme.subtitle2,
              hintText: title,
              errorStyle: Theme.of(context).textTheme.subtitle2
                  .merge(SavingMoneyTextTheme.font_color_error),
              errorBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(4),
                borderSide: BorderSide(
                  width: 0.25,
                  color: Colors.red,
                ),
              ),
              focusedErrorBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(4),
                borderSide: BorderSide(
                  width: 0.25,
                  color: Colors.red,
                ),
              ),
              enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide(
                  width: 0.25,
                  color: (brightness == Brightness.light) ? kDarkPrimaryGreyColor : kPrimaryTextColor,
                ),
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide(
                  width: 0.25,
                  color: (brightness == Brightness.light) ? kDarkPrimaryGreyColor : kPrimaryTextColor,
                ),
              ),
              fillColor: (brightness == Brightness.light) ? Colors.white : kDarkSecondaryBackgroundColor,
              filled: true),
          validator: validator,
          onFieldSubmitted: onFieldSubmitted,
          onChanged: callback,
        ),
      ),
    );
  }

  
  Widget build(BuildContext context) {
    return _entryField(context);
  }
}

呼び出し

          FormTextField(
            formKey: _formMoneyValueKey,
            title: Localized.of(context).value,
            hintText: Localized.of(context).presetValueHint,
            textInputAction:  TextInputAction.next,
            isNumberOnly: true,
            isAutoFocus: false,
            focusNode: moneyTitleFocus,
            controller: _valueController,
            validator: (value) {
              if (value.isEmpty || value == '0') {
                // 任意のエラーメッセージ
                return Localized.of(context).addMoneyErrorValue;
              } else {
                return null;
              }
            },
            callback: (value) {
              print(value);
            },
            onFieldSubmitted: (v) {
              FocusScope.of(context).requestFocus(focus);
            },
          ),
mcz9mmmcz9mm

Flutter Web を想定したマウスカーソル対応 (Card)

MouseRegionでラップしてあげるだけで良い。
onHoverやonExit、onEnterなどマウスカーソルの検知ができる。

class CardCell extends StatefulWidget {

  final String title;
  final String subtitle;

  CardCell({
    this.title,
    this.subtitle,
  });

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

class _CardCellState extends State<CardCell> {

 bool _isHover = false;

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      cursor: SystemMouseCursors.click,
      onHover: (_) {
        setState(() {
          _isHover = true;
        });
      },
      onExit: (_) {
        setState(() {
          _isHover = false;
        });
      },
      onEnter: (_) {
        setState(() {
          _isHover = true;
        });
      },
      child: Card(
        elevation: _isHover ? 2 : 0,
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 8),
          child: ListTile(
            title: Text(
              widget.title,
              style: TextStyle(
                fontSize: 18,
                color: _isHover ? Colors.blueAccent : Colors.black,
                fontWeight: _isHover ? FontWeight.bold : FontWeight.w500,
              ),
            ),
            subtitle: Text(
              widget.subtitle,
              maxLines: 3,
            ),
          ),
        ),
      ),
    );
  }
}

参考

MouseRegion