Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

166 linhas
4.9 KiB

  1. import 'package:flutter/material.dart';
  2. import 'dart:async';
  3. class ChatScene extends StatefulWidget {
  4. @override
  5. _ChatSceneState createState() => _ChatSceneState();
  6. }
  7. class _ChatSceneState extends State<ChatScene> {
  8. bool _isInCall = false; // 记录是否在通话状态
  9. // 模拟的聊天消息数据,包括语音消息和文字消息
  10. final List<Map<String, dynamic>> _messages = [
  11. {
  12. 'type': 'audio',
  13. 'audioDuration': 5, // 音频时长 5秒
  14. 'audioUrl':
  15. 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3',
  16. 'text': '你好,我是一个语音消息'
  17. },
  18. {'type': 'text', 'text': '这是一个文本消息'},
  19. {
  20. 'type': 'audio',
  21. 'audioDuration': 8, // 音频时长 8秒
  22. 'audioUrl':
  23. 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3',
  24. 'text': '这是另一条语音消息'
  25. }
  26. ];
  27. // 切换按钮状态
  28. void _toggleCallStatus() {
  29. setState(() {
  30. _isInCall = !_isInCall;
  31. });
  32. }
  33. @override
  34. Widget build(BuildContext context) {
  35. return Scaffold(
  36. appBar: AppBar(title: Text("Chat Scene")),
  37. body: ListView.builder(
  38. itemCount: _messages.length,
  39. itemBuilder: (context, index) {
  40. var message = _messages[index];
  41. if (message['type'] == 'audio') {
  42. // 语音消息
  43. return _buildAudioMessage(message);
  44. } else {
  45. // 文本消息
  46. return _buildTextMessage(message);
  47. }
  48. },
  49. ),
  50. bottomNavigationBar: Padding(
  51. padding: const EdgeInsets.all(20.0),
  52. child: InkWell(
  53. onTap: _toggleCallStatus, // 点击按钮时切换状态
  54. onLongPress: () {
  55. // 按住时切换为通话状态
  56. _toggleCallStatus();
  57. },
  58. child: Container(
  59. decoration: BoxDecoration(
  60. borderRadius: BorderRadius.circular(30), // 圆角按钮
  61. color: _isInCall ? Colors.red : Colors.green, // 通话状态红色,非通话状态绿色
  62. ),
  63. padding:
  64. EdgeInsets.symmetric(vertical: 15, horizontal: 40), // 调整按钮大小
  65. child: Row(
  66. mainAxisAlignment: MainAxisAlignment.center,
  67. children: [
  68. Icon(
  69. _isInCall ? Icons.call_end : Icons.mic, // 图标变化
  70. color: Colors.white,
  71. size: 30,
  72. ),
  73. SizedBox(width: 10),
  74. Text(
  75. _isInCall ? '挂断' : '开始通话', // 状态文字变化
  76. style: TextStyle(
  77. color: Colors.white,
  78. fontSize: 18,
  79. ),
  80. ),
  81. ],
  82. ),
  83. ),
  84. ),
  85. ),
  86. );
  87. }
  88. // 构建文本消息
  89. Widget _buildTextMessage(Map<String, dynamic> message) {
  90. return Padding(
  91. padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
  92. child: Align(
  93. alignment: Alignment.centerLeft,
  94. child: Container(
  95. padding: EdgeInsets.all(10),
  96. decoration: BoxDecoration(
  97. color: Colors.blue[100],
  98. borderRadius: BorderRadius.circular(10),
  99. ),
  100. child: Text(
  101. message['text'],
  102. style: TextStyle(fontSize: 16),
  103. ),
  104. ),
  105. ),
  106. );
  107. }
  108. // 构建语音消息
  109. Widget _buildAudioMessage(Map<String, dynamic> message) {
  110. return Padding(
  111. padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
  112. child: Column(
  113. crossAxisAlignment: CrossAxisAlignment.start,
  114. children: [
  115. // 音频时长显示
  116. Text(
  117. '${message['audioDuration']}秒',
  118. style: TextStyle(fontSize: 14, color: Colors.grey),
  119. ),
  120. SizedBox(height: 5),
  121. // 音频播放按钮
  122. GestureDetector(
  123. onTap: () {
  124. // 这里可以实现点击播放音频的功能
  125. print("播放音频: ${message['audioUrl']}");
  126. },
  127. child: Container(
  128. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
  129. decoration: BoxDecoration(
  130. color: Colors.green,
  131. borderRadius: BorderRadius.circular(30),
  132. ),
  133. child: Row(
  134. children: [
  135. Icon(
  136. Icons.play_arrow,
  137. color: Colors.white,
  138. ),
  139. SizedBox(width: 10),
  140. Text(
  141. '播放音频',
  142. style: TextStyle(color: Colors.white),
  143. ),
  144. ],
  145. ),
  146. ),
  147. ),
  148. SizedBox(height: 5),
  149. // 文字内容
  150. Text(
  151. message['text'],
  152. style: TextStyle(fontSize: 16),
  153. ),
  154. ],
  155. ),
  156. );
  157. }
  158. }