基於 Flutter+Dart 仿微信 App 聊天應用|flutter 聊天介面

xiaoyan2015發表於2020-05-13

專案簡介

Flutter作為前端比較熱門的框架技術,有必要學習瞭解。今天給大家分享的是基於flutter+dart全家桶技術開發仿微信介面聊天專案。實現了訊息/表情傳送、圖片預覽、長按PopupWin選單、紅包/視訊/朋友圈等功能。

技術點

  • 使用技術:Flutter 1.12.13/Dart 2.7.0
  • 視訊元件:chewie: ^0.9.7
  • 圖片/拍照:image_picker: ^0.6.6+1
  • 圖片預覽元件:photo_view: ^0.9.2
  • 彈窗元件:showModalBottomSheet/AlertDialog/SnackBar(基於flutter自定義彈窗模式)
  • 本地儲存:shared_preferences: ^0.5.7+1
  • 字型圖示:IconData+阿里iconfont字型圖示

Flutter入口頁面main.dart

/**
 * @tpl Flutter入口頁面 | create by andy | Q:282310962
 */

import 'package:flutter/material.dart';

// 引入公共樣式
import 'styles/common.dart';

// 引入底部Tabbar頁面導航
import 'components/tabbar.dart';

// 引入地址路由
import 'router/routes.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter App',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: GStyle.appbarColor,
      ),
      home: TabBarPage(),
      onGenerateRoute: onGenerateRoute,
    );
  }
}


















flutter實現沉浸式狀態列/仿鹹魚導航

在flutter中如何實現頂部透明狀態列(去掉狀態列黑色半透明背景),去掉右上角banner,詳細介紹可以去看之前的這篇分享
基於Flutter+Dart仿微信app聊天應用|flutter聊天介面
Flutter沉浸式狀態列/AppBar導航欄/仿鹹魚底部凸起導航

flutter圖示Icon及自定義圖示IconData元件

flutter中使用圖示很簡單,系統自帶圖示元件Icon Icon(Icons.search)
如果字型圖示不能滿足要求,比如想要使用阿里iconfont字型圖示庫檔案,這時就需要用到IconData來實現自定義圖示了。Icon(IconData(0xe60e, fontFamily:'iconfont'), size:24.0)
先下載阿里圖示庫字型檔案,然後在pubspec.yaml中引入字型

class GStyle {
    // __ 自定義圖示
    static iconfont(int codePoint, {double size = 16.0, Color color}) {
        return Icon(
            IconData(codePoint, fontFamily: 'iconfont', matchTextDirection: true),
            size: size,
            color: color,
        );
    }
}

需要把Unicode編碼&#xe60e改為0xe60e即可。支援自定義顏色、圖示大小
GStyle.iconfont(0xe60e, color: Colors.orange, size: 17.0)

flutter桌面app啟動圖示右上角圓點|未讀訊息小紅點

在flutter中沒有提供如下紅點提示元件,只能封裝實現。

class GStyle {
    // 訊息紅點
    static badge(int count, {Color color = Colors.red, bool isdot = false, double height = 18.0, double width = 18.0}) {
        final _num = count > 99 ? '···' : count;
        return Container(
            alignment: Alignment.center, height: !isdot ? height : height/2, width: !isdot ? width : width/2,
            decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(100.0)),
            child: !isdot ? Text('$_num', style: TextStyle(color: Colors.white, fontSize: 12.0)) : null
        );
    }
}

支援自定義紅點大小、顏色,預設數字超過99就…顯示;
GStyle.badge(0, isdot:true)
GStyle.badge(13)
GStyle.badge(168, color: Colors.green, height: 17.0, width: 17.0)

flutter仿微信長按位置PopopWin彈窗選單

  • flutter中實現長按,在長按位置彈出選單 置頂聊天/複製/轉發/撤回/刪除

    通過InkWell元件提供的onTapDown事件獲取長按座標點

    InkWell(
      splashColor: Colors.grey[200],
      child: Container(...),
      onTapDown: (TapDownDetails details) {
          _globalPositionX = details.globalPosition.dx;
          _globalPositionY = details.globalPosition.dy;
      },
      onLongPress: () {
          _showPopupMenu(context);
      },
    ),
    // 長按彈窗
    double _globalPositionX = 0.0; //長按位置的橫座標
    double _globalPositionY = 0.0; //長按位置的縱座標
    void _showPopupMenu(BuildContext context) {
      // 確定點選位置在左側還是右側
      bool isLeft = _globalPositionX > MediaQuery.of(context).size.width/2 ? false : true;
      // 確定點選位置在上半螢幕還是下半螢幕
      bool isTop = _globalPositionY > MediaQuery.of(context).size.height/2 ? false : true;
    
      showDialog(
        context: context,
        builder: (context) {
          return Stack(
            children: <Widget>[
              Positioned(
                top: isTop ? _globalPositionY : _globalPositionY - 200.0,
                left: isLeft ? _globalPositionX : _globalPositionX - 120.0,
                width: 120.0,
                child: Material(
                  ...
                ),
              )
            ],
          );
        }
      );
    }
  • flutter去掉AlertDialog彈窗大小限制
    通過SizedBox和無限制容器UnconstrainedBox元件配合實現改變彈窗大小

    void _showCardPopup(BuildContext context) {
      showDialog(
        context: context,
        builder: (context) {
          return UnconstrainedBox(
            constrainedAxis: Axis.vertical,
            child: SizedBox(
              width: 260,
              child: AlertDialog(
                content: Container(
                  ...
                ),
                elevation: 0,
                contentPadding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
              ),
            ),
          );
        }
      );
    }

flutter換行編輯器插入表情|聊天訊息滾動最底部


flutter中TextField文字框提供的maxLines屬性可實現多行文字,不過預設會有個高度。 可在外層加個容器限制最小高度,然後設定 maxLines: null keyboardType: TextInputType.multiline

Container(
    margin: GStyle.margin(10.0),
    decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(3.0)),
    constraints: BoxConstraints(minHeight: 30.0, maxHeight: 150.0),
    child: TextField(
        maxLines: null,
        keyboardType: TextInputType.multiline,
        decoration: InputDecoration(
          hintStyle: TextStyle(fontSize: 14.0),
          isDense: true,
          contentPadding: EdgeInsets.all(5.0),
          border: OutlineInputBorder(borderSide: BorderSide.none)
        ),
        controller: _textEditingController,
        focusNode: _focusNode,
        onChanged: (val) {
          setState(() {
            editorLastCursor = _textEditingController.selection.baseOffset;
          });
        },
        onTap: () {handleEditorTaped();},
    ),
),

flutter聊天訊息滾動到最下部,通過ListView裡controller控制實現;

ScrollController _msgController = new ScrollController();
...
ListView(
    controller: _msgController,
    padding: EdgeInsets.all(10.0),
    children: renderMsgTpl(),
)

// 滾動訊息至聊天底部
void scrollMsgBottom() {
    timer = Timer(Duration(milliseconds: 100), () => _msgController.jumpTo(_msgController.position.maxScrollExtent));
}

okay,基於flutter+dart開發仿微信手機App聊天專案就介紹到這裡,希望能有些幫助!!??
electron聊天室|vue+electron-vue仿微信客戶端|electron桌面聊天
基於vue+uniapp直播專案|uni-app仿抖音/陌陌直播室

本作品採用《CC 協議》,轉載必須註明作者和本文連結

本文為原創文章,未經作者允許不得轉載,歡迎大家一起交流 QQ(282310962) wx(xy190310)

相關文章