Android: Use addContentView() to encapsulate easy-to-use universal loading and prevent repeated clicks on page buttons

O. Preface

In application development, since accessing the network is a time-consuming operation, when the page loads data or submits data, we generally display a loading loading diagram on the page, prompting the user to wait for a while. There are many ways to implement loading loading graphs. For example, some refreshing frameworks come with loading graphs when the user pulls down to refresh, or use Dialog to customize loading pop-ups. When it needs to be displayed, showDialog can be dismissed when it needs to be hidden.

However, in actual use, the drop-down loading that comes with the refresh framework often cannot be used when submitting data, and the custom Dialog may have an exception of form leakage during use. This article will introduce a different from the above The loading method of the method is implemented: With the addContentView() method of the Activity, a general loading is encapsulated in the base class of the Activity. The subclasses can be used directly and optimized to prevent repeated clicks of the page buttons.

1. Encapsulate a general loading in the base class of Activity

Android projects generally have an Activity base class BaseActivity, directly add the following code in BaseActivity:

    /**
     * mliuxb:通用的Loading加载图
     * 使用方法:在需要显示Loading的地方调用showCenterLoading(),在需要隐藏loading的地方调用hideCenterLoading()即可
     * 若需修改Loading底部的文字提示则调用重载方法showCenterLoading(String text)
     * 注意:以下三个方法在本类中没有调用,而是在子类中调用,所以不影响本基类的任何逻辑
     */
    private LinearLayout llLoading;
    private TextView tvLoading;

    /**
     * 显示Loading
     */
    public void showCenterLoading() {
        showCenterLoading("数据加载中...");
    }

    /**
     * 显示Loading
     */
    public void showCenterLoading(String text) {
        addLoadingView();
        if (llLoading != null && tvLoading != null) {
            tvLoading.setText(text);
            llLoading.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 隐藏Loading
     */
    public void hideCenterLoading() {
        if (llLoading != null) {
            llLoading.setVisibility(View.GONE);
        }
    }

    /**
     * 添加Loading布局
     */
    private void addLoadingView() {
        if (llLoading == null || tvLoading == null) {
            final View loadingView = View.inflate(this, R.layout.layout_global_center_loading, null);
            final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            params.gravity = Gravity.CENTER;
            addContentView(loadingView, params);//核心方法
            llLoading = findViewById(R.id.ll_global_center_loading);
            tvLoading = findViewById(R.id.tv_global_center_loading);
        }
    }

The layout file layout_global_center_loading is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ll_global_center_loading"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/shape_global_center_loading_bg"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="20dp"
    android:visibility="gone">

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminateDrawable="@drawable/anim_global_rotate_loading" />

    <TextView
        android:id="@+id/tv_global_center_loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:textColor="@android:color/black"
        android:textSize="14sp"
        tools:text="数据加载中..." />
</LinearLayout>

The shape_global_center_loading_bg in the layout file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">

    <!--颜色-->
    <solid android:color="#CCCCCCCC"/>

    <!--给矩形加圆角-->
    <corners android:radius="10dp"/>

    <!--边框-->
    <!--<stroke android:width="5dp" android:color="@color/blue_base"/>-->

</shape>

The anim_global_rotate_loading in the layout file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_global_center_loading"
    android:fromDegrees="0"
    android:toDegrees="1800">

</rotate>

The above is to encapsulate a general loading in the base class of Activity, call it in the subclass as described in the comments, call showCenterLoading() where loading needs to be displayed, and call hideCenterLoading() where loading needs to be hidden.

The two methods are available everywhere and avoid the risk of form leakage in the custom Dialog. Generally, the showCenterLoading() method is called before the network access request is sent, and hideCenterLoading() is called after the response is received.

2. Optimize loading to prevent repeated clicks on page buttons

In the actual use process of the application, due to the network stuck or the function is too time-consuming, users will inevitably carry out repeated operations in a hurry. If the data is submitted (that is, the database is writing data), it may cause multiple submissions. The database may write data multiple times, resulting in dirty data. At this time, it is necessary for the server to perform verification. Of course, it is also necessary to add the first line of defense on the front end.

When the front end interacts with the server, our loading loading diagram is displayed at this time. This time period happens to be the time to avoid repeated operations by the user, so modify the loading diagram to full screen and set the root layout to android:clickable="true "At this time, the layout of the normal page at the bottom layer is covered and cannot respond to clicks and other operations, which avoids repeated clicks by users.

Modify the code in the BaseActivity base class as follows:

    /**
	 * mliuxb更新:通用的Loading加载图
	 * 使用方法:在需要显示Loading的地方调用showCenterLoading(),在需要隐藏loading的地方调用hideCenterLoading()即可
	 * 若需修改Loading底部的文字提示则调用重载方法showCenterLoading(String text)
	 * 注意:以下三个方法在本类中没有调用,而是在子类中调用,所以不影响本类的任何逻辑
	 */
	private FrameLayout flLoading;
	private TextView tvLoading;

	/**
	 * 显示Loading
	 */
	public void showCenterLoading() {
		showCenterLoading("数据加载中...");
	}

	/**
	 * 显示Loading
	 */
	public void showCenterLoading(String text) {
		addLoadingView();
		if (flLoading != null && tvLoading != null) {
			tvLoading.setText(text);
			flLoading.setVisibility(View.VISIBLE);
		}
	}

	/**
	 * 隐藏Loading
	 */
	public void hideCenterLoading() {
		if (flLoading != null) {
			flLoading.setVisibility(View.GONE);
		}
	}

	/**
	 * 添加Loading布局
	 */
	private void addLoadingView() {
		if (flLoading == null || tvLoading == null) {
			final View loadingView = View.inflate(this, R.layout.layout_global_center_loading, null);
			final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
			params.gravity = Gravity.CENTER;
			addContentView(loadingView, params);//核心方法
			flLoading = findViewById(R.id.fl_global_center_loading);
			tvLoading = findViewById(R.id.tv_global_center_loading);
		}
	}

The main reason is that the layout parameters are changed from FrameLayout.LayoutParams.WRAP_CONTENT to FrameLayout.LayoutParams.MATCH_PARENT to ensure that the loading layout is full screen.

The corresponding layout file layout_global_center_loading is modified as follows:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fl_global_center_loading"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:clickable="true"
    android:focusable="true"
    android:visibility="gone">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@drawable/shape_global_center_loading_bg"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="20dp">

        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminateDrawable="@drawable/anim_global_rotate_loading" />

        <TextView
            android:id="@+id/tv_global_center_loading"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:textColor="@android:color/black"
            android:textSize="14sp"
            tools:text="数据加载中..." />
    </LinearLayout>
</FrameLayout>

As above, first add a layer of FrameLayout nesting, make the root layout FrameLayout match_parent to ensure that the original loading size remains unchanged, and then set the root layout android:clickable="true", at this time the underlying layout is covered and cannot respond Click and so on.

Among them, shape_global_center_loading_bg and anim_global_rotate_loading remain unchanged, the same as above.

 

 

Guess you like

Origin blog.csdn.net/beita08/article/details/115028939