Flutter - Smooth switching between chat keyboard and panel
Overview
I believe everyone will encounter this problem when you make a chat app, that is, how to implement smooth switching between the keyboard and other panels on the chat page. This problem has also been raised by issue
, such as
It can be seen that when switching from the emoji panel to the keyboard, it will jitter, which affects the user experience.
But several years have passed and it still hasn’t been solved. In addition, I also have this little trouble, so I developed this chat_bottom_container
together with GitLqr (GitHub: github.com/GitLqr) to help us implement this smooth switching effect quickly.
Effect
Let’s take a look at the effect first, so that everyone can feel it intuitively~
OK, let’s take a look at how to use it.
Integration
Add chat_bottom_container
to your pubspec.yaml
file.
dependencies:
chat_bottom_container: latest_version
Please copy the latest version on pub.dev
, the link is: https://pub.dev/packages/chat_bottom_container
The Android
side needs to add the jitpack
to the root build.gradle
file of your project at the end of repositories.
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Import chat_bottom_container
where needed:
import 'package:chat_bottom_container/chat_bottom_container.dart';
Use
Page Layout
The first thing you need to do is determine the overall page layout.
@override
Widget build(BuildContext context) {
return Scaffold(
// Set to false
resizeToAvoidBottomInset: false,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: ListView.builder(
...
),
),
// Input box view
_buildInputView(),
// Bottom panel container
_buildPanelContainer(),
],
),
);
}
Here are two points to note:
- Place the bottom container at the bottom.
- The
resizeToAvoidBottomInset
must be set tofalse
.
Bottom container
There are various styles of input box view, so I won’t go into them here. You can implement them however you like. Next, let’s take a look at how to use the chat_bottom_container
package to implement the bottom container. The code is as follows:
/// Custom bottom panel type
enum PanelType {
none,
keyboard,
emoji,
tool,
}
/// The controller of chat_bottom_container, it is used to inform
/// chat_bottom_container that the panel type needs to be switched.
/// Note: The generic PanelType is passed here to associate with the external
/// panel type.
final controller = ChatBottomPanelContainerController<PanelType>();
/// The focus object of the input box.
final FocusNode inputFocusNode = FocusNode();
/// Record the current bottom panel type.
PanelType currentPanelType = PanelType.none;
Widget _buildPanelContainer() {
return ChatBottomPanelContainer<PanelType>(
controller: controller,
inputFocusNode: inputFocusNode,
otherPanelWidget: (type) {
// Return the customized panel view.
if (type == null) return const SizedBox.shrink();
switch (type) {
case PanelType.emoji: // emoji panel
return _buildEmojiPickerPanel();
case PanelType.tool: // tools panel
return _buildToolPanel();
default:
return const SizedBox.shrink();
}
},
onPanelTypeChange: (panelType, data) {
// This callback can be used to record the current panel type
// (this operation is not necessary~)
// panelType: There are three types of panels defined in
// chat_bottom_container(.none|.keyboard|.other).
// data: External custom bottom panel type.
switch (panelType) {
case ChatBottomPanelType.none:
currentPanelType = PanelType.none;
break;
case ChatBottomPanelType.keyboard:
currentPanelType = PanelType.keyboard;
break;
case ChatBottomPanelType.other:
if (data == null) return;
switch (data) {
case PanelType.emoji:
currentPanelType = PanelType.emoji;
break;
case PanelType.tool:
currentPanelType = PanelType.tool;
break;
default:
currentPanelType = PanelType.none;
break;
}
break;
}
},
// Bottom panel container background color.
panelBgColor: panelBgColor,
);
}
There are only three internally defined panel types.
enum ChatBottomPanelType {
none,
keyboard,
other,
}
Because chat_bottom_container
doesn't care how many external panel types you have besides the keyboard, it is uniformly regarded as ChatBottomPanelType.other
here.
It is impossible for us business developers not to care, so when we click the emoji panel button, we call controller.updatePanelType
to switch the bottom panel type, and pass in the external customized PanelType for the parameter data
, as shown in the following code.
controller.updatePanelType(
// Set the current bottom panel type of ChatBottomPanelContainer.
// Can be passed to ChatBottomPanelType.keyboard | ChatBottomPanelType.other | ChatBottomPanelType.none
ChatBottomPanelType.other,
// Callback will include the PanelType customized by external developers,
// this parameter must be passed when ChatBottomPanelType.other.
data: PanelType.emoji, // PanelType.tool
);
So the generics mentioned above are to associate the type of parameter data in the otherPanelWidget
and onPanelTypeChange
callbacks for our convenience.
Finally
Okay, the above are the core usage steps of this package. I have published the chat_bottom_container
package to GitHub
: https://github.com/LinXunFeng/flutter_chat_packages/tree/main/packages/chat_bottom_container.
Open source is not easy. If you also think this package is useful, please give it a Star
👍 .