精华内容
下载资源
问答
  • 基于html,css写的web端静态聊天页面简单实用,web页面聊天窗口的html、css、js,界面简单清晰
  • 安卓聊天页面

    2017-06-17 17:30:37
    如何写出优雅的代码,耦合性低的代码,详细介绍请查看:http://blog.csdn.net/xiangzhihong8/article/details/73381892
  • 很实用的模板工具,基于bootstrap响应式界面设计 很实用的模板工具,基于bootstrap响应式界面设计
  • HTML5仿微信聊天页面框架, 一个页面内四个TAB页,完成了添加条目与对话条目部分,直接后台对接即可。
  • html5聊天页面

    2018-08-21 09:57:16
    html5聊天页面
  • uni-app聊天页面

    2019-04-04 14:46:58
    uni-app聊天的页面模板,和微信上的聊天页面差不多,可以放心使用。
  • 本篇文章主要介绍了iOS实现搭建聊天页面的实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 简单的在线沟通系统页面的实现,没有实现功能,可以作为初学者的教学文本
  • 这是一个h5页面的聊天页面,方便大家在做聊天的过程中学习与使用,更是能够让大家从学习过程中,找到快捷的方式,其中页面中包含了:好友列表,会话列表,会话内容等多个页面
  • Android软键盘与聊天页面底部布局之间优雅地切换 http://blog.csdn.net/huanghuangjin/article/details/78228823
  • 类似QQ聊天页面,包含了表情的发送,以及录音的发送和播放等等,也是参考了别人写的代码,希望对大家有所帮助。
  • 网页聊天页面

    2015-11-12 10:06:36
    插件描述:网页聊天页面. 参考示例:http://www.jq22.com/jquery-info4688
  • iOS简易聊天页面以及容联云IM自定义聊天页面的实现思路 首先,楼主所在的公司只有楼主一个iOS开发,在代码规范上大神们也许会反感,请多包涵。我会不断改进。 一、关于UI页面实现 1) 整体是UITableView,自定义Cell...
  • 实例用bootstrap 搭建响应式手机软件交谈聊天页面样式
  • 实例用bootstrap 搭建响应式手机软件交谈聊天页面样式
  • axure怎么制作聊天页面

    千次阅读 2020-02-01 23:24:23
    产品经理是站在上帝身边axure怎么制作聊天页面的人。(上帝了解人性,懂得如何运用群体的特性去驾驭人类,产品终究是联系人与思想的媒介,虚无缥缈的道贯穿在产品经理和用户之间,隔着一层薄薄的纱,隐约可见,霎那...

    前言
    产品经理是站在上帝身边axure怎么制作聊天页面的人。(上帝了解人性,懂得如何运用群体的特性去驾驭人类,产品终究是联系人与思想的媒介,虚无缥缈的道贯穿在产品经理和用户之间,隔着一层薄薄的纱,隐约可见,霎那间很近,转身就又很远)
    一款好的产品是建立在一切近乎完美的情景下开发出来的。axure怎么制作聊天页面产品是有灵性的,你怀着什么样的心情创造它,那么它就会以相同的姿态对待你的用户。产品是需要养的。

    axure怎么制作聊天页面
    标题


    微信聊天
    微信的axure怎么制作聊天页面出现让聊天变得更加便捷,更便宜。让人可以专注的去思考聊天的内容。这里也要感谢QQ,感谢QQ许多年的陪伴。
    实现微信聊天效果
    在Axure中实现微信聊天效果,需要对中继器,动态面板,变量,函数等有一定的认识,同时可以将这些知识融会贯通使用。
    聊天机制
    A选择给B发送信息,输入信息后,点击发送,提示发送成功,B收到A发送的信息,并可以回复axure怎么制作聊天页面。

    绘制草图

    1. 三个色块矩形叠放,增加矩形阴影,形成层级关系。从大到小分别对应背景、列表栏、输入区域。
    2. 添加细节元素图标、文字等,图标可以在其他软件中做好导出直接使用axure怎么制作聊天页面。
    3. 然后到了添加元件的步骤,输入栏直接拉一个和输入区域等高的文本框,去掉边框,添加提示文字为“请输入…”即可,左边列表栏我是用中继器做的。

    交互实现

     

    (3)为聊天界面显示时设置文字变化,如点击第一行时显示头部为小明,消息为hello,第二行显示头部为二明,消息为我要睡觉了,以此类推。上一步设置隐藏再显示面板,就是为了刷新axure怎么制作聊天页面这个文字变化。

    1. 设置选中状态 -未回复(文本标签)为true;axure怎么制作聊天页面其他两个标签选项为false。其他两个标签设置同理,设置完成之后,就可以看到点击有选中效果了。
    2. 再显示中继器内容的跟随事件:仍然是鼠标单击时的事例,把未回复(当前标签对应中继器)设置为显示,动画可以设置为向左滑动或者向右滑动,随便axure怎么制作聊天页面设置都可以,axure怎么制作聊天页面统一就行了。接着把剩下的两个中继器内容设置为隐藏。设置完成后,就有下边的列表切换效果了。
    3. 再是蓝色矩形条的切换跟随,[[wh.left]]代表蓝色矩形条的x轴起点位置绝对固定到wh这个元件的左端,[[wh.bottom]]代表蓝色矩形条的Y轴位置起点在wh元件的底部,其他两个标签也设置起来,注意,axure怎么制作聊天页面第六步的变量要一一对应起来,比如:我这里wh代表text-未回复,yh代表text-已回复,yj代表text-已结束。
    4. 添加行(我的消息发送),选中刚刚聊天面板中建的中继器然后点击添加行,img对应的是自己的头像,neirong栏可以填写默认变量[[LVAR1]]或者自己定一个,axure怎么制作聊天页面然后点击后面的fx编辑变量,将输入框的文字赋值给它。
    5. 拖入一个大小为375x667的动态面板,命名为d_talk,在状态1里面绘制聊天页面,为中继器的每一行设置点击事件,点击时,令动态面板d_talk,向上滑动显示。实现效果。
    6. 最后就是点击左侧列表,右边聊天面板跟随变化

      (1)将右边聊天面板编组,转为动态面板,并设为隐藏。(可以先把面板移到别的地方,添加一个空状态时的文字,再将面板移回原位)

      (2)然后为左侧中继器的项目添加鼠标点击时的事例axure怎么制作聊天页面。

    7. 第一行为定义num1(全局变量)为鼠标点击中继器项目的所在行数。
    8. 第二行为axure怎么制作聊天页面设置点击该项目时使该项目变成选中状态(这个用于前面的单行选中)。
    9. 第三行为点击使数量气泡消失。
    10. 第四行+第五行 为设置点击刷新聊天面板显示时的axure怎么制作聊天页面状态。

     

    展开全文
  • netty案例,netty4.1中级拓展篇五《基于Netty搭建WebSocket,模仿微信聊天页面》源码 ...
  • 目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果。 先看下效果图:   仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高斯...
  • Flutter 聊天页面及功能开发

    万次阅读 2019-05-27 11:29:49
    用flutter开发了一个聊天页面 支持发视频,语音,图片,有需要的可以参考一下. 目前功能还不是特别完美,发送语音不太理想,实在找不到好的解决方案了,如果哪位有好的方案,可以给我留言,多多指教 效果如下: import ...

    用flutter开发了一个聊天页面  支持发视频,语音,图片,有需要的可以参考一下.

    目前功能还不是特别完美,发送语音不太理想,实在找不到好的解决方案了,如果哪位有好的方案,可以给我留言,多多指教

    效果如下:

    import 'dart:async';
    import 'dart:io';
    
    import 'package:dio/dio.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_sound/flutter_sound.dart';
    import 'package:flutter_wanandroid/common/component_index.dart';
    import 'package:flutter_wanandroid/data/protocol/messaget_bean_entity.dart';
    import 'package:flutter_wanandroid/data/repository/wan_repository.dart';
    import 'package:flutter_wanandroid/models/EnmuModels.dart';
    
    import 'package:flutter/scheduler.dart';
    import 'package:flutter_wanandroid/models/message_detail_bean_entity.dart';
    import 'package:flutter_wanandroid/ui/dialog/simple_dialog.dart';
    import 'package:flutter_wanandroid/ui/pages/demos/image_picker_demo.dart';
    import 'package:flutter_wanandroid/ui/pages/demos/sound_demo.dart';
    import 'package:flutter_wanandroid/ui/pages/demos/video_demo.dart';
    import 'package:flutter_wanandroid/ui/widgets/audio_record_button.dart';
    import 'package:flutter_wanandroid/ui/widgets/bubble_item.dart';
    import 'package:flutter_wanandroid/ui/widgets/message_detail_item.dart';
    import 'package:http_parser/http_parser.dart';
    import 'package:video_player/video_player.dart';
    
    class MessageDetailPage extends StatefulWidget {
      final MessagetBeanReturnvalueListvo model;
    
      MessageDetailPage(this.model);
    
      @override
      _MessageDetailState createState() => _MessageDetailState();
    }
    
    class _MessageDetailState extends State<MessageDetailPage> {
      RefreshController _refreshController;
      ScrollController _scrollController;
      List<MessageDetailBeanReturnvalueListvo> data = [];
      int mobileId;
    
      String mUserId;
      int mDataPage = 0;
    
      TextEditingController _replyFieldController = new TextEditingController();
    
      get _result => (result, audioLength) {
            _replyAudioMessage(result, audioLength);
          };
    
      void _getDatas() {
        mobileId = SpHelper.getIndentityBean().mobileId;
        mUserId = SpHelper.getIndentityBean().userVo.id.toString();
        _onLoading(true);
      }
    
      void scrollTop() {
        _scrollController.animateTo(0.0,
            duration: const Duration(milliseconds: 200), curve: Curves.linear);
      }
    
      void enterRefresh() {
        _refreshController.requestRefresh();
      }
    
      @override
      void dispose() {
        if (flutterSound.isPlaying) flutterSound.stopPlayer();
    
        super.dispose();
      }
    
      void _onOffsetCallback(bool isUp, double offset) {}
      FlutterSound flutterSound;
    
      bool _isPlaying = false;
      StreamSubscription _playerSubscription;
    
      @override
      void initState() {
        _getDatas();
        _scrollController = ScrollController(keepScrollOffset: true);
        _refreshController = RefreshController();
        flutterSound = new FlutterSound();
        flutterSound.setSubscriptionDuration(0.01);
        flutterSound.setDbPeakLevelUpdate(0.8);
        flutterSound.setDbLevelEnabled(true);
    
        SchedulerBinding.instance.addPostFrameCallback((_) {
    //      _refreshController.requestRefresh(true);
        });
        super.initState();
      }
    
      bool isRecord = false;
      bool _autovalidate = false;
    
      void startPlayer(String videoPath) async {
        String path = await flutterSound.startPlayer(videoPath);
        await flutterSound.setVolume(1.0);
    
        try {
          _playerSubscription = flutterSound.onPlayerStateChanged.listen((e) {
            if (e != null) {
              print(
                  'startPlayer: ${e.runtimeType}   ${e.currentPosition}   ${e.duration}');
    //          slider_current_position = e.currentPosition;
    //          max_duration = e.duration;
    //
    //          DateTime date = new DateTime.fromMillisecondsSinceEpoch(
    //              e.currentPosition.toInt(),
    //              isUtc: true);
    //          String txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
              this.setState(() {
                this._isPlaying = true;
    //            this._playerTxt = txt.substring(0, 8);
              });
            }
          });
        } catch (err) {
          print('error: $err');
        }
      }
    
      @override
      Widget build(BuildContext context) {
        var headView = new Container(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            new Expanded(
                child: Container(
              color: Colors.grey,
              child: SmartRefresher(
                  controller: _refreshController,
                  enablePullDown: true,
                  isNestWrapped: true,
                  header: ClassicHeader(
                    idleIcon: Container(),
                    idleText: "Load more...",
                  ),
                  enablePullUp: true,
                  onRefresh: () {
                    _onLoading(true);
                  },
                  onLoading: () {
                    _onLoading(false);
                  },
                  footer: new ClassicFooter(
                    noDataText: '没有更多数据',
                    noMoreIcon: Text(""),
                  ),
                  onOffsetChange: _onOffsetCallback,
                  child: ListView.builder(
                    itemCount: data.length + 1,
                    itemBuilder: _itemBuild,
                  )),
            )),
            new Row(
              crossAxisAlignment: CrossAxisAlignment.end,
              children: <Widget>[
                new IconButton(
                  icon:
                      Image.asset(Utils.getImgPath(isRecord ? 'yuyin' : 'jianpan')),
                  onPressed: () {
                    setState(() {
                      isRecord = !isRecord;
                    });
                  },
                ),
                new Expanded(
                  child: new Stack(
                    children: <Widget>[
                      new Offstage(
                        offstage: isRecord,
                        child: new TextField(
                          controller: _replyFieldController,
                          onSubmitted: (value) {
                            _replyMessage(value);
                          },
                          /*onChanged: (value) {
                      LogUtil.e("onChanged ${value}");
    
                      LogUtil.e(
                          "onChanged _replyFieldController${_replyFieldController.value.toString()}");
                    },*/
                          maxLines: 10,
                          minLines: 1,
                          decoration: new InputDecoration(
                              contentPadding: EdgeInsets.only(
                                  left: 8.0, top: 10.0, bottom: 6.0, right: 10.0),
                              labelText: '请输入',
                              fillColor: Colors.blue,
                              border: new OutlineInputBorder(
                                  borderSide: BorderSide(color: Colors.blue)),
                              focusedBorder: new OutlineInputBorder(
                                  borderSide: BorderSide(color: Colors.blue))),
                          style: TextStyle(color: Colors.black87),
                          focusNode: FocusNode(),
                        ),
                      ),
                      new Offstage(
                        offstage: !isRecord,
                        child: Container(
                          alignment: Alignment.center,
                          decoration: BoxDecoration(
                              color: Colors.grey.withAlpha(21),
                              border: Border.all(
                            color: Colors.blueAccent,
                          )),
                          height: 36.0,
                          child:  new AudioRecordButton(_result)),
    
                      ),
                    ],
                  ),
                ),
                new IconButton(
                  icon: Image.asset(Utils.getImgPath('bj_fabu_tupian')),
                  onPressed: () async {
                    LocalMediaType result =
                        await Navigator.push(context, new ImagePickerPage());
                    print(
                        '${result.mimeType}${result.filePath}${result.width}${result.height}');
                    _replyImageMessage(result);
                  },
                ),
                new Padding(
                    padding: EdgeInsets.only(right: 6.0),
                    child: new Theme(
                      data: Theme.of(context).copyWith(
                          buttonTheme: ButtonThemeData(
                              minWidth: 40.0,
                              height: 5,
                              padding: EdgeInsets.only(
                                  left: 10.0, top: 0.0, right: 10.0, bottom: 0.0))),
                      child: new RaisedButton(
                        padding: EdgeInsets.only(
                            left: 10.0, top: 2, bottom: 2.0, right: 10.0),
                        onPressed: () {
                          _replyMessage(_replyFieldController.text);
                        },
                        color: Colors.blueAccent,
                        child: Text(
                          "提交",
                          style: TextStyle(color: Colors.white),
                        ),
                        shape: new RoundedRectangleBorder(
                            borderRadius: BorderRadius.all(Radius.circular(5.0))),
                      ),
                    )),
              ],
            ),
          ],
        ));
        return Scaffold(
          backgroundColor: Theme.of(context).canvasColor,
          appBar: new MyAppBar(
            title: Text("通知详情"),
            centerTitle: true,
          ),
          body: headView,
        );
      }
    
    /*   String guessMimeType(String path) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String tempPath = path.replaceAll("-","");
        String contentTypeFor = fileNameMap.getContentTypeFor(tempPath);
        if (contentTypeFor == null) {
          contentTypeFor = "application/octet-stream";
        }
        return contentTypeFor;
      }*/
      void _replyAudioMessage(String imageResult, int length) {
        Map<String, dynamic> dataMap = {
    //      'content': imagePath,
          'userId': mUserId,
          'messageId': widget.model.messageId.toString(),
        };
    
        if (imageResult != null && length > 0) {
          dataMap.putIfAbsent('musicTime', () {
            return "${length}";
          });
    
          dataMap.putIfAbsent('music', () {
            return new UploadFileInfo(new File(imageResult),
                imageResult.substring(imageResult.lastIndexOf("/") + 1),
                contentType: ContentType.parse(new MediaType('music',
                        imageResult.substring(imageResult.lastIndexOf(".") + 1))
                    .mimeType));
          });
        }
    
        FormData formData = new FormData.from(dataMap);
        var dialog = showDialog<Null>(
            context: context, //BuildContext对象
            barrierDismissible: false,
            builder: (BuildContext context) {
              return new LoadingDialog(
                //调用对话框
                text: '请等待...',
              );
            });
        wanRepository.replayMessages(formData).then((list) {
          Navigator.pop(context);
    
          if (mounted)
            setState(() {
              _onLoading(true);
            });
        });
      }
    
      void _replyImageMessage(LocalMediaType imageResult) {
        Map<String, dynamic> dataMap = {
    //      'content': imagePath,
          'userId': mUserId,
          'messageId': widget.model.messageId.toString(),
        };
    
        if (imageResult.mimeType == 1) {
          String imagePath = imageResult.filePath;
          dataMap.putIfAbsent('photo', () {
            return new UploadFileInfo(new File(imagePath),
                imagePath.substring(imagePath.lastIndexOf("/") + 1),
                contentType:
                    ContentType.parse(new MediaType('image', 'jpeg').mimeType));
          });
        } else if (imageResult.mimeType == 2) {
          String imagePath = imageResult.filePath;
    
          print(
              "${imagePath.substring(imagePath.lastIndexOf("/") + 1)} ${imagePath.substring(imagePath.lastIndexOf(".") + 1)}             ");
          dataMap.putIfAbsent('video', () {
            return new UploadFileInfo(new File(imagePath),
                imagePath.substring(imagePath.lastIndexOf("/") + 1),
                contentType: ContentType.parse(new MediaType('audio',
                        imagePath.substring(imagePath.lastIndexOf(".") + 1))
                    .mimeType));
          });
        }
    
        FormData formData = new FormData.from(dataMap);
    
        String ownerMobileUserId = widget.model.ownerMobileUserId.toString();
        var dialog = showDialog<Null>(
            context: context, //BuildContext对象
            barrierDismissible: false,
            builder: (BuildContext context) {
              return new LoadingDialog(
                //调用对话框
                text: '请等待...',
              );
            });
        wanRepository.replayMessages(formData).then((list) {
          Navigator.pop(context);
          if (mounted)
            setState(() {
              _onLoading(true);
            });
        });
      }
    
      void _replyMessage(String content) {
        LogUtil.e(content);
        Map<String, String> dataMap = {
          'content': content,
          'userId': mobileId.toString(),
          'messageId': widget.model.messageId.toString()
        };
        String ownerMobileUserId = widget.model.ownerMobileUserId.toString();
        if (ownerMobileUserId != null) {
          /* dataMap.putIfAbsent("ownerMobileUserId", () {
            return ownerMobileUserId;
          });*/
        }
        var dialog = showDialog<Null>(
            context: context, //BuildContext对象
            barrierDismissible: false,
            builder: (BuildContext context) {
              return new LoadingDialog(
                //调用对话框
                text: '请等待...',
              );
            });
        wanRepository.replayMessages(dataMap).then((list) {
          Navigator.pop(context);
          if (mounted)
            setState(() {
              _replyFieldController.clear();
              _onLoading(true);
            });
        });
      }
    
      Widget _itemBuild(context, index) => (index == 0)
          ? buildSwiper(context)
          : Item(mobileId.toString(), data[index - 1], flutterSound);
    
      WanRepository wanRepository = new WanRepository();
    
      void _onLoading(bool isRefresh) {
        if (isRefresh || mDataPage < 0) {
          mDataPage = 0;
        } else {
          mDataPage++;
        }
        Map<String, String> dataMap = {
          'page': mDataPage.toString(),
          'mobileId': mobileId.toString(),
          'userId': mUserId.toString(),
          'messageId': widget.model.messageId.toString()
        };
        String ownerMobileUserId = widget.model.ownerMobileUserId.toString();
        if (ownerMobileUserId != null) {
          dataMap.putIfAbsent("ownerMobileUserId", () {
            return ownerMobileUserId;
          });
        }
        /* var dialog = showDialog<Null>(
            context: context, //BuildContext对象
            barrierDismissible: false,
            builder: (BuildContext context) {
              return new LoadingDialog(
                //调用对话框
                text: '请等待...',.
              );
            });*/
        wanRepository.getMessageDetail(dataMap).then((list) {
    //      Navigator.pop(context);
          if (mounted)
            setState(() {
              if (mDataPage == 0) {
                data.clear();
              }
              if (list == null || list.listVo == null) {
                mDataPage--;
                _refreshController.refreshFailed();
                return;
              }
              if (list.listVo.length <= 0) {
                mDataPage--;
                _refreshController.loadNoData();
                return;
              }
              data.addAll(list.listVo);
              if (!isRefresh) {
                _refreshController.loadComplete();
              } else {
                _refreshController.resetNoData();
                _refreshController.refreshCompleted();
              }
            });
        });
      }
    
      Widget buildSwiper(BuildContext context) {
        return new Container(
          child: new Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                new Text(
                  widget.model.msgTitle,
                  textAlign: TextAlign.start,
                  style: TextStyle(
                      color: Colors.black54,
                      fontSize: 18.0,
                      fontWeight: FontWeight.bold),
                ),
                Gaps.vGap5,
                new Text("时间:${widget.model.createDateApi}"),
                Gaps.vGap10,
                new Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    new Expanded(
                        child: new Text(
                      "发布人:${widget.model.sendName}",
                      maxLines: 1,
                      style: TextStyle(color: Colors.blue),
                    )),
                    new Expanded(
                        child: new Text("接收人:${widget.model.msgReceiveNames}",
                            style: TextStyle(color: Colors.blue), maxLines: 1)),
                    new Text(MessageType.getPushTypeString(widget.model.msgType),
                        style: TextStyle(color: Colors.blue), maxLines: 1),
                  ],
                ),
                SizedBox(
                    height: 10.0,
                    child: Container(
                      decoration: BoxDecoration(
                          color: Colors.white,
                          border: new Border(
                              bottom: new BorderSide(
                                  width: 0.33, color: Colours.divider))),
                    )),
                Gaps.vGap5,
                new Container(
                    padding: new EdgeInsets.only(right: 13.0),
                    child: new Text(
                      widget.model.msgContent,
    //                  maxLines: 50,
                    ))
              ]),
          padding:
              EdgeInsets.only(left: 18.0, top: 10.0, right: 18.0, bottom: 10.0),
          decoration: new BoxDecoration(
              color: Colors.white,
              border: new Border.all(width: 0.33, color: Colours.divider)),
        );
      }
    
      PopupMenuButton showChiocePopwin(BuildContext context) {
        return PopupMenuButton(itemBuilder: _popMenuItemBuild);
      }
    
      List<String> _imageOptions = ['相册', "相机", '选择视频', '录视频'];
    
      List<PopupMenuEntry> _popMenuItemBuild(BuildContext context) {
        return List.generate(_imageOptions.length, (index) {
          new RaisedButton(
            onPressed: () {},
            child: Text(_imageOptions[index]),
          );
        }).toList();
      }
    }
    
    class LocalMediaType {
      final int mimeType;
      final String filePath;
      int width;
      int height;
      int duration;
    
      LocalMediaType(this.mimeType, this.filePath,
          {this.width, this.height, this.duration});
    }
    
    class Item extends StatefulWidget {
      final MessageDetailBeanReturnvalueListvo itemData;
      final String userId;
      final FlutterSound flutterSound;
    
      Item(this.userId, this.itemData, this.flutterSound);
    
      @override
      _ItemState createState() => _ItemState();
    }
    
    class _ItemState extends State<Item> with TickerProviderStateMixin {
      VideoPlayerController _butterflyController;
    
      final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
      final Completer<void> connectedCompleter = Completer<void>();
      bool isSupported = true;
      bool isDisposed = false;
    
      StreamSubscription _playerSubscription;
      var leftSoundNames = [
        'assets/images/sound_left_0.png',
        'assets/images/sound_left_1.png',
        'assets/images/sound_left_2.png' /*,
        'assets/images/sound_left_3.png'*/
      ];
      var rightSoundNames = [
        'assets/images/sound_right_0.png',
        'assets/images/sound_right_1.png',
        'assets/images/sound_right_2.png' /*,
        'assets/images/sound_right_3.png'*/
      ];
      int _animationPosition = 3;
      AnimationController controller;
      Animation animation;
    
      @override
      void initState() {
        super.initState();
        //控制语音动画
        controller = AnimationController(
            duration: const Duration(milliseconds: 1000), vsync: this);
        final Animation curve =
            CurvedAnimation(parent: controller, curve: Curves.easeOut);
        animation = IntTween(begin: 0, end: 3).animate(curve)
          ..addStatusListener((status) {
            if (status == AnimationStatus.completed) {
              controller.reverse();
            }
            if (status == AnimationStatus.dismissed) {
              controller.forward();
            }
          });
    
        if (widget.itemData.videoUrl != null) {
          Future<void> initController(
              VideoPlayerController controller, String name) async {
            controller.setLooping(false);
            controller.setVolume(0.0);
            controller.pause();
            await connectedCompleter.future;
            await controller.initialize();
            if (mounted) {
              setState(() {});
            }
          }
    
          _butterflyController =
              VideoPlayerController.network(widget.itemData.videoUrl);
          initController(_butterflyController, 'butterfly');
          isIOSSimulator().then<void>((bool result) {
            isSupported = !result;
          });
        }
      }
    
      void startPlayer(String videoPath) async {
        controller.forward();
        if (widget.flutterSound.isPlaying) {
          widget.flutterSound.stopPlayer();
        }
        String path = await widget.flutterSound.startPlayer(videoPath);
        await widget.flutterSound.setVolume(1.0);
    
        try {
          _playerSubscription =
              widget.flutterSound.onPlayerStateChanged.listen((e) {
            if (e != null) {
              if (e.duration <= e.currentPosition) {
                controller.reset();
              }
              print(
                  'startPlayer: ${e.currentPosition}     ${e.duration}      ${e.runtimeType}');
    //          slider_current_position = ;
    //          max_duration = ;
    //
    //          DateTime date = new DateTime.fromMillisecondsSinceEpoch(
    //              e.currentPosition.toInt(),
    //              isUtc: true);
    //          String txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
              if (mounted)
                this.setState(() {
    //            this._isPlaying = true;
    //            this._playerTxt = txt.substring(0, 8);
                });
            }
          });
        } catch (err) {
          print('error: $err');
        }
      }
    
      @override
      Widget build(BuildContext context) {
        var itemData = widget.itemData;
    //    print("${itemData.musicTime}    ${itemData.musicTime}");
        int _offstate_status = itemData.musicUrl != null && 0 < itemData.musicTime
            ? 3
            : (itemData.photoUrl != null ? 1 : (itemData.videoUrl != null ? 2 : 0));
    
        if (widget.userId.compareTo(itemData.userId.toString()) != 0) //我发的,在右边
    
          return Container(
              alignment: Alignment.topRight,
              color: Colors.grey.withAlpha(245),
              padding: EdgeInsets.only(left: 10.0, right: 10.0, top: 10.0),
              child: Column(
                children: <Widget>[
                  Text(
                    '${itemData.createDate}',
                    style: TextStyle(color: Colors.black54),
                  ),
                  new Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      new Expanded(
                          child: new Container(
                              padding: EdgeInsets.only(left: 37.0),
                              child: new Column(
                                crossAxisAlignment: CrossAxisAlignment.end,
                                children: <Widget>[
                                  new Padding(
                                    padding: EdgeInsets.only(right: 10.0),
                                    child: Text(
                                      '${itemData.userName == null ? "匿名用户" : itemData.userName}',
                                      textAlign: TextAlign.end,
                                      style: TextStyle(
                                          fontSize: 12.0, color: Colors.black54),
                                    ),
                                  ),
                                  Gaps.vGap10,
                                  new Stack(
                                    children: <Widget>[
                                      new Offstage(
                                        offstage: _offstate_status != 0,
                                        child: new Container(
                                            padding: EdgeInsets.only(
                                                left: 7.0,
                                                top: 9.0,
                                                right: 22.0,
                                                bottom: 5.0),
                                            decoration: BoxDecoration(
                                              image: DecorationImage(
                                                image: AssetImage(
                                                    Utils.getImgPath('qipao_you')),
                                                centerSlice: new Rect.fromLTRB(
                                                    4.0, 20.0, 5.0, 20.5),
                                              ),
                                            ),
                                            child: Text(
                                              '${itemData.content}',
                                              style: TextStyle(
                                                fontSize: 14.0,
                                              ),
                                              maxLines: 10,
                                            )),
                                      ),
                                      new Offstage(
                                          offstage: _offstate_status != 1,
                                          child: new Container(
                                            padding: EdgeInsets.only(right: 10.0),
                                            child: new ConstrainedBox(
                                              constraints: new BoxConstraints(
                                                  maxHeight: 200),
                                              child: new CachedNetworkImage(
                                                fit: BoxFit.fill,
                                                imageUrl: itemData.photoUrl == null
                                                    ? "http://126306.sgss8.com/upload/2016042923/232418_1381.jpg"
                                                    : itemData.photoUrl,
                                                placeholder: new ProgressView(),
                                                errorWidget: new Icon(Icons.error),
                                              ),
                                            ),
                                          )),
                                      new Offstage(
                                        offstage: _offstate_status != 2,
                                        child: new Container(
                                          padding: EdgeInsets.only(right: 10.0),
                                          child: isSupported &&
                                                  _butterflyController != null
                                              ? ConnectivityOverlay(
                                                  child: Padding(
                                                    padding:
                                                        EdgeInsets.only(left: 10.0),
                                                    child: SingleVideoCard(
                                                      controller:
                                                          _butterflyController,
                                                      firstScreen: widget
                                                          .itemData.firstVideoUrl,
                                                    ),
                                                  ),
                                                  connectedCompleter:
                                                      connectedCompleter,
                                                  scaffoldKey: scaffoldKey,
                                                )
                                              : const Center(
                                                  child: Text(
                                                    'Video playback not supported on the iOS Simulator.',
                                                  ),
                                                ),
                                        ),
                                      ),
                                      new Offstage(
                                        offstage: _offstate_status != 3,
                                        child: new Container(
                                            width: itemData.musicTime != null &&
                                                    60 > itemData.musicTime
                                                ? ((MediaQuery.of(context)
                                                            .size
                                                            .width -
                                                        100) /
                                                    60.0 *
                                                    (itemData.musicTime < 30
                                                        ? 30
                                                        : itemData.musicTime))
                                                : (MediaQuery.of(context)
                                                        .size
                                                        .width -
                                                    100),
                                            padding: EdgeInsets.only(right: 10.0),
                                            child: RaisedButton(
                                              padding: EdgeInsets.only(
                                                  left: 8.0, right: 4.0),
                                              child: Row(
                                                mainAxisAlignment:
                                                    MainAxisAlignment.spaceBetween,
                                                children: <Widget>[
                                                  Text(
                                                    "${itemData.musicTime}\"",
                                                    textAlign: TextAlign.start,
                                                    maxLines: 1,
                                                    style: TextStyle(
                                                        color: Colors.white),
                                                  ),
                                                  Image.asset(rightSoundNames[
                                                      animation.value % 3])
                                                ],
                                              ),
                                              shape: RoundedRectangleBorder(
                                                  borderRadius:
                                                      BorderRadius.circular(18)),
                                              color: Colors.blueAccent,
                                              onPressed: () {
                                                startPlayer(itemData.musicUrl);
                                              },
                                            )),
                                      ),
                                    ],
                                  )
                                ],
                              ))),
                      Image.network(
                        "http://126306.sgss8.com/upload/2016042923/232418_1381.jpg",
                        width: 35.0,
                        height: 35.0,
                        fit: BoxFit.cover,
                      ),
                    ],
                  ),
                ],
              ));
        else {
          //对方发的,在左边
          return Container(
              color: Colors.grey.withAlpha(5),
              padding: EdgeInsets.only(left: 10.0, right: 10.0, top: 10.0),
              child: Column(
                children: <Widget>[
                  Text(
                    '${itemData.createDate}',
                    style: TextStyle(color: Colors.black54),
                  ),
                  new Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Image.network(
                        "http://126306.sgss8.com/upload/2016042923/232418_1381.jpg",
                        width: 35.0,
                        height: 35.0,
                        fit: BoxFit.cover,
                      ),
                      new Expanded(
                          child: new Container(
                              padding: EdgeInsets.only(right: 38.0),
                              child: new Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: <Widget>[
                                  new Padding(
                                    padding: EdgeInsets.only(left: 10.0),
                                    child: Text(
                                      '${itemData.userName == null ? "匿名用户" : itemData.userName}',
                                      textAlign: TextAlign.start,
                                      style: TextStyle(
                                          fontSize: 12.0, color: Colors.black54),
                                    ),
                                  ),
                                  Gaps.vGap10,
                                  new Stack(
                                    children: <Widget>[
                                      new Offstage(
                                        offstage: _offstate_status != 0,
                                        child: new Container(
                                            padding: EdgeInsets.only(
                                                left: 27.0,
                                                top: 9.0,
                                                right: 8.0,
                                                bottom: 5.0),
                                            decoration: BoxDecoration(
                                              image: DecorationImage(
                                                fit: BoxFit.fill,
                                                image: AssetImage(
                                                    Utils.getImgPath('qipao_zuo')),
                                                centerSlice: new Rect.fromLTRB(
                                                    31.0, 24.0, 32.0, 25.0),
                                              ),
                                            ),
                                            child: Text(
                                              '${itemData.content}拉年拉年拉年拉年拉年拉年拉年拉年拉年拉年拉年拉年拉年',
                                              style: TextStyle(
                                                fontSize: 14.0,
                                              ),
                                              maxLines: 10,
                                            )),
                                      ),
                                      new Offstage(
                                        offstage: _offstate_status != 1,
                                        child: new Container(
                                          padding: EdgeInsets.only(left: 10.0),
                                          child: new ConstrainedBox(
                                            constraints:
                                                new BoxConstraints(maxHeight: 200),
                                            child: new CachedNetworkImage(
                                              fit: BoxFit.fill,
                                              imageUrl: itemData.photoUrl == null
                                                  ? "http://126306.sgss8.com/upload/2016042923/232418_1381.jpg"
                                                  : itemData.photoUrl,
                                              placeholder: new ProgressView(),
                                              errorWidget: new Icon(Icons.error),
                                            ),
                                          ),
                                        ),
                                      ),
                                      new Offstage(
                                        offstage: _offstate_status != 2,
                                        child: isSupported &&
                                                _butterflyController != null
                                            ? ConnectivityOverlay(
                                                child: Padding(
                                                  padding:
                                                      EdgeInsets.only(left: 10.0),
                                                  child: SingleVideoCard(
                                                    controller:
                                                        _butterflyController,
                                                    firstScreen: widget
                                                        .itemData.firstVideoUrl,
                                                  ),
                                                ),
                                                connectedCompleter:
                                                    connectedCompleter,
                                                scaffoldKey: scaffoldKey,
                                              )
                                            : const Center(
                                                child: Text(
                                                  'Video playback not supported on the iOS Simulator.',
                                                ),
                                              ),
                                      ),
                                      new Offstage(
                                        offstage: _offstate_status != 3,
                                        child: new Container(
                                            width: itemData.musicTime != null &&
                                                    60 > itemData.musicTime
                                                ? ((MediaQuery.of(context)
                                                            .size
                                                            .width -
                                                        100) /
                                                    60.0 *
                                                    (itemData.musicTime < 30
                                                        ? 30
                                                        : itemData.musicTime))
                                                : (MediaQuery.of(context)
                                                        .size
                                                        .width -
                                                    100),
                                            height: 30,
                                            padding: EdgeInsets.only(right: 10.0),
                                            child: RaisedButton(
                                              padding: EdgeInsets.only(
                                                  left: 4.0, right: 8.0),
                                              child: Row(
                                                mainAxisAlignment:
                                                    MainAxisAlignment.spaceBetween,
                                                children: <Widget>[
                                                  Image.asset(leftSoundNames[
                                                      animation.value % 3]),
                                                  Text(
                                                    "${itemData.musicTime}\"",
                                                    textAlign: TextAlign.start,
                                                    maxLines: 1,
                                                    style: TextStyle(
                                                        color: Colors.white),
                                                  ),
                                                ],
                                              ),
                                              shape: RoundedRectangleBorder(
                                                  borderRadius:
                                                      BorderRadius.circular(15)),
                                              color: Colors.blueAccent,
                                              onPressed: () {
                                                startPlayer(itemData.musicUrl);
                                              },
                                            )),
                                      ),
                                    ],
                                  )
                                ],
                              ))),
                    ],
                  ),
                ],
              ));
        }
      }
    
      @override
      void dispose() {
        print('> VideoDemo dispose');
        isDisposed = true;
        if (_butterflyController != null) _butterflyController.dispose();
    
        print('< VideoDemo dispose');
        super.dispose();
      }
    }
    

     

    展开全文
  • 智能聊天静态页面,基本样式,js处理响应等处理,仿照微信聊天界面
  • ios移动聊天布局,移动聊天布局,消息、语音、图片布局
  • 高仿微信 实现了聊天页面和朋友圈功能,包括朋友圈点赞和评论 朋友圈页面设计模式采用的是简书文章 中提及的方案三,文章中对三种不同的方案都有分析利弊 效果图:
  • web在线聊天页面代码,web在线聊天页面代码,web在线聊天页面代码
  • 网页聊天页面效果

    2021-06-01 20:45:57
    网页聊天页面效果
  • EmojiChat聊天页面实现支持发送失败重发.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • 无框架,纯html5写的移动端web页面模板,可对接融云的JS API实现聊天功能
  • 小程序在线聊天页面

    2020-04-24 18:44:37
    小程序在线聊天页面 公司要实现在线聊天功能 我一个后台 让我写页面 哎 难受的一批 开始 首先 因为本人比较懒 刚开始直接网上找页面模板 最终找到了原文如下 ...将基础页面以及文字聊天实现了 接下来就是语音聊天了 ...

    小程序在线聊天页面

    公司要实现在线聊天功能 我一个后台 让我写页面 哎 难受的一批  
    

    开始

    1. 首先 因为本人比较懒 刚开始直接网上找页面模板 最终找到了原文如下
      https://blog.csdn.net/java558/article/details/86001064
      通过这位大神写的文章 将基础页面以及文字聊天实现了
      在这里插入图片描述

    2. 接下来就是语音聊天了 这里自己写的
      在这里插入图片描述
      找了半天文档总算搞好了

    3. 表情 然后是表情部分了 一开始用的微信文档里的 不过他那个有问题 他将表情放在一个块里面 文字一个块 你填几个表情然后写几个文字莫名奇妙的变行 所以改用了微博表情 这里看的知乎大神的案例 链接在下面
      https://zhuanlan.zhihu.com/p/111959621
      增增改改实现了 滑稽
      在这里插入图片描述

    ·

    1. 最后是图片了 这个最好弄
      在这里插入图片描述

    最后在对接上websocket 就ok了不过还有一个bug发送聊天后要将聊天记录给顶上来 哎 改去了
    最后 是不是发现没有代码 我呢再写这些功能的时候看了好多篇文章 基本一个样 说实话我怕 所以要代码的话 加我微信吧 a1007325868 无偿的

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 86,273
精华内容 34,509
关键字:

聊天页面