【uniapp】聊天记录列表长按消息计算弹出菜单方向

1. 效果图

1.1 消息靠上接近导航栏,菜单显在消息体下方弹出,箭头向上

在这里插入图片描述

1.2 消息体没有贴近上方导航栏,菜单在消息体上方弹出,箭头向下

在这里插入图片描述

1.3 长消息,菜单在手指按下的位置弹出,无箭头

在这里插入图片描述

2. 代码实现

<view class="message-box" :id="'messageBox' + item.msgUID">
  <!-- 消息操作 -->
  <view :class="['message-popup-box', elementPosition == 'nearTop' ? 'right-up-box' : elementPosition == 'nearBottom' ? 'right-down-box' : '']" :style="elementPosition == 'overstep' ? computedRightMenuStyle : ''" v-if="item.messagePopup">
    <view class="message-operate">
      <view class="operate-item" v-if="item.messageType == 'TxtMsg'" @click.stop="copyMessage(item, index)">
        <image src="https://img.yiqitogether.com/yyqc/20231221/upload_o261zsurq4k7fugtfa3u2uvihq1ta4uo.png" mode="aspectFill" alt="" class="operate-item-icon"></image>
        <view class="operate-item-txt">复制</view>
      </view>
      <view class="operate-item" v-if="item.messageType == 'TxtMsg' || item.messageType == 'ImgMsg' || item.messageType == 'ReferenceMsg'" @click.stop="referenceMessage(item, index)">
        <image src="https://img.yiqitogether.com/yyqc/20231221/upload_60riqndcd93gnl4eiy8gejopf6xm9z48.png" mode="aspectFill" alt="" class="operate-item-icon"></image>
        <view class="operate-item-txt">回复</view>
      </view>
      <!-- 撤回功能:只有文字,语音,图片,引用消息并且没有被拉黑和时间小于两分钟的时候才显示 -->
      <view class="operate-item" v-if="isRecall" @click.stop="recallMessage(item, index)">
        <image src="https://img.yiqitogether.com/yyqc/20231221/upload_dh3xhatlcjchcbh2blbke9c453sv580k.png" mode="aspectFill" alt="" class="operate-item-icon"></image>
        <view class="operate-item-txt">撤回</view>
      </view>
      <view class="operate-item" v-if="!isRecall" @click.stop="deleteMessage(item, index)">
        <image src="http://img.yiqitogether.com/static/images/messageGray/icon_delete_white.png" mode="aspectFill" alt="" class="operate-item-icon"></image>
        <view class="operate-item-txt">删除</view>
      </view>
      <view class="operate-item" @click.stop="multipleChoice(item, index)">
        <image src="https://img.yiqitogether.com/yyqc/20240222/upload_qegsjb8mwt6tr6nzp2yv7bmn4c03cn4x.png" mode="aspectFill" alt="" class="operate-item-icon"></image>
        <view class="operate-item-txt">多选</view>
      </view>
    </view>
  </view>
</view>
computed: {
  computedRightMenuStyle() {
    if (this.elementPosition == 'overstep') {
      return { top: `${this.elTop}px`, right: 0 }
    }
  }
}
// 长按提示消息框
handleLongPress(e, item, index) {
  if (this.isMultipleChoice) {
    return
  }
  // 当前手指按下位置距离页面顶部的距离
  let currClientY = e.changedTouches[0].clientY
  const query = uni.createSelectorQuery().in(this)
  query
    .select(`#messageBox${item.msgUID}`)
    .boundingClientRect(res => {
      if (res.top > 180) {
        // 离顶部有足够距离,长按菜单在消息体上面弹出,箭头向下
        this.elementPosition = 'nearBottom'
      } else {
        if (res.height > this.windowSize.height / 2) {
          // 长消息,长按菜单在手指按下位置弹出
          if (currClientY < 200) {
            this.elTop = -res.top + currClientY
          } else {
            // 靠近顶部时减去菜单高度
            this.elTop = -res.top + currClientY - 60
          }
          this.elementPosition = 'overstep'
        } else {
          // 非长消息且位置靠上,长按菜单在消息体下面弹出,箭头向上
          this.elementPosition = 'nearTop'
        }
      }
    })
    .exec()
  this.isRecall = false
  if (this.messageItem) {
    this.messageItem.messagePopup = false
  }
  this.messageItem = item
  this.messageList[index].messagePopup = true
  this.$forceUpdate()
  // 判断是否超过两分钟
  let now = +new Date()
  let recalTime = item.sendDate
  let timediff = Math.abs(now - recalTime) / 1000
  if (timediff <= 120) {
    this.isRecall = true
  } else {
    this.isRecall = false
  }
}
.message-popup-box {
  position: absolute;
  z-index: 99;
  background: #595a5a;
  border-radius: 16rpx;
  .message-operate {
    display: flex;
    box-sizing: border-box;
    padding: 16rpx;
    .operate-item {
      padding: 0 20rpx;
      .operate-item-icon {
        display: block;
        width: 44rpx;
        height: 44rpx;
        background-size: cover;
      }
      .operate-item-txt {
        font-size: 24rpx;
        text-align: center;
        color: #ffffff;
        margin-top: 4rpx;
      }
    }
  }
}
.right-up-box {
  right: 0;
  bottom: -78rpx;
}
.right-down-box {
  right: 0;
  top: -120rpx;
}
.right-up-box:before {
  content: '';
  position: absolute;
  bottom: 98%;
  right: 120rpx;
  border: 16rpx solid transparent;
  border-bottom: 16rpx solid #595a5a;
}
.right-down-box::before {
  content: '';
  position: absolute;
  top: 98%;
  right: 120rpx;
  border: 16rpx solid transparent;
  border-top: 16rpx solid #595a5a;
}
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Komorebi゛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值