分割の後片付け終了

This commit is contained in:
joe 2026-02-27 16:25:27 +09:00
parent 7baba0091b
commit 39759be02a
7 changed files with 499 additions and 326 deletions

View file

@ -299,15 +299,17 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
context: context, context: context,
builder: (context) => StatefulBuilder( builder: (context) => StatefulBuilder(
builder: (context, setDialogState) { builder: (context, setDialogState) {
return AlertDialog( final inset = MediaQuery.of(context).viewInsets.bottom;
return MediaQuery.removeViewInsets(
removeBottom: true,
context: context,
child: AlertDialog(
insetPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
contentPadding: const EdgeInsets.fromLTRB(16, 12, 16, 8), contentPadding: const EdgeInsets.fromLTRB(16, 12, 16, 8),
title: Text(isEdit ? "顧客を編集" : "顧客を新規登録"), title: Text(isEdit ? "顧客を編集" : "顧客を新規登録"),
content: KeyboardInsetWrapper( content: SingleChildScrollView(
basePadding: const EdgeInsets.fromLTRB(0, 0, 0, 12),
extraBottom: 32,
child: SingleChildScrollView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
padding: const EdgeInsets.only(bottom: 24), padding: EdgeInsets.only(bottom: inset + 12),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -396,7 +398,7 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
], ],
), ),
), ),
), actionsPadding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
actions: [ actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text("キャンセル")), TextButton(onPressed: () => Navigator.pop(context), child: const Text("キャンセル")),
TextButton( TextButton(
@ -423,6 +425,7 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
child: const Text("保存"), child: const Text("保存"),
), ),
], ],
),
); );
}, },
), ),
@ -663,6 +666,7 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
leading: const BackButton(), leading: const BackButton(),
title: Text(widget.selectionMode ? "C2:顧客選択" : "C1:顧客一覧"), title: Text(widget.selectionMode ? "C2:顧客選択" : "C1:顧客一覧"),
@ -712,12 +716,14 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
), ),
], ],
), ),
body: KeyboardInsetWrapper( body: Padding(
basePadding: const EdgeInsets.fromLTRB(0, 8, 0, 80), padding: const EdgeInsets.only(top: 8, bottom: 8),
extraBottom: 40, child: CustomScrollView(
child: Column( physics: const AlwaysScrollableScrollPhysics(),
children: [ keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
Padding( slivers: [
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
@ -731,8 +737,10 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
onChanged: (_) => setState(_applyFilter), onChanged: (_) => setState(_applyFilter),
), ),
), ),
),
if (!widget.selectionMode) if (!widget.selectionMode)
Padding( SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
child: SwitchListTile( child: SwitchListTile(
title: const Text('株式会社/有限会社などの接頭辞を無視してソート'), title: const Text('株式会社/有限会社などの接頭辞を無視してソート'),
@ -743,13 +751,21 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
}), }),
), ),
), ),
Expanded( ),
child: _isLoading if (_isLoading)
? const Center(child: CircularProgressIndicator()) const SliverFillRemaining(
: _filtered.isEmpty hasScrollBody: false,
? const Center(child: Text("顧客が登録されていません")) child: Center(child: CircularProgressIndicator()),
: ListView.builder( )
padding: const EdgeInsets.only(bottom: 120, top: 4), else if (_filtered.isEmpty)
const SliverFillRemaining(
hasScrollBody: false,
child: Center(child: Text("顧客が登録されていません")),
)
else
SliverPadding(
padding: const EdgeInsets.only(bottom: 80, top: 4),
sliver: SliverList.builder(
itemCount: _filtered.length, itemCount: _filtered.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final c = _filtered[index]; final c = _filtered[index];
@ -782,12 +798,16 @@ class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
], ],
), ),
), ),
floatingActionButton: FloatingActionButton.extended( floatingActionButton: Builder(
builder: (context) {
return FloatingActionButton.extended(
onPressed: _showAddMenu, onPressed: _showAddMenu,
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
label: Text(widget.selectionMode ? "選択" : "追加"), label: Text(widget.selectionMode ? "選択" : "追加"),
backgroundColor: Colors.indigo, backgroundColor: Colors.indigo,
foregroundColor: Colors.white, foregroundColor: Colors.white,
);
},
), ),
); );
} }

View file

@ -222,11 +222,13 @@ class _CustomerPickerModalState extends State<CustomerPickerModal> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Material( return Material(
child: KeyboardInsetWrapper( child: KeyboardInsetWrapper(
basePadding: const EdgeInsets.fromLTRB(0, 0, 0, 24), basePadding: const EdgeInsets.fromLTRB(0, 0, 0, 16),
extraBottom: 24, extraBottom: 32,
child: Column( child: CustomScrollView(
children: [ keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
Padding( slivers: [
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -262,15 +264,22 @@ class _CustomerPickerModalState extends State<CustomerPickerModal> {
], ],
), ),
), ),
const Divider(height: 1), ),
Expanded( const SliverToBoxAdapter(child: Divider(height: 1)),
child: _isLoading if (_isLoading)
? const Center(child: CircularProgressIndicator()) const SliverFillRemaining(
: _filteredCustomers.isEmpty hasScrollBody: false,
? const Center(child: Text("該当する顧客がいません")) child: Center(child: CircularProgressIndicator()),
: ListView.builder( )
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, else if (_filteredCustomers.isEmpty)
padding: const EdgeInsets.only(bottom: 80), const SliverFillRemaining(
hasScrollBody: false,
child: Center(child: Text("該当する顧客がいません")),
)
else
SliverPadding(
padding: const EdgeInsets.only(bottom: 120),
sliver: SliverList.builder(
itemCount: _filteredCustomers.length, itemCount: _filteredCustomers.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final customer = _filteredCustomers[index]; final customer = _filteredCustomers[index];

View file

@ -11,7 +11,7 @@ import 'invoice_input_screen.dart';
import 'settings_screen.dart'; import 'settings_screen.dart';
import 'company_info_screen.dart'; import 'company_info_screen.dart';
import '../widgets/slide_to_unlock.dart'; import '../widgets/slide_to_unlock.dart';
import '../main.dart'; // InvoiceFlowScreen // InvoiceFlowScreen import removed; using inline type picker
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import '../widgets/invoice_pdf_preview_page.dart'; import '../widgets/invoice_pdf_preview_page.dart';
import 'invoice_history/invoice_history_list.dart'; import 'invoice_history/invoice_history_list.dart';
@ -375,15 +375,7 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
), ),
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
onPressed: _isUnlocked onPressed: _isUnlocked
? () async { ? () => _showCreateTypeMenu()
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => InvoiceFlowScreen(onComplete: _loadData),
),
);
_loadData();
}
: _requireUnlock, : _requireUnlock,
label: const Text("新規伝票作成"), label: const Text("新規伝票作成"),
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
@ -392,4 +384,51 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
), ),
); );
} }
void _showCreateTypeMenu() {
showModalBottomSheet(
context: context,
builder: (ctx) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.insert_drive_file_outlined),
title: const Text('下書き: 見積書', style: TextStyle(fontSize: 24)),
onTap: () => _startNew(DocumentType.estimation),
),
ListTile(
leading: const Icon(Icons.local_shipping_outlined),
title: const Text('下書き: 納品書', style: TextStyle(fontSize: 24)),
onTap: () => _startNew(DocumentType.delivery),
),
ListTile(
leading: const Icon(Icons.request_quote_outlined),
title: const Text('下書き: 請求書', style: TextStyle(fontSize: 24)),
onTap: () => _startNew(DocumentType.invoice),
),
ListTile(
leading: const Icon(Icons.receipt_long_outlined),
title: const Text('下書き: 領収書', style: TextStyle(fontSize: 24)),
onTap: () => _startNew(DocumentType.receipt),
),
],
),
),
);
}
Future<void> _startNew(DocumentType type) async {
Navigator.pop(context);
await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => InvoiceInputForm(
onInvoiceGenerated: (inv, path) {},
initialDocumentType: type,
),
),
);
_loadData();
}
} }

View file

@ -9,17 +9,19 @@ import '../widgets/invoice_pdf_preview_page.dart';
import 'invoice_detail_page.dart'; import 'invoice_detail_page.dart';
import '../services/gps_service.dart'; import '../services/gps_service.dart';
import 'customer_master_screen.dart'; import 'customer_master_screen.dart';
import 'product_picker_modal.dart'; import 'product_master_screen.dart';
import '../widgets/keyboard_inset_wrapper.dart'; import '../models/product_model.dart';
class InvoiceInputForm extends StatefulWidget { class InvoiceInputForm extends StatefulWidget {
final Function(Invoice invoice, String filePath) onInvoiceGenerated; final Function(Invoice invoice, String filePath) onInvoiceGenerated;
final Invoice? existingInvoice; // : final Invoice? existingInvoice; // :
final DocumentType initialDocumentType;
const InvoiceInputForm({ const InvoiceInputForm({
super.key, super.key,
required this.onInvoiceGenerated, required this.onInvoiceGenerated,
this.existingInvoice, // this.existingInvoice, //
this.initialDocumentType = DocumentType.invoice,
}); });
@override @override
@ -72,21 +74,26 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
_taxRate = 0; _taxRate = 0;
_includeTax = false; _includeTax = false;
_isDraft = true; _isDraft = true;
_documentType = widget.initialDocumentType;
} }
}); });
} }
void _addItem() { void _addItem() {
showModalBottomSheet( Navigator.push<Product>(
context: context, context,
isScrollControlled: true, MaterialPageRoute(builder: (_) => const ProductMasterScreen(selectionMode: true)),
builder: (context) => ProductPickerModal( ).then((product) {
onItemSelected: (item) { if (product == null) return;
setState(() => _items.add(item)); setState(() {
Navigator.pop(context); _items.add(InvoiceItem(
}, productId: product.id,
), description: product.name,
); quantity: 1,
unitPrice: product.defaultUnitPrice,
));
});
});
} }
int get _subTotal => _items.fold(0, (sum, item) => sum + (item.unitPrice * item.quantity)); int get _subTotal => _items.fold(0, (sum, item) => sum + (item.unitPrice * item.quantity));
@ -215,19 +222,12 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
), ),
body: Stack( body: Stack(
children: [ children: [
KeyboardInsetWrapper( Column(
basePadding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
extraBottom: 24,
child: InteractiveViewer(
panEnabled: false,
minScale: 0.8,
maxScale: 2.5,
clipBehavior: Clip.none,
child: Column(
children: [ children: [
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 160), padding: EdgeInsets.fromLTRB(16, 16, 16, MediaQuery.of(context).viewInsets.bottom + 140),
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -250,8 +250,6 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
_buildBottomActionBar(), _buildBottomActionBar(),
], ],
), ),
),
),
if (_isSaving) if (_isSaving)
Container( Container(
color: Colors.black54, color: Colors.black54,
@ -404,17 +402,11 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
TextButton.icon( TextButton.icon(
icon: const Icon(Icons.search, size: 18), icon: const Icon(Icons.search, size: 18),
label: const Text("マスター参照"), label: const Text("マスター参照"),
onPressed: () { onPressed: () async {
showModalBottomSheet( Navigator.pop(context); // close edit dialog before jumping
context: context, await Navigator.push(
isScrollControlled: true, this.context,
builder: (context) => ProductPickerModal( MaterialPageRoute(builder: (_) => const ProductMasterScreen()),
onItemSelected: (selected) {
descCtrl.text = selected.description;
priceCtrl.text = selected.unitPrice.toString();
Navigator.pop(context); // close picker
},
),
); );
}, },
), ),

View file

@ -3,10 +3,11 @@ import 'package:uuid/uuid.dart';
import '../models/product_model.dart'; import '../models/product_model.dart';
import '../services/product_repository.dart'; import '../services/product_repository.dart';
import 'barcode_scanner_screen.dart'; import 'barcode_scanner_screen.dart';
import '../widgets/keyboard_inset_wrapper.dart';
class ProductMasterScreen extends StatefulWidget { class ProductMasterScreen extends StatefulWidget {
const ProductMasterScreen({super.key}); final bool selectionMode;
const ProductMasterScreen({super.key, this.selectionMode = false});
@override @override
State<ProductMasterScreen> createState() => _ProductMasterScreenState(); State<ProductMasterScreen> createState() => _ProductMasterScreenState();
@ -59,12 +60,17 @@ class _ProductMasterScreenState extends State<ProductMasterScreen> {
final result = await showDialog<Product>( final result = await showDialog<Product>(
context: context, context: context,
builder: (context) => StatefulBuilder( builder: (context) => StatefulBuilder(
builder: (context, setDialogState) => AlertDialog( builder: (context, setDialogState) {
final inset = MediaQuery.of(context).viewInsets.bottom;
return MediaQuery.removeViewInsets(
removeBottom: true,
context: context,
child: AlertDialog(
insetPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
title: Text(product == null ? "商品追加" : "商品編集"), title: Text(product == null ? "商品追加" : "商品編集"),
content: KeyboardInsetWrapper( content: SingleChildScrollView(
basePadding: EdgeInsets.zero, keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
extraBottom: 16, padding: EdgeInsets.only(bottom: inset + 12),
child: SingleChildScrollView(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -95,7 +101,6 @@ class _ProductMasterScreenState extends State<ProductMasterScreen> {
], ],
), ),
), ),
),
actions: [ actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text("キャンセル")), TextButton(onPressed: () => Navigator.pop(context), child: const Text("キャンセル")),
ElevatedButton( ElevatedButton(
@ -118,6 +123,8 @@ class _ProductMasterScreenState extends State<ProductMasterScreen> {
), ),
], ],
), ),
);
},
), ),
); );
@ -131,6 +138,7 @@ class _ProductMasterScreenState extends State<ProductMasterScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
leading: const BackButton(), leading: const BackButton(),
title: const Text("P1:商品マスター"), title: const Text("P1:商品マスター"),
@ -157,15 +165,15 @@ class _ProductMasterScreenState extends State<ProductMasterScreen> {
), ),
), ),
), ),
body: KeyboardInsetWrapper( body: Padding(
basePadding: EdgeInsets.zero, padding: const EdgeInsets.only(top: 8, bottom: 8),
extraBottom: 72,
child: _isLoading child: _isLoading
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: _filteredProducts.isEmpty : _filteredProducts.isEmpty
? const Center(child: Text("商品が見つかりません")) ? const Center(child: Text("商品が見つかりません"))
: ListView.builder( : ListView.builder(
padding: const EdgeInsets.only(bottom: 120, top: 8), physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.only(bottom: 80, top: 8),
itemCount: _filteredProducts.length, itemCount: _filteredProducts.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final p = _filteredProducts[index]; final p = _filteredProducts[index];
@ -182,8 +190,59 @@ class _ProductMasterScreenState extends State<ProductMasterScreen> {
), ),
title: Text(p.name, style: TextStyle(fontWeight: FontWeight.bold, color: p.isLocked ? Colors.grey : Colors.black87)), title: Text(p.name, style: TextStyle(fontWeight: FontWeight.bold, color: p.isLocked ? Colors.grey : Colors.black87)),
subtitle: Text("${p.category ?? '未分類'} - ¥${p.defaultUnitPrice} (在庫: ${p.stockQuantity})"), subtitle: Text("${p.category ?? '未分類'} - ¥${p.defaultUnitPrice} (在庫: ${p.stockQuantity})"),
onTap: () => _showDetailPane(p), onTap: () {
trailing: IconButton( if (widget.selectionMode) {
Navigator.pop(context, p);
} else {
_showDetailPane(p);
}
},
onLongPress: () async {
await showModalBottomSheet(
context: context,
builder: (ctx) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.edit),
title: const Text("編集"),
onTap: () {
Navigator.pop(ctx);
_showEditDialog(product: p);
},
),
if (!p.isLocked)
ListTile(
leading: const Icon(Icons.delete_outline, color: Colors.redAccent),
title: const Text("削除", style: TextStyle(color: Colors.redAccent)),
onTap: () async {
Navigator.pop(ctx);
final confirmed = await showDialog<bool>(
context: context,
builder: (_) => AlertDialog(
title: const Text("削除の確認"),
content: Text("${p.name} を削除しますか?"),
actions: [
TextButton(onPressed: () => Navigator.pop(context, false), child: const Text("キャンセル")),
TextButton(onPressed: () => Navigator.pop(context, true), child: const Text("削除", style: TextStyle(color: Colors.red))),
],
),
);
if (confirmed == true) {
await _productRepo.deleteProduct(p.id);
if (mounted) _loadProducts();
}
},
),
],
),
),
);
},
trailing: widget.selectionMode
? null
: IconButton(
icon: const Icon(Icons.edit), icon: const Icon(Icons.edit),
onPressed: p.isLocked ? null : () => _showEditDialog(product: p), onPressed: p.isLocked ? null : () => _showEditDialog(product: p),
tooltip: p.isLocked ? "ロック中" : "編集", tooltip: p.isLocked ? "ロック中" : "編集",

View file

@ -45,12 +45,15 @@ class _ProductPickerModalState extends State<ProductPickerModal> {
child: Column( child: Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.fromLTRB(8, 8, 16, 8),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
const SizedBox(width: 4),
const Text("商品・サービス選択", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const Text("商品・サービス選択", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
IconButton(icon: const Icon(Icons.close), onPressed: () => Navigator.pop(context)),
], ],
), ),
), ),
@ -101,14 +104,63 @@ class _ProductPickerModalState extends State<ProductPickerModal> {
leading: const Icon(Icons.inventory_2_outlined), leading: const Icon(Icons.inventory_2_outlined),
title: Text(product.name), title: Text(product.name),
subtitle: Text("${product.defaultUnitPrice} (在庫: ${product.stockQuantity})"), subtitle: Text("${product.defaultUnitPrice} (在庫: ${product.stockQuantity})"),
onTap: () => widget.onItemSelected( onTap: () {
widget.onItemSelected(
InvoiceItem( InvoiceItem(
productId: product.id, productId: product.id,
description: product.name, description: product.name,
quantity: 1, quantity: 1,
unitPrice: product.defaultUnitPrice, unitPrice: product.defaultUnitPrice,
), ),
);
Navigator.pop(context);
},
onLongPress: () async {
await showModalBottomSheet(
context: context,
builder: (ctx) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.edit),
title: const Text("編集"),
onTap: () async {
Navigator.pop(ctx);
await Navigator.push(
context,
MaterialPageRoute(builder: (_) => const ProductMasterScreen()),
);
_onSearch(_searchController.text);
},
), ),
ListTile(
leading: const Icon(Icons.delete_outline, color: Colors.redAccent),
title: const Text("削除", style: TextStyle(color: Colors.redAccent)),
onTap: () async {
Navigator.pop(ctx);
final confirmed = await showDialog<bool>(
context: context,
builder: (_) => AlertDialog(
title: const Text("削除の確認"),
content: Text("${product.name} を削除しますか?"),
actions: [
TextButton(onPressed: () => Navigator.pop(context, false), child: const Text("キャンセル")),
TextButton(onPressed: () => Navigator.pop(context, true), child: const Text("削除", style: TextStyle(color: Colors.red))),
],
),
);
if (confirmed == true) {
await _productRepo.deleteProduct(product.id);
if (mounted) _onSearch(_searchController.text);
}
},
),
],
),
),
);
},
); );
}, },
), ),

View file

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:convert'; import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../widgets/keyboard_inset_wrapper.dart';
import 'company_info_screen.dart'; import 'company_info_screen.dart';
class SettingsScreen extends StatefulWidget { class SettingsScreen extends StatefulWidget {
@ -227,6 +226,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
final listBottomPadding = 24 + bottomInset;
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
@ -238,11 +239,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
), ),
], ],
), ),
body: KeyboardInsetWrapper( body: Padding(
basePadding: const EdgeInsets.fromLTRB(16, 16, 16, 80), padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
extraBottom: 40,
child: ListView( child: ListView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
physics: const AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.only(bottom: listBottomPadding),
children: [ children: [
_section( _section(
title: '自社情報', title: '自社情報',