uni-app中swiper-item安卓视频滑动失效问题求解:安卓上下滑动视频有时会失效,ios正常;且请求数据时,ios可追加查看视频,安卓返回第一条数据

uni-app中swiper-item安卓视频滑动失效问题求解:安卓上下滑动视频有时会失效,ios正常;且请求数据时,ios可追加查看视频,安卓返回第一条数据

开发环境 版本号 项目创建方式
Windows HBuilderX

产品分类:uniapp/App

PC开发环境操作系统:Windows

PC开发环境操作系统版本号:windows7 旗舰版

HBuilderX类型:正式

HBuilderX版本号:3.1.12

手机系统:Android

手机系统版本号:Android 10

手机厂商:华为

手机机型:华为荣耀10

页面类型:nvue

打包方式:云端

App下载地址或H5网址:

https://www.pgyer.com/eFF4

示例代码:

//组件滑动处理视频
changeCurrent(e) {
    let that = this;
    console.error(e.detail.current)
    // if (plus.os.name.toLowerCase() === 'ios') {
    that.changVideo(e.detail.current);
    // }
},
//统一处理视频加载问题
changVideo(index) {
    let that = this;
    this.$nextTick(() => {
        this.index = index;
        for (let item of this.videoList) {
            item.video.flag = true
        }
        that.videoList[that.index].video.flag = false;
        if (this.Page < this.totalPages) {
            console.error('下标对比:', this.index, this.oldIndex)
            console.error('当前视频位数:' + index)
            this.dangqianvideoId = this.videoList[this.index].video.videoId
            this.redCount = this.videoList[this.index].video.redCount
            var len = this.videoList.filter(item => item.video.url).length
            //剩余两条的时候加载视频
            console.error('剩余两条的时候加载视频:' + len)
            if (len - index - 1 <= 2 && index > 0) {
                this.Page++
                console.error('数据长度:' + this.videoList.length)
                this.oldIndex = this.index
                this.userList(this.Page);
            }
            this.music = this.videoList[this.index].music.musicId
            this.musicid = this.videoList[this.index].music.musicId
            this.musicName = this.videoList[this.index].music.musicName
            this.musicList.push(this.videoList[this.index].music.musicName)
            console.log('musicid:' + this.musicid)
        } else {
            this.Page = this.totalPages - 1;
        }
        // this.videoList[this.index].video.flag = true
        this.listTouchDirection = null
        this.goods = null
        this.isCheck(this.videoList[index].video.videoId);
    })
},
// 视频列表
userList(page) {
    let that = this;
    uni.request({
        url: config.APIHOST2 + '/video/userListByPraise',
        data: {
            page: page,
            userId: uni.getStorageSync("userId"),
            size: 10
        },
        sslVerify: false,
        header: {
            "content-type": "application/json"
        },
        method: "GET",
        success: function(res) {
            console.error('推荐视频:' + JSON.stringify(res.data.data))
            uni.hideLoading();
            if (res.data.status == 0 && res.data.data.length > 0) {
                let dataArr = res.data.data;
                that.totalPages = res.data.data.length;
                // that.videoTotalElements = res.data.data.totalElements
                console.log('推荐视频:', dataArr)
                for (let i = 0; i < dataArr.length; i++) {
                    if (dataArr[i].videoStatistics.sumPraise == null || dataArr[i].videoStatistics.sumPraise == '') {
                        dataArr[i].videoStatistics.sumPraise = 0
                    }
                    dataArr[i].video = Object.assign(dataArr[i].video, {
                        "flag": true,
                        "check": false,
                        "card": true
                    })
                }
                that.$nextTick(res => {
                    // let videoGroup = dataArr
                    let len = that.videoList.length
                    dataArr.forEach(val => {
                        that.videoList.push(val);
                    })
                    that.oldIndex = that.index + 1
                    that.dangqianvideoId = that.videoList[that.index].video.videoId
                    that.redCount = that.videoList[that.index].videoStatistics.redCount
                    console.error('检查集合数据' + that.videoList.length)
                    console.error('检查当前位置' + that.index, that.dangqianvideoId)
                    let localId = uni.getStorageSync("userId");
                    if (localId == that.videoList[that.index].userInfo.userId) {
                        that.who = 'my'
                    } else {
                        that.who = 'other'
                    }
                    that.music = that.videoList[that.index].music.musicId
                    that.videoList[that.index].video.flag = false;
                    that.refresh(); //用户分享    
                    // 视频评论数   
                    // that.getTotal(that.videoList[that.index].videoId)
                    that.blockShow = true;
                    that.getUser(that.videoList[that.index].userInfo.userId); //用户信息  
                    setTimeout(() => {
                        // that.getUser(that.videoList[that.index].userInfo.userId); //用户信息   
                        // that.videoList[that.index-1].video.flag = false;
                    }, 2000)
                    // 观看视频 记录  
                    let userId = uni.getStorageSync("userId");
                    if (timer2) {
                        clearTimeout(timer2)
                        timer2 = null
                    };
                    timer2 = setTimeout(() => {
                        that.viewVideo(userId, that.videoList[that.index].video.videoId)
                    }, 1000)
                    that.giftNum(that.videoList[that.index].video.videoId)
                    that.realyFollow(that.videoList[that.index].userInfo.userId); //关注检测  
                    that.addVideoList(that.videoList); //共分享页面 共享数据   

                    if (that.slideCurrentIndex == 0) {
                        that.videoList[that.index].video.flag = false;
                    } else {
                        that.videoList[that.index].video.flag = true;
                    }
                })
            }
        },
        fail: function(err) {
            uni.hideLoading();
        }
    })
}

操作步骤:

<swiper :style="{ height: height,width: width }" class="swiper" :vertical="true"  
@change.stop="changeCurrent" :current="index">
    <swiper-item :style="{ height: height,width: width }" v-for="(item, idx) in videoList"  
        :key="idx" :item-id="idx" class="swiper-item" :skip-hidden-item-layout='true'  
        :display-multiple-items='5'>
        <view v-if="Math.abs(index-idx)<=1" :style="{ height: height,width: width }">
            <lizhao-video v-if="Math.abs(index-idx)<=1" class="video" :src="item.video.url"  
                :height="height" :duration='item.video.duration' :width="width"  
                :poster='item.video.coverImg' :play="item.video.flag"  
                :short="item.video.videoHeight=='1024'?false:true">
            </lizhao-video>
            
            <cover-view class="cover-view-marks">
                <view :data-index='idx' :style="{ height: height,width: width }"  
                    @touchmove="ListTouchMove" @touchend.stop="ListTouchEnd"  
                    @touchstart="ListTouchStart">
                </view>
            </cover-view>
            <cover-view class="cover-view-left" style="z-index:999">
                <block>
                    <view class="goods" v-if="goods">
                        <image class="goods_img" :src="goods.itempic+'_310x310.jpg'"></image>
                        <view class="words">
                            <view class="words_top">
                                <text class="goods_title">{{goods.itemtitle}}</text>
                                <image class="goods_close" @click.stop="closeCard"  
                                    src="../../static/close.png"></image>
                            </view>
                            <view class="words_bottom">
                                <view class="w_left">
                                    <view class="w_bg">
                                        <text class="j">劵</text>
                                        <text class="w_price">{{goods.couponmoney}}元</text>
                                    </view>
                                    <view class="pri_wrap">
                                        <text class="red_word"> ¥{{goods.itemendprice}}</text>
                                        <text class="gry_pri">¥{{goods.itemprice}}</text>
                                    </view>
                                </view>
                                <text class="w_right" @click="shop(goods.itemid)">立即购买</text>
                            </view>
                        </view>
                    </view>
                </block>
                <view class="icon_wrap" @click.stop="bangDan(item)"  
                    v-if="item.videoStatistics.giftGiveCount&&item.videoStatistics.giftGiveCount>0">
                    <image class="icon_shop" src="../../static/bangdan.png" mode="aspectFit">
                    </image>
                    <text class="icon_title">查看礼物榜单</text>
                    <!-- {{des}} -->
                </view>
                
                <view class="icon_wrap" @click.stop="singleGoods(item)">
                    <image class="icon_shop" src="../../static/shops.png" mode="aspectFit">
                    </image>
                    <text class="icon_title">查看视频同款商品</text>
                    <!-- {{des}} -->
                </view>
                <view class="icon_wrap" v-if="item.video.city"  
                    @click.stop="cityType(item)">
                    <image class="icon_position" src="../../static/position.png"></image>
                    <view class="iconGry"><text class="icon_title">{{item.video.city}}</text></view>
                </view>
                <text class="view-left-text"  
                    v-if="item.userInfo.userName">{{item.userInfo.userName}}</text>
                <view class="view-left-text-content" v-if="item.video.title">
                    <text class="text-content-text">{{item.video.title}}</text>
                    <text class="text-content-advert" v-if="false">广告</text>
                </view>
                <view style="flex-direction: row;" v-if="musicName" @click="clickMusic(item)">
                    <text class="iconfont view-left-icon musicicon">&#xe600;</text>
                    <view class="view-left-dubbedText" style="lines: 1; overflow: hidden; text-overflow: ellipsis;">
                        <text class="view-left-dubbedText-text" style="lines: 1; overflow: hidden; text-overflow: ellipsis;"  
                            :style="{transform: `translateX(${translateX}px)}`}>{{musicName}}</text>
                    </view>
                </view>
                <view class="seedetails" v-if="false">
                    <text class="seedetails-text" @click="navigateTo(item.video.advertUrl)">查看详情</text>
                </view>
                <!-- 合集 -->
                <view v-if="hejiShow && item.video.listName" class="icon_wrap heji"  
                    :style="{width: width}" @click="heji(item)">
                    <image class="icon_shop" src="../../static/jihe.png" mode="aspectFit"></image>
                    <text class="icon_title hejiTitle"  
                        style="width: 600upx;">合集·{{item.video.listName}}</text>
                    <image class="icon_shop hejiY" src="../../static/author/join.png"  
                        mode="aspectFit"></image>
                </view>
            </cover-view>
            <!-- 右下角图标 -->
            <cover-view class="cover-view-right">
                <cover-image v-if="item.userInfo.userImg" :src="item.userInfo.userImg"  
                    class="avater img" @click.stop="tapAvater(item.userInfo.userId)"></cover-image>
                <cover-image v-else src="../../static/author/head.png" class="avater img"  
                    @click.stop="tapAvater(item.userInfo.userId)"></cover-image>
                <text class="right-follow" v-if="who=='other'&&item.videoStatistics.followCount==0"  
                    @click="Follow(item.userInfo.userId)">+</text>
                <cover-image  
                    :src="item.video.check?'../../static/img/axc.png':'../../static/img/bed.png' "  
                    class="img-left" @click.stop="tapLove"></cover-image>
                <text class="right-text">{{item.videoStatistics.sumPraise}}</text>
                <!-- 点击评论 -->
                <cover-image src="../../static/img/ay2.png" style="height: 80upx;" class="img-left"  
                    @click.stop="tapMsg"></cover-image>
                <text class="right-text">{{item.videoStatistics.commentCount}}</text>
                <!-- 点击转发 -->
                <cover-image src="../../static/img/b6p.png" style="height: 76upx;" class="img-left"  
                    @click.stop="tapShare(item)"></cover-image>
                <text class="right-text">{{item.videoStatistics.shareCount}}</text>
                <!-- 礼物 -->
                <cover-image v-if="who=='other'" src="../../static/img/gift.png"  
                    style="width:76upx;height: 66upx;" class="img-left" @click.stop="tapGift">
                </cover-image>
                <cover-image v-else src="../../static/img/gift.png"  
                    style="width:76upx;height: 66upx;" class="img-left"></cover-image>
                <text class="right-text">{{item.videoStatistics.giftGiveCount}}</text>
                <!-- 同款  v-if="item.typeId" -->
                <cover-image src="../../static/img/same.png" style="width:63upx;height: 54upx;"  
                    class="img-left" @click.stop="same(item)">
                </cover-image>
            </cover-view>
        </view>
    </swiper-item>
</swiper>

预期结果:

安卓和ios上下滑动顺畅,并且请求数据后滑动查看顺畅

实际结果:

ios上下滑动数据和请求追加数据顺畅,安卓滑动出现卡顿,每次追加完数据后,视频返回到了第一条

更多关于uni-app中swiper-item安卓视频滑动失效问题求解:安卓上下滑动视频有时会失效,ios正常;且请求数据时,ios可追加查看视频,安卓返回第一条数据的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于uni-app中swiper-item安卓视频滑动失效问题求解:安卓上下滑动视频有时会失效,ios正常;且请求数据时,ios可追加查看视频,安卓返回第一条数据的实战教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个典型的Android平台swiper组件在nvue页面中的兼容性问题。从代码分析来看,主要问题在于:

  1. Android swiper滑动事件触发机制差异:Android平台在快速滑动时,change事件可能无法稳定触发,导致视频切换逻辑执行不完整。

  2. 数据更新后的current重置问题:当userList请求返回数据并更新videoList后,Android平台swiper的current索引可能被重置为0,导致跳回第一条。

解决方案:

  1. 优化滑动事件处理
changeCurrent(e) {
    if (this.isScrolling) return; // 防止重复触发
    this.isScrolling = true;
    setTimeout(() => {
        this.isScrolling = false;
    }, 300);
    
    const current = e.detail.current;
    if (this.index === current) return;
    
    this.changVideo(current);
}
  1. 修复数据更新后的索引保持: 在userList的success回调中,移除或优化可能重置current索引的代码:
// 移除这行可能导致问题的代码
// that.oldIndex = that.index + 1
  1. 使用@animationfinish替代@change
<swiper [@animationfinish](/user/animationfinish)="changeCurrent" :current="index">

[@animationfinish](/user/animationfinish)在Android平台有更好的稳定性。

  1. 添加防抖处理
let changeTimer = null;
changeCurrent(e) {
    clearTimeout(changeTimer);
    changeTimer = setTimeout(() => {
        this.changVideo(e.detail.current);
    }, 50);
}
  1. 检查cover-view事件冒泡: Android平台cover-view的touch事件可能影响swiper滑动,确保cover-view的touch事件正确处理:
ListTouchStart(e) {
    // 添加阻止默认行为
    e.preventDefault();
}
回到顶部