🍱 Add app icon
✨ Multiple pages
			
			
This commit is contained in:
		
							
								
								
									
										50
									
								
								lib/screens/about_page.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/screens/about_page.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| class AboutPage extends StatelessWidget { | ||||
|   const AboutPage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       appBar: AppBar(title: const Text('About')), | ||||
|       body: Padding( | ||||
|         padding: const EdgeInsets.all(16.0), | ||||
|         child: Column( | ||||
|           crossAxisAlignment: CrossAxisAlignment.center, | ||||
|           children: [ | ||||
|             const SizedBox(height: 20), | ||||
|             Icon( | ||||
|               Icons.calculate, | ||||
|               size: 80, | ||||
|               color: Theme.of(context).colorScheme.primary, | ||||
|             ), | ||||
|             const SizedBox(height: 20), | ||||
|             Text( | ||||
|               '方程计算器', | ||||
|               style: Theme.of(context).textTheme.headlineMedium, | ||||
|               textAlign: TextAlign.center, | ||||
|             ), | ||||
|             const SizedBox(height: 10), | ||||
|             Text( | ||||
|               'Version 1.0.0', | ||||
|               style: Theme.of(context).textTheme.bodyLarge, | ||||
|               textAlign: TextAlign.center, | ||||
|             ), | ||||
|             const SizedBox(height: 20), | ||||
|             Text( | ||||
|               '这是一个用于求解方程和表达式的计算器应用。\n\n支持多种类型的数学计算,包括代数方程、表达式求值等。', | ||||
|               style: Theme.of(context).textTheme.bodyMedium, | ||||
|               textAlign: TextAlign.center, | ||||
|             ), | ||||
|             const SizedBox(height: 30), | ||||
|             Text( | ||||
|               '© 2025 Simple Math Calculator', | ||||
|               style: Theme.of(context).textTheme.bodySmall, | ||||
|               textAlign: TextAlign.center, | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										195
									
								
								lib/screens/calculator_home_page.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								lib/screens/calculator_home_page.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:latext/latext.dart'; | ||||
| import 'package:simple_math_calc/models/calculation_step.dart'; | ||||
| import 'package:simple_math_calc/solver.dart'; | ||||
| import 'dart:math'; | ||||
|  | ||||
| class CalculatorHomePage extends StatefulWidget { | ||||
|   const CalculatorHomePage({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<CalculatorHomePage> createState() => _CalculatorHomePageState(); | ||||
| } | ||||
|  | ||||
| class _CalculatorHomePageState extends State<CalculatorHomePage> { | ||||
|   final TextEditingController _controller = TextEditingController(); | ||||
|   final SolverService _solverService = SolverService(); | ||||
|  | ||||
|   CalculationResult? _result; | ||||
|   bool _isLoading = false; | ||||
|  | ||||
|   void _solveEquation() { | ||||
|     if (_controller.text.isEmpty) { | ||||
|       return; | ||||
|     } | ||||
|     setState(() { | ||||
|       _isLoading = true; | ||||
|       _result = null; // 清除上次结果 | ||||
|     }); | ||||
|  | ||||
|     try { | ||||
|       // 调用核心服务来解决问题 | ||||
|       final result = _solverService.solve(_controller.text); | ||||
|       setState(() { | ||||
|         _result = result; | ||||
|       }); | ||||
|     } catch (e) { | ||||
|       // 错误处理 | ||||
|       setState(() { | ||||
|         _result = CalculationResult( | ||||
|           steps: [], | ||||
|           finalAnswer: "错误: ${e.toString()}", | ||||
|         ); | ||||
|       }); | ||||
|     } finally { | ||||
|       setState(() { | ||||
|         _isLoading = false; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       appBar: AppBar( | ||||
|         title: const Text('方程与表达式计算器'), | ||||
|         centerTitle: false, | ||||
|         leading: const Icon(Icons.calculate_outlined), | ||||
|       ), | ||||
|       body: Column( | ||||
|         children: [ | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.only(left: 16.0, right: 16.0, top: 16.0), | ||||
|             child: Row( | ||||
|               spacing: 8, | ||||
|               children: [ | ||||
|                 Expanded( | ||||
|                   child: TextField( | ||||
|                     controller: _controller, | ||||
|                     textAlign: TextAlign.center, | ||||
|                     decoration: InputDecoration( | ||||
|                       border: const OutlineInputBorder(), | ||||
|                       labelText: '输入方程或表达式', | ||||
|                       floatingLabelAlignment: FloatingLabelAlignment.center, | ||||
|                       hintText: '例如: 2x^2 - 8x + 6 = 0', | ||||
|                     ), | ||||
|                     onSubmitted: (_) => _solveEquation(), | ||||
|                   ), | ||||
|                 ), | ||||
|                 IconButton( | ||||
|                   onPressed: _solveEquation, | ||||
|                   icon: Icon(Icons.play_arrow), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|           Expanded( | ||||
|             child: _isLoading | ||||
|                 ? const Center(child: CircularProgressIndicator()) | ||||
|                 : _result == null | ||||
|                 ? const Center(child: Text('请输入方程开始计算')) | ||||
|                 : buildResultView(_result!), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   // 构建结果展示视图 | ||||
|   Widget buildResultView(CalculationResult result) { | ||||
|     return ListView( | ||||
|       padding: EdgeInsets.only( | ||||
|         left: 16, | ||||
|         right: 16, | ||||
|         bottom: MediaQuery.of(context).padding.bottom + 16, | ||||
|         top: 16, | ||||
|       ), | ||||
|       children: [ | ||||
|         ...result.steps.map( | ||||
|           (step) => Card( | ||||
|             margin: const EdgeInsets.symmetric(vertical: 8), | ||||
|             child: ClipRRect( | ||||
|               borderRadius: const BorderRadius.all(Radius.circular(8)), | ||||
|               child: Stack( | ||||
|                 children: [ | ||||
|                   Padding( | ||||
|                     padding: const EdgeInsets.only( | ||||
|                       left: 12, | ||||
|                       right: 12, | ||||
|                       bottom: 4, | ||||
|                       top: 16, | ||||
|                     ), | ||||
|                     child: Column( | ||||
|                       crossAxisAlignment: CrossAxisAlignment.center, | ||||
|                       children: [ | ||||
|                         Text( | ||||
|                           step.title, | ||||
|                           style: Theme.of(context).textTheme.titleMedium, | ||||
|                         ), | ||||
|                         const SizedBox(height: 4), | ||||
|                         SelectableText(step.explanation), | ||||
|                         Center( | ||||
|                           child: LaTexT( | ||||
|                             laTeXCode: Text( | ||||
|                               step.formula, | ||||
|                               style: Theme.of(context).textTheme.titleMedium, | ||||
|                             ), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|                   Positioned( | ||||
|                     left: -8, | ||||
|                     top: -8, | ||||
|                     child: Transform.rotate( | ||||
|                       angle: pi / -5, | ||||
|                       child: Opacity( | ||||
|                         opacity: 0.8, | ||||
|                         child: Badge( | ||||
|                           backgroundColor: Theme.of( | ||||
|                             context, | ||||
|                           ).colorScheme.primary, | ||||
|                           label: Text( | ||||
|                             step.stepNumber.toString(), | ||||
|                             style: TextStyle(fontSize: 32), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|         ), | ||||
|         const SizedBox(height: 10), | ||||
|         Card( | ||||
|           color: Theme.of(context).colorScheme.primaryContainer, | ||||
|           child: Padding( | ||||
|             padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), | ||||
|             child: Column( | ||||
|               children: [ | ||||
|                 const SizedBox(height: 16), | ||||
|                 Text( | ||||
|                   "最终答案", | ||||
|                   style: Theme.of(context).textTheme.titleLarge?.copyWith( | ||||
|                     color: Theme.of(context).colorScheme.onPrimaryContainer, | ||||
|                   ), | ||||
|                 ), | ||||
|                 LaTexT( | ||||
|                   laTeXCode: Text( | ||||
|                     result.finalAnswer, | ||||
|                     style: Theme.of(context).textTheme.titleMedium?.copyWith( | ||||
|                       color: Theme.of(context).colorScheme.onPrimaryContainer, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										43
									
								
								lib/screens/home_screen.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								lib/screens/home_screen.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'calculator_home_page.dart'; | ||||
| import 'about_page.dart'; | ||||
|  | ||||
| class HomeScreen extends StatefulWidget { | ||||
|   const HomeScreen({super.key}); | ||||
|  | ||||
|   @override | ||||
|   State<HomeScreen> createState() => _HomeScreenState(); | ||||
| } | ||||
|  | ||||
| class _HomeScreenState extends State<HomeScreen> { | ||||
|   int _selectedIndex = 0; | ||||
|  | ||||
|   static const List<Widget> _widgetOptions = <Widget>[ | ||||
|     CalculatorHomePage(), | ||||
|     AboutPage(), | ||||
|   ]; | ||||
|  | ||||
|   void _onItemTapped(int index) { | ||||
|     setState(() { | ||||
|       _selectedIndex = index; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       body: _widgetOptions.elementAt(_selectedIndex), | ||||
|       bottomNavigationBar: BottomNavigationBar( | ||||
|         items: const <BottomNavigationBarItem>[ | ||||
|           BottomNavigationBarItem( | ||||
|             icon: Icon(Icons.calculate), | ||||
|             label: 'Calculator', | ||||
|           ), | ||||
|           BottomNavigationBarItem(icon: Icon(Icons.info), label: 'About'), | ||||
|         ], | ||||
|         currentIndex: _selectedIndex, | ||||
|         onTap: _onItemTapped, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user