您好,登錄后才能下訂單哦!
Flutter視頻滾動播放的解決方案是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
視頻列表滾動播放。
視頻列表的播放規則一般需要和具體產品、交互確認,播放一般都是靜音的,根據露出坐標規律,常見的有兩大類:
固定位置播放
如滑動屏幕的中間位時,延遲若干毫秒自動播放。
固定索引+屏占比播放
如第一個符合屏占比的視頻可以自動播放;屏占比可以是當前視頻組件的高度百分比,也可以是屏幕上的固定位置;當我們把屏占比定位60%時,第一個視頻的可見區小于60%會暫停播放,觸發可見的下一個視頻。
更多相關學習內容看GitHub: https://github.com/Meng997998/AndroidJX
以下視頻內容學習vx:xx13414521
在開發安居客-有料
內容Feed流時,我們遇到的交互是第二種,由于視頻貼出現不固定,待播放的位置也不固定。 在這種情況下要實現與Native一致的效果是一個不小的難題。
我們在開發過程中將這個問題進行了分解:
滾動檢測:拋開視頻,單純設計一個組件,能夠按需檢測特定Widget
視頻播放組件:引入視頻播放,將視頻控件根據滾動檢測要求,進行接入
下面看一下我們設計的原型組件效果。
video-play.gif
我們將視頻貼子用一個色塊進行占位。通過監聽滑動事件,當停止后,從屏幕頂端開始,遍歷當前視窗范圍內的控件,如果是視頻控件,并且在屏幕上的露出比符合預期,那么將其返回。供開發者后續處理。
核心流程如下圖所示:
基于這個思路,我們開發了一個ScrollDetectListener
組件:
使用ScrollDetectListener包裹ListView,ListView為業務相關的視頻流帖子。
視頻帖子使用MetaConsumer包裹;
MetaConsumer( index: index, data: data, builder: (BuildContext context, VideoPlayModel model, Widget child) { var play = model.playIndex == index; return Container( width: MediaQuery.of(context).size.width, alignment: Alignment.center, height: 100, padding: EdgeInsets.zero, child: play ? Text('Playing $data') : Text('$data'), color: play ? Colors.redAccent : Colors.grey[100] ?? Colors.grey, ); })
通過原型完成必要的調試和優化之后,我們可以嘗試接入視頻控件。
在處理視頻的時候,需要注意的點也很多,比如:
視頻貼的首幀預覽圖/封面圖,采用視頻首幀,會遇到視頻開頭是黑屏的問題,采用獨立封面圖相對效果會更好。
視頻高寬比控制
帖子狀態控制:待播放,加載中,播放,循環/靜音等
除了我們的實現方案,目前還可以找到的一個開源庫: inview_notifier_list。
這個開源庫它支持固定位置播放,也就是我們說的以第一種類型。
該項目提供了預覽效果和demo,非常良心的作者。
他的基本原理如下:
設計了一個InViewState容器,繼承了ChangeNotify,用于記錄列表中的子Widget的context信息,InViewState state = InViewNotifierList.of(context);
當視頻Widget執行build時,調用InViewState.addContext加入集合中
同時視頻Widget本身需要用AnimatedBuilder將InViewState和視頻狀態進行關聯,也就是當InViewState更新時,重新構建視頻Widget
什么時候更新InViewState呢?答案是滑動過程中。滑動的時候開始遍歷前面加入的視頻Widget的contxt,其實就是為了通過context難道控件最終的坐標,判斷是不是符合規則
如果坐標位置命中規則,就會吧當前的控件的標識id緩存到一個集合中_currentInViewIds
,然后通知觀察者數據變化了,所以AnimatedBuilder會觸發child的build
在child的build時(也就是前面提到的視頻空間build),就會在判斷當前視頻的id是否在_currentInViewIds
中,進行差異化繪制。
我們用一張圖來概括性大致流程:
image
可以看到這里面有兩個集合,分別用那個有緩存控件的Context和名中控件數據。為了避免遍歷的性能問題,作者引入了緩存閾值,可以由使用者根據實際情況調整緩存context的個數。比如我們可以把個數設置為一個屏幕最多能展示的視頻條數。這樣很可能不超過5個。
///Add the widget's context and an unique string id that needs to be notified.void addContext({@required BuildContext context, @required String id}) { _contexts.add(_WidgetData(context: context, id: id)); }///Keeps the number of widget's contexts the InViewNotifierList should stored/cached for///the calculations thats needed to be done to check if the widgets are inView or not.///Defaults to 10 and should be greater than 1\. This is done to reduce the number of calculations being performed.void removeContexts(int letRemain) { if (_contexts.length > letRemain) { _contexts = _contexts.skip(_contexts.length - letRemain).toSet(); } }
這個實現方案基本滿足的場景一的規則。并且實現了局部刷新的監聽。
下面我們看下場景二,如果要基于當前視頻的位置做計算,這個庫支持不了。
可以看到它暴露的參數: 視頻控件上邊緣差值,下邊緣差值值,視窗高度H
//Check if the item is in the viewport by evaluating the provided widget's isInViewPortCondition condition. isInViewport = _isInViewCondition(deltaTop, deltaBottom, vpHeight);
如果我們要計算視頻控件自身的露出情況,需要單獨獲取控件的坐標和大小來計算。如果進行二次開發,只需要將判定函數擴展一些參數即可。
這兩種方案,在檢測視頻貼的邏輯上分別采用了主動檢測和被動檢測; 最大差異是我們沒有將視頻貼提前添加到集合中,所以不用維護一個固定容量的緩存集合。
關于Flutter視頻滾動播放的解決方案是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。