Skip to content

Commit c4b0e23

Browse files
committed
Merge branch 'feature/chat_bottom_container_dev' into develop
2 parents 32d7393 + 77af072 commit c4b0e23

12 files changed

+629
-190
lines changed

packages/chat_bottom_container/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 0.1.0
2+
3+
* Adjust keyboard height listener manager logic.
4+
* Add `safeAreaBottom` and `changeKeyboardPanelHeight`.
5+
* Adjust the logic about obtaining the bottom height of the safe area.
6+
* Adjust the constraints of the SDK (sdk: ">=3.0.0 <4.0.0").
7+
* Fix version of `FSAChatBottomContainer.xcframework`.
8+
19
## 0.0.2
210

311
* Adjust the way to download framework.

packages/chat_bottom_container/README-zh.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,51 @@ controller.updatePanelType(
153153
);
154154
```
155155

156+
---
157+
158+
<details>
159+
<summary>下面再提供一些额外的功能与说明</summary>
160+
161+
### 隐藏面板
162+
163+
```dart
164+
hidePanel() {
165+
inputFocusNode.unfocus();
166+
if (ChatBottomPanelType.none == controller.currentPanelType) return;
167+
controller.updatePanelType(ChatBottomPanelType.none);
168+
}
169+
```
170+
171+
### 自定义底部安全区高度
172+
173+
在默认情况下,`chat_bottom_container` 会自动帮你添加底部安全区高度,但在一些场景下你可能不希望如此,那你可以通过将 `safeAreaBottom` 设置为 `0` 来自定义这个高度。
174+
175+
```dart
176+
return ChatBottomPanelContainer<PanelType>(
177+
...
178+
safeAreaBottom: 0,
179+
...
180+
);
181+
```
182+
183+
### 调整键盘面板高度
184+
185+
如示例中位于首页的聊天页面,需要减去外层底部固定的 `BottomNavigationBar` 高度
186+
187+
```dart
188+
return ChatBottomPanelContainer<PanelType>(
189+
...
190+
changeKeyboardPanelHeight: (keyboardHeight) {
191+
final renderObj = bottomNavigationBarKey.currentContext?.findRenderObject();
192+
if (renderObj is! RenderBox) return keyboardHeight;
193+
return keyboardHeight - renderObj.size.height;
194+
},
195+
...
196+
);
197+
```
198+
199+
</details>
200+
156201
## 🖨 关于我
157202

158203
- GitHub: [https://github.com/LinXunFeng](https://github.com/LinXunFeng)

packages/chat_bottom_container/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,51 @@ controller.updatePanelType(
155155
);
156156
```
157157

158+
---
159+
160+
<details>
161+
<summary>Here are some additional features and instructions</summary>
162+
163+
### Hide Panel
164+
165+
```dart
166+
hidePanel() {
167+
inputFocusNode.unfocus();
168+
if (ChatBottomPanelType.none == controller.currentPanelType) return;
169+
controller.updatePanelType(ChatBottomPanelType.none);
170+
}
171+
```
172+
173+
### Customize bottom safe area height
174+
175+
By default, `chat_bottom_container` will automatically add the bottom safe area height for you, but in some scenarios you may not want this, you can customize this height by setting `safeAreaBottom` to `0`.
176+
177+
```dart
178+
return ChatBottomPanelContainer<PanelType>(
179+
...
180+
safeAreaBottom: 0,
181+
...
182+
);
183+
```
184+
185+
### Adjust the keyboard panel height
186+
187+
For example, in the chat page on the home page, the height of the fixed `BottomNavigationBar` at the bottom of the outer layer needs to be subtracted.
188+
189+
```dart
190+
return ChatBottomPanelContainer<PanelType>(
191+
...
192+
changeKeyboardPanelHeight: (keyboardHeight) {
193+
final renderObj = bottomNavigationBarKey.currentContext?.findRenderObject();
194+
if (renderObj is! RenderBox) return keyboardHeight;
195+
return keyboardHeight - renderObj.size.height;
196+
},
197+
...
198+
);
199+
```
200+
201+
</details>
202+
158203
## 🖨 About Me
159204

160205
- GitHub: [https://github.com/LinXunFeng](https://github.com/LinXunFeng)

packages/chat_bottom_container/example/ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ EXTERNAL SOURCES:
1919
:path: ".symlinks/plugins/integration_test/ios"
2020

2121
SPEC CHECKSUMS:
22-
chat_bottom_container: 78144ab7711d932c482e6991cb4a6748a1671c83
22+
chat_bottom_container: d8b077152c91b0ab90001e900748ea50353a5520
2323
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
2424
integration_test: 13825b8a9334a850581300559b8839134b124670
2525

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*
2+
* @Author: LinXunFeng [email protected]
3+
* @Repo: https://github.com/LinXunFeng/flutter_chat_packages
4+
* @Date: 2024-06-29 11:55:20
5+
*/
6+
7+
import 'package:chat_bottom_container/panel_container.dart';
8+
import 'package:chat_bottom_container_example/main.dart';
9+
import 'package:flutter/material.dart';
10+
11+
enum PanelType {
12+
none,
13+
keyboard,
14+
emoji,
15+
tool,
16+
}
17+
18+
class ChatPage extends StatefulWidget {
19+
const ChatPage({
20+
super.key,
21+
this.safeAreaBottom,
22+
this.showAppBar = true,
23+
this.changeKeyboardPanelHeight,
24+
});
25+
26+
final double? safeAreaBottom;
27+
28+
final bool showAppBar;
29+
30+
final ChatKeyboardChangeKeyboardPanelHeight? changeKeyboardPanelHeight;
31+
32+
@override
33+
State<ChatPage> createState() => _ChatPageState();
34+
}
35+
36+
class _ChatPageState extends State<ChatPage> with RouteAware {
37+
Color panelBgColor = const Color(0xFFF5F5F5);
38+
39+
final FocusNode inputFocusNode = FocusNode();
40+
41+
final controller = ChatBottomPanelContainerController<PanelType>();
42+
43+
PanelType currentPanelType = PanelType.none;
44+
45+
@override
46+
void didChangeDependencies() {
47+
super.didChangeDependencies();
48+
App.routeObserver.subscribe(this, ModalRoute.of(context)!);
49+
}
50+
51+
@override
52+
void dispose() {
53+
inputFocusNode.dispose();
54+
App.routeObserver.unsubscribe(this);
55+
super.dispose();
56+
}
57+
58+
@override
59+
void didPushNext() {
60+
super.didPushNext();
61+
hidePanel();
62+
}
63+
64+
@override
65+
Widget build(BuildContext context) {
66+
return Scaffold(
67+
resizeToAvoidBottomInset: false,
68+
appBar: widget.showAppBar
69+
? AppBar(
70+
title: const Text('Chat Page'),
71+
)
72+
: null,
73+
body: Column(
74+
mainAxisAlignment: MainAxisAlignment.center,
75+
children: [
76+
Expanded(child: _buildList()),
77+
_buildInputView(),
78+
_buildPanelContainer(),
79+
],
80+
),
81+
);
82+
}
83+
84+
Widget _buildList() {
85+
Widget resultWidget = ListView.builder(
86+
padding: EdgeInsets.zero,
87+
reverse: true,
88+
itemBuilder: (context, index) {
89+
return ListTile(
90+
title: Text('Item $index'),
91+
);
92+
},
93+
);
94+
resultWidget = Listener(
95+
child: resultWidget,
96+
onPointerDown: (event) {
97+
// Hide panel when touch ListView.
98+
hidePanel();
99+
},
100+
);
101+
return resultWidget;
102+
}
103+
104+
Widget _buildPanelContainer() {
105+
return ChatBottomPanelContainer<PanelType>(
106+
controller: controller,
107+
inputFocusNode: inputFocusNode,
108+
otherPanelWidget: (type) {
109+
if (type == null) return const SizedBox.shrink();
110+
switch (type) {
111+
case PanelType.emoji:
112+
return _buildEmojiPickerPanel();
113+
case PanelType.tool:
114+
return _buildToolPanel();
115+
default:
116+
return const SizedBox.shrink();
117+
}
118+
},
119+
onPanelTypeChange: (panelType, data) {
120+
switch (panelType) {
121+
case ChatBottomPanelType.none:
122+
currentPanelType = PanelType.none;
123+
break;
124+
case ChatBottomPanelType.keyboard:
125+
currentPanelType = PanelType.keyboard;
126+
break;
127+
case ChatBottomPanelType.other:
128+
if (data == null) return;
129+
switch (data) {
130+
case PanelType.emoji:
131+
currentPanelType = PanelType.emoji;
132+
break;
133+
case PanelType.tool:
134+
currentPanelType = PanelType.tool;
135+
break;
136+
default:
137+
currentPanelType = PanelType.none;
138+
break;
139+
}
140+
break;
141+
}
142+
},
143+
changeKeyboardPanelHeight: widget.changeKeyboardPanelHeight,
144+
panelBgColor: panelBgColor,
145+
safeAreaBottom: widget.safeAreaBottom,
146+
);
147+
}
148+
149+
Widget _buildToolPanel() {
150+
return Container(
151+
height: 450,
152+
color: Colors.red[50],
153+
child: const Center(
154+
child: Text('Tool Panel'),
155+
),
156+
);
157+
}
158+
159+
Widget _buildEmojiPickerPanel() {
160+
return Container(
161+
padding: EdgeInsets.zero,
162+
height: 300,
163+
color: Colors.blue[50],
164+
child: const Center(
165+
child: Text('Emoji Panel'),
166+
),
167+
);
168+
}
169+
170+
Widget _buildInputView() {
171+
return Container(
172+
height: 50,
173+
color: Colors.white,
174+
child: Row(
175+
children: [
176+
const SizedBox(width: 15),
177+
Expanded(
178+
child: TextField(
179+
focusNode: inputFocusNode,
180+
),
181+
),
182+
GestureDetector(
183+
child: const Icon(Icons.emoji_emotions_outlined, size: 30),
184+
onTap: () {
185+
updatePanelType(PanelType.emoji);
186+
},
187+
),
188+
GestureDetector(
189+
child: const Icon(Icons.add, size: 30),
190+
onTap: () {
191+
updatePanelType(PanelType.tool);
192+
},
193+
),
194+
const SizedBox(width: 15),
195+
],
196+
),
197+
);
198+
}
199+
200+
updatePanelType(PanelType type) {
201+
controller.updatePanelType(
202+
type == currentPanelType
203+
? ChatBottomPanelType.keyboard
204+
: ChatBottomPanelType.other,
205+
data: type,
206+
);
207+
}
208+
209+
hidePanel() {
210+
if (inputFocusNode.hasFocus) {
211+
inputFocusNode.unfocus();
212+
}
213+
if (ChatBottomPanelType.none == controller.currentPanelType) return;
214+
controller.updatePanelType(ChatBottomPanelType.none);
215+
}
216+
}

0 commit comments

Comments
 (0)