main.dart 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_compass/flutter_compass.dart';
  3. import 'dart:math' as math;
  4. import 'package:url_launcher/url_launcher.dart'; // 导入 url_launcher 包
  5. void main() {
  6. runApp(MyApp());
  7. }
  8. class MyApp extends StatelessWidget {
  9. @override
  10. Widget build(BuildContext context) {
  11. return MaterialApp(
  12. home: HomePage(),
  13. );
  14. }
  15. }
  16. class HomePage extends StatelessWidget {
  17. @override
  18. Widget build(BuildContext context) {
  19. double screenWidth = MediaQuery.of(context).size.width;
  20. double screenHeight = MediaQuery.of(context).size.height;
  21. return Scaffold(
  22. appBar: AppBar(
  23. title: Text('Ask Tao'),
  24. ),
  25. body: SingleChildScrollView(
  26. child: Column(
  27. crossAxisAlignment: CrossAxisAlignment.stretch,
  28. children: [
  29. // Daily Tao 图片背景
  30. Container(
  31. width: screenWidth,
  32. height: screenHeight * 0.25,
  33. decoration: BoxDecoration(
  34. image: DecorationImage(
  35. image: AssetImage('assets/daily_tao_background.png'),
  36. fit: BoxFit.cover,
  37. ),
  38. ),
  39. child: Padding(
  40. padding: EdgeInsets.symmetric(
  41. horizontal: screenWidth * 0.05,
  42. vertical: screenHeight * 0.02,
  43. ),
  44. child: Column(
  45. crossAxisAlignment: CrossAxisAlignment.start,
  46. mainAxisAlignment: MainAxisAlignment.end,
  47. children: [
  48. Text(
  49. 'Daily Tao',
  50. style: TextStyle(
  51. color: Colors.white,
  52. fontSize: screenWidth * 0.07,
  53. fontWeight: FontWeight.bold,
  54. ),
  55. ),
  56. SizedBox(height: screenHeight * 0.01),
  57. Text(
  58. '行者南游归,慈云洞庭开。\n寻经十二部,普度度有生。',
  59. style: TextStyle(
  60. color: Colors.white,
  61. fontSize: screenWidth * 0.04,
  62. ),
  63. ),
  64. SizedBox(height: screenHeight * 0.02),
  65. ElevatedButton(
  66. onPressed: () {
  67. // 按钮点击事件
  68. },
  69. style: ElevatedButton.styleFrom(
  70. backgroundColor: Colors.white.withOpacity(0.6),
  71. padding: EdgeInsets.symmetric(
  72. horizontal: screenWidth * 0.1,
  73. vertical: screenHeight * 0.02,
  74. ),
  75. shape: RoundedRectangleBorder(
  76. borderRadius: BorderRadius.circular(30),
  77. ),
  78. ),
  79. child: Text(
  80. 'Learn more →',
  81. style: TextStyle(
  82. fontSize: screenWidth * 0.05,
  83. ),
  84. ),
  85. ),
  86. ],
  87. ),
  88. ),
  89. ),
  90. // Study Tao & Find Inner Peace
  91. Padding(
  92. padding: EdgeInsets.all(screenWidth * 0.05),
  93. child: ListView(
  94. shrinkWrap: true,
  95. physics: NeverScrollableScrollPhysics(),
  96. children: [
  97. _buildOptionCard(
  98. screenWidth: screenWidth,
  99. screenHeight: screenHeight,
  100. image: 'assets/study_tao.png',
  101. title: 'Study Tao',
  102. subtitle: 'Chat to gain deeper understanding of Tao.',
  103. ),
  104. SizedBox(height: screenHeight * 0.02),
  105. _buildOptionCard(
  106. screenWidth: screenWidth,
  107. screenHeight: screenHeight,
  108. image: 'assets/inner_peace.png',
  109. title: 'Find Inner Peace',
  110. subtitle: 'Tell your troubles and find your inner peace.',
  111. ),
  112. SizedBox(height: screenHeight * 0.02),
  113. // 下方的小图标部分
  114. Padding(
  115. padding: EdgeInsets.all(screenWidth * 0.05),
  116. child: GridView.count(
  117. crossAxisCount: 3,
  118. shrinkWrap: true,
  119. physics: NeverScrollableScrollPhysics(),
  120. crossAxisSpacing: screenWidth * 0.02,
  121. mainAxisSpacing: screenHeight * 0.02,
  122. children: [
  123. _buildIconTile(
  124. screenWidth: screenWidth,
  125. icon: 'assets/fengshui.png',
  126. label: 'Fengshui',
  127. onTap: () {
  128. Navigator.push(
  129. context,
  130. MaterialPageRoute(builder: (context) => PropertyPage()),
  131. );
  132. },
  133. ),
  134. _buildIconTile(
  135. screenWidth: screenWidth,
  136. icon: 'assets/fortune_telling.png',
  137. label: 'Fortune telling',
  138. onTap: () {
  139. Navigator.push(
  140. context,
  141. MaterialPageRoute(builder: (context) => FortuneTellingPage()),
  142. );
  143. },
  144. ),
  145. _buildIconTile(
  146. screenWidth: screenWidth,
  147. icon: 'assets/divination.png',
  148. label: 'Divination',
  149. onTap: () {
  150. Navigator.push(
  151. context,
  152. MaterialPageRoute(builder: (context) => ClickAndDrawPage()),
  153. );
  154. },
  155. ),
  156. _buildIconTile(
  157. screenWidth: screenWidth,
  158. icon: 'assets/taoistpractice.png',
  159. label: 'Taoist practice',
  160. ),
  161. _buildIconTile(
  162. screenWidth: screenWidth,
  163. icon: 'assets/interpretdream.png',
  164. label: 'Interpret dream',
  165. onTap: () {
  166. Navigator.push(
  167. context,
  168. MaterialPageRoute(builder: (context) => DreamInterpretationScreen()),
  169. );
  170. },
  171. ),
  172. _buildIconTile(
  173. screenWidth: screenWidth,
  174. icon: 'assets/taoistculture.png',
  175. label: 'Taoist culture',
  176. ),
  177. ],
  178. ),
  179. ),
  180. ],
  181. ),
  182. ),
  183. ],
  184. ),
  185. ),
  186. );
  187. }
  188. Widget _buildOptionCard({
  189. required double screenWidth,
  190. required double screenHeight,
  191. required String image,
  192. required String title,
  193. required String subtitle,
  194. }) {
  195. return Container(
  196. width: screenWidth,
  197. height: screenHeight * 0.12,
  198. decoration: BoxDecoration(
  199. borderRadius: BorderRadius.circular(20),
  200. image: DecorationImage(
  201. image: AssetImage(image),
  202. fit: BoxFit.cover,
  203. ),
  204. ),
  205. child: Padding(
  206. padding: EdgeInsets.all(screenWidth * 0.05),
  207. child: Column(
  208. crossAxisAlignment: CrossAxisAlignment.start,
  209. mainAxisAlignment: MainAxisAlignment.center,
  210. children: [
  211. Text(
  212. title,
  213. style: TextStyle(
  214. color: Colors.white,
  215. fontSize: screenWidth * 0.06,
  216. fontWeight: FontWeight.bold,
  217. ),
  218. ),
  219. SizedBox(height: screenHeight * 0.01),
  220. Flexible(
  221. child: Text(
  222. subtitle,
  223. style: TextStyle(
  224. color: Colors.white,
  225. fontSize: screenWidth * 0.04,
  226. ),
  227. overflow: TextOverflow.ellipsis,
  228. maxLines: 2,
  229. ),
  230. ),
  231. ],
  232. ),
  233. ),
  234. );
  235. }
  236. Widget _buildIconTile({
  237. required double screenWidth,
  238. required String icon,
  239. required String label,
  240. VoidCallback? onTap,
  241. }) {
  242. return GestureDetector(
  243. onTap: onTap,
  244. child: Column(
  245. mainAxisSize: MainAxisSize.min,
  246. children: [
  247. Container(
  248. width: screenWidth * 0.15,
  249. height: screenWidth * 0.15,
  250. decoration: BoxDecoration(
  251. shape: BoxShape.circle,
  252. image: DecorationImage(
  253. image: AssetImage(icon),
  254. fit: BoxFit.cover,
  255. ),
  256. ),
  257. ),
  258. SizedBox(height: screenWidth * 0.01),
  259. Text(
  260. label,
  261. style: TextStyle(
  262. fontSize: screenWidth * 0.03,
  263. ),
  264. textAlign: TextAlign.center,
  265. maxLines: 2,
  266. overflow: TextOverflow.ellipsis,
  267. ),
  268. ],
  269. ),
  270. );
  271. }
  272. }
  273. PreferredSizeWidget commonAppBar(BuildContext context, String title) {
  274. return AppBar(
  275. title: Text(
  276. title,
  277. style: TextStyle(
  278. color: Colors.white,
  279. fontWeight: FontWeight.bold,
  280. ),
  281. ),
  282. backgroundColor: Colors.black,
  283. leading: IconButton(
  284. icon: Icon(Icons.arrow_back, color: Colors.white),
  285. onPressed: () => Navigator.of(context).pop(),
  286. ),
  287. actions: [
  288. IconButton(
  289. icon: Icon(Icons.home, color: Colors.white),
  290. onPressed: () {
  291. Navigator.of(context).popUntil((route) => route.isFirst);
  292. },
  293. ),
  294. ],
  295. );
  296. }
  297. class PropertyPage extends StatelessWidget {
  298. @override
  299. Widget build(BuildContext context) {
  300. double screenHeight = MediaQuery.of(context).size.height;
  301. double screenWidth = MediaQuery.of(context).size.width;
  302. return Scaffold(
  303. appBar: commonAppBar(context, 'Property Type'),
  304. body: SingleChildScrollView(
  305. child: Column(
  306. children: [
  307. // Yang Property Section
  308. Container(
  309. color: Color(0xFF00164C),
  310. child: ListTile(
  311. leading: Icon(Icons.house, color: Colors.white),
  312. title: Text(
  313. "Yang Property",
  314. style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
  315. ),
  316. ),
  317. ),
  318. Container(
  319. height: screenHeight * 0.3,
  320. child: PageView(
  321. scrollDirection: Axis.horizontal,
  322. children: [
  323. PropertyCard(
  324. title: "Town House",
  325. imageAsset: 'assets/townhouse.png',
  326. ),
  327. PropertyCard(
  328. title: "Single Family House",
  329. imageAsset: 'assets/singlefamily.png',
  330. ),
  331. PropertyCard(
  332. title: "Condo",
  333. imageAsset: 'assets/condo.png',
  334. ),
  335. ],
  336. ),
  337. ),
  338. SizedBox(height: screenHeight * 0.02),
  339. // Yin Property Section
  340. Container(
  341. color: Color(0xFF00164C),
  342. child: ListTile(
  343. leading: Icon(Icons.nights_stay, color: Colors.white),
  344. title: Text(
  345. "Yin Property",
  346. style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
  347. ),
  348. ),
  349. ),
  350. Container(
  351. height: screenHeight * 0.3,
  352. child: PropertyCard(
  353. title: "Grave",
  354. imageAsset: 'assets/grave.png',
  355. ),
  356. ),
  357. ],
  358. ),
  359. ),
  360. );
  361. }
  362. }
  363. class PropertyCard extends StatelessWidget {
  364. final String title;
  365. final String imageAsset;
  366. PropertyCard({required this.title, required this.imageAsset});
  367. @override
  368. Widget build(BuildContext context) {
  369. return Card(
  370. child: InkWell(
  371. onTap: () {
  372. print("PropertyCard tapped: $title");
  373. Navigator.push(
  374. context,
  375. MaterialPageRoute(builder: (context) => CompassPage()),
  376. );
  377. },
  378. child: Column(
  379. children: [
  380. Expanded(
  381. child: Image.asset(
  382. imageAsset,
  383. fit: BoxFit.cover,
  384. width: double.infinity,
  385. ),
  386. ),
  387. Padding(
  388. padding: const EdgeInsets.all(8.0),
  389. child: Text(
  390. title,
  391. style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
  392. ),
  393. ),
  394. ],
  395. ),
  396. ),
  397. );
  398. }
  399. }
  400. class CompassPage extends StatefulWidget {
  401. @override
  402. _CompassPageState createState() => _CompassPageState();
  403. }
  404. class _CompassPageState extends State<CompassPage> {
  405. String address = "";
  406. bool isAddressEntered = false;
  407. double _direction = 0;
  408. double _confirmedDirection = 0;
  409. @override
  410. void initState() {
  411. super.initState();
  412. FlutterCompass.events!.listen((CompassEvent event) {
  413. setState(() {
  414. _direction = event.heading ?? 0;
  415. });
  416. });
  417. }
  418. @override
  419. Widget build(BuildContext context) {
  420. double screenHeight = MediaQuery.of(context).size.height;
  421. double screenWidth = MediaQuery.of(context).size.width;
  422. return Scaffold(
  423. appBar: commonAppBar(context, 'Property Type'),
  424. body: Container(
  425. decoration: BoxDecoration(
  426. gradient: LinearGradient(
  427. colors: [Colors.green[100]!, Colors.white],
  428. begin: Alignment.topLeft,
  429. end: Alignment.bottomRight,
  430. ),
  431. ),
  432. child: Column(
  433. children: [
  434. SizedBox(height: screenHeight * 0.02),
  435. Text(
  436. 'Gate Direction',
  437. style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
  438. ),
  439. Text(
  440. 'Use the compass to confirm your gate direction',
  441. style: TextStyle(color: Colors.grey, fontSize: 14),
  442. ),
  443. SizedBox(height: screenHeight * 0.03),
  444. Container(
  445. width: screenWidth * 0.75,
  446. height: screenWidth * 0.75,
  447. child: Transform.rotate(
  448. angle: ((_direction ?? 0) * (math.pi / 180) * -1),
  449. child: Image.asset('assets/compass.png'),
  450. ),
  451. ),
  452. SizedBox(height: screenHeight * 0.02),
  453. Text(
  454. '${_confirmedDirection.toStringAsFixed(0)}°',
  455. style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
  456. ),
  457. Text(
  458. _getDirectionText(_confirmedDirection),
  459. style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
  460. ),
  461. SizedBox(height: screenHeight * 0.05),
  462. ElevatedButton(
  463. onPressed: () {
  464. setState(() {
  465. _confirmedDirection = _direction;
  466. });
  467. },
  468. style: ElevatedButton.styleFrom(
  469. backgroundColor: Colors.black,
  470. padding: EdgeInsets.symmetric(horizontal: 50, vertical: 15),
  471. ),
  472. child: Text(
  473. 'Confirm',
  474. style: TextStyle(color: Colors.white, fontSize: 18),
  475. ),
  476. ),
  477. SizedBox(height: screenHeight * 0.02),
  478. TextField(
  479. decoration: InputDecoration(
  480. labelText: 'Input your address',
  481. border: OutlineInputBorder(),
  482. ),
  483. onChanged: (value) {
  484. setState(() {
  485. address = value;
  486. isAddressEntered = value.isNotEmpty;
  487. });
  488. },
  489. ),
  490. SizedBox(height: screenHeight * 0.02),
  491. ElevatedButton(
  492. onPressed: isAddressEntered
  493. ? () {
  494. // 跳转到上传页面
  495. Navigator.push(
  496. context,
  497. MaterialPageRoute(builder: (context) => UploadPage()),
  498. );
  499. }
  500. : null,
  501. style: ElevatedButton.styleFrom(
  502. backgroundColor: isAddressEntered ? Colors.black : Colors.grey,
  503. padding: EdgeInsets.symmetric(horizontal: 50, vertical: 15),
  504. ),
  505. child: Text(
  506. 'Continue',
  507. style: TextStyle(color: Colors.white, fontSize: 18),
  508. ),
  509. ),
  510. ],
  511. ),
  512. ),
  513. );
  514. }
  515. String _getDirectionText(double direction) {
  516. if (direction >= 337.5 || direction < 22.5) return 'North';
  517. if (direction >= 22.5 && direction < 67.5) return 'North East';
  518. if (direction >= 67.5 && direction < 112.5) return 'East';
  519. if (direction >= 112.5 && direction < 157.5) return 'South East';
  520. if (direction >= 157.5 && direction < 202.5) return 'South';
  521. if (direction >= 202.5 && direction < 247.5) return 'South West';
  522. if (direction >= 247.5 && direction < 292.5) return 'West';
  523. if (direction >= 292.5 && direction < 337.5) return 'North West';
  524. return '';
  525. }
  526. }
  527. class UploadPage extends StatefulWidget {
  528. @override
  529. _UploadPageState createState() => _UploadPageState();
  530. }
  531. class _UploadPageState extends State<UploadPage> {
  532. String? selectedOption = "Floor Plan"; // 默认选择 "Floor Plan"
  533. @override
  534. Widget build(BuildContext context) {
  535. double screenHeight = MediaQuery.of(context).size.height;
  536. double screenWidth = MediaQuery.of(context).size.width;
  537. return Scaffold(
  538. appBar: commonAppBar(context, 'Property Type'),
  539. body: Container(
  540. padding: EdgeInsets.all(screenHeight * 0.02),
  541. decoration: BoxDecoration(
  542. gradient: LinearGradient(
  543. colors: [Colors.green[100]!, Colors.white],
  544. begin: Alignment.topLeft,
  545. end: Alignment.bottomRight,
  546. ),
  547. ),
  548. child: Column(
  549. children: [
  550. Text(
  551. "Upload",
  552. style: TextStyle(
  553. fontSize: screenWidth * 0.06,
  554. fontWeight: FontWeight.bold,
  555. color: Colors.black,
  556. ),
  557. ),
  558. SizedBox(height: screenHeight * 0.02),
  559. Container(
  560. width: screenWidth * 0.85,
  561. height: screenHeight * 0.2,
  562. decoration: BoxDecoration(
  563. color: Colors.grey.withOpacity(0.5),
  564. borderRadius: BorderRadius.circular(15),
  565. ),
  566. child: Center(
  567. child: Text(
  568. "Select File",
  569. style: TextStyle(color: Colors.black),
  570. ),
  571. ),
  572. ),
  573. SizedBox(height: screenHeight * 0.02),
  574. Column(
  575. children: [
  576. _buildRadioOption("Floor Plan"),
  577. _buildRadioOption("Indoor Photo"),
  578. _buildRadioOption("Surroundings"),
  579. ],
  580. ),
  581. SizedBox(height: screenHeight * 0.02),
  582. SizedBox(height: screenHeight * 0.02),
  583. ElevatedButton(
  584. onPressed: () async {
  585. const url = 'https://your-payment-url.com'; // 替换为实际的付费链接
  586. if (await canLaunch(url)) {
  587. await launch(url);
  588. Navigator.push(
  589. context,
  590. MaterialPageRoute(builder: (context) => FengShuiInterpretationPage()),
  591. );
  592. } else {
  593. throw 'Could not launch $url';
  594. }
  595. },
  596. child: Text("Pay to unlock", style: TextStyle(color: Colors.white, fontSize: 18)),
  597. style: ElevatedButton.styleFrom(
  598. backgroundColor: Colors.black,
  599. padding: EdgeInsets.symmetric(vertical: 15, horizontal: 30),
  600. ),
  601. ),
  602. SizedBox(height: screenHeight * 0.02),
  603. Row(
  604. children: [
  605. Expanded(child: Divider(color: Colors.grey)),
  606. Padding(
  607. padding: const EdgeInsets.symmetric(horizontal: 8.0),
  608. child: Text("or", style: TextStyle(color: Colors.black)),
  609. ),
  610. Expanded(child: Divider(color: Colors.grey)),
  611. ],
  612. ),
  613. SizedBox(height: screenHeight * 0.02),
  614. Container(
  615. decoration: BoxDecoration(
  616. color: Colors.black,
  617. borderRadius: BorderRadius.circular(30),
  618. ),
  619. child: TextButton(
  620. onPressed: () {
  621. Navigator.push(
  622. context,
  623. MaterialPageRoute(builder: (context) => FengShuiInterpretationPage()),
  624. );
  625. },
  626. child: Text(
  627. "Skip",
  628. style: TextStyle(color: Colors.white, fontSize: 18),
  629. ),
  630. ),
  631. ),
  632. ],
  633. ),
  634. ),
  635. );
  636. }
  637. Widget _buildRadioOption(String title) {
  638. bool isSelected = selectedOption == title;
  639. return Container(
  640. width: MediaQuery.of(context).size.width * 0.65,
  641. margin: EdgeInsets.symmetric(vertical: 5.0),
  642. decoration: BoxDecoration(
  643. color: isSelected ? Colors.black.withOpacity(0.6) : Colors.grey.withOpacity(0.3),
  644. borderRadius: BorderRadius.circular(10),
  645. ),
  646. child: RadioListTile(
  647. value: title,
  648. groupValue: selectedOption,
  649. title: Text(
  650. title,
  651. style: TextStyle(color: Colors.white),
  652. ),
  653. onChanged: (value) {
  654. setState(() {
  655. selectedOption = value as String?;
  656. });
  657. },
  658. activeColor: Colors.white,
  659. controlAffinity: ListTileControlAffinity.trailing,
  660. ),
  661. );
  662. }
  663. }
  664. class FengShuiInterpretationPage extends StatelessWidget {
  665. final TextEditingController _controller = TextEditingController();
  666. @override
  667. Widget build(BuildContext context) {
  668. return Scaffold(
  669. appBar: commonAppBar(context, 'Feng Shui Interpretation'),
  670. body: Container(
  671. decoration: BoxDecoration(
  672. gradient: LinearGradient(
  673. colors: [Colors.green[100]!, Colors.white],
  674. begin: Alignment.topLeft,
  675. end: Alignment.bottomRight,
  676. ),
  677. ),
  678. child: Column(
  679. children: [
  680. Expanded(
  681. child: Container(
  682. padding: EdgeInsets.all(16.0),
  683. decoration: BoxDecoration(
  684. color: Colors.grey[200],
  685. borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
  686. ),
  687. child: SingleChildScrollView(
  688. child: Column(
  689. crossAxisAlignment: CrossAxisAlignment.start,
  690. children: [
  691. Text(
  692. 'Feng Shui Interpretation Content',
  693. style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
  694. ),
  695. SizedBox(height: 10),
  696. Text(
  697. 'Here you can provide detailed interpretations based on the user\'s input.',
  698. style: TextStyle(fontSize: 16),
  699. ),
  700. ],
  701. ),
  702. ),
  703. ),
  704. ),
  705. Padding(
  706. padding: const EdgeInsets.all(8.0),
  707. child: Row(
  708. children: [
  709. Expanded(
  710. child: TextField(
  711. controller: _controller,
  712. decoration: InputDecoration(
  713. hintText: 'Type your message...',
  714. border: OutlineInputBorder(
  715. borderRadius: BorderRadius.circular(30),
  716. ),
  717. filled: true,
  718. fillColor: Colors.white,
  719. ),
  720. ),
  721. ),
  722. IconButton(
  723. icon: Icon(Icons.send, color: Colors.black),
  724. onPressed: () {
  725. String message = _controller.text;
  726. if (message.isNotEmpty) {
  727. print("Message sent: $message");
  728. _controller.clear();
  729. }
  730. },
  731. ),
  732. ],
  733. ),
  734. ),
  735. ],
  736. ),
  737. ),
  738. );
  739. }
  740. }
  741. class FortuneTellingPage extends StatefulWidget {
  742. @override
  743. _FortuneTellingPageState createState() => _FortuneTellingPageState();
  744. }
  745. class _FortuneTellingPageState extends State<FortuneTellingPage> {
  746. String? selectedGender;
  747. int? selectedHour;
  748. int? selectedMinute;
  749. TextEditingController countryController = TextEditingController();
  750. TextEditingController stateController = TextEditingController();
  751. TextEditingController cityController = TextEditingController();
  752. bool isAllFieldsFilled = false;
  753. void checkFieldsFilled() {
  754. if (selectedHour != null &&
  755. selectedMinute != null &&
  756. selectedGender != null &&
  757. countryController.text.isNotEmpty &&
  758. stateController.text.isNotEmpty &&
  759. cityController.text.isNotEmpty) {
  760. setState(() {
  761. isAllFieldsFilled = true;
  762. });
  763. } else {
  764. setState(() {
  765. isAllFieldsFilled = false;
  766. });
  767. }
  768. }
  769. @override
  770. Widget build(BuildContext context) {
  771. final screenHeight = MediaQuery.of(context).size.height;
  772. final screenWidth = MediaQuery.of(context).size.width;
  773. return Scaffold(
  774. appBar: commonAppBar(context, 'Fortune Telling'),
  775. body: Container(
  776. decoration: BoxDecoration(
  777. gradient: LinearGradient(
  778. colors: [Colors.green[100]!, Colors.white],
  779. begin: Alignment.topLeft,
  780. end: Alignment.bottomRight,
  781. ),
  782. ),
  783. padding: EdgeInsets.symmetric(
  784. horizontal: screenWidth * 0.08,
  785. vertical: screenHeight * 0.05,
  786. ),
  787. child: Column(
  788. crossAxisAlignment: CrossAxisAlignment.start,
  789. children: [
  790. // Birthday Section
  791. ListTile(
  792. title: Text('Birthday', style: TextStyle(fontSize: 18)),
  793. trailing: TextButton(
  794. child: Text('Select', style: TextStyle(color: Colors.green[800])),
  795. onPressed: () {
  796. showDatePicker(
  797. context: context,
  798. initialDate: DateTime.now(),
  799. firstDate: DateTime(1900),
  800. lastDate: DateTime(2100),
  801. );
  802. },
  803. ),
  804. ),
  805. SizedBox(height: screenHeight * 0.03),
  806. // Birth-time Section
  807. ListTile(
  808. title: Text('Birth-time', style: TextStyle(fontSize: 18)),
  809. trailing: Row(
  810. mainAxisSize: MainAxisSize.min,
  811. children: [
  812. _buildDropdownHour(),
  813. SizedBox(width: screenWidth * 0.02),
  814. _buildDropdownMinute(),
  815. ],
  816. ),
  817. ),
  818. SizedBox(height: screenHeight * 0.03),
  819. // Gender Section
  820. ListTile(
  821. title: Text('Gender', style: TextStyle(fontSize: 18)),
  822. trailing: _buildGenderDropdown(),
  823. ),
  824. SizedBox(height: screenHeight * 0.03),
  825. // Birth Place Section
  826. ListTile(
  827. title: Text('Birth Place', style: TextStyle(fontSize: 18)),
  828. ),
  829. _buildTextField(countryController, 'Country', (value) {
  830. checkFieldsFilled();
  831. }),
  832. SizedBox(height: screenHeight * 0.01),
  833. _buildTextField(stateController, 'State', (value) {
  834. checkFieldsFilled();
  835. }),
  836. SizedBox(height: screenHeight * 0.01),
  837. _buildTextField(cityController, 'City', (value) {
  838. checkFieldsFilled();
  839. }),
  840. SizedBox(height: screenHeight * 0.05),
  841. // Fortune Telling Button
  842. Center(
  843. child: ElevatedButton(
  844. style: ButtonStyle(
  845. backgroundColor: MaterialStateProperty.all(
  846. isAllFieldsFilled ? Colors.orange : Colors.grey,
  847. ),
  848. padding: MaterialStateProperty.all(EdgeInsets.symmetric(vertical: 15, horizontal: 30)),
  849. shape: MaterialStateProperty.all(RoundedRectangleBorder(
  850. borderRadius: BorderRadius.circular(30),
  851. )),
  852. ),
  853. onPressed: isAllFieldsFilled
  854. ? () {
  855. // Implement your fortune telling logic here
  856. }
  857. : null,
  858. child: Text('Fortune Telling', style: TextStyle(fontSize: 18)),
  859. ),
  860. ),
  861. ],
  862. ),
  863. ),
  864. );
  865. }
  866. Widget _buildDropdownHour() {
  867. return DropdownButton<int>(
  868. hint: Text('hr'),
  869. value: selectedHour,
  870. items: List.generate(24, (index) {
  871. return DropdownMenuItem(
  872. value: index,
  873. child: Text(index.toString().padLeft(2, '0')),
  874. );
  875. }),
  876. onChanged: (value) {
  877. setState(() {
  878. selectedHour = value;
  879. });
  880. checkFieldsFilled();
  881. },
  882. );
  883. }
  884. Widget _buildDropdownMinute() {
  885. return DropdownButton<int>(
  886. hint: Text('min'),
  887. value: selectedMinute,
  888. items: List.generate(60, (index) {
  889. return DropdownMenuItem(
  890. value: index,
  891. child: Text(index.toString().padLeft(2, '0')),
  892. );
  893. }),
  894. onChanged: (value) {
  895. setState(() {
  896. selectedMinute = value;
  897. });
  898. checkFieldsFilled();
  899. },
  900. );
  901. }
  902. Widget _buildGenderDropdown() {
  903. return DropdownButton<String>(
  904. hint: Text('Select'),
  905. value: selectedGender,
  906. items: [
  907. DropdownMenuItem(value: 'Male', child: Text('Male')),
  908. DropdownMenuItem(value: 'Female', child: Text('Female')),
  909. DropdownMenuItem(value: 'Other', child: Text('Other')),
  910. ],
  911. onChanged: (value) {
  912. setState(() {
  913. selectedGender = value;
  914. });
  915. checkFieldsFilled();
  916. },
  917. );
  918. }
  919. Widget _buildTextField(TextEditingController controller, String hint, Function(String) onChanged) {
  920. return TextField(
  921. controller: controller,
  922. decoration: InputDecoration(
  923. hintText: hint,
  924. border: OutlineInputBorder(
  925. borderRadius: BorderRadius.circular(30),
  926. ),
  927. filled: true,
  928. fillColor: Colors.white,
  929. ),
  930. onChanged: onChanged,
  931. );
  932. }
  933. }
  934. class ClickAndDrawPage extends StatelessWidget {
  935. @override
  936. Widget build(BuildContext context) {
  937. return Scaffold(
  938. appBar: commonAppBar(context, 'Divination'),
  939. body: Container(
  940. decoration: BoxDecoration(
  941. image: DecorationImage(
  942. image: AssetImage('assets/抽签.gif'), // 确保您有这个GIF文件
  943. fit: BoxFit.cover,
  944. ),
  945. ),
  946. child: Padding(
  947. padding: EdgeInsets.only(top: 30.0),
  948. child: Align(
  949. alignment: Alignment.topCenter,
  950. child: ElevatedButton(
  951. onPressed: () {
  952. Navigator.push(
  953. context,
  954. MaterialPageRoute(builder: (context) => ResultPage()),
  955. );
  956. },
  957. child: Text(
  958. 'Click & Draw',
  959. style: TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold),
  960. ),
  961. style: ElevatedButton.styleFrom(
  962. backgroundColor: Colors.orange.withOpacity(0.6),
  963. padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
  964. shape: RoundedRectangleBorder(
  965. borderRadius: BorderRadius.circular(30),
  966. ),
  967. ),
  968. ),
  969. ),
  970. ),
  971. ),
  972. );
  973. }
  974. }
  975. class ResultPage extends StatelessWidget {
  976. @override
  977. Widget build(BuildContext context) {
  978. final screenHeight = MediaQuery.of(context).size.height;
  979. final screenWidth = MediaQuery.of(context).size.width;
  980. return Scaffold(
  981. appBar: commonAppBar(context, 'Divination Result'),
  982. body: Container(
  983. padding: EdgeInsets.all(20),
  984. child: Column(
  985. mainAxisAlignment: MainAxisAlignment.center,
  986. children: [
  987. Container(
  988. height: screenHeight * 0.6,
  989. width: screenWidth * 0.9,
  990. decoration: BoxDecoration(
  991. color: Colors.white,
  992. borderRadius: BorderRadius.circular(20),
  993. boxShadow: [
  994. BoxShadow(
  995. color: Colors.grey.withOpacity(0.5),
  996. spreadRadius: 5,
  997. blurRadius: 7,
  998. offset: Offset(0, 3),
  999. ),
  1000. ],
  1001. ),
  1002. padding: EdgeInsets.all(20),
  1003. child: SingleChildScrollView(
  1004. child: Text(
  1005. 'Your divination result will be displayed here...',
  1006. style: TextStyle(fontSize: 18),
  1007. textAlign: TextAlign.center,
  1008. ),
  1009. ),
  1010. ),
  1011. SizedBox(height: 30),
  1012. ElevatedButton(
  1013. onPressed: () {
  1014. // 这里添加更多详情的逻辑
  1015. },
  1016. child: Text(
  1017. 'More Details',
  1018. style: TextStyle(fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold),
  1019. ),
  1020. style: ElevatedButton.styleFrom(
  1021. backgroundColor: Colors.black,
  1022. padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
  1023. shape: RoundedRectangleBorder(
  1024. borderRadius: BorderRadius.circular(30),
  1025. ),
  1026. ),
  1027. ),
  1028. ],
  1029. ),
  1030. ),
  1031. );
  1032. }
  1033. }
  1034. class DreamInterpretationScreen extends StatefulWidget {
  1035. @override
  1036. _DreamInterpretationScreenState createState() => _DreamInterpretationScreenState();
  1037. }
  1038. class _DreamInterpretationScreenState extends State<DreamInterpretationScreen> {
  1039. int selectedIndex = -1;
  1040. String selectedFilter = 'New';
  1041. bool isTyping = false;
  1042. final List<String> dreamObjects = [
  1043. 'Teeth', 'Parents', 'Cats', 'Thunder', 'Frog', 'Rain', 'Sea', 'Flying', 'Chasing'
  1044. ];
  1045. List<String> userQuestions = [];
  1046. @override
  1047. Widget build(BuildContext context) {
  1048. return Scaffold(
  1049. appBar: commonAppBar(context, 'Dream Interpretation'),
  1050. body: Container(
  1051. decoration: BoxDecoration(
  1052. gradient: LinearGradient(
  1053. begin: Alignment.topCenter,
  1054. end: Alignment.bottomCenter,
  1055. colors: [Colors.blue[100]!, Colors.blue[900]!],
  1056. ),
  1057. ),
  1058. child: Column(
  1059. children: [
  1060. Padding(
  1061. padding: const EdgeInsets.all(16.0),
  1062. child: Text(
  1063. 'Let Zhou Gong interpret your dream',
  1064. style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
  1065. textAlign: TextAlign.center,
  1066. ),
  1067. ),
  1068. // Dream objects wrap
  1069. Padding(
  1070. padding: const EdgeInsets.symmetric(horizontal: 16.0),
  1071. child: Container(
  1072. width: MediaQuery.of(context).size.width * 0.85,
  1073. child: Wrap(
  1074. alignment: WrapAlignment.spaceEvenly,
  1075. spacing: 8.0,
  1076. runSpacing: 8.0,
  1077. children: List.generate((dreamObjects.length / 3).ceil(), (rowIndex) {
  1078. return Row(
  1079. mainAxisAlignment: MainAxisAlignment.center,
  1080. children: List.generate(3, (colIndex) {
  1081. final index = rowIndex * 3 + colIndex;
  1082. if (index >= dreamObjects.length) return SizedBox.shrink();
  1083. return Expanded(
  1084. child: Padding(
  1085. padding: const EdgeInsets.symmetric(horizontal: 4.0),
  1086. child: GestureDetector(
  1087. onTap: () {
  1088. setState(() {
  1089. selectedIndex = index;
  1090. });
  1091. },
  1092. child: Container(
  1093. padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
  1094. decoration: BoxDecoration(
  1095. color: Colors.white,
  1096. borderRadius: BorderRadius.circular(20),
  1097. border: Border.all(
  1098. color: selectedIndex == index ? Colors.blue : Colors.transparent,
  1099. width: 2,
  1100. ),
  1101. ),
  1102. child: Text(
  1103. dreamObjects[index],
  1104. style: TextStyle(
  1105. color: Colors.blue,
  1106. fontWeight: FontWeight.bold,
  1107. ),
  1108. textAlign: TextAlign.center,
  1109. ),
  1110. ),
  1111. ),
  1112. ),
  1113. );
  1114. }),
  1115. );
  1116. }).toList(),
  1117. ),
  1118. ),
  1119. ),
  1120. SizedBox(height: 16),
  1121. // Content frame
  1122. Expanded(
  1123. child: Container(
  1124. margin: EdgeInsets.fromLTRB(16, 0, 16, 16),
  1125. decoration: BoxDecoration(
  1126. color: Colors.white.withOpacity(0.1),
  1127. borderRadius: BorderRadius.circular(20),
  1128. ),
  1129. child: Column(
  1130. children: [
  1131. // Filter buttons for "New" and "Hot"
  1132. Padding(
  1133. padding: const EdgeInsets.all(16.0),
  1134. child: Row(
  1135. mainAxisAlignment: MainAxisAlignment.center,
  1136. children: [
  1137. _buildFilterButton('New'),
  1138. SizedBox(width: 16),
  1139. _buildFilterButton('Hot'),
  1140. ],
  1141. ),
  1142. ),
  1143. // User content
  1144. Expanded(
  1145. child: ListView.builder(
  1146. itemCount: userQuestions.length,
  1147. itemBuilder: (context, index) {
  1148. return Card(
  1149. margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
  1150. child: ListTile(
  1151. title: Text(userQuestions[index]),
  1152. trailing: ElevatedButton(
  1153. onPressed: () {
  1154. Navigator.push(
  1155. context,
  1156. MaterialPageRoute(builder: (context) => DreamResultPage()),
  1157. );
  1158. },
  1159. child: Text('More', style: TextStyle(color: Colors.white)),
  1160. style: ElevatedButton.styleFrom(
  1161. backgroundColor: Colors.blue,
  1162. shape: RoundedRectangleBorder(
  1163. borderRadius: BorderRadius.circular(20),
  1164. ),
  1165. ),
  1166. ),
  1167. ),
  1168. );
  1169. },
  1170. ),
  1171. ),
  1172. ],
  1173. ),
  1174. ),
  1175. ),
  1176. Padding(
  1177. padding: const EdgeInsets.all(16.0),
  1178. child: _buildInputField(),
  1179. ),
  1180. ],
  1181. ),
  1182. ),
  1183. );
  1184. }
  1185. Widget _buildFilterButton(String label) {
  1186. return ElevatedButton(
  1187. onPressed: () {
  1188. setState(() {
  1189. selectedFilter = label;
  1190. });
  1191. },
  1192. style: ElevatedButton.styleFrom(
  1193. backgroundColor: selectedFilter == label ? Colors.blue[700] : Colors.blue[300],
  1194. shape: RoundedRectangleBorder(
  1195. borderRadius: BorderRadius.circular(20),
  1196. ),
  1197. ),
  1198. child: Text(
  1199. label,
  1200. style: TextStyle(
  1201. color: Colors.white,
  1202. fontWeight: FontWeight.bold,
  1203. ),
  1204. ),
  1205. );
  1206. }
  1207. Widget _buildInputField() {
  1208. return TextField(
  1209. onSubmitted: (value) {
  1210. if (value.isNotEmpty) {
  1211. setState(() {
  1212. userQuestions.insert(0, "User: $value");
  1213. });
  1214. Navigator.push(
  1215. context,
  1216. MaterialPageRoute(builder: (context) => DreamResultPage()),
  1217. );
  1218. }
  1219. },
  1220. decoration: InputDecoration(
  1221. hintText: 'Ask Zhou Gong Anything...',
  1222. border: OutlineInputBorder(
  1223. borderRadius: BorderRadius.circular(25),
  1224. ),
  1225. fillColor: Colors.white,
  1226. filled: true,
  1227. suffixIcon: IconButton(
  1228. icon: Icon(Icons.send),
  1229. onPressed: () {
  1230. Navigator.push(
  1231. context,
  1232. MaterialPageRoute(builder: (context) => DreamResultPage()),
  1233. );
  1234. },
  1235. ),
  1236. ),
  1237. );
  1238. }
  1239. }
  1240. class DreamResultPage extends StatelessWidget {
  1241. @override
  1242. Widget build(BuildContext context) {
  1243. final screenHeight = MediaQuery.of(context).size.height;
  1244. final screenWidth = MediaQuery.of(context).size.width;
  1245. return Scaffold(
  1246. appBar: commonAppBar(context, 'Dream Interpretation'),
  1247. body: Container(
  1248. padding: EdgeInsets.all(20),
  1249. child: Column(
  1250. mainAxisAlignment: MainAxisAlignment.center,
  1251. children: [
  1252. Container(
  1253. height: screenHeight * 0.6,
  1254. width: screenWidth * 0.9,
  1255. decoration: BoxDecoration(
  1256. color: Colors.white,
  1257. borderRadius: BorderRadius.circular(20),
  1258. boxShadow: [
  1259. BoxShadow(
  1260. color: Colors.grey.withOpacity(0.5),
  1261. spreadRadius: 5,
  1262. blurRadius: 7,
  1263. offset: Offset(0, 3),
  1264. ),
  1265. ],
  1266. ),
  1267. padding: EdgeInsets.all(20),
  1268. child: SingleChildScrollView(
  1269. child: Text(
  1270. 'Your dream interpretation result will be displayed here...',
  1271. style: TextStyle(fontSize: 18),
  1272. textAlign: TextAlign.center,
  1273. ),
  1274. ),
  1275. ),
  1276. SizedBox(height: 30),
  1277. ElevatedButton(
  1278. onPressed: () {
  1279. // 这里添加更多详情的逻辑
  1280. },
  1281. child: Text(
  1282. 'More Details',
  1283. style: TextStyle(fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold),
  1284. ),
  1285. style: ElevatedButton.styleFrom(
  1286. backgroundColor: Colors.black,
  1287. padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
  1288. shape: RoundedRectangleBorder(
  1289. borderRadius: BorderRadius.circular(30),
  1290. ),
  1291. ),
  1292. ),
  1293. ],
  1294. ),
  1295. ),
  1296. );
  1297. }
  1298. }