After Width: | Height: | Size: 706 B |
After Width: | Height: | Size: 622 B |
After Width: | Height: | Size: 894 B |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 844 B |
After Width: | Height: | Size: 512 B |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 370 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 271 B |
After Width: | Height: | Size: 487 B |
After Width: | Height: | Size: 827 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 706 B |
After Width: | Height: | Size: 622 B |
After Width: | Height: | Size: 894 B |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 844 B |
After Width: | Height: | Size: 512 B |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 370 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 271 B |
After Width: | Height: | Size: 487 B |
After Width: | Height: | Size: 827 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 706 B |
After Width: | Height: | Size: 622 B |
After Width: | Height: | Size: 894 B |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 844 B |
After Width: | Height: | Size: 512 B |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 370 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 271 B |
After Width: | Height: | Size: 487 B |
After Width: | Height: | Size: 827 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,198 @@
|
|||||||
|
// import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
|
||||||
|
// import 'package:emoji_picker_flutter/src/category_emoji.dart';
|
||||||
|
// import 'package:emoji_picker_flutter/src/config.dart';
|
||||||
|
// import 'package:emoji_picker_flutter/src/emoji_picker_builder.dart';
|
||||||
|
// import 'package:emoji_picker_flutter/src/emoji_view_state.dart';
|
||||||
|
import 'package:bytedesk_kefu/vendors/emoji_picker_flutter/emoji_picker_flutter.dart';
|
||||||
|
import 'package:bytedesk_kefu/vendors/emoji_picker_flutter/src/category_emoji.dart';
|
||||||
|
// import 'package:bytedesk_kefu/vendors/emoji_picker_flutter/src/config.dart';
|
||||||
|
// import 'package:bytedesk_kefu/vendors/emoji_picker_flutter/src/emoji_picker_builder.dart';
|
||||||
|
// import 'package:bytedesk_kefu/vendors/emoji_picker_flutter/src/emoji_view_state.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// EmojiPicker Implementation
|
||||||
|
class EmojiPickerView extends EmojiPickerBuilder {
|
||||||
|
/// Constructor
|
||||||
|
EmojiPickerView(
|
||||||
|
Config config,
|
||||||
|
EmojiViewState state,
|
||||||
|
this.handleSendPressed,
|
||||||
|
) : super(config, state);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EmojiPickerViewState createState() => _EmojiPickerViewState();
|
||||||
|
|
||||||
|
/// See [AttachmentButton.onPressed]
|
||||||
|
final void Function()? handleSendPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmojiPickerViewState extends State<EmojiPickerView>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
PageController? _pageController;
|
||||||
|
TabController? _tabController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
var initCategory = widget.state.categoryEmoji.indexWhere(
|
||||||
|
(element) => element.category == widget.config.initCategory);
|
||||||
|
if (initCategory == -1) {
|
||||||
|
initCategory = 0;
|
||||||
|
}
|
||||||
|
_tabController = TabController(
|
||||||
|
initialIndex: initCategory,
|
||||||
|
length: widget.state.categoryEmoji.length,
|
||||||
|
vsync: this);
|
||||||
|
_pageController = PageController(initialPage: initCategory);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final emojiSize = widget.config.getEmojiSize(constraints.maxWidth);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
color: Color.fromRGBO(251, 251, 251, 1.0), //widget.config.bgColor,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TabBar(
|
||||||
|
labelColor: widget.config.iconColorSelected,
|
||||||
|
indicatorColor: widget.config.indicatorColor,
|
||||||
|
unselectedLabelColor: widget.config.iconColor,
|
||||||
|
controller: _tabController,
|
||||||
|
labelPadding: EdgeInsets.zero,
|
||||||
|
onTap: (index) {
|
||||||
|
_pageController!.jumpToPage(index);
|
||||||
|
},
|
||||||
|
tabs: widget.state.categoryEmoji
|
||||||
|
.asMap()
|
||||||
|
.entries
|
||||||
|
.map<Widget>((item) =>
|
||||||
|
_buildCategory(item.key, item.value.category))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
padding: const EdgeInsets.only(bottom: 2),
|
||||||
|
icon: Icon(
|
||||||
|
Icons.backspace,
|
||||||
|
color: widget.config.backspaceColor,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
widget.state.onBackspacePressed!();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
// IconButton(
|
||||||
|
// // iconSize: 16,
|
||||||
|
// onPressed: () {
|
||||||
|
// widget.handleSendPressed!();
|
||||||
|
// },
|
||||||
|
// // backgroundColor: Colors.lightGreen,
|
||||||
|
// icon: Icon(Icons.send),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: PageView.builder(
|
||||||
|
itemCount: widget.state.categoryEmoji.length,
|
||||||
|
controller: _pageController,
|
||||||
|
onPageChanged: (index) {
|
||||||
|
_tabController!.animateTo(
|
||||||
|
index,
|
||||||
|
duration: widget.config.tabIndicatorAnimDuration,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemBuilder: (context, index) =>
|
||||||
|
_buildPage(emojiSize, widget.state.categoryEmoji[index]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCategory(int index, Category category) {
|
||||||
|
return Tab(
|
||||||
|
icon: Icon(
|
||||||
|
widget.config.getIconForCategory(category),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildButtonWidget(
|
||||||
|
{required VoidCallback onPressed, required Widget child}) {
|
||||||
|
if (widget.config.buttonMode == ButtonMode.MATERIAL) {
|
||||||
|
return TextButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: child,
|
||||||
|
style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.zero)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero, onPressed: onPressed, child: child);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPage(double emojiSize, CategoryEmoji categoryEmoji) {
|
||||||
|
// Display notice if recent has no entries yet
|
||||||
|
if (categoryEmoji.category == Category.RECENT &&
|
||||||
|
categoryEmoji.emoji.isEmpty) {
|
||||||
|
return _buildNoRecent();
|
||||||
|
}
|
||||||
|
// Build page normally
|
||||||
|
return GridView.count(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
physics: const ScrollPhysics(),
|
||||||
|
shrinkWrap: true,
|
||||||
|
primary: true,
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
crossAxisCount: widget.config.columns,
|
||||||
|
mainAxisSpacing: widget.config.verticalSpacing,
|
||||||
|
crossAxisSpacing: widget.config.horizontalSpacing,
|
||||||
|
children: categoryEmoji.emoji
|
||||||
|
.map<Widget>((item) => _buildEmoji(emojiSize, categoryEmoji, item))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildEmoji(
|
||||||
|
double emojiSize,
|
||||||
|
CategoryEmoji categoryEmoji,
|
||||||
|
Emoji emoji,
|
||||||
|
) {
|
||||||
|
return _buildButtonWidget(
|
||||||
|
onPressed: () {
|
||||||
|
widget.state.onEmojiSelected(categoryEmoji.category, emoji);
|
||||||
|
},
|
||||||
|
child: FittedBox(
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
child: Text(
|
||||||
|
emoji.emoji,
|
||||||
|
textScaleFactor: 1.0,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: emojiSize,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildNoRecent() {
|
||||||
|
return Center(
|
||||||
|
child: Text( '无最近使用表情',
|
||||||
|
// widget.config.noRecentsText,
|
||||||
|
// style: widget.config.noRecentsStyle,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,297 @@
|
|||||||
|
import 'package:carousel_slider/carousel_slider.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
// import 'package:flutter/widgets.dart';
|
||||||
|
// import 'package:get/get.dart';
|
||||||
|
// import 'package:get/get_utils/src/extensions/internacionalization.dart';
|
||||||
|
// import 'package:imboy/config/const.dart';
|
||||||
|
|
||||||
|
class ExtraItem extends StatelessWidget {
|
||||||
|
const ExtraItem({
|
||||||
|
Key? key,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.image,
|
||||||
|
double? this.width,
|
||||||
|
double? this.height,
|
||||||
|
required this.title,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final ImageProvider image;
|
||||||
|
final void Function()? onPressed;
|
||||||
|
final double? width;
|
||||||
|
final double? height;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: this.onPressed ?? () => {
|
||||||
|
print('功能暂未实现')
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 15, top: 13, right: 15, bottom: 0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: this.width ?? 56,
|
||||||
|
height: this.height ?? 56,
|
||||||
|
// margin: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Material(
|
||||||
|
color: AppColors.ChatInputBackgroundColor,
|
||||||
|
// INK可以实现装饰容器
|
||||||
|
child: new Ink(
|
||||||
|
// 用ink圆角矩形
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
// 背景
|
||||||
|
color: AppColors.ChatInputBackgroundColor,
|
||||||
|
// 设置四周圆角 角度
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(16.0)),
|
||||||
|
// 设置四周边框
|
||||||
|
border: Border.all(
|
||||||
|
width: 1,
|
||||||
|
color: AppColors.ChatInputBackgroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Image(
|
||||||
|
image: this.image,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(this.title),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExtraItems extends StatefulWidget {
|
||||||
|
const ExtraItems({
|
||||||
|
Key? key,
|
||||||
|
this.handleImageSelection,
|
||||||
|
this.handleFileSelection,
|
||||||
|
this.handlePickerSelection,
|
||||||
|
this.handleUploadVideo,
|
||||||
|
this.handleCaptureVideo,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final void Function()? handleImageSelection;
|
||||||
|
final void Function()? handleFileSelection;
|
||||||
|
final void Function()? handlePickerSelection;
|
||||||
|
final void Function()? handleUploadVideo;
|
||||||
|
final void Function()? handleCaptureVideo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ExtraItemsState createState() => _ExtraItemsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExtraItemsState extends State<ExtraItems> {
|
||||||
|
int _current = 0;
|
||||||
|
CarouselController _controller = CarouselController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var items = [
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ExtraItem(
|
||||||
|
title: "照片",
|
||||||
|
image: AssetImage('assets/images/chat/extra_photo.webp'),
|
||||||
|
onPressed: widget.handleImageSelection,
|
||||||
|
),
|
||||||
|
ExtraItem(
|
||||||
|
title: "拍摄",
|
||||||
|
image: AssetImage('assets/images/chat/extra_camera.webp'),
|
||||||
|
onPressed: widget.handlePickerSelection,
|
||||||
|
),
|
||||||
|
ExtraItem(
|
||||||
|
title: "上传视频",
|
||||||
|
image: AssetImage('assets/images/chat/extra_media.webp'),
|
||||||
|
onPressed: widget.handleUploadVideo,
|
||||||
|
),
|
||||||
|
ExtraItem(
|
||||||
|
title: "录制视频",
|
||||||
|
image: AssetImage('assets/images/chat/extra_videocall.webp'),
|
||||||
|
onPressed: widget.handleCaptureVideo,
|
||||||
|
),
|
||||||
|
// ExtraItem(
|
||||||
|
// title: "位置",
|
||||||
|
// image: AssetImage('assets/images/chat/extra_localtion.webp'),
|
||||||
|
// onPressed: null,
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
// TODO: 选择文件
|
||||||
|
// ExtraItem(
|
||||||
|
// title: "文件",
|
||||||
|
// image: AssetImage('assets/images/chat/extra_file.webp'),
|
||||||
|
// onPressed: widget.handleFileSelection,
|
||||||
|
// ),
|
||||||
|
// ExtraItem(
|
||||||
|
// title: "语音输入",
|
||||||
|
// image: AssetImage('assets/images/chat/extra_voice.webp'),
|
||||||
|
// onPressed: null,
|
||||||
|
// ),
|
||||||
|
// ExtraItem(
|
||||||
|
// title: "收藏",
|
||||||
|
// image: AssetImage('assets/images/chat/extra_favorite.webp'),
|
||||||
|
// onPressed: null,
|
||||||
|
// ),
|
||||||
|
// ExtraItem(
|
||||||
|
// title: "个人名片",
|
||||||
|
// image: AssetImage('assets/images/chat/extra_card.webp'),
|
||||||
|
// onPressed: null,
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// Column(
|
||||||
|
// children: <Widget>[
|
||||||
|
// Row(children: [
|
||||||
|
// ExtraItem(
|
||||||
|
// title: "文件",
|
||||||
|
// image: AssetImage('assets/images/chat/extra_file.webp'),
|
||||||
|
// onPressed: widget.handleFileSelection,
|
||||||
|
// ),
|
||||||
|
// ExtraItem(
|
||||||
|
// title: "卡券",
|
||||||
|
// image: AssetImage('assets/images/chat/extra_wallet.png'),
|
||||||
|
// onPressed: null,
|
||||||
|
// ),
|
||||||
|
// ]),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
];
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: CarouselSlider(
|
||||||
|
options: CarouselOptions(
|
||||||
|
height: 50, // Get.height,
|
||||||
|
viewportFraction: 1.0,
|
||||||
|
aspectRatio: 2.0,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
disableCenter: true,
|
||||||
|
initialPage: 1,
|
||||||
|
enableInfiniteScroll: false,
|
||||||
|
onPageChanged: (index, reason) {
|
||||||
|
setState(() {
|
||||||
|
_current = index;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
items: items.map((tab) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(left: 8),
|
||||||
|
child: tab,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: items.asMap().entries.map((entry) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => _controller.animateToPage(entry.key),
|
||||||
|
child: Container(
|
||||||
|
width: 10.0,
|
||||||
|
height: 10.0,
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0,
|
||||||
|
horizontal: 6.0,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: (Theme.of(context).brightness == Brightness.dark
|
||||||
|
? Colors.white
|
||||||
|
: Colors.black)
|
||||||
|
.withOpacity(_current == entry.key ? 0.7 : 0.2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppColors {
|
||||||
|
static const AppBarColor = Color.fromRGBO(237, 237, 237, 1);
|
||||||
|
|
||||||
|
static const BgColor = Color.fromRGBO(255, 255, 255, 1);
|
||||||
|
|
||||||
|
static const LineColor = Colors.grey;
|
||||||
|
|
||||||
|
static const TipColor = Color.fromRGBO(89, 96, 115, 1.0);
|
||||||
|
|
||||||
|
static const MainTextColor = Color.fromRGBO(115, 115, 115, 1.0);
|
||||||
|
|
||||||
|
static const LabelTextColor = Color.fromRGBO(144, 144, 144, 1.0);
|
||||||
|
|
||||||
|
static const ItemBgColor = Color.fromRGBO(75, 75, 75, 1.0);
|
||||||
|
|
||||||
|
static const ItemOnColor = Color.fromRGBO(68, 68, 68, 1.0);
|
||||||
|
|
||||||
|
static const ButtonTextColor = Color.fromRGBO(112, 113, 135, 1.0);
|
||||||
|
|
||||||
|
static const TitleColor = 0xff181818;
|
||||||
|
static const ButtonArrowColor = 0xffadadad;
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// 主背景 白色
|
||||||
|
static const Color primaryBackground = Color.fromARGB(255, 255, 255, 255);
|
||||||
|
|
||||||
|
/// 主文本 灰色
|
||||||
|
static const Color primaryText = Color.fromARGB(255, 45, 45, 47);
|
||||||
|
|
||||||
|
/// 主控件-背景 绿色
|
||||||
|
static const Color primaryElement = Color.fromARGB(255, 109, 192, 102);
|
||||||
|
|
||||||
|
/// 主控件-文本 白色
|
||||||
|
static const Color primaryElementText = Color.fromARGB(255, 255, 255, 255);
|
||||||
|
|
||||||
|
// *****************************************
|
||||||
|
|
||||||
|
/// 第二种控件-背景色 淡灰色
|
||||||
|
static const Color secondaryElement = Color.fromARGB(255, 246, 246, 246);
|
||||||
|
|
||||||
|
/// 第二种控件-文本 浅绿色
|
||||||
|
static const Color secondaryElementText = Color.fromRGBO(169, 234, 122, 1.0);
|
||||||
|
|
||||||
|
// *****************************************
|
||||||
|
|
||||||
|
/// 第三种控件-背景色 石墨色
|
||||||
|
static const Color thirdElement = Color.fromARGB(255, 45, 45, 47);
|
||||||
|
|
||||||
|
/// 第三种控件-文本 浅灰色2
|
||||||
|
static const Color thirdElementText = Color.fromARGB(255, 141, 141, 142);
|
||||||
|
|
||||||
|
// *****************************************
|
||||||
|
|
||||||
|
/// tabBar 默认颜色 灰色
|
||||||
|
static const Color tabBarElement = Color.fromARGB(255, 208, 208, 208);
|
||||||
|
|
||||||
|
/// tabCellSeparator 单元格底部分隔条 颜色
|
||||||
|
static const Color tabCellSeparator = Color.fromARGB(255, 230, 230, 231);
|
||||||
|
|
||||||
|
// for chat
|
||||||
|
static const ChatBg = Color.fromRGBO(243, 243, 243, 1.0);
|
||||||
|
static const ChatSendMessgeBgColor = Color.fromRGBO(169, 234, 122, 1.0);
|
||||||
|
static const ChatSentMessageBodyTextColor = Color.fromRGBO(19, 29, 13, 1.0);
|
||||||
|
|
||||||
|
static const ChatReceivedMessageBodyTextColor =
|
||||||
|
Color.fromRGBO(25, 25, 25, 1.0);
|
||||||
|
static const ChatReceivedMessageBodyBgColor =
|
||||||
|
Color.fromRGBO(255, 255, 255, 1.0);
|
||||||
|
static const ChatInputBackgroundColor = Color.fromRGBO(240, 240, 240, 1.0);
|
||||||
|
static const ChatInputFillGgColor = Color.fromRGBO(251, 251, 251, 1.0);
|
||||||
|
// end for chat
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ImageButton extends StatefulWidget {
|
||||||
|
const ImageButton({
|
||||||
|
Key? key,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.image,
|
||||||
|
double? this.width,
|
||||||
|
double? this.height,
|
||||||
|
String? this.title,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final ImageProvider image;
|
||||||
|
final void Function()? onPressed;
|
||||||
|
final double? width;
|
||||||
|
final double? height;
|
||||||
|
final String? title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ImageButtonState createState() => _ImageButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ImageButtonState extends State<ImageButton> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: widget.onPressed,
|
||||||
|
child: Container(
|
||||||
|
width: widget.width ?? 44,
|
||||||
|
height: widget.height ?? 44,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Image(
|
||||||
|
image: widget.image,
|
||||||
|
width: widget.width ?? 35,
|
||||||
|
height: widget.height ?? 35,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
/// Used to toggle the visibility behavior of the [SendButton] based on the
|
||||||
|
/// [TextField] state inside the [Input] widget.
|
||||||
|
enum SendButtonVisibilityMode {
|
||||||
|
/// Always show the [SendButton] regardless of the [TextField] state.
|
||||||
|
always,
|
||||||
|
|
||||||
|
/// The [SendButton] will only appear when the [TextField] is not empty.
|
||||||
|
editing,
|
||||||
|
|
||||||
|
/// Always hide the [SendButton] regardless of the [TextField] state.
|
||||||
|
hidden,
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CustomOverlay extends StatelessWidget {
|
||||||
|
final Widget? icon;
|
||||||
|
final BoxDecoration decoration;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
|
||||||
|
const CustomOverlay({
|
||||||
|
Key? key,
|
||||||
|
this.icon,
|
||||||
|
this.decoration = const BoxDecoration(
|
||||||
|
color: Color(0xff77797A),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
||||||
|
),
|
||||||
|
this.width = 160,
|
||||||
|
this.height = 160,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Positioned(
|
||||||
|
top: MediaQuery.of(context).size.height * 0.5 - width / 2,
|
||||||
|
left: MediaQuery.of(context).size.width * 0.5 - height / 2,
|
||||||
|
child: Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: Center(
|
||||||
|
child: Opacity(
|
||||||
|
opacity: 0.8,
|
||||||
|
child: Container(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
decoration: decoration,
|
||||||
|
child: icon,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
library emoji_picker_flutter;
|
||||||
|
|
||||||
|
export './src/category_icons.dart';
|
||||||
|
export './src/config.dart';
|
||||||
|
export './src/emoji.dart';
|
||||||
|
export './src/emoji_picker.dart';
|
||||||
|
export './src/emoji_picker_builder.dart';
|
||||||
|
export './src/emoji_picker_utils.dart';
|
||||||
|
export './src/emoji_view_state.dart';
|
@ -0,0 +1,13 @@
|
|||||||
|
import '../emoji_picker_flutter.dart';
|
||||||
|
|
||||||
|
/// Container for Category and their emoji
|
||||||
|
class CategoryEmoji {
|
||||||
|
/// Constructor
|
||||||
|
CategoryEmoji(this.category, this.emoji);
|
||||||
|
|
||||||
|
/// Category instance
|
||||||
|
final Category category;
|
||||||
|
|
||||||
|
/// List of emoji of this category
|
||||||
|
List<Emoji> emoji;
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Class that defines the icon representing a [Category]
|
||||||
|
class CategoryIcon {
|
||||||
|
/// Icon of Category
|
||||||
|
const CategoryIcon({
|
||||||
|
required this.icon,
|
||||||
|
this.color = const Color.fromRGBO(211, 211, 211, 1),
|
||||||
|
this.selectedColor = const Color.fromRGBO(178, 178, 178, 1),
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The icon to represent the category
|
||||||
|
final IconData icon;
|
||||||
|
|
||||||
|
/// The default color of the icon
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
/// The color of the icon once the category is selected
|
||||||
|
final Color selectedColor;
|
||||||
|
}
|