flutter聊天界面-加號【?】更多展開相機、相冊等操作Panel
在之前實現(xiàn)了flutter聊天界面的自定義表情的展示,這里記錄一下更多操作展開的相機、相冊等操作功能實現(xiàn)。
一、查看效果
更多操作展開的相機、相冊等操作功能實現(xiàn)。
二、代碼實現(xiàn)
展開的操作按鈕可能比較多,一頁顯示8個、多個可以左右滑動,這里就用到的flutter_swiper插件
這里使用的swpier插件是
# 輪播圖
flutter_swiper_null_safety: ^1.0.2
Swiper左右滑動的元素為GridView。
GridView網(wǎng)格布局是一種常見的布局類型,GridView 組件正是實現(xiàn)了網(wǎng)格布局的組件,
SliverGridDelegate是一個抽象類,定義了GridView Layout相關接口,子類需要通過實現(xiàn)它們來實現(xiàn)具體的布局算法。Flutter中提供了兩個SliverGridDelegate的子類SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent,
每個GridView包括多個相機、相冊等操作按鈕
按鈕如下
// 每個option的大小
class ChatMoreOptionButton extends StatelessWidget {
const ChatMoreOptionButton({
Key? key,
required this.commMoreOption,
required this.onMoreOptionPressed,
}) : super(key: key);
final CommMoreOption commMoreOption;
final Function(CommMoreOption commMoreOption) onMoreOptionPressed;
Widget build(BuildContext context) {
EdgeInsets viewPadding = MediaQuery.of(context).viewPadding;
Size screenSize = MediaQuery.of(context).size;
double aWidth = (screenSize.width - (kOptionSperate * 5)) / 4;
double aHeight = (kMorePanelHeight -
(kOptionSperate * 3) -
viewPadding.bottom -
kSwiperPaginationHeight) /
2;
double aMin = min(aWidth, aHeight);
double marginSpace = kOptionSperate / 2;
return ButtonWidget(
margin: EdgeInsets.symmetric(
vertical: marginSpace,
horizontal: marginSpace,
),
width: aMin,
height: aMin,
borderRadius: 6.0,
bgColor: ColorUtil.hexColor(0xffffff),
bgHighlightedColor: ColorUtil.hexColor(0xf0f0f0),
onPressed: () {
onMoreOptionPressed(commMoreOption);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
buildButtonIcon(context),
SizedBox(
height: 5.0,
),
Text(
"${commMoreOption.name}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
color: ColorUtil.hexColor(0x333333),
decoration: TextDecoration.none,
),
),
],
),
);
}
Widget buildButtonIcon(BuildContext context) {
if (CommMoreOptionIconType.commMoreOptionIconFile ==
commMoreOption.iconType) {
// 本地圖片
String imageUrl = "${commMoreOption.icon ?? ""}";
String start = "file://";
if (imageUrl.startsWith(start)) {
String imageAssetFile = imageUrl.substring(start.length);
return ImageHelper.wrapAssetAtImages(
"icons/${imageAssetFile}",
fit: BoxFit.cover,
width: 26.0,
height: 26.0,
);
}
} else if (CommMoreOptionIconType.commMoreOptionIconUrl ==
commMoreOption.iconType) {
// 網(wǎng)絡圖片
String imageUrl = "${commMoreOption.icon ?? ""}";
return ImageHelper.imageNetwork(
imageUrl: imageUrl,
fit: BoxFit.cover,
width: 40.0,
height: 40.0,
);
}
return Container();
}
}
GridView實現(xiàn)排列展示
// 一個swiper的容器
class ChatMoreOptionSwiperContainer extends StatefulWidget {
const ChatMoreOptionSwiperContainer({
Key? key,
required this.moreOptions,
required this.onMoreOptionPressed,
}) : super(key: key);
final List<CommMoreOption> moreOptions;
final Function(CommMoreOption commMoreOption) onMoreOptionPressed;
State<ChatMoreOptionSwiperContainer> createState() =>
_ChatMoreOptionSwiperContainerState();
}
class _ChatMoreOptionSwiperContainerState
extends State<ChatMoreOptionSwiperContainer> {
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: kGridCrossAxisCount, //每行三列
childAspectRatio: 1.0, //顯示區(qū)域寬高相等
),
itemCount: widget.moreOptions.length,
itemBuilder: (context, index) {
CommMoreOption commMoreOption = widget.moreOptions[index];
return ChatMoreOptionButton(
onMoreOptionPressed: widget.onMoreOptionPressed,
commMoreOption: commMoreOption,
);
},
),
);
}
}
最后使用Swiper實現(xiàn)左右滑動的效果,代碼如下
// 中間間隔
const double kOptionSperate = 15.0;
const double kSwiperPaginationHeight = 10.0;
const int kGridCrossAxisCount = 4;
const int kGridCrossAxisRow = 2;
// 更多操作
class ChatMoreOptionPanel extends StatefulWidget {
const ChatMoreOptionPanel({
Key? key,
required this.morePanelHeight,
required this.chatInputBarController,
required this.moreOptionEntries,
}) : super(key: key);
final double morePanelHeight;
final ChatInputBarController chatInputBarController;
final List<CommMoreOption> moreOptionEntries;
State<ChatMoreOptionPanel> createState() => _ChatMoreOptionPanelState();
}
class _ChatMoreOptionPanelState extends State<ChatMoreOptionPanel> {
List<CommMoreOption> allOptionList = [];
List<List<CommMoreOption>> optionSwiperList = [];
void initState() {
// TODO: implement initState
super.initState();
CommMoreOption commMoreOption = CommMoreOption();
commMoreOption.icon = "file://ic_toolbar_camera.png";
commMoreOption.name = "相機";
commMoreOption.iconType = CommMoreOptionIconType.commMoreOptionIconFile;
commMoreOption.type = 0;
commMoreOption.linkUrl = kOptionCamera;
allOptionList.add(commMoreOption);
CommMoreOption commMoreOption1 = CommMoreOption();
commMoreOption1.icon = "file://ic_toolbar_ablum.png";
commMoreOption1.name = "相冊";
commMoreOption1.iconType = CommMoreOptionIconType.commMoreOptionIconFile;
commMoreOption1.type = 0;
commMoreOption1.linkUrl = kOptionAlbum;
allOptionList.add(commMoreOption1);
CommMoreOption commMoreOption2 = CommMoreOption();
commMoreOption2.icon = "file://ic_toolbar_coupon.png";
commMoreOption2.name = "卡券";
commMoreOption2.iconType = CommMoreOptionIconType.commMoreOptionIconFile;
commMoreOption2.type = 0;
commMoreOption2.linkUrl = kOptionCoupon;
allOptionList.add(commMoreOption2);
if (widget.moreOptionEntries.isNotEmpty) {
allOptionList.addAll(widget.moreOptionEntries);
}
handlerSwiperList();
}
void handlerSwiperList() {
List<List<CommMoreOption>> tmpOptionSwiperList = [];
int aPageNum = kGridCrossAxisCount * kGridCrossAxisRow;
int swiperCount = (allOptionList.length % aPageNum == 0
? allOptionList.length / aPageNum
: (allOptionList.length / aPageNum + 1))
.toInt();
for (int i = 0; i < swiperCount; i++) {
int location = 0;
int length = 0;
location = i * aPageNum;
if (i == 0) {
length =
aPageNum > allOptionList.length ? allOptionList.length : aPageNum;
} else {
length = (1 + i) * aPageNum > allOptionList.length
? (allOptionList.length - i * aPageNum)
: aPageNum;
}
List<CommMoreOption> swiperItems =
allOptionList.sublist(location, (location + length));
tmpOptionSwiperList.add(swiperItems);
}
optionSwiperList = tmpOptionSwiperList;
setState(() {});
}
void dispose() {
// TODO: implement dispose
super.dispose();
}
// 點擊不同的操作Option
void onMoreOptionPressed(CommMoreOption commMoreOption) {
// 點擊不同的操作Option
// 發(fā)送eventBus事件
CommEventBusModel eventBusModel = CommEventBusModel(
commEventBusType: CommEventBusType.commEventBusTypeMoreOption,
data: commMoreOption,
);
kCommEventBus.fire(eventBusModel);
}
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Container(
width: screenSize.width,
height: widget.morePanelHeight,
decoration: BoxDecoration(
color: ColorUtil.hexColor(0xf7f7f7),
),
padding: EdgeInsets.only(
left: 0.0,
right: 0.0,
bottom: 0.0,
top: 0.0,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Swiper(
// 橫向
scrollDirection: Axis.horizontal,
// 布局構建
itemBuilder: (BuildContext context, int index) {
List<CommMoreOption> optionList = optionSwiperList[index];
return ChatMoreOptionSwiperContainer(
moreOptions: optionList,
onMoreOptionPressed: (CommMoreOption commMoreOption) {
onMoreOptionPressed(commMoreOption);
},
);
},
//條目個數(shù)
itemCount: optionSwiperList.length,
// 自動翻頁
autoplay: false,
// 分頁指示
pagination: SwiperPagination(
//指示器顯示的位置 Alignment.bottomCenter 底部中間
alignment: Alignment.bottomCenter,
// 距離調整
margin: const EdgeInsets.only(bottom: 0.0),
// 指示器構建
builder: DotSwiperPaginationBuilder(
// 點之間的間隔
space: 3,
// 沒選中時的大小
size: 6,
// 選中時的大小
activeSize: 6,
// 沒選中時的顏色
color: ColorUtil.hexColor(0xDCDCDC),
//選中時的顏色
activeColor: ColorUtil.hexColor(0xff462e),
),
),
// pagination: _buildSwiperPagination(),
// pagination: _buildNumSwiperPagination(),
//點擊事件
onTap: (index) {
print(" 點擊 " + index.toString());
},
// 相鄰子條目視窗比例
viewportFraction: 1,
// 用戶進行操作時停止自動翻頁
autoplayDisableOnInteraction: true,
// 無限輪播
loop: false,
//當前條目的縮放比例
scale: 1,
),
),
buildAreaBottom(context),
],
),
);
}
Widget buildAreaBottom(BuildContext context) {
EdgeInsets viewPadding = MediaQuery.of(context).viewPadding;
Size screenSize = MediaQuery.of(context).size;
return Container(
decoration: BoxDecoration(
color: ColorUtil.hexColor(0xf7f7f7),
),
height: viewPadding.bottom,
width: screenSize.width,
);
}
}
三、小結
flutter聊天界面-加號【?】更多展開相機、相冊等操作Panel菜單,主要Swiper和GridView排列相機、相冊等按鈕,點擊按鈕時候發(fā)送事件,使用EventBus來處理后續(xù)的邏輯實現(xiàn)。文章來源:http://www.zghlxwxcb.cn/news/detail-537631.html
學習記錄,每天不停進步。文章來源地址http://www.zghlxwxcb.cn/news/detail-537631.html
到了這里,關于flutter聊天界面-加號【?】更多展開相機、相冊等操作Panel的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!