✨ Virtual toolbar
This commit is contained in:
@@ -5,11 +5,14 @@ PODS:
|
|||||||
- path_provider_foundation (0.0.1):
|
- path_provider_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- url_launcher_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
Flutter:
|
Flutter:
|
||||||
@@ -18,11 +21,14 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
|
url_launcher_ios:
|
||||||
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
|
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||||
|
|
||||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
||||||
|
|
||||||
|
@@ -43,7 +43,7 @@ class AboutPage extends StatelessWidget {
|
|||||||
Opacity(
|
Opacity(
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
child: Text(
|
child: Text(
|
||||||
'这是一个用于求解方程和表达式的计算器应用。\n支持多种类型的数学计算,包括代数方程、表达式求值等。\n\n结果仅供参考,纯机器计算,无 AI 成分。\n\n在书写方程的时候,请勿使用中文符号,平方请使用 ^n 来表示 n 次方。\n\n理性使用,仅为辅助学习目的,过量使用有害考试成绩。',
|
'这是一个用于求解方程和表达式的计算器应用。\n支持多种类型的数学计算,包括代数方程、表达式求值等。\n\n结果仅供参考,纯机器计算,无 AI 成分。\n\n在书写方程的时候,请勿使用中文符号,平方请使用 ^n 来表示 n 次方。\n\n虽然本项目存在的原因是小羊不想写数学作业,但是我还是要说\n理性使用,仅为辅助学习目的,过量使用有害考试成绩。',
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
@@ -78,7 +78,7 @@ class AboutPage extends StatelessWidget {
|
|||||||
|
|
||||||
Future<void> _launchUrl(String url) async {
|
Future<void> _launchUrl(String url) async {
|
||||||
final Uri uri = Uri.parse(url);
|
final Uri uri = Uri.parse(url);
|
||||||
if (!await launchUrl(uri)) {
|
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
|
||||||
throw Exception('Could not launch $url');
|
throw Exception('Could not launch $url');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:latext/latext.dart';
|
import 'package:latext/latext.dart';
|
||||||
import 'package:simple_math_calc/models/calculation_step.dart';
|
import 'package:simple_math_calc/models/calculation_step.dart';
|
||||||
import 'package:simple_math_calc/solver.dart';
|
import 'package:simple_math_calc/solver.dart';
|
||||||
@@ -14,9 +15,28 @@ class CalculatorHomePage extends StatefulWidget {
|
|||||||
class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
||||||
final TextEditingController _controller = TextEditingController();
|
final TextEditingController _controller = TextEditingController();
|
||||||
final SolverService _solverService = SolverService();
|
final SolverService _solverService = SolverService();
|
||||||
|
late final FocusNode _focusNode;
|
||||||
|
|
||||||
CalculationResult? _result;
|
CalculationResult? _result;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
bool _isInputFocused = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_focusNode = FocusNode();
|
||||||
|
_focusNode.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
_isInputFocused = _focusNode.hasFocus;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_focusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
void _solveEquation() {
|
void _solveEquation() {
|
||||||
if (_controller.text.isEmpty) {
|
if (_controller.text.isEmpty) {
|
||||||
@@ -48,6 +68,16 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _insertSymbol(String symbol) {
|
||||||
|
final text = _controller.text;
|
||||||
|
final selection = _controller.selection;
|
||||||
|
final newText = text.replaceRange(selection.start, selection.end, symbol);
|
||||||
|
_controller.text = newText;
|
||||||
|
_controller.selection = TextSelection.collapsed(
|
||||||
|
offset: selection.start + symbol.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -66,6 +96,7 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
|
focusNode: _focusNode,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
@@ -74,8 +105,6 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
|||||||
hintText: '例如: 2x^2 - 8x + 6 = 0',
|
hintText: '例如: 2x^2 - 8x + 6 = 0',
|
||||||
),
|
),
|
||||||
onSubmitted: (_) => _solveEquation(),
|
onSubmitted: (_) => _solveEquation(),
|
||||||
onTapOutside: (_) =>
|
|
||||||
FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -92,6 +121,7 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
|||||||
? const Center(child: Text('请输入方程开始计算'))
|
? const Center(child: Text('请输入方程开始计算'))
|
||||||
: buildResultView(_result!),
|
: buildResultView(_result!),
|
||||||
),
|
),
|
||||||
|
if (_isInputFocused) _buildToolbar(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -118,7 +148,7 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
|||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 12,
|
left: 12,
|
||||||
right: 12,
|
right: 12,
|
||||||
bottom: 4,
|
bottom: 16,
|
||||||
top: 16,
|
top: 16,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -169,10 +199,9 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
|||||||
Card(
|
Card(
|
||||||
color: Theme.of(context).colorScheme.primaryContainer,
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
Text(
|
||||||
"最终答案",
|
"最终答案",
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
@@ -194,4 +223,37 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildToolbar() {
|
||||||
|
return Material(
|
||||||
|
elevation: 8,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
spacing: 16,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => _insertSymbol('('),
|
||||||
|
child: Text('(', style: GoogleFonts.robotoMono()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => _insertSymbol(')'),
|
||||||
|
child: Text(')', style: GoogleFonts.robotoMono()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => _insertSymbol('^'),
|
||||||
|
child: Text('^', style: GoogleFonts.robotoMono()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user