|
@@ -0,0 +1,1356 @@
|
|
|
|
+import 'package:flutter/material.dart';
|
|
|
|
+import 'package:flutter_compass/flutter_compass.dart';
|
|
|
|
+import 'dart:math' as math;
|
|
|
|
+import 'package:url_launcher/url_launcher.dart'; // 导入 url_launcher 包
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void main() {
|
|
|
|
+ runApp(MyApp());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class MyApp extends StatelessWidget {
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ return MaterialApp(
|
|
|
|
+ home: HomePage(),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class HomePage extends StatelessWidget {
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ double screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
+ double screenHeight = MediaQuery.of(context).size.height;
|
|
|
|
+
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: AppBar(
|
|
|
|
+ title: Text('Ask Tao'),
|
|
|
|
+ ),
|
|
|
|
+ body: SingleChildScrollView(
|
|
|
|
+ child: Column(
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
|
|
+ children: [
|
|
|
|
+ // Daily Tao 图片背景
|
|
|
|
+ Container(
|
|
|
|
+ width: screenWidth,
|
|
|
|
+ height: screenHeight * 0.25,
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ image: DecorationImage(
|
|
|
|
+ image: AssetImage('assets/daily_tao_background.png'),
|
|
|
|
+ fit: BoxFit.cover,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Padding(
|
|
|
|
+ padding: EdgeInsets.symmetric(
|
|
|
|
+ horizontal: screenWidth * 0.05,
|
|
|
|
+ vertical: screenHeight * 0.02,
|
|
|
|
+ ),
|
|
|
|
+ child: Column(
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.end,
|
|
|
|
+ children: [
|
|
|
|
+ Text(
|
|
|
|
+ 'Daily Tao',
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ fontSize: screenWidth * 0.07,
|
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.01),
|
|
|
|
+ Text(
|
|
|
|
+ '行者南游归,慈云洞庭开。\n寻经十二部,普度度有生。',
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ fontSize: screenWidth * 0.04,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ ElevatedButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ // 按钮点击事件
|
|
|
|
+ },
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: Colors.white.withOpacity(0.6),
|
|
|
|
+ padding: EdgeInsets.symmetric(
|
|
|
|
+ horizontal: screenWidth * 0.1,
|
|
|
|
+ vertical: screenHeight * 0.02,
|
|
|
|
+ ),
|
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Text(
|
|
|
|
+ 'Learn more →',
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ fontSize: screenWidth * 0.05,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+
|
|
|
|
+ // Study Tao & Find Inner Peace
|
|
|
|
+ Padding(
|
|
|
|
+ padding: EdgeInsets.all(screenWidth * 0.05),
|
|
|
|
+ child: ListView(
|
|
|
|
+ shrinkWrap: true,
|
|
|
|
+ physics: NeverScrollableScrollPhysics(),
|
|
|
|
+ children: [
|
|
|
|
+ _buildOptionCard(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ screenHeight: screenHeight,
|
|
|
|
+ image: 'assets/study_tao.png',
|
|
|
|
+ title: 'Study Tao',
|
|
|
|
+ subtitle: 'Chat to gain deeper understanding of Tao.',
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ _buildOptionCard(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ screenHeight: screenHeight,
|
|
|
|
+ image: 'assets/inner_peace.png',
|
|
|
|
+ title: 'Find Inner Peace',
|
|
|
|
+ subtitle: 'Tell your troubles and find your inner peace.',
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+
|
|
|
|
+ // 下方的小图标部分
|
|
|
|
+ Padding(
|
|
|
|
+ padding: EdgeInsets.all(screenWidth * 0.05),
|
|
|
|
+ child: GridView.count(
|
|
|
|
+ crossAxisCount: 3,
|
|
|
|
+ shrinkWrap: true,
|
|
|
|
+ physics: NeverScrollableScrollPhysics(),
|
|
|
|
+ crossAxisSpacing: screenWidth * 0.02,
|
|
|
|
+ mainAxisSpacing: screenHeight * 0.02,
|
|
|
|
+ children: [
|
|
|
|
+ _buildIconTile(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ icon: 'assets/fengshui.png',
|
|
|
|
+ label: 'Fengshui',
|
|
|
|
+ onTap: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => PropertyPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ _buildIconTile(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ icon: 'assets/fortune_telling.png',
|
|
|
|
+ label: 'Fortune telling',
|
|
|
|
+ onTap: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => FortuneTellingPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ _buildIconTile(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ icon: 'assets/divination.png',
|
|
|
|
+ label: 'Divination',
|
|
|
|
+ onTap: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => ClickAndDrawPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ _buildIconTile(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ icon: 'assets/taoistpractice.png',
|
|
|
|
+ label: 'Taoist practice',
|
|
|
|
+ ),
|
|
|
|
+ _buildIconTile(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ icon: 'assets/interpretdream.png',
|
|
|
|
+ label: 'Interpret dream',
|
|
|
|
+ onTap: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => DreamInterpretationScreen()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ _buildIconTile(
|
|
|
|
+ screenWidth: screenWidth,
|
|
|
|
+ icon: 'assets/taoistculture.png',
|
|
|
|
+ label: 'Taoist culture',
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildOptionCard({
|
|
|
|
+ required double screenWidth,
|
|
|
|
+ required double screenHeight,
|
|
|
|
+ required String image,
|
|
|
|
+ required String title,
|
|
|
|
+ required String subtitle,
|
|
|
|
+ }) {
|
|
|
|
+ return Container(
|
|
|
|
+ width: screenWidth,
|
|
|
|
+ height: screenHeight * 0.12,
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
|
+ image: DecorationImage(
|
|
|
|
+ image: AssetImage(image),
|
|
|
|
+ fit: BoxFit.cover,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Padding(
|
|
|
|
+ padding: EdgeInsets.all(screenWidth * 0.05),
|
|
|
|
+ child: Column(
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
+ children: [
|
|
|
|
+ Text(
|
|
|
|
+ title,
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ fontSize: screenWidth * 0.06,
|
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.01),
|
|
|
|
+ Flexible(
|
|
|
|
+ child: Text(
|
|
|
|
+ subtitle,
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ fontSize: screenWidth * 0.04,
|
|
|
|
+ ),
|
|
|
|
+ overflow: TextOverflow.ellipsis,
|
|
|
|
+ maxLines: 2,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildIconTile({
|
|
|
|
+ required double screenWidth,
|
|
|
|
+ required String icon,
|
|
|
|
+ required String label,
|
|
|
|
+ VoidCallback? onTap,
|
|
|
|
+ }) {
|
|
|
|
+ return GestureDetector(
|
|
|
|
+ onTap: onTap,
|
|
|
|
+ child: Column(
|
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
|
+ children: [
|
|
|
|
+ Container(
|
|
|
|
+ width: screenWidth * 0.15,
|
|
|
|
+ height: screenWidth * 0.15,
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ shape: BoxShape.circle,
|
|
|
|
+ image: DecorationImage(
|
|
|
|
+ image: AssetImage(icon),
|
|
|
|
+ fit: BoxFit.cover,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenWidth * 0.01),
|
|
|
|
+ Text(
|
|
|
|
+ label,
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ fontSize: screenWidth * 0.03,
|
|
|
|
+ ),
|
|
|
|
+ textAlign: TextAlign.center,
|
|
|
|
+ maxLines: 2,
|
|
|
|
+ overflow: TextOverflow.ellipsis,
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+PreferredSizeWidget commonAppBar(BuildContext context, String title) {
|
|
|
|
+ return AppBar(
|
|
|
|
+ title: Text(
|
|
|
|
+ title,
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ backgroundColor: Colors.black,
|
|
|
|
+ leading: IconButton(
|
|
|
|
+ icon: Icon(Icons.arrow_back, color: Colors.white),
|
|
|
|
+ onPressed: () => Navigator.of(context).pop(),
|
|
|
|
+ ),
|
|
|
|
+ actions: [
|
|
|
|
+ IconButton(
|
|
|
|
+ icon: Icon(Icons.home, color: Colors.white),
|
|
|
|
+ onPressed: () {
|
|
|
|
+ Navigator.of(context).popUntil((route) => route.isFirst);
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ );
|
|
|
|
+}
|
|
|
|
+class PropertyPage extends StatelessWidget {
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ double screenHeight = MediaQuery.of(context).size.height;
|
|
|
|
+ double screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
+
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Property Type'),
|
|
|
|
+
|
|
|
|
+ body: SingleChildScrollView(
|
|
|
|
+ child: Column(
|
|
|
|
+ children: [
|
|
|
|
+ // Yang Property Section
|
|
|
|
+ Container(
|
|
|
|
+ color: Color(0xFF00164C),
|
|
|
|
+ child: ListTile(
|
|
|
|
+ leading: Icon(Icons.house, color: Colors.white),
|
|
|
|
+ title: Text(
|
|
|
|
+ "Yang Property",
|
|
|
|
+ style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ Container(
|
|
|
|
+ height: screenHeight * 0.3,
|
|
|
|
+ child: PageView(
|
|
|
|
+ scrollDirection: Axis.horizontal,
|
|
|
|
+ children: [
|
|
|
|
+ PropertyCard(
|
|
|
|
+ title: "Town House",
|
|
|
|
+ imageAsset: 'assets/townhouse.png',
|
|
|
|
+ ),
|
|
|
|
+ PropertyCard(
|
|
|
|
+ title: "Single Family House",
|
|
|
|
+ imageAsset: 'assets/singlefamily.png',
|
|
|
|
+ ),
|
|
|
|
+ PropertyCard(
|
|
|
|
+ title: "Condo",
|
|
|
|
+ imageAsset: 'assets/condo.png',
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+
|
|
|
|
+ // Yin Property Section
|
|
|
|
+ Container(
|
|
|
|
+ color: Color(0xFF00164C),
|
|
|
|
+ child: ListTile(
|
|
|
|
+ leading: Icon(Icons.nights_stay, color: Colors.white),
|
|
|
|
+ title: Text(
|
|
|
|
+ "Yin Property",
|
|
|
|
+ style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ Container(
|
|
|
|
+ height: screenHeight * 0.3,
|
|
|
|
+ child: PropertyCard(
|
|
|
|
+ title: "Grave",
|
|
|
|
+ imageAsset: 'assets/grave.png',
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class PropertyCard extends StatelessWidget {
|
|
|
|
+ final String title;
|
|
|
|
+ final String imageAsset;
|
|
|
|
+
|
|
|
|
+ PropertyCard({required this.title, required this.imageAsset});
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ return Card(
|
|
|
|
+ child: InkWell(
|
|
|
|
+ onTap: () {
|
|
|
|
+ print("PropertyCard tapped: $title");
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => CompassPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ child: Column(
|
|
|
|
+ children: [
|
|
|
|
+ Expanded(
|
|
|
|
+ child: Image.asset(
|
|
|
|
+ imageAsset,
|
|
|
|
+ fit: BoxFit.cover,
|
|
|
|
+ width: double.infinity,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
|
+ child: Text(
|
|
|
|
+ title,
|
|
|
|
+ style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class CompassPage extends StatefulWidget {
|
|
|
|
+ @override
|
|
|
|
+ _CompassPageState createState() => _CompassPageState();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class _CompassPageState extends State<CompassPage> {
|
|
|
|
+ String address = "";
|
|
|
|
+ bool isAddressEntered = false;
|
|
|
|
+ double _direction = 0;
|
|
|
|
+ double _confirmedDirection = 0;
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ void initState() {
|
|
|
|
+ super.initState();
|
|
|
|
+ FlutterCompass.events!.listen((CompassEvent event) {
|
|
|
|
+ setState(() {
|
|
|
|
+ _direction = event.heading ?? 0;
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ double screenHeight = MediaQuery.of(context).size.height;
|
|
|
|
+ double screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
+
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Property Type'),
|
|
|
|
+
|
|
|
|
+ body: Container(
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ gradient: LinearGradient(
|
|
|
|
+ colors: [Colors.green[100]!, Colors.white],
|
|
|
|
+ begin: Alignment.topLeft,
|
|
|
|
+ end: Alignment.bottomRight,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Column(
|
|
|
|
+ children: [
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ Text(
|
|
|
|
+ 'Gate Direction',
|
|
|
|
+ style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ Text(
|
|
|
|
+ 'Use the compass to confirm your gate direction',
|
|
|
|
+ style: TextStyle(color: Colors.grey, fontSize: 14),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.03),
|
|
|
|
+ Container(
|
|
|
|
+ width: screenWidth * 0.75,
|
|
|
|
+ height: screenWidth * 0.75,
|
|
|
|
+ child: Transform.rotate(
|
|
|
|
+ angle: ((_direction ?? 0) * (math.pi / 180) * -1),
|
|
|
|
+ child: Image.asset('assets/compass.png'),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ Text(
|
|
|
|
+ '${_confirmedDirection.toStringAsFixed(0)}°',
|
|
|
|
+ style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ Text(
|
|
|
|
+ _getDirectionText(_confirmedDirection),
|
|
|
|
+ style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.05),
|
|
|
|
+ ElevatedButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ setState(() {
|
|
|
|
+ _confirmedDirection = _direction;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: Colors.black,
|
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 50, vertical: 15),
|
|
|
|
+ ),
|
|
|
|
+ child: Text(
|
|
|
|
+ 'Confirm',
|
|
|
|
+ style: TextStyle(color: Colors.white, fontSize: 18),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ TextField(
|
|
|
|
+ decoration: InputDecoration(
|
|
|
|
+ labelText: 'Input your address',
|
|
|
|
+ border: OutlineInputBorder(),
|
|
|
|
+ ),
|
|
|
|
+ onChanged: (value) {
|
|
|
|
+ setState(() {
|
|
|
|
+ address = value;
|
|
|
|
+ isAddressEntered = value.isNotEmpty;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ ElevatedButton(
|
|
|
|
+ onPressed: isAddressEntered
|
|
|
|
+ ? () {
|
|
|
|
+ // 跳转到上传页面
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => UploadPage()),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ : null,
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: isAddressEntered ? Colors.black : Colors.grey,
|
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 50, vertical: 15),
|
|
|
|
+ ),
|
|
|
|
+ child: Text(
|
|
|
|
+ 'Continue',
|
|
|
|
+ style: TextStyle(color: Colors.white, fontSize: 18),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String _getDirectionText(double direction) {
|
|
|
|
+ if (direction >= 337.5 || direction < 22.5) return 'North';
|
|
|
|
+ if (direction >= 22.5 && direction < 67.5) return 'North East';
|
|
|
|
+ if (direction >= 67.5 && direction < 112.5) return 'East';
|
|
|
|
+ if (direction >= 112.5 && direction < 157.5) return 'South East';
|
|
|
|
+ if (direction >= 157.5 && direction < 202.5) return 'South';
|
|
|
|
+ if (direction >= 202.5 && direction < 247.5) return 'South West';
|
|
|
|
+ if (direction >= 247.5 && direction < 292.5) return 'West';
|
|
|
|
+ if (direction >= 292.5 && direction < 337.5) return 'North West';
|
|
|
|
+ return '';
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class UploadPage extends StatefulWidget {
|
|
|
|
+ @override
|
|
|
|
+ _UploadPageState createState() => _UploadPageState();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class _UploadPageState extends State<UploadPage> {
|
|
|
|
+ String? selectedOption = "Floor Plan"; // 默认选择 "Floor Plan"
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ double screenHeight = MediaQuery.of(context).size.height;
|
|
|
|
+ double screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
+
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Property Type'),
|
|
|
|
+
|
|
|
|
+ body: Container(
|
|
|
|
+ padding: EdgeInsets.all(screenHeight * 0.02),
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ gradient: LinearGradient(
|
|
|
|
+ colors: [Colors.green[100]!, Colors.white],
|
|
|
|
+ begin: Alignment.topLeft,
|
|
|
|
+ end: Alignment.bottomRight,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Column(
|
|
|
|
+ children: [
|
|
|
|
+
|
|
|
|
+ Text(
|
|
|
|
+ "Upload",
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ fontSize: screenWidth * 0.06,
|
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
|
+ color: Colors.black,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ Container(
|
|
|
|
+ width: screenWidth * 0.85,
|
|
|
|
+ height: screenHeight * 0.2,
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: Colors.grey.withOpacity(0.5),
|
|
|
|
+ borderRadius: BorderRadius.circular(15),
|
|
|
|
+ ),
|
|
|
|
+ child: Center(
|
|
|
|
+ child: Text(
|
|
|
|
+ "Select File",
|
|
|
|
+ style: TextStyle(color: Colors.black),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ Column(
|
|
|
|
+ children: [
|
|
|
|
+ _buildRadioOption("Floor Plan"),
|
|
|
|
+ _buildRadioOption("Indoor Photo"),
|
|
|
|
+ _buildRadioOption("Surroundings"),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ ElevatedButton(
|
|
|
|
+ onPressed: () async {
|
|
|
|
+ const url = 'https://your-payment-url.com'; // 替换为实际的付费链接
|
|
|
|
+ if (await canLaunch(url)) {
|
|
|
|
+ await launch(url);
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => FengShuiInterpretationPage()),
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ throw 'Could not launch $url';
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ child: Text("Pay to unlock", style: TextStyle(color: Colors.white, fontSize: 18)),
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: Colors.black,
|
|
|
|
+ padding: EdgeInsets.symmetric(vertical: 15, horizontal: 30),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ Row(
|
|
|
|
+ children: [
|
|
|
|
+ Expanded(child: Divider(color: Colors.grey)),
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
|
|
+ child: Text("or", style: TextStyle(color: Colors.black)),
|
|
|
|
+ ),
|
|
|
|
+ Expanded(child: Divider(color: Colors.grey)),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.02),
|
|
|
|
+ Container(
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: Colors.black,
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ ),
|
|
|
|
+ child: TextButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => FengShuiInterpretationPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ child: Text(
|
|
|
|
+ "Skip",
|
|
|
|
+ style: TextStyle(color: Colors.white, fontSize: 18),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildRadioOption(String title) {
|
|
|
|
+ bool isSelected = selectedOption == title;
|
|
|
|
+ return Container(
|
|
|
|
+ width: MediaQuery.of(context).size.width * 0.65,
|
|
|
|
+ margin: EdgeInsets.symmetric(vertical: 5.0),
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: isSelected ? Colors.black.withOpacity(0.6) : Colors.grey.withOpacity(0.3),
|
|
|
|
+ borderRadius: BorderRadius.circular(10),
|
|
|
|
+ ),
|
|
|
|
+ child: RadioListTile(
|
|
|
|
+ value: title,
|
|
|
|
+ groupValue: selectedOption,
|
|
|
|
+ title: Text(
|
|
|
|
+ title,
|
|
|
|
+ style: TextStyle(color: Colors.white),
|
|
|
|
+ ),
|
|
|
|
+ onChanged: (value) {
|
|
|
|
+ setState(() {
|
|
|
|
+ selectedOption = value as String?;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ activeColor: Colors.white,
|
|
|
|
+ controlAffinity: ListTileControlAffinity.trailing,
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class FengShuiInterpretationPage extends StatelessWidget {
|
|
|
|
+ final TextEditingController _controller = TextEditingController();
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Feng Shui Interpretation'),
|
|
|
|
+
|
|
|
|
+ body: Container(
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ gradient: LinearGradient(
|
|
|
|
+ colors: [Colors.green[100]!, Colors.white],
|
|
|
|
+ begin: Alignment.topLeft,
|
|
|
|
+ end: Alignment.bottomRight,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Column(
|
|
|
|
+ children: [
|
|
|
|
+ Expanded(
|
|
|
|
+ child: Container(
|
|
|
|
+ padding: EdgeInsets.all(16.0),
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: Colors.grey[200],
|
|
|
|
+ borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
|
|
|
+ ),
|
|
|
|
+ child: SingleChildScrollView(
|
|
|
|
+ child: Column(
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
+ children: [
|
|
|
|
+ Text(
|
|
|
|
+ 'Feng Shui Interpretation Content',
|
|
|
|
+ style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: 10),
|
|
|
|
+ Text(
|
|
|
|
+ 'Here you can provide detailed interpretations based on the user\'s input.',
|
|
|
|
+ style: TextStyle(fontSize: 16),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.all(8.0),
|
|
|
|
+ child: Row(
|
|
|
|
+ children: [
|
|
|
|
+ Expanded(
|
|
|
|
+ child: TextField(
|
|
|
|
+ controller: _controller,
|
|
|
|
+ decoration: InputDecoration(
|
|
|
|
+ hintText: 'Type your message...',
|
|
|
|
+ border: OutlineInputBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ ),
|
|
|
|
+ filled: true,
|
|
|
|
+ fillColor: Colors.white,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ IconButton(
|
|
|
|
+ icon: Icon(Icons.send, color: Colors.black),
|
|
|
|
+ onPressed: () {
|
|
|
|
+ String message = _controller.text;
|
|
|
|
+ if (message.isNotEmpty) {
|
|
|
|
+ print("Message sent: $message");
|
|
|
|
+ _controller.clear();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class FortuneTellingPage extends StatefulWidget {
|
|
|
|
+ @override
|
|
|
|
+ _FortuneTellingPageState createState() => _FortuneTellingPageState();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class _FortuneTellingPageState extends State<FortuneTellingPage> {
|
|
|
|
+ String? selectedGender;
|
|
|
|
+ int? selectedHour;
|
|
|
|
+ int? selectedMinute;
|
|
|
|
+ TextEditingController countryController = TextEditingController();
|
|
|
|
+ TextEditingController stateController = TextEditingController();
|
|
|
|
+ TextEditingController cityController = TextEditingController();
|
|
|
|
+ bool isAllFieldsFilled = false;
|
|
|
|
+
|
|
|
|
+ void checkFieldsFilled() {
|
|
|
|
+ if (selectedHour != null &&
|
|
|
|
+ selectedMinute != null &&
|
|
|
|
+ selectedGender != null &&
|
|
|
|
+ countryController.text.isNotEmpty &&
|
|
|
|
+ stateController.text.isNotEmpty &&
|
|
|
|
+ cityController.text.isNotEmpty) {
|
|
|
|
+ setState(() {
|
|
|
|
+ isAllFieldsFilled = true;
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ setState(() {
|
|
|
|
+ isAllFieldsFilled = false;
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ final screenHeight = MediaQuery.of(context).size.height;
|
|
|
|
+ final screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
+
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Fortune Telling'),
|
|
|
|
+
|
|
|
|
+ body: Container(
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ gradient: LinearGradient(
|
|
|
|
+ colors: [Colors.green[100]!, Colors.white],
|
|
|
|
+ begin: Alignment.topLeft,
|
|
|
|
+ end: Alignment.bottomRight,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ padding: EdgeInsets.symmetric(
|
|
|
|
+ horizontal: screenWidth * 0.08,
|
|
|
|
+ vertical: screenHeight * 0.05,
|
|
|
|
+ ),
|
|
|
|
+ child: Column(
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
+ children: [
|
|
|
|
+ // Birthday Section
|
|
|
|
+ ListTile(
|
|
|
|
+ title: Text('Birthday', style: TextStyle(fontSize: 18)),
|
|
|
|
+ trailing: TextButton(
|
|
|
|
+ child: Text('Select', style: TextStyle(color: Colors.green[800])),
|
|
|
|
+ onPressed: () {
|
|
|
|
+ showDatePicker(
|
|
|
|
+ context: context,
|
|
|
|
+ initialDate: DateTime.now(),
|
|
|
|
+ firstDate: DateTime(1900),
|
|
|
|
+ lastDate: DateTime(2100),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.03),
|
|
|
|
+
|
|
|
|
+ // Birth-time Section
|
|
|
|
+ ListTile(
|
|
|
|
+ title: Text('Birth-time', style: TextStyle(fontSize: 18)),
|
|
|
|
+ trailing: Row(
|
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
|
+ children: [
|
|
|
|
+ _buildDropdownHour(),
|
|
|
|
+ SizedBox(width: screenWidth * 0.02),
|
|
|
|
+ _buildDropdownMinute(),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.03),
|
|
|
|
+
|
|
|
|
+ // Gender Section
|
|
|
|
+ ListTile(
|
|
|
|
+ title: Text('Gender', style: TextStyle(fontSize: 18)),
|
|
|
|
+ trailing: _buildGenderDropdown(),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: screenHeight * 0.03),
|
|
|
|
+
|
|
|
|
+ // Birth Place Section
|
|
|
|
+ ListTile(
|
|
|
|
+ title: Text('Birth Place', style: TextStyle(fontSize: 18)),
|
|
|
|
+ ),
|
|
|
|
+ _buildTextField(countryController, 'Country', (value) {
|
|
|
|
+ checkFieldsFilled();
|
|
|
|
+ }),
|
|
|
|
+ SizedBox(height: screenHeight * 0.01),
|
|
|
|
+ _buildTextField(stateController, 'State', (value) {
|
|
|
|
+ checkFieldsFilled();
|
|
|
|
+ }),
|
|
|
|
+ SizedBox(height: screenHeight * 0.01),
|
|
|
|
+ _buildTextField(cityController, 'City', (value) {
|
|
|
|
+ checkFieldsFilled();
|
|
|
|
+ }),
|
|
|
|
+ SizedBox(height: screenHeight * 0.05),
|
|
|
|
+
|
|
|
|
+ // Fortune Telling Button
|
|
|
|
+ Center(
|
|
|
|
+ child: ElevatedButton(
|
|
|
|
+ style: ButtonStyle(
|
|
|
|
+ backgroundColor: MaterialStateProperty.all(
|
|
|
|
+ isAllFieldsFilled ? Colors.orange : Colors.grey,
|
|
|
|
+ ),
|
|
|
|
+ padding: MaterialStateProperty.all(EdgeInsets.symmetric(vertical: 15, horizontal: 30)),
|
|
|
|
+ shape: MaterialStateProperty.all(RoundedRectangleBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ )),
|
|
|
|
+ ),
|
|
|
|
+ onPressed: isAllFieldsFilled
|
|
|
|
+ ? () {
|
|
|
|
+ // Implement your fortune telling logic here
|
|
|
|
+ }
|
|
|
|
+ : null,
|
|
|
|
+ child: Text('Fortune Telling', style: TextStyle(fontSize: 18)),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildDropdownHour() {
|
|
|
|
+ return DropdownButton<int>(
|
|
|
|
+ hint: Text('hr'),
|
|
|
|
+ value: selectedHour,
|
|
|
|
+ items: List.generate(24, (index) {
|
|
|
|
+ return DropdownMenuItem(
|
|
|
|
+ value: index,
|
|
|
|
+ child: Text(index.toString().padLeft(2, '0')),
|
|
|
|
+ );
|
|
|
|
+ }),
|
|
|
|
+ onChanged: (value) {
|
|
|
|
+ setState(() {
|
|
|
|
+ selectedHour = value;
|
|
|
|
+ });
|
|
|
|
+ checkFieldsFilled();
|
|
|
|
+ },
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildDropdownMinute() {
|
|
|
|
+ return DropdownButton<int>(
|
|
|
|
+ hint: Text('min'),
|
|
|
|
+ value: selectedMinute,
|
|
|
|
+ items: List.generate(60, (index) {
|
|
|
|
+ return DropdownMenuItem(
|
|
|
|
+ value: index,
|
|
|
|
+ child: Text(index.toString().padLeft(2, '0')),
|
|
|
|
+ );
|
|
|
|
+ }),
|
|
|
|
+ onChanged: (value) {
|
|
|
|
+ setState(() {
|
|
|
|
+ selectedMinute = value;
|
|
|
|
+ });
|
|
|
|
+ checkFieldsFilled();
|
|
|
|
+ },
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildGenderDropdown() {
|
|
|
|
+ return DropdownButton<String>(
|
|
|
|
+ hint: Text('Select'),
|
|
|
|
+ value: selectedGender,
|
|
|
|
+ items: [
|
|
|
|
+ DropdownMenuItem(value: 'Male', child: Text('Male')),
|
|
|
|
+ DropdownMenuItem(value: 'Female', child: Text('Female')),
|
|
|
|
+ DropdownMenuItem(value: 'Other', child: Text('Other')),
|
|
|
|
+ ],
|
|
|
|
+ onChanged: (value) {
|
|
|
|
+ setState(() {
|
|
|
|
+ selectedGender = value;
|
|
|
|
+ });
|
|
|
|
+ checkFieldsFilled();
|
|
|
|
+ },
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildTextField(TextEditingController controller, String hint, Function(String) onChanged) {
|
|
|
|
+ return TextField(
|
|
|
|
+ controller: controller,
|
|
|
|
+ decoration: InputDecoration(
|
|
|
|
+ hintText: hint,
|
|
|
|
+ border: OutlineInputBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ ),
|
|
|
|
+ filled: true,
|
|
|
|
+ fillColor: Colors.white,
|
|
|
|
+ ),
|
|
|
|
+ onChanged: onChanged,
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class ClickAndDrawPage extends StatelessWidget {
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Divination'),
|
|
|
|
+ body: Container(
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ image: DecorationImage(
|
|
|
|
+ image: AssetImage('assets/抽签.gif'), // 确保您有这个GIF文件
|
|
|
|
+ fit: BoxFit.cover,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Padding(
|
|
|
|
+ padding: EdgeInsets.only(top: 30.0),
|
|
|
|
+ child: Align(
|
|
|
|
+ alignment: Alignment.topCenter,
|
|
|
|
+ child: ElevatedButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => ResultPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ child: Text(
|
|
|
|
+ 'Click & Draw',
|
|
|
|
+ style: TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: Colors.orange.withOpacity(0.6),
|
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
|
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class ResultPage extends StatelessWidget {
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ final screenHeight = MediaQuery.of(context).size.height;
|
|
|
|
+ final screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
+
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Divination Result'),
|
|
|
|
+ body: Container(
|
|
|
|
+ padding: EdgeInsets.all(20),
|
|
|
|
+ child: Column(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
+ children: [
|
|
|
|
+ Container(
|
|
|
|
+ height: screenHeight * 0.6,
|
|
|
|
+ width: screenWidth * 0.9,
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
|
+ boxShadow: [
|
|
|
|
+ BoxShadow(
|
|
|
|
+ color: Colors.grey.withOpacity(0.5),
|
|
|
|
+ spreadRadius: 5,
|
|
|
|
+ blurRadius: 7,
|
|
|
|
+ offset: Offset(0, 3),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ padding: EdgeInsets.all(20),
|
|
|
|
+ child: SingleChildScrollView(
|
|
|
|
+ child: Text(
|
|
|
|
+ 'Your divination result will be displayed here...',
|
|
|
|
+ style: TextStyle(fontSize: 18),
|
|
|
|
+ textAlign: TextAlign.center,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: 30),
|
|
|
|
+ ElevatedButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ // 这里添加更多详情的逻辑
|
|
|
|
+ },
|
|
|
|
+ child: Text(
|
|
|
|
+ 'More Details',
|
|
|
|
+ style: TextStyle(fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: Colors.black,
|
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
|
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class DreamInterpretationScreen extends StatefulWidget {
|
|
|
|
+ @override
|
|
|
|
+ _DreamInterpretationScreenState createState() => _DreamInterpretationScreenState();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class _DreamInterpretationScreenState extends State<DreamInterpretationScreen> {
|
|
|
|
+ int selectedIndex = -1;
|
|
|
|
+ String selectedFilter = 'New';
|
|
|
|
+ bool isTyping = false;
|
|
|
|
+
|
|
|
|
+ final List<String> dreamObjects = [
|
|
|
|
+ 'Teeth', 'Parents', 'Cats', 'Thunder', 'Frog', 'Rain', 'Sea', 'Flying', 'Chasing'
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ List<String> userQuestions = [];
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Dream Interpretation'),
|
|
|
|
+ body: Container(
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ gradient: LinearGradient(
|
|
|
|
+ begin: Alignment.topCenter,
|
|
|
|
+ end: Alignment.bottomCenter,
|
|
|
|
+ colors: [Colors.blue[100]!, Colors.blue[900]!],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Column(
|
|
|
|
+ children: [
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.all(16.0),
|
|
|
|
+ child: Text(
|
|
|
|
+ 'Let Zhou Gong interpret your dream',
|
|
|
|
+ style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
|
|
|
+ textAlign: TextAlign.center,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ // Dream objects wrap
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
|
|
+ child: Container(
|
|
|
|
+ width: MediaQuery.of(context).size.width * 0.85,
|
|
|
|
+ child: Wrap(
|
|
|
|
+ alignment: WrapAlignment.spaceEvenly,
|
|
|
|
+ spacing: 8.0,
|
|
|
|
+ runSpacing: 8.0,
|
|
|
|
+ children: List.generate((dreamObjects.length / 3).ceil(), (rowIndex) {
|
|
|
|
+ return Row(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
+ children: List.generate(3, (colIndex) {
|
|
|
|
+ final index = rowIndex * 3 + colIndex;
|
|
|
|
+ if (index >= dreamObjects.length) return SizedBox.shrink();
|
|
|
|
+ return Expanded(
|
|
|
|
+ child: Padding(
|
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
|
|
|
+ child: GestureDetector(
|
|
|
|
+ onTap: () {
|
|
|
|
+ setState(() {
|
|
|
|
+ selectedIndex = index;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ child: Container(
|
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
|
+ border: Border.all(
|
|
|
|
+ color: selectedIndex == index ? Colors.blue : Colors.transparent,
|
|
|
|
+ width: 2,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Text(
|
|
|
|
+ dreamObjects[index],
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ color: Colors.blue,
|
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
|
+ ),
|
|
|
|
+ textAlign: TextAlign.center,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }),
|
|
|
|
+ );
|
|
|
|
+ }).toList(),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: 16),
|
|
|
|
+ // Content frame
|
|
|
|
+ Expanded(
|
|
|
|
+ child: Container(
|
|
|
|
+ margin: EdgeInsets.fromLTRB(16, 0, 16, 16),
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: Colors.white.withOpacity(0.1),
|
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
|
+ ),
|
|
|
|
+ child: Column(
|
|
|
|
+ children: [
|
|
|
|
+ // Filter buttons for "New" and "Hot"
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.all(16.0),
|
|
|
|
+ child: Row(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
+ children: [
|
|
|
|
+ _buildFilterButton('New'),
|
|
|
|
+ SizedBox(width: 16),
|
|
|
|
+ _buildFilterButton('Hot'),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ // User content
|
|
|
|
+ Expanded(
|
|
|
|
+ child: ListView.builder(
|
|
|
|
+ itemCount: userQuestions.length,
|
|
|
|
+ itemBuilder: (context, index) {
|
|
|
|
+ return Card(
|
|
|
|
+ margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
|
|
+ child: ListTile(
|
|
|
|
+ title: Text(userQuestions[index]),
|
|
|
|
+ trailing: ElevatedButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => DreamResultPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ child: Text('More', style: TextStyle(color: Colors.white)),
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: Colors.blue,
|
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.all(16.0),
|
|
|
|
+ child: _buildInputField(),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildFilterButton(String label) {
|
|
|
|
+ return ElevatedButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ setState(() {
|
|
|
|
+ selectedFilter = label;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: selectedFilter == label ? Colors.blue[700] : Colors.blue[300],
|
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ child: Text(
|
|
|
|
+ label,
|
|
|
|
+ style: TextStyle(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Widget _buildInputField() {
|
|
|
|
+ return TextField(
|
|
|
|
+ onSubmitted: (value) {
|
|
|
|
+ if (value.isNotEmpty) {
|
|
|
|
+ setState(() {
|
|
|
|
+ userQuestions.insert(0, "User: $value");
|
|
|
|
+ });
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => DreamResultPage()),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ decoration: InputDecoration(
|
|
|
|
+ hintText: 'Ask Zhou Gong Anything...',
|
|
|
|
+ border: OutlineInputBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(25),
|
|
|
|
+ ),
|
|
|
|
+ fillColor: Colors.white,
|
|
|
|
+ filled: true,
|
|
|
|
+ suffixIcon: IconButton(
|
|
|
|
+ icon: Icon(Icons.send),
|
|
|
|
+ onPressed: () {
|
|
|
|
+ Navigator.push(
|
|
|
|
+ context,
|
|
|
|
+ MaterialPageRoute(builder: (context) => DreamResultPage()),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class DreamResultPage extends StatelessWidget {
|
|
|
|
+ @override
|
|
|
|
+ Widget build(BuildContext context) {
|
|
|
|
+ final screenHeight = MediaQuery.of(context).size.height;
|
|
|
|
+ final screenWidth = MediaQuery.of(context).size.width;
|
|
|
|
+
|
|
|
|
+ return Scaffold(
|
|
|
|
+ appBar: commonAppBar(context, 'Dream Interpretation'),
|
|
|
|
+ body: Container(
|
|
|
|
+ padding: EdgeInsets.all(20),
|
|
|
|
+ child: Column(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
+ children: [
|
|
|
|
+ Container(
|
|
|
|
+ height: screenHeight * 0.6,
|
|
|
|
+ width: screenWidth * 0.9,
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: Colors.white,
|
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
|
+ boxShadow: [
|
|
|
|
+ BoxShadow(
|
|
|
|
+ color: Colors.grey.withOpacity(0.5),
|
|
|
|
+ spreadRadius: 5,
|
|
|
|
+ blurRadius: 7,
|
|
|
|
+ offset: Offset(0, 3),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ padding: EdgeInsets.all(20),
|
|
|
|
+ child: SingleChildScrollView(
|
|
|
|
+ child: Text(
|
|
|
|
+ 'Your dream interpretation result will be displayed here...',
|
|
|
|
+ style: TextStyle(fontSize: 18),
|
|
|
|
+ textAlign: TextAlign.center,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ SizedBox(height: 30),
|
|
|
|
+ ElevatedButton(
|
|
|
|
+ onPressed: () {
|
|
|
|
+ // 这里添加更多详情的逻辑
|
|
|
|
+ },
|
|
|
|
+ child: Text(
|
|
|
|
+ 'More Details',
|
|
|
|
+ style: TextStyle(fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold),
|
|
|
|
+ ),
|
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
|
+ backgroundColor: Colors.black,
|
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
|
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
|
+ borderRadius: BorderRadius.circular(30),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+}
|