自定义View之MultiStateView根据不同状态显示不同布局的View(雷惊风)

   想成为大牛就必须扫清研发道路上的每一个障碍,其中自定义控件这个障碍相信对于初上路者来说就是一个不小的障碍,今天就跟大家一起来一步一步的写一个自定义控件(DEMO下载),支持通过设置不同状态在界面上显示不同布局,多用于网络请求,如网络请求失败了显示一种错误提示的布局、请求过程中显示另一种布局,请求回来数据了又是一种布局,服务器没有数据还是不同的布局。先看一下实现后的效果:


好了,知道了我们今天要干的事了,那么就让我们屡一下实现思路,共分为如下几步:

1.创建Java类实现FrameLayout,attrs中定义相关属性;

2.定义每种布局对应的标志及View、标志状态的枚举类;

3.在构造函数中初始化自定义属性;

4.onAttachedToWindow()方法中赋值当正常显示的View,并设置初始状态下的View;

5.设置对外公开的一些方法。

只需要如上几步就可以实现我们的View了,就不啰嗦了,开始吧。一步一步来,先看第一步,我们创建一个Java类实现FrameLayout,代码如下:

public class MyMultiStateView extends FrameLayout {

    /**
     * when creating a view from code.
     * 当我们在代码中以new的方式创建View时调用当前方法创建View对象;
     *
     * @param context
     */
    public MyMultiStateView(@NonNull Context context) {
        super(context);
    }

    /***
     * 当在Layout中定义MyMultiStateView时,系统调用当前方法创建View对象,可以通过AttributeSet获取自定义属性内容;
     * @param context
     * @param attrs
     */
    public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

    }

    /**
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }}

然后在res/values目录下新建attrs文件,写如我们需要的自定义属性,如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyMultiStateView">
        <attr name="emptyView" format="reference" />
        <attr name="errorView" format="reference" />
        <attr name="loadingView" format="reference" />
        <attr name="initialViewStatus" format="enum">
            <enum name="load" value="0" />
            <enum name="empty" value="1" />
            <enum name="error" value="2" />
            <enum name="inxmlshow" value="3" />
        </attr>
    </declare-styleable>
</resources>

这里解释一下MyMultiStateView为我们的自定义控件,四个<attr/>标签代表我们在Layout中用MyMultiStateView时用到的属性,name为自定义属性名称,如:android:id=”...”中的id;format为类型,很多种color、Integer等,这里的reference代表资源id;enum代表枚举,枚举的值就是内部四个<enum>的name值。以上自定义属性中的emptyView定义无数据时显示的View,errorView定义访问出问题使得View,loadingView定义加载时的View,initialViewStatus定义初始化MyMultiStateView时的状态(是处于loading状态还是error状态还是empty状态)。好了,第一步就算是完成了。

   接下来看第二步设置一些辅助变量。首先我们定义一个表示不同状态的枚举类,代码如下:

public enum ViewStatus {
    errorStatus,
    loadingStatus,
    emptyStatus,
    inXMLViewStatus

}

然后就是一些成员变量:

public class MyMultiStateViewextendsFrameLayout {

private LayoutInflatermInflater;//加载各种状态布局的Inflater;
private ViewmErrorView;//当处于error状态下要显示的View;
private ViewmEmptyView;//当处于empty状态下要显示的View;
private ViewmLoadingView;//当处于loading状态下要显示的View;
private ViewmInXMLView;//正常状态显示的View;(就是我们在XML中定义MyMultiStateView时包裹的子View)
private ViewStatusmViewStatus= ViewStatus.loadingStatus;//记录当前正处于的状态;
private final int STATUS_LOADVIEW=0;//以下四种为四种不同状态标识;
private final int STATUS_EMPTYVIEW=1;
private final int STATUS_ERRORVIEW=2;
private final int STATUS_INXMLVIEW=3;

//省略构造方法;

...

}

这样我们的的准备工作就算是做完了。下边看第三步:从XML中获取自定义属性并赋值相应View,代码如下:

/**
 * when creating a view from code.
 * 当我们在代码中以new的方式创建View时调用当前方法创建View对象;
 *
 * @param context
 */
public MyMultiStateView(@NonNull Context context) {
    this(context, null);
}

/***
 * 当在Layout中定义MyMultiStateView时,系统调用当前方法创建View对象,可以通过AttributeSet获取自定义属性内容;
 * @param context
 * @param attrs
 */
public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);

}

/**
 * @param context
 * @param attrs
 * @param defStyleAttr
 */
public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(attrs);
}

public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

private void init(AttributeSet attrs) {
    mInflater = LayoutInflater.from(getContext());
    //获取各个状态对应的View,并添加到当前View;
    TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyMultiStateView);
    int errorViewId = ta.getResourceId(R.styleable.MyMultiStateView_errorView, -1);
    if (errorViewId != -1) {
        mErrorView = mInflater.inflate(errorViewId, null, false);
        addView(mErrorView);
    }
    int emptyViewId = ta.getResourceId(R.styleable.MyMultiStateView_emptyView, -1);
    if (errorViewId != -1) {
        mEmptyView = mInflater.inflate(emptyViewId, null, false);
        addView(mEmptyView);
    }
    int loadViewId = ta.getResourceId(R.styleable.MyMultiStateView_loadingView, -1);
    if (loadViewId != -1) {
        mLoadingView = mInflater.inflate(loadViewId, null, false);
        addView(mLoadingView);
    }
    //获取初始状态时定义的显示状态;
    int initailViewStatus = ta.getInt(R.styleable.MyMultiStateView_initialViewStatus, -1);
    if (initailViewStatus != -1) {
        switch (initailViewStatus) {
            case STATUS_LOADVIEW:
                mViewStatus = ViewStatus.loadingStatus;
                break;
            case STATUS_EMPTYVIEW:
                mViewStatus = ViewStatus.emptyStatus;
                break;
            case STATUS_ERRORVIEW:
                mViewStatus = ViewStatus.errorStatus;
                break;
            case STATUS_INXMLVIEW:
                mViewStatus = ViewStatus.inXMLViewStatus;
                break;
        }
    }
ta.recycle();

}

大家都知道当我们在java文件中以new的方式创建一个View的时候,会调用单参数的构造函数,在XML中定义View的时候会调用两个参数的构造函数,我们没有给View设置style,所以我们重点关注前两个构造函数,上边的代码很简单,获取了在XML中定义的不同情况下要显示的View,如果设置了,则赋值给对应的View,这里调用了一个addView()方法,后边说,接着获取了初始状态处于的status,赋值给mViewStatus。看一下这个addView()方法,我们实现了父类的几个addview相关方法,如下:

@Override
public void addView(View child) {
    if (isInXMLView(child))
        mInXMLView = child;
    super.addView(child);
}

@Override
public void addView(View child, int index) {
    if (isInXMLView(child))
        mInXMLView = child;
    super.addView(child, index);
}

@Override
public void addView(View child, int width, int height) {
    if (isInXMLView(child))
        mInXMLView = child;
    super.addView(child, width, height);
}

@Override
public void addView(View child, ViewGroup.LayoutParams params) {
    if (isInXMLView(child))
        mInXMLView = child;
    super.addView(child, params);
}

@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
    if (isInXMLView(child))
        mInXMLView = child;
    super.addView(child, index, params);
}

@Override
protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params) {
    if (isInXMLView(child))
        mInXMLView = child;
    return super.addViewInLayout(child, index, params);
}

@Override
protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout) {
    if (isInXMLView(child))
        mInXMLView = child;
    return super.addViewInLayout(child, index, params, preventRequestLayout);
}

这里每一个方法都有一个判断,判断当前传进来的child是不是XML中定义的View的子类,如果是,赋值给mInXMLView,然后调用父类的添加方法,添加到当前View中,这里说一下需要注意的地方,系统会调用我们addView(View child, ViewGroup.LayoutParams params)这个方法,将XML中定义的MyMultiStateView的子类传递进来,看一下判断方法isInXMLView(child)

private boolean isInXMLView(View child) {
    if (mInXMLView != null && mInXMLView != child) {
        return false;
    }
    if (child != mEmptyView && child != mErrorView && child != mLoadingView) {
        return true;
    }
    return false;
}

可以看到当在init(AttributeSet attrs)方法中调用addView()方法时,因为传递的是mEmptyView或者mErrorView或者mLoadingview,说以不会赋值给mInXMLView,而只会添加到当前View中,当系统调用对应的addView()方法时满足了条件,mInXMLView也回被附上值并添加到当前View中,这样就使mEmptyView、mErrorView、mLoadingview、mInXMLView都被赋值并添加到View中了。

到现在我们只是设置了不同状态下的View及当前显示的状态,并没有去显示某一个View,接下来我们就在onAttachedToWindow()方法中显示初始状态的View,onAttachedToWindow()方法会在当前View被加载到Window时调用,是系统调用的,会在系统调用addView()以后调用。看一下代码:

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    Log.i("Log_LYL:", "onAttachedToWindow()");
    if (mInXMLView == null)
        throw new IllegalArgumentException("MyMultiStateView in XML must have child");
    //设置初始View;
    setInitailView();
}

private void setInitailView() {
    switch (mViewStatus) {
        case loadingStatus:
            if (mLoadingView == null)
                throw new NullPointerException("LoadingView is null");
            setViewShowOrHidden(mLoadingView);
            break;
        case emptyStatus:
            if (mEmptyView == null)
                throw new NullPointerException("EmptyView is null");
            setViewShowOrHidden(mEmptyView);
            break;
        case errorStatus:
            if (mErrorView == null)
                throw new NullPointerException("ErrorView is null");
            setViewShowOrHidden(mErrorView);
            break;
        case inXMLViewStatus:
            if (mInXMLView == null)
                throw new NullPointerException("InXMLView is null");
            setViewShowOrHidden(mInXMLView);
            break;
        default:
            break;
    }

}

private void setViewShowOrHidden(View v) {
    mInXMLView.setVisibility(GONE);
    mLoadingView.setVisibility(GONE);
    mEmptyView.setVisibility(GONE);
    mErrorView.setVisibility(GONE);
    v.setVisibility(VISIBLE);
}

以上代码逻辑就是根据获取到的不同状态,显示隐藏不同布局,也很简单。

下面是最后一步,对外公开的方法:

/**
 * 通过指定状态获取对应的View;
 *
 * @param status
 * @return
 */
public View getViewByState(ViewStatus status) {
    switch (status) {
        case loadingStatus:
            return mLoadingView;
        case emptyStatus:
            return mEmptyView;
        case errorStatus:
            return mErrorView;
        case inXMLViewStatus:
            return mInXMLView;
    }
    return null;
}

/**
 * 获取当前状态;
 *
 * @return
 */
public ViewStatus getNowViewStatus() {
    return mViewStatus;
}

/**
 * 设置View状态;
 *
 * @param status
 */
public void setViewStatus(@NonNull ViewStatus status) {
    mViewStatus = status;
    setInitailView();
}

/**
 * 设置指定状态对应的Layout;
 * @param resouseId
 * @param status
 */
public void setViewBindStatus(@LayoutRes int resouseId, ViewStatus status) {
    setViewBindStatus(mInflater.inflate(resouseId, null), status);
}
/**
 * 设置指定状态对应的Layout,并包含是否马上切换到当前状态;
 * @param resouseId
 * @param status
 */
public void setViewBindStatus(@LayoutRes int resouseId, ViewStatus status, boolean showRightNow) {
    setViewBindStatus(mInflater.inflate(resouseId, null), status, showRightNow);
}

/**
 * 外部设置status对应的View
 *
 * @param v
 * @param status
 */
public void setViewBindStatus(@NonNull View v, @NonNull ViewStatus status) {
    setViewBindStatus(v, status, false);
}

/**
 * 设置status对应的View,并设置是否马上显示当前状态;
 *
 * @param v            status对应的view;
 * @param status       四种status对应的状态;
 * @param showRightNow 是否马上切换至当前状态;
 */
public void setViewBindStatus(@NonNull View v, @NonNull ViewStatus status, boolean showRightNow) {
    switch (status) {
        case loadingStatus:
            if (mLoadingView != null)
                removeView(mLoadingView);
            mLoadingView = v;
            addView(mLoadingView);
            break;
        case emptyStatus:
            if (mEmptyView != null)
                removeView(mEmptyView);
            mEmptyView = v;
            addView(mEmptyView);
            break;
        case errorStatus:
            if (mErrorView != null)
                removeView(mErrorView);
            mErrorView = v;
            addView(mErrorView);
            break;
        case inXMLViewStatus:
            if (mInXMLView != null)
                removeView(mInXMLView);
            mInXMLView = v;
            addView(mInXMLView);
            break;
    }
    //如果支持马上去显示当前状态下的View;
    if (showRightNow) {
        mViewStatus = status;
        setInitailView();
    }

}

代码都添加了注释,对外公开了如下几类方法:

1.通过状态获取对应View;

2.获取当前状态;

3.设置状态;

4.为指定状态设置View,并是否马上切换到当前状态(包括View,LayoutId)。

到这里我们的自定义控件部分就算是完成了。

接下来新建三个Layout分别对应Error,Loading,Empty状态,然后在XML中定义我们的View,看代码:

<com.jason.mymultistateview.MyMultiStateView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:multistateView="http://schemas.android.com/apk/res-auto"
    android:id="@+id/multiStateView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="inXML view"
        android:textColor="@android:color/black"
        android:textSize="50sp" />

</com.jason.mymultistateview.MyMultiStateView>

然后在Activity中获取View并作操作:

public class MainActivity extends AppCompatActivity {
    int count;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final MyMultiStateView myMultiStateView = (MyMultiStateView) findViewById(R.id.multiStateView);
//        myMultiStateView.setViewBindStatus(R.layout.loading_view, MyMultiStateView.ViewStatus.loadingStatus);
//        myMultiStateView.setViewBindStatus(R.layout.empty_view, MyMultiStateView.ViewStatus.emptyStatus);
//        myMultiStateView.setViewBindStatus(R.layout.error_view, MyMultiStateView.ViewStatus.errorStatus,true);
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        count++;
                        if (count == 0) {
                            myMultiStateView.setViewStatus(MyMultiStateView.ViewStatus.loadingStatus);
                        } else if (count == 1) {
                            myMultiStateView.setViewStatus(MyMultiStateView.ViewStatus.emptyStatus);
                        } else if (count == 2) {
                            myMultiStateView.setViewStatus(MyMultiStateView.ViewStatus.errorStatus);
                        } else if (count == 3) {
                            myMultiStateView.setViewStatus(MyMultiStateView.ViewStatus.inXMLViewStatus);
                            count = -1;
                        }
                    }
                });
            }
        },1000, 3000);
    }}

我们也可以不在XML中定义自定义属性,那么我们就把上边添加注释的代码放开也可以实现功能。好了今天就写到这里,你可以点击下载源码,希望对你了解自定义View有点帮助,下边附上完整的自定义View代码。

package com.jason.mymultistateview;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.AttrRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

/**
 * @Explain:自定义支持多种状态的View,常用于网络请求(有数据,空数据,网络异常等状态的显示);
 * @Author:LYL
 * @Version:
 * @Time:2017/5/23
 */

public class MyMultiStateView extends FrameLayout {
    private LayoutInflater mInflater;//加载各种状态布局的Inflater;
    private View mErrorView;//当处于error状态下要显示的View;
    private View mEmptyView;//当处于empty状态下要显示的View;
    private View mLoadingView;//当处于loading状态下要显示的View;
    private View mInXMLView;//正常状态显示的View;(就是我们在XML中定义MyMultiStateView时包裹的子View)
    private ViewStatus mViewStatus = ViewStatus.loadingStatus;//记录当前正处于的状态;
    private final int STATUS_LOADVIEW = 0;//以下四种为四种不同状态标识;
    private final int STATUS_EMPTYVIEW = 1;
    private final int STATUS_ERRORVIEW = 2;
    private final int STATUS_INXMLVIEW = 3;


    /**
     * when creating a view from code.
     * 当我们在代码中以new的方式创建View时调用当前方法创建View对象;
     *
     * @param context
     */
    public MyMultiStateView(@NonNull Context context) {
        this(context, null);
    }

    /***
     * 当在Layout中定义MyMultiStateView时,系统调用当前方法创建View对象,可以通过AttributeSet获取自定义属性内容;
     * @param context
     * @param attrs
     */
    public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);

    }

    /**
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    public MyMultiStateView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init(AttributeSet attrs) {
        mInflater = LayoutInflater.from(getContext());
        //获取各个状态对应的View,并添加到当前View;
        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyMultiStateView);
        int errorViewId = ta.getResourceId(R.styleable.MyMultiStateView_errorView, -1);
        if (errorViewId != -1) {
            mErrorView = mInflater.inflate(errorViewId, null, false);
            addView(mErrorView);
        }
        int emptyViewId = ta.getResourceId(R.styleable.MyMultiStateView_emptyView, -1);
        if (errorViewId != -1) {
            mEmptyView = mInflater.inflate(emptyViewId, null, false);
            addView(mEmptyView);
        }
        int loadViewId = ta.getResourceId(R.styleable.MyMultiStateView_loadingView, -1);
        if (loadViewId != -1) {
            mLoadingView = mInflater.inflate(loadViewId, null, false);
            addView(mLoadingView);
        }
        //获取初始状态时定义的显示状态;
        int initailViewStatus = ta.getInt(R.styleable.MyMultiStateView_initialViewStatus, -1);
        if (initailViewStatus != -1) {
            switch (initailViewStatus) {
                case STATUS_LOADVIEW:
                    mViewStatus = ViewStatus.loadingStatus;
                    break;
                case STATUS_EMPTYVIEW:
                    mViewStatus = ViewStatus.emptyStatus;
                    break;
                case STATUS_ERRORVIEW:
                    mViewStatus = ViewStatus.errorStatus;
                    break;
                case STATUS_INXMLVIEW:
                    mViewStatus = ViewStatus.inXMLViewStatus;
                    break;
            }
        }
        ta.recycle();
    }

    @Override
    public void addView(View child) {
        if (isInXMLView(child))
            mInXMLView = child;
        super.addView(child);
    }

    @Override
    public void addView(View child, int index) {
        if (isInXMLView(child))
            mInXMLView = child;
        super.addView(child, index);
    }

    @Override
    public void addView(View child, int width, int height) {
        if (isInXMLView(child))
            mInXMLView = child;
        super.addView(child, width, height);
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        if (isInXMLView(child))
            mInXMLView = child;
        super.addView(child, params);
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (isInXMLView(child))
            mInXMLView = child;
        super.addView(child, index, params);
    }

    @Override
    protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params) {
        if (isInXMLView(child))
            mInXMLView = child;
        return super.addViewInLayout(child, index, params);
    }

    @Override
    protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout) {
        if (isInXMLView(child))
            mInXMLView = child;
        return super.addViewInLayout(child, index, params, preventRequestLayout);
    }

    /**
     * 判断是不是XML中MyMultiStatusView的子类;
     *
     * @param child
     * @return
     */
    private boolean isInXMLView(View child) {
        if (mInXMLView != null && mInXMLView != child) {
            return false;
        }
        if (child != mEmptyView && child != mErrorView && child != mLoadingView) {
            return true;
        }
        return false;
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.i("Log_LYL:", "onAttachedToWindow()");
        if (mInXMLView == null)
            throw new IllegalArgumentException("MyMultiStateView in XML must have child");
        //设置初始View;
        setInitailView();
    }

    private void setInitailView() {
        switch (mViewStatus) {
            case loadingStatus:
                if (mLoadingView == null)
                    throw new NullPointerException("LoadingView is null");
                setViewShowOrHidden(mLoadingView);
                break;
            case emptyStatus:
                if (mEmptyView == null)
                    throw new NullPointerException("EmptyView is null");
                setViewShowOrHidden(mEmptyView);
                break;
            case errorStatus:
                if (mErrorView == null)
                    throw new NullPointerException("ErrorView is null");
                setViewShowOrHidden(mErrorView);
                break;
            case inXMLViewStatus:
                if (mInXMLView == null)
                    throw new NullPointerException("InXMLView is null");
                setViewShowOrHidden(mInXMLView);
                break;
            default:
                break;
        }

    }

    private void setViewShowOrHidden(View v) {
        mInXMLView.setVisibility(GONE);
        mLoadingView.setVisibility(GONE);
        mEmptyView.setVisibility(GONE);
        mErrorView.setVisibility(GONE);
        v.setVisibility(VISIBLE);
    }

    /**
     * 通过指定状态获取对应的View;
     *
     * @param status
     * @return
     */
    public View getViewByState(ViewStatus status) {
        switch (status) {
            case loadingStatus:
                return mLoadingView;
            case emptyStatus:
                return mEmptyView;
            case errorStatus:
                return mErrorView;
            case inXMLViewStatus:
                return mInXMLView;
        }
        return null;
    }

    /**
     * 获取当前状态;
     *
     * @return
     */
    public ViewStatus getNowViewStatus() {
        return mViewStatus;
    }

    /**
     * 设置View状态;
     *
     * @param status
     */
    public void setViewStatus(@NonNull ViewStatus status) {
        mViewStatus = status;
        setInitailView();
    }

    /**
     * 设置指定状态对应的Layout;
     * @param resouseId
     * @param status
     */
    public void setViewBindStatus(@LayoutRes int resouseId, ViewStatus status) {
        setViewBindStatus(mInflater.inflate(resouseId, null), status);
    }
    /**
     * 设置指定状态对应的Layout,并包含是否马上切换到当前状态;
     * @param resouseId
     * @param status
     */
    public void setViewBindStatus(@LayoutRes int resouseId, ViewStatus status, boolean showRightNow) {
        setViewBindStatus(mInflater.inflate(resouseId, null), status, showRightNow);
    }

    /**
     * 外部设置status对应的View
     *
     * @param v
     * @param status
     */
    public void setViewBindStatus(@NonNull View v, @NonNull ViewStatus status) {
        setViewBindStatus(v, status, false);
    }

    /**
     * 设置status对应的View,并设置是否马上显示当前状态;
     *
     * @param v            status对应的view;
     * @param status       四种status对应的状态;
     * @param showRightNow 是否马上切换至当前状态;
     */
    public void setViewBindStatus(@NonNull View v, @NonNull ViewStatus status, boolean showRightNow) {
        switch (status) {
            case loadingStatus:
                if (mLoadingView != null)
                    removeView(mLoadingView);
                mLoadingView = v;
                addView(mLoadingView);
                break;
            case emptyStatus:
                if (mEmptyView != null)
                    removeView(mEmptyView);
                mEmptyView = v;
                addView(mEmptyView);
                break;
            case errorStatus:
                if (mErrorView != null)
                    removeView(mErrorView);
                mErrorView = v;
                addView(mErrorView);
                break;
            case inXMLViewStatus:
                if (mInXMLView != null)
                    removeView(mInXMLView);
                mInXMLView = v;
                addView(mInXMLView);
                break;
        }
        //如果支持马上去显示当前状态下的View;
        if (showRightNow) {
            mViewStatus = status;
            setInitailView();
        }

    }


    /**
     * 在此控件被通过xml声明的方式创建之后调用;
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        Log.i("Log_LYL:", "onFinishInflate()");
    }

    public enum ViewStatus {
        errorStatus,
        loadingStatus,
        emptyStatus,
        inXMLViewStatus

    }
}

吃水不忘挖井人,必须感谢挖井人



猜你喜欢

转载自blog.csdn.net/liuyonglei1314/article/details/72654792