flutter 自己发消息,列表跳到最底部,收到消息,如果不在底部就显示“有未读消息”,点击跳到最底部

先判断该消息是否时自己发的,如果是自己发的,列表就跳到底部,如果不是自己发的消息,就判断是否在底部,如果不在底部就显示“有未读消息”,如果在底部就不用显示“有未读消息”。点击“有未读消息”跳转到列表底部。因为列表反转了,所以底部是0。顶部是列表高度

  late StreamSubscription<ReceiveNewMessageEvent> _receiveNewMessageEvent;
  final ScrollController _scrollController = ScrollController();

  //插入一条新消息,判断是否时自己的消息
  handleMessage(int userId) {
    if ('$userId' == Global.userId) {
      //是自己发的消息
      EventBusUtil.fire(ReceiveNewMessageEvent(CloudCustomDataBean.LIVE_MESSAGE, true));
    } else {
      //不是自己发的消息
      EventBusUtil.fire(ReceiveNewMessageEvent(CloudCustomDataBean.LIVE_MESSAGE, false));
    }
  }

    ///新消息处理
    _receiveNewMessageEvent = EventBusUtil.listen((event) {
      if (event.messageType == CloudCustomDataBean.LIVE_MESSAGE) {
        if (event.isOneself) {
          //是自己的消息,弹到底部
          _scrollController.animateTo(
              _scrollController.position.minScrollExtent, //滚动到底部
              duration: const Duration(milliseconds: 200),
              curve: Curves.easeOut);
        } else {
          //不是自己的消息,不在列表底部就判断是否显示未读消息控件
          if (!isOnTheBottom) {
            //显示有未读消息控件
            isNewMessage = true;
            mySetState(() {});
          }
        }
      }
    });


    /// 监听滚动事件,判断列表是否到达底部
    _scrollController.addListener(() {
      if (_scrollController.position.pixels <=
          _scrollController.position.minScrollExtent + 30) {
        //小于距离底部30位置的算滑到底部了
        ///达到最大指定滚动位置
        isOnTheBottom = true;
        isNewMessage = false;
      } else {
        //因为列表反转了,底下是0,顶部是列表最大高度,所以列表滑动超过距离底部30的位置时就会设置还没到列表底部(大概滑到距离底部两条消息的距离才会显示还有未读消息)
        isOnTheBottom = false;
      }
      mySetState(() {});
    });

  @override
  void dispose() {
  _receiveNewMessageEvent.cancel();
  _scrollController.dispose();
  super.dispose();
  }
//列表数据
            DirectSeedingList(
                                  widget.roomId ?? '0',
                                  liveGroupInfo,
                                  _scrollController,
                                  widget.anchorInfo),

//点击未读消息按钮跳到底部
      Offstage(
          offstage: !isNewMessage,
          child: GestureDetector(
              onTap: () {
                _scrollController.animateTo(
                    _scrollController.position.minScrollExtent, //滚动到底部
                    duration: const Duration(milliseconds: 200),
                    curve: Curves.easeOut);
              },
              child: Container(
                  margin: const EdgeInsets.only(bottom: 8,left: 15),
                  padding: const EdgeInsets.fromLTRB(11, 8, 11, 8),
                  decoration: BoxDecorationUtil()
                      .setFillBoxDecoration(Colors.white, 15.0),
                  child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        ContentText(S.current.group_unread, 12.0,
                            const Color(0xFFE95D47),
                            fontWeight: FontWeight.w500),
                        RightPadding(4),
                        const Image(
                            image: AssetImage(
                                'assets/images/group/icon_group_new_message.png'),
                            width: 9,
                            height: 9,
                            gaplessPlayback: true,color: Color(0xFFE95D47),)
                      ]))))

列表布局

import 'dart:async';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:social_im/common/globalEventBus.dart';
import 'package:social_im/models/cloudCustomDataBean.dart';
import 'package:social_im/models/group/groupInfoBean.dart';
import 'package:social_im/utils/loadingUtil.dart';
import 'package:social_im/utils/widgetAdaptation.dart';
import '../../../provider/direct_seeding_message_list_model.dart';
import '../direct_model/direct_anchor_info.dart';
import '../direct_seeding_message_model/direct_seeding_all_message_model.dart';
import 'direct_message_item.dart';

class DirectSeedingList extends StatefulWidget {
  String groupId;
  GroupInfoBean? liveGroupInfo;
  ScrollController scrollController;
  DirectAnchorInfoEnter? anchorInfo;

  DirectSeedingList(
      this.groupId, this.liveGroupInfo, this.scrollController, this.anchorInfo);

  @override
  State<StatefulWidget> createState() => DirectSeedingListState();
}

class DirectSeedingListState extends State<DirectSeedingList> {
  /// 滚动控制器
  final GlobalKey _containerKey = GlobalKey();
  List<DirectSeedingAllMessageModel> groupMessageList = [];
  double clmHeight = 0;
  AudioPlayer audioPlayer = AudioPlayer();

  late StreamSubscription<GetSelfRole>? _getSelfRole;

  int userRole = 0;

  @override
  void initState() {
    super.initState();
    _getSelfRole = EventBusUtil.listen((event) {
      userRole = event.userRole;
      mySetState(() {});
    });
    // receiveMessage();
    WidgetsBinding.instance!.addPostFrameCallback(_afterLayout);
  }

  @override
  void dispose() {
    if (_getSelfRole != null) {
      _getSelfRole!.cancel();
    }
    LoadingUtil.dismissLoading();
    // removeMessage();
    super.dispose();
  }

  _afterLayout(_) {
    Future.delayed(const Duration(milliseconds: 100), () {
      if (mounted) {
        setState(() {
          clmHeight = _containerKey.currentContext!.size!.height;
        });
      }
    });
  }

  mySetState(callBack) {
    if (mounted) {
      setState(() {
        callBack();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    groupMessageList =
        Provider.of<DirectSeedingMessageListModel>(context, listen: true)
            .directSeedingMessageList;

    return ShaderMask(
        //此处是背景透明度渐变的处理
        shaderCallback: (Rect bounds) {
          return const LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [
              Color.fromRGBO(0, 0, 0, 0),
              Color.fromRGBO(0, 0, 0, 1),
              Color.fromRGBO(0, 0, 0, 1),
              Color.fromRGBO(0, 0, 0, 1),
              Color.fromRGBO(0, 0, 0, 1),
              Color.fromRGBO(0, 0, 0, 1),
              Color.fromRGBO(0, 0, 0, 1),
              Color.fromRGBO(0, 0, 0, 1),
            ],
          ).createShader(Rect.fromLTRB(0, 0, bounds.width, bounds.height));
        },
        blendMode: BlendMode.dstIn,
        child: SingleChildScrollView(
            controller: widget.scrollController,
            scrollDirection: Axis.vertical,
            key: _containerKey,

            ///注意设置为反向,
            reverse: groupMessageList.length >= 2 ? true : false,
            child: Column(children: [
              MediaQuery.removePadding(
                  removeTop: true,
                  context: context,
                  child: ListView.builder(
                      shrinkWrap: true,
                      physics: const NeverScrollableScrollPhysics(),
                      itemCount: groupMessageList.length,
                      itemBuilder: (BuildContext context, int index) {
                        return showItemView(groupMessageList[index]);
                      }))
            ])));
  }

  Widget showItemView(DirectSeedingAllMessageModel groupMessage) {
    Widget groupMessageView = Container();
    groupMessageView = Container(
      margin: EdgeInsets.only(
          left: WidgetAdaptation.getWidth(15),
          right: WidgetAdaptation.getWidth(15)),
      child: DirectMessageItem(
        groupMessage,
        audioPlayer,
        activityType: CloudCustomDataBean.WORLD_LIVE_GROUP,
        roomId: int.parse(widget.groupId),
        anchorInfo: widget.anchorInfo,
        userRole: userRole,
      ),
    );
    return groupMessageView;
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值