前言
前篇文章把每個頁面的統(tǒng)一加載框?qū)懥讼率行洹T趹弥校思虞d框,還有頁面請求數(shù)據(jù)為空的時候颗品,或者請求網(wǎng)絡錯誤的時候需要統(tǒng)一處理,也就是根據(jù)不同的狀態(tài)顯示不同的頁面StatusView
IStatusView
這里有四種顯示狀態(tài)沃缘,顯示應用發(fā)生未知錯誤頁面躯枢,顯示網(wǎng)絡錯誤頁面,顯示空頁面槐臀,以及顯示正常頁面锄蹂,所以定義的接口如下
interface IStateView {
fun showErrorView()
fun showNetErrorView()
fun showEmptyView()
fun dismissStatusView()
}
StatusViewController
接下來就是寫一個幫助類實現(xiàn)上面接口,然后進行相應的切換操作
class StatusViewController(private var mContext: Context, private var mBindView:View) : IStateView {
private var mParentView:ViewGroup? = null
private var mCurrentIndex = 0
private var mEmptyView: View? = null
private var mErrorView:View? = null
private var mNetErrorView:View? = null
private var mBindViewParams:ViewGroup.LayoutParams? = null
private var netErrorLayoutResId:Int = 0
private var errorLayoutResId:Int = 0
private var emptyLayoutResId:Int = 0
private var mEmptyStatus:StatusInfo = StatusInfo(R.drawable.icon_empty,mContext.getString(R.string.LoadingController_empty),mContext.getString(R.string.LoadingController_empty_retry))
private var mErrorStatus:StatusInfo = StatusInfo(R.drawable.icon_error,mContext.getString(R.string.LoadingController_error),mContext.getString(R.string.LoadingController_error_retry))
private var mNetErrorStatus:StatusInfo = StatusInfo(R.drawable.icon_net_error,mContext.getString(R.string.LoadingController_net_error),mContext.getString(R.string.LoadingController_net_error_retry))
private var mEmptyBtnRetryListener:BtnRetryListener? = null
private var mNetErrorBtnRetryListener:BtnRetryListener? = null
private var mErrorBtnRetryListener:BtnRetryListener? = null
init {
mBindViewParams = mBindView.layoutParams
mParentView = if(mBindView.parent != null)
mBindView.parent as ViewGroup
else
mBindView.rootView.find(android.R.id.content)
val childCount = mParentView!!.childCount
(0 until childCount)
.filter { mParentView!!.getChildAt(it) == mBindView }
.forEach { mCurrentIndex = it }
}
override fun showErrorView() {
if(mErrorView!=null){
showView(mErrorView!!)
return
}
if(errorLayoutResId>0){
mErrorView = mContext.layoutInflater.inflate(errorLayoutResId,mParentView,false)
}else{
mErrorView = mContext.layoutInflater.inflate(R.layout.error,mParentView,false)
updateDefaultView(mErrorView!!,mErrorStatus,mErrorBtnRetryListener)
}
showView(mErrorView!!)
}
override fun showNetErrorView() {
if(mNetErrorView!=null){
showView(mNetErrorView!!)
return
}
if(errorLayoutResId>0){
mNetErrorView = mContext.layoutInflater.inflate(netErrorLayoutResId,mParentView,false)
}else{
mNetErrorView = mContext.layoutInflater.inflate(R.layout.error,mParentView,false)
updateDefaultView(mNetErrorView!!,mNetErrorStatus,mNetErrorBtnRetryListener)
}
showView(mNetErrorView!!)
}
override fun showEmptyView() {
if(mEmptyView!=null){
showView(mEmptyView!!)
return
}
if(emptyLayoutResId>0){
mEmptyView = mContext.layoutInflater.inflate(emptyLayoutResId,mParentView,false)
}else{
mEmptyView = mContext.layoutInflater.inflate(R.layout.error,mParentView,false)
updateDefaultView(mEmptyView!!,mEmptyStatus,mEmptyBtnRetryListener)
}
showView(mEmptyView!!)
}
override fun dismissStatusView() {
showView(mBindView)
}
private fun showView(statusView:View){
if(mParentView!!.getChildAt(mCurrentIndex) != statusView){
statusView.parent?:(statusView.parent as? ViewGroup)?.removeView(statusView)
mParentView!!.removeViewAt(mCurrentIndex)
mParentView!!.addView(statusView,mCurrentIndex,mBindViewParams)
}
}
private fun updateDefaultView(updateView:View,statusInfo:StatusInfo,listener:BtnRetryListener?=null){
val errorView = updateView.find<ImageView>(R.id.iv_error)
val msgView = updateView.find<TextView>(R.id.tv_errorMessage)
val btnRetryView = updateView.find<TextView>(R.id.btn_retry)
if(statusInfo.icon>0){
errorView.show()
errorView.imageResource = statusInfo.icon
}else errorView.hide()
if(!statusInfo.msg.isNullOrEmpty()){
msgView.show()
msgView.text = statusInfo.msg
}else msgView.hide()
if(!statusInfo.btnText.isNullOrEmpty()){
btnRetryView.show()
btnRetryView.text = statusInfo.btnText
btnRetryView.onClick {
listener?.onRetryClick(btnRetryView)
}
}else btnRetryView.hide()
}
fun setErrorLayoutResId(resId: Int):StatusViewController{
this.errorLayoutResId = resId
return this
}
fun setNetErrorLayoutResId(resId: Int):StatusViewController{
this.netErrorLayoutResId = resId
return this
}
fun setEmptyLayoutResId(resId: Int):StatusViewController{
this.emptyLayoutResId = resId
return this
}
fun setEmptyStatusInfo(statusInfo:StatusInfo):StatusViewController{
this.mEmptyStatus = statusInfo
return this
}
fun setErrorStatusInfo(statusInfo:StatusInfo):StatusViewController{
this.mErrorStatus = statusInfo
return this
}
fun setNetErrorStatusInfo(statusInfo:StatusInfo):StatusViewController{
this.mNetErrorStatus = statusInfo
return this
}
fun setEmptyBtnClickListener(listener:BtnRetryListener):StatusViewController{
this.mEmptyBtnRetryListener = listener
return this
}
fun setErrorBtnClickListener(listener:BtnRetryListener):StatusViewController{
this.mErrorBtnRetryListener = listener
return this
}
fun setNetErrorBtnClickListener(listener:BtnRetryListener):StatusViewController{
this.mNetErrorBtnRetryListener = listener
return this
}
interface BtnRetryListener{
fun onRetryClick(view:View)
}
class StatusInfo(val icon:Int,val msg:CharSequence?,val btnText:CharSequence?)
}
傳入兩個參數(shù)水慨,一個是Context
得糜,另外一個是mBindView
,這個參數(shù)意思是需要顯示在哪個控件上面晰洒,比如RecyclerView
朝抖。可以自定義對應顯示的布局谍珊,也可以通過StatusInfo
是傳入信息治宣,然后顯示默認對應的布局
使用
最簡單的使用如下
先獲取StatusViewController
實例
val mStatusView by lazy { StatusViewController(context,mRecyclerView)}
或者自定義對應的布局
或者自定義點擊事件
顯示網(wǎng)絡錯誤
mStatusView.showNetErrorView()
顯示未知錯誤頁面
mStatusView.showErrorView()
顯示空頁面
mStatusView.showEmptyView()
最后顯示如下
網(wǎng)絡錯誤
未知錯誤
空頁面