打造简单灵活的支持所有View的Android 空页面及错误页面


当页面加载数据失败,数据为空,或者数据加载中需要可以操作其他地方,我们应该怎么办?

体验良好的APP都会做相应的处理。

  1. 比如网络异常,会显示一个网络异常页面,提示用户去检查网络;

  2. 数据为空时,出现一个温馨的空页面,引导用户去创建数据等;

  3. 当数据在加载中时,我想按返回按钮,想切换tab,想做更多的事情时,弹出一个loading就不是那么友好了,直接在页面的内容显示区域显示加载中,问题就解决了。

这些方法各大app都在使用,但是怎么发开?每一个页面都写一个空页、面错误页面和loading页面吗?那也太恶心了吧。

下面我们一起打造简单灵活的支持所有View的Android 空页面及错误页面:

开始之前先看效果:

打造简单灵活的支持所有View的Android 空页面及错误页面.png

继承LinearLayout

public class EmptyLayout extends LinearLayout{

public EmptyLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

我们需要实现三种不同的页面,所以需要定义三种类型:


/**
    * The empty state
    */
   public final static int TYPE_EMPTY = 1;
   /**
    * The loading state
    */
   public final static int TYPE_LOADING = 2;
   /**
    * The error state
    */
   public final static int TYPE_ERROR = 3;

定义操作方法:


/**
     * 展示错误信息
     * @param resId 图片资源id
     * @param text
     */
    public void showError(int resId,String text)

/**
     * 展示空信息
     * @param resId 图片资源id
     * @param text
     */
    public void showEmpty(int resId,String text)

/**
     * 展示加载中
     * @param resId 图片资源id
     * @param text
     */
    public void showLoading(int resId,String text)

/**
     *隐藏EmptyLayout
     */
    public void hide()

获得EmptyLayout的子view,方便隐藏或者展示子view(这里的子view 一般用户展示本来的内容)

/**
     * 获得EmptyLayout的子view
     */
    private void getChildViews(){
        int childCount = getChildCount();
        Log.d("EmptyLayout","ChildCount:"+childCount);
        View view;
        for (int i=0;i<childCount;i++){
            view = getChildAt(i);
            if (isEmptyView(view)){
                continue;
            }
            childViews.add(view);
        }
    }

判断view 对象是否是EmptyView :


/**
     * 判断view 对象是否是EmptyView
     * @param view
     * @return
     */
    private boolean isEmptyView(View view){
        if ((view == null||mEmptyRelativeLayout == view||view == mLoadingView||view == mEmptyView||view == mErrorView)){
            return true;
        }
        return false;
    }

当数据为空时调用:

public void showEmpty(){

        getChildViews(); //获得除EmptyView的其他子view
        hideChildView(); //把子view隐藏了
        this.mEmptyType = TYPE_EMPTY;
        changeEmptyType();
        
    }

其他方法和这个类似,思路很简单,大家可以试试

使用很简单

在布局文件里增加:

<name.quanke.app.libs.emptylayout.EmptyLayout
        android:id="@+id/emptyLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/textHello"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />

</name.quanke.app.libs.emptylayout.EmptyLayout>

代码里增加:

findViewById(R.id.btnLoading).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                emptyLayout.showLoading();
            }
        });
        findViewById(R.id.btnEmpty).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                emptyLayout.showEmpty();
            }
        });
        findViewById(R.id.btnError).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                emptyLayout.showError();
            }
        });
        findViewById(R.id.btnData).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                emptyLayout.hide();
            }
        });

好了,使用起来就这么简单。。。支持所有的view

源码放在github上:https://github.com/quanke/AndroidEmptyLayout

欢迎讨论