[Harmony OS] [JAVA UI] webView animation loading resource loading animation interaction

When webview loads a web page in HarmonyOS, it needs a progress bar or loading animation for user-perceived interaction, which can optimize the user experience, so today I wrote a loading animation (the effect is as follows) for students to learn, how to achieve it? First of all, we need to learn the three knowledge reserves of " CommonDialog ", "  WebView " and " Animation Development Guide "

We are divided into "preparation stage", "custom CommonDialog implementation", "animation implementation", "webview implementation", "running effect" five steps to implement.

20220119-090152(WeLinkPC).gif

 

1. Preparation stage

Prepare a loading picture (picture below) in the resources \base\ media\ directory and the storage location is as follows

image.png

 

Loading pictures

image.png

Storage location

 

2. Customize the implementation of CommonDialog

2.1 Create a new xml named general_dialog.xml, and draw a picture in the xml file (the code is as follows)

<?xml version="1.0" encoding="utf-8"?>

<DirectionalLayout

    xmlns:ohos="http://schemas.huawei.com/res/ohos"

    ohos:height="80vp"

    ohos:orientation="vertical"

    ohos:alignment="center"

    ohos:width="80vp">

    <Image

        ohos:id="$+id:loading"

        ohos:height="match_parent"

        ohos:width="match_parent"

        ohos:scale_mode="clip_center"

        ohos:image_src="$media:loading"/>

</DirectionalLayout>

The effect diagram is as follows

image.png

 

2.2 Create a new GeneralDialog file, we refer to the custom CommonDialog scene example of HarmonyOS

The specific code is as follows

package com.harmony.alliance.mydemo.utils;
 
import java.util.Optional;
 
import com.harmony.alliance.mydemo.ResourceTable;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
 
public class GeneralDialog {
    private float dim = -1f;
    private   CommonDialog sDialog;
    private  Context mContext;
    private boolean mOutsideTouchClosable = false;
    public  GeneralDialog(Context context){
        this.mContext=context;
    }
    public void show() {
        if (sDialog != null) {
            sDialog.show();
            if (dim >= 0) {
                changeDialogDim(sDialog, dim);
            }
        }
    }
    public void remove(){
        if (sDialog != null) {
            sDialog.destroy();
        }
    }
    public void create() {
         sDialog = new CommonDialog(mContext);
        sDialog.setSize(ComponentContainer.LayoutConfig.MATCH_CONTENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
        sDialog.setAlignment(LayoutAlignment.CENTER);
        sDialog.setOffset(0,0);
        sDialog.setTransparent(true);
        sDialog.setContentCustomComponent(initDialog(sDialog));
        sDialog.setAutoClosable(mOutsideTouchClosable);
    }
 
 
 
    private void changeDialogDim(CommonDialog dialog, float dim) {
        Optional<WindowManager.LayoutConfig> configOpt = dialog.getWindow().getLayoutConfig();
        configOpt.ifPresent(config -> {
            config.dim = dim;
            dialog.getWindow().setLayoutConfig(config);
        });
    }
 
    public interface ClickedListener{
        void onClick(GeneralDialog dialog);
    }
 
 
    private Component initDialog(CommonDialog sDialog) {
        Component dialogLayout = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_general_dialog, null, false);
        dialogLayout.setBackground(new ShapeElement(){{
            setRgbColor(RgbColor.fromArgbInt(ResourceTool.getColor(mContext, ResourceTable.Color_bg_dialog_light, 0xffffff)));
            setCornerRadius(ResourceTool.getFloat(mContext, ResourceTable.Float_dialog_corner_radius, 0));
        }});
        Image image= (Image) dialogLayout.findComponentById(ResourceTable.Id_loading);
      
        return dialogLayout;
    }
 
}

 2.2.3 Call the following code under the onStart method of MainAbility

GeneralDialog mGeneralDialog = new GeneralDialog(getContext());

        mGeneralDialog.create();

        mGeneralDialog.show();

The effect is as follows

image.png

 

2.3 Animation implementation

2.3.1 Animation function We can refer to the relevant knowledge points of AnimatorProperty in the HarmonyOS animation development guide . Next, we initDialog to open the animation function code of image as follows

Image image= (Image) dialogLayout.findComponentById(ResourceTable.Id_loading);

        animatorProperty    = new AnimatorProperty();

        animatorProperty.setTarget(image);

        animatorProperty

                .rotate(360)

                //无限循环

                .setLoopedCount(AnimatorValue.INFINITE)

                //反弹力效果

                .setCurveType(Animator.CurveType.BOUNCE);

 

        if(sDialog!=null){

            sDialog.setDestroyedListener(new CommonDialog.DestroyedListener() {

                @Override

                public void onDestroy() {

                    if(animatorProperty.isRunning()){

                        animatorProperty.stop();

                    }

                }

            });

        }

2.3.2 Write an open animation method in the GeneralDialog class (the code is as follows)

public void   StartanimatorProperty(){

        if(animatorProperty!=null&&animatorProperty.isRunning()){

            animatorProperty.stop();

        }

        if(animatorProperty!=null&&!animatorProperty.isRunning()){

            if(!animatorProperty.isRunning()){

                animatorProperty.start();

            }

        }

}

2.3.3 Seal a tool class for displaying, playing and disappearing the loading popup (the code is as follows)

package com.harmony.alliance.mydemo.utils;
 
import ohos.app.Context;
 
public class LoadingDialogUtils {
    private static   GeneralDialog mGeneralDialog;
    public static  GeneralDialog  getInstance(Context mContext){
        if(mGeneralDialog==null){
            mGeneralDialog=new GeneralDialog(mContext);
        }
        return  mGeneralDialog;
    }
 
    public static void show(Context mContext){
        LoadingDialogUtils.getInstance(mContext);
        mGeneralDialog.create();
        mGeneralDialog.show();
        mGeneralDialog.StartanimatorProperty();
    }
    public static void dismiss(Context mContext){
        LoadingDialogUtils.getInstance(mContext);
        mGeneralDialog.remove();
    }
}

2.3.4 The code for opening the animation is as follows

  LoadingDialogUtils.show(MainAbility.this);

The closing animation code is as follows

LoadingDialogUtils.dismiss(MainAbility.this);

 

 2.4 Implementation of webview

webview loads web pages, we can refer to the components of HarmonyOS's WebView

2.4.1 We learn to observe the setWebAgent of the Web state (the code is as follows)

webView.setWebAgent(new WebAgent() {

    @Override

    public void onLoadingPage(WebView webview, String url, PixelMap favicon) {

        super.onLoadingPage(webview, url, favicon);

        //todo  页面开始加载时自定义处理 开启动画

    }

 

    @Override

    public void onPageLoaded(WebView webview, String url) {

        super.onPageLoaded(webview, url);

         // todo 页面加载结束后自定义处理 关闭动画

    }

 

    @Override

    public void onLoadingContent(WebView webview, String url) {

        super.onLoadingContent(webview, url);

        // 加载资源时自定义处理

    }

 

    @Override

    public void onError(WebView webview, ResourceRequest request, ResourceError error) {

        super.onError(webview, request, error);

        //todo 发生错误时自定义处理 关闭动画

    }

});

2.4.2 We create a new java class of abilitySlice, and the new layout code is as follows

<?xml version="1.0" encoding="utf-8"?>

<DirectionalLayout

    xmlns:ohos="http://schemas.huawei.com/res/ohos"

    ohos:height="match_parent"

    ohos:width="match_parent"

    ohos:orientation="vertical">

    <ohos.agp.components.webengine.WebView

        ohos:id="$+id:my_webView"

        ohos:height="match_parent"

        ohos:width="match_parent">

    </ohos.agp.components.webengine.WebView>

 

</DirectionalLayout>

2.4.3 The java class code of webview is as follows

package com.harmony.alliance.mydemo.slice;
 
import com.harmony.alliance.mydemo.ResourceTable;
import com.harmony.alliance.mydemo.utils.LoadingDialogUtils;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.webengine.*;
import ohos.media.image.PixelMap;
 
public class NewMyWebview  extends AbilitySlice {
    private WebView mMyWebview;
    private static final String EXAMPLE_URL = "https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-fa-calls-pa-examples-0000000000618000";
    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        setUIContent(ResourceTable.Layout_new_my_webview);
        mMyWebview= (WebView) findComponentById(ResourceTable.Id_my_webView);
        WebConfig webConfig = mMyWebview.getWebConfig();
        webConfig.setJavaScriptPermit(true);
        webConfig.setWebStoragePermit(true);
        webConfig.setDataAbilityPermit(true);
        webConfig.setLoadsImagesPermit(true);
        webConfig.setMediaAutoReplay(true);
        webConfig.setLocationPermit(true);
        webConfig.setSecurityMode(WebConfig.SECURITY_SELF_ADAPTIVE);
        mMyWebview.setWebAgent(new WebAgent() {
            @Override
            public void onLoadingPage(WebView webview, String url, PixelMap favicon) {
                super.onLoadingPage(webview, url, favicon);
                //todo  页面开始加载时自定义处理 开启动画
                LoadingDialogUtils.show(NewMyWebview.this);
            }
 
            @Override
            public void onPageLoaded(WebView webview, String url) {
                super.onPageLoaded(webview, url);
                // todo 页面加载结束后自定义处理 关闭动画
                LoadingDialogUtils.dismiss(NewMyWebview.this);
            }
 
            @Override
            public void onLoadingContent(WebView webview, String url) {
                super.onLoadingContent(webview, url);
                // 加载资源时自定义处理
            }
 
            @Override
            public void onError(WebView webview, ResourceRequest request, ResourceError error) {
                super.onError(webview, request, error);
                //todo  发生错误时自定义处理 关闭动画
                LoadingDialogUtils.dismiss(NewMyWebview.this);
            }
        });
        mMyWebview.load(EXAMPLE_URL);
 
 
    }
}
 

2.5 The operation effect is as follows

All codes are as follows

2.5.1general_dialog.xml code

<?xml version="1.0" encoding="utf-8"?>

<DirectionalLayout

    xmlns:ohos="http://schemas.huawei.com/res/ohos"

    ohos:height="80vp"

    ohos:orientation="vertical"

    ohos:alignment="center"

    ohos:width="80vp">

    <Image

        ohos:id="$+id:loading"

        ohos:height="match_parent"

        ohos:width="match_parent"

        ohos:scale_mode="clip_center"

        ohos:image_src="$media:loading"/>

 

</DirectionalLayout>

2.5.2 java class of GeneralDialog

//请根据实际工程/包名引入

package com.harmony.alliance.mydemo.utils;

 

import java.util.Optional;

 

import com.harmony.alliance.mydemo.ResourceTable;

import ohos.agp.animation.Animator;

import ohos.agp.animation.AnimatorProperty;

import ohos.agp.animation.AnimatorValue;

import ohos.agp.colors.RgbColor;

import ohos.agp.components.*;

import ohos.agp.components.element.ShapeElement;

import ohos.agp.utils.LayoutAlignment;

import ohos.agp.window.dialog.CommonDialog;

import ohos.agp.window.service.WindowManager;

import ohos.app.Context;

 

public class GeneralDialog {

    private float dim = -1f;

    private    AnimatorProperty animatorProperty;

    private   CommonDialog sDialog;

    private  Context mContext;

    private boolean mOutsideTouchClosable = false;

    public  GeneralDialog(Context context){

        this.mContext=context;

    }

    public void show() {

        if (sDialog != null) {

            sDialog.show();

            if (dim >= 0) {

                changeDialogDim(sDialog, dim);

            }

        }

    }

    public void remove(){

        if (sDialog != null) {

            sDialog.destroy();

        }

    }

    public void create() {

         sDialog = new CommonDialog(mContext);

        sDialog.setSize(ComponentContainer.LayoutConfig.MATCH_CONTENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);

        sDialog.setAlignment(LayoutAlignment.CENTER);

        sDialog.setOffset(0,0);

        sDialog.setTransparent(true);

        sDialog.setContentCustomComponent(initDialog(sDialog));

        sDialog.setAutoClosable(mOutsideTouchClosable);

    }

 

    public void   StartanimatorProperty(){

        if(animatorProperty!=null&&animatorProperty.isRunning()){

            animatorProperty.stop();

        }

        if(animatorProperty!=null&&!animatorProperty.isRunning()){

            if(!animatorProperty.isRunning()){

                animatorProperty.start();

            }

        }

    }

 

    private void changeDialogDim(CommonDialog dialog, float dim) {

        Optional<WindowManager.LayoutConfig> configOpt = dialog.getWindow().getLayoutConfig();

        configOpt.ifPresent(config -> {

            config.dim = dim;

            dialog.getWindow().setLayoutConfig(config);

        });

    }

 

    public interface ClickedListener{

        void onClick(GeneralDialog dialog);

    }

 

 

    private Component initDialog(CommonDialog sDialog) {

        Component dialogLayout = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_general_dialog, null, false);

        dialogLayout.setBackground(new ShapeElement(){{

            setRgbColor(RgbColor.fromArgbInt(ResourceTool.getColor(mContext, ResourceTable.Color_bg_dialog_light, 0xffffff)));

            setCornerRadius(ResourceTool.getFloat(mContext, ResourceTable.Float_dialog_corner_radius, 0));

        }});

        Image image= (Image) dialogLayout.findComponentById(ResourceTable.Id_loading);

        animatorProperty    = new AnimatorProperty();

        animatorProperty.setTarget(image);

        animatorProperty

                .rotate(360)

                //无限循环

                .setLoopedCount(AnimatorValue.INFINITE)

                //反弹力效果

                .setCurveType(Animator.CurveType.BOUNCE);

 

        if(sDialog!=null){

            sDialog.setDestroyedListener(new CommonDialog.DestroyedListener() {

                @Override

                public void onDestroy() {

                    if(animatorProperty.isRunning()){

                        animatorProperty.stop();

                    }

                }

            });

        }

        return dialogLayout;

    }

 

}

2.5.3 The tool class of LoadingDialogUtils is as follows

package com.harmony.alliance.mydemo.utils;

 

import ohos.app.Context;

 

public class LoadingDialogUtils {

    private static   GeneralDialog mGeneralDialog;

    private static  GeneralDialog  getInstance(Context mContext){

        if(mGeneralDialog==null){

            mGeneralDialog=new GeneralDialog(mContext);

        }

        return  mGeneralDialog;

    }

 

    public static void show(Context mContext){

        LoadingDialogUtils.getInstance(mContext);

        mGeneralDialog.create();

        mGeneralDialog.show();

        mGeneralDialog.StartanimatorProperty();

    }

    public static void dismiss(Context mContext){

        LoadingDialogUtils.getInstance(mContext);

        mGeneralDialog.remove();

    } 

}

2.5.4 The xml code of the layout of webViewAbilitySlice is as follows

<?xml version="1.0" encoding="utf-8"?>

<DirectionalLayout

    xmlns:ohos="http://schemas.huawei.com/res/ohos"

    ohos:height="match_parent"

    ohos:width="match_parent"

    ohos:orientation="vertical">

    <ohos.agp.components.webengine.WebView

        ohos:id="$+id:my_webView"

        ohos:height="match_parent"

        ohos:width="match_parent">

    </ohos.agp.components.webengine.WebView>

 

</DirectionalLayout>

2.5.5 The class code of WebViewAbiltySlice is as follows

package com.harmony.alliance.mydemo.slice;

 

import com.harmony.alliance.mydemo.ResourceTable;

import com.harmony.alliance.mydemo.utils.LoadingDialogUtils;

import ohos.aafwk.ability.AbilitySlice;

import ohos.aafwk.content.Intent;

import ohos.agp.components.webengine.*;

import ohos.media.image.PixelMap;

 

public class NewMyWebview  extends AbilitySlice {

    private WebView mMyWebview;

    private static final String EXAMPLE_URL = "https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-fa-calls-pa-examples-0000000000618000";

    @Override

    protected void onStart(Intent intent) {

        super.onStart(intent);

        setUIContent(ResourceTable.Layout_new_my_webview);

        mMyWebview= (WebView) findComponentById(ResourceTable.Id_my_webView);

        WebConfig webConfig = mMyWebview.getWebConfig();

        webConfig.setJavaScriptPermit(true);

        webConfig.setWebStoragePermit(true);

        webConfig.setDataAbilityPermit(true);

        webConfig.setLoadsImagesPermit(true);

        webConfig.setMediaAutoReplay(true);

        webConfig.setLocationPermit(true);

        webConfig.setSecurityMode(WebConfig.SECURITY_SELF_ADAPTIVE);

        mMyWebview.setWebAgent(new WebAgent() {

            @Override

            public void onLoadingPage(WebView webview, String url, PixelMap favicon) {

                super.onLoadingPage(webview, url, favicon);

                //todo  页面开始加载时自定义处理 开启动画

                LoadingDialogUtils.show(NewMyWebview.this);

            }

 

            @Override

            public void onPageLoaded(WebView webview, String url) {

                super.onPageLoaded(webview, url);

                // todo 页面加载结束后自定义处理 关闭动画

                LoadingDialogUtils.dismiss(NewMyWebview.this);

            }

 

            @Override

            public void onLoadingContent(WebView webview, String url) {

                super.onLoadingContent(webview, url);

                // 加载资源时自定义处理

            }

 

            @Override

            public void onError(WebView webview, ResourceRequest request, ResourceError error) {

                super.onError(webview, request, error);

                //todo  发生错误时自定义处理 关闭动画

                LoadingDialogUtils.dismiss(NewMyWebview.this);

            }

        });

        mMyWebview.load(EXAMPLE_URL);

     }

}

The effect is as follows

20220119-090152(WeLinkPC).gif

{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4478396/blog/5504573