鴻蒙開源第三方組件的遷移-加載動畫庫
https://harmonyos.51cto.com/#zz
前言
基于安卓平臺的加載動畫庫AVLoadingIndicatorView(https://github.com/81813780/AVLoadingIndicatorView),實現了鴻蒙化遷移和重構,代碼已經開源到(https://gitee.com/iscas-ohos/avloading-indicator-view_ohos.git),歡迎各位下載使用并提出寶貴意見!
背景
服務器在加載數據的時候有時需要等待一段時間,加載動畫可以緩解用戶等待過程中的焦慮情緒,使等待過程變得更加友好、流暢。AVLoadingIndicatorView是一個開源的加載動畫庫,通過動畫庫的調用,可以實現各種各樣的加載效果。
組件功能展示
1. 動畫效果
在原Android版本中,本組件庫里共有28個加載動畫,鴻蒙版本的組件庫成功實現其中21種動畫效果。由于鴻蒙系統部分API功能缺失,目前有7個動畫效果未成功遷移。

圖1 AVLoadingIndicatorView效果示意圖
圖1所示為鴻蒙平臺的AVLoadingIndicatorView的動畫效果展示,可分為6行4列,動畫效果的對應名稱(從左至右)如下:
Row 1 BallPulseIndicator,BallGridPulseIndicator,BallClipRotateIndicator,BallClipRotatePulseIndicator
Row 2 PacmanIndicator,BallClipRotateMultipleIndicator, SemiCircleSpinIndicator,BallRotateIndicator
Row 3 BallScaleIndicator,LineScaleIndicator,LineScalePartyIndicator,BallScaleMultipleIndicator
Row 4 BallPulseSyncIndicator,BallBeatIndicator,LineScalePulseOutIndicator,LineScalePulseOutRapidIndicator
Row 5 BallScaleRippleIndicator,BallScaleRippleMultipleIndicator,BallSpinFadeLoaderIndicator,LineSpinFadeLoaderIndicator
Row 6 BallGridBeatIndicator
2. 動畫控制效果
AVLoadingIndicatorView組件支持對各加載動畫的效果進行控制,控制類型分為4種:動畫啟動、動畫停止、動畫顯示和動畫隱藏。動畫啟動和動畫停止相互關聯,二者用于控制動畫是否運行;動畫顯示和動畫隱藏相互關聯,二者用于控制動畫是否出現,控制效果如圖2所示。

圖2 四種效果控制示意圖
Sample解析
本組件庫中的每個動畫都有啟動、停止、隱藏和顯示四種控制效果。為了方便調試和演示,Sample中將所有動畫的對象放入同一個list,通過四個不同的按鈕,控制所有動畫同時啟動、停止、隱藏和顯示,效果如圖2所示。
下面介紹控制所有動畫同時啟動、停止、隱藏和顯示的步驟:
1、導入AVLoadingIndicatorView類
- import com.wang.avi.AVLoadingIndicatorView;
2、動畫添加到Layout
此處需要將所有動畫添加到Layout中,并將各動畫的對象放入同一list(即代碼中的animatorList)。
- //以BallPulseIndicator為例
- myLayout.addComponent(ballPulseIndicator);//BallPulseIndicator添加到Layout
- animatorList.add(ballPulseIndicator);//BallPulseIndicator對象放入list
- //以BallGridPulseIndicator為例
- myLayout.addComponent(ballGridPulseIndicator);
- animatorList.add(ballGridPulseIndicator);
3、設置四個按鈕,用以控制所有動畫同時啟動、停止、隱藏和顯示。
以"啟動"效果為例,startBtn按鈕設置了Click監聽,按下按鈕時,會執行startAllAnimator ()方法,startAllAnimator ()方法中借助for循環,遍歷animatorList中的每一個動畫的對象,并調用每個對象的start()方法,達到動畫啟動的效果。
- //按鈕監聽
- startBtn.setClickedListener(component-> startAllAnimator(animatorList));//啟動
- endBtn.setClickedListener(component-> stopAllAnimator(animatorList));//停止
- hideBtn.setClickedListener(component-> hideAllAnimator(animatorList));//隱藏
- showBtn.setClickedListener(component-> showAllAnimator(animatorList));//顯示
- //start
- private void startAllAnimator(ArrayList<AVLoadingIndicatorView> avLoadingIndicatorViews){
- for (int i = 0; i < avLoadingIndicatorViews.size(); i++) {
- avLoadingIndicatorViews.get(i).start();//啟動
- }
- }
- //stop
- private void stopAllAnimator(ArrayList<AVLoadingIndicatorView> avLoadingIndicatorViews){
- for (int i = 0; i < avLoadingIndicatorViews.size(); i++) {
- avLoadingIndicatorViews.get(i).stop();//停止
- }
- }
- //hide
- private void hideAllAnimator(ArrayList<AVLoadingIndicatorView> avLoadingIndicatorViews){
- for (int i = 0; i < avLoadingIndicatorViews.size(); i++) {
- avLoadingIndicatorViews.get(i).hide();//隱藏
- }
- }
- //show
- private void showAllAnimator(ArrayList<AVLoadingIndicatorView> avLoadingIndicatorViews){
- for (int i = 0; i < avLoadingIndicatorViews.size(); i++) {
- avLoadingIndicatorViews.get(i).show();//顯示
- }
- }
Library解析
1. 功能實現
每個動畫效果的繪制都需要執行初始化設置、添加繪畫任務、創建動畫三個步驟,下面以BallPulseIndicator為例對這三個步驟進行詳細介紹。
(1) 初始化設置 聲明setPaint(),setBound(),draw()方法。
- public BallPulseIndicator(Context context) {
- super(context);
- Component.DrawTask task = (component, canvas) -> {
- setPaint();//設置畫筆
- setBound();//設置動畫邊界
- draw(canvas,getPaint());//內容繪制
- };
- addDrawTask(task);
- }
(2) 動畫繪制 用draw()方法在畫布上繪制動畫樣式。
由于BallPulseIndicator動畫主體是三個圓,第二、第三個圓均是由前一個圓平移得到,因此要設置每兩個圓之間的距離,圓的半徑大小等屬性。
- public void draw(Canvas canvas, Paint paint) {
- float circleSpacing=4; //設置圓之間距離
- float radius=(Math.min(getWidth(),getHeight())-circleSpacing*2)/6; //設置圓的半徑大小
- float x = getWidth()/ 2-(radius*2+circleSpacing);//圓心的x軸坐標
- float y=getHeight() / 2;//圓心的y軸坐標
- for (int i = 0; i < 3; i++) {
- canvas.save();
- float translateX=x+(radius*2)*i+circleSpacing*i;//平移后新圓心的x軸坐標
- canvas.translate(translateX, y);
- canvas.scale(scaleFloats[i], scaleFloats[i]);//縮放效果繪制
- canvas.drawCircle(0, 0, radius, paint);//繪制圓
- canvas.restore();
- }
- }
(3) 動畫參數設置
通過AnimatorValue對動畫參數進行具體設置,包括動畫的持續時間、重復次數、啟動延遲時間、縮放和旋轉等(BallPulseIndicator只涉及縮放而無旋轉)。
- public ArrayList<AnimatorValue> onCreateAnimators() {
- ArrayList<AnimatorValue> animators=new ArrayList<>();
- int[] delays=new int[]{120,240,360}; //設置三個圓的延遲時間
- for (int i = 0; i < 3; i++) {
- final int index=i;
- AnimatorValue scaleAnim=new AnimatorValue(); //值動畫
- scaleAnim.setDuration(750); //動畫持續時間
- scaleAnim.setLoopedCount(-1); //動畫無限次重復
- scaleAnim.setDelay(delays[i]); //每個圓的延遲時間
- addUpdateListener(scaleAnim, (animatorValue, v) -> {
- scaleFloats[index] = v;//控制縮放
- invalidate();//刷新界面
- });
- animators.add(scaleAnim);
- }
- return animators;
- }
2. 移植方法
(1) API直接替換
在安卓中使用ValueAnimator類設置加載動畫的屬性,移植之后這些功能主要基于鴻蒙的AnimatorValue類實現。這兩個類中的方法名也不同,在進行鴻蒙化遷移時需要根據功能逐一替換。例如:鴻蒙中使用setLoopedCount()方法替換原setRepeatCount()方法來實現動畫重復次數的設置。
(2) 函數重寫
鴻蒙的AnimatorValue類相比較于安卓,缺少很多接口,若在實現部分復雜動畫時,需要調用這些接口,只能采用函數重寫的方法,這也是移植中的主要難點。如安卓中用ValueAnimator.ofFloat(1,0.5f,1)來設置動畫的屬性值1—0.5f—1的兩次變化,實現動畫的運行效果,而鴻蒙中缺少該接口,屬性值只能在0—1之間單次變化,無法實現動畫的完美效果,需要進行功能重寫,下面給出此功能重寫的代碼 。
- public void onUpdate(AnimatorValue animatorValue, float v) {
- if(v<=0.5f)
- scaleFloats[index] =1-v;
- else
- scaleFloats[index] = v;
- invalidate();
- }
©著作權歸作者和HarmonyOS技術社區共同所有,如需轉載,請注明出處,否則將追究法律責任。
https://harmonyos.51cto.com/#zz