Android搭建應用框架系列之StatusView

前言

前篇文章把每個頁面的統(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)}

或者自定義對應的布局


image.png

或者自定義點擊事件


image.png

顯示網(wǎng)絡錯誤

mStatusView.showNetErrorView()

顯示未知錯誤頁面

mStatusView.showErrorView()

顯示空頁面

mStatusView.showEmptyView()

最后顯示如下

網(wǎng)絡錯誤

網(wǎng)絡錯誤.png

未知錯誤

未知錯誤.png

空頁面

空頁面.png
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市砌滞,隨后出現(xiàn)的幾起案子侮邀,更是在濱河造成了極大的恐慌,老刑警劉巖布持,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豌拙,死亡現(xiàn)場離奇詭異,居然都是意外死亡题暖,警方通過查閱死者的電腦和手機按傅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門捉超,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唯绍,你說我怎么就攤上這事】雒ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵耐版,是天一觀的道長。 經(jīng)常有香客問我压汪,道長粪牲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任腺阳,我火速辦了婚禮,結(jié)果婚禮上亭引,老公的妹妹穿的比我還像新娘。我一直安慰自己皮获,他們只是感情好焙蚓,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著魔市,像睡著了一般。 火紅的嫁衣襯著肌膚如雪待德。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天绘闷,我揣著相機與錄音,去河邊找鬼印蔗。 笑死丑勤,一個胖子當著我的面吹牛华嘹,可吹牛的內(nèi)容都是我干的法竞。 我是一名探鬼主播强挫,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼薛躬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了型宝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤梨树,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后劝萤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慎璧,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡跨释,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鳖谈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岁疼。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡缆娃,死狀恐怖捷绒,靈堂內(nèi)的尸體忽然破棺而出贯要,到底是詐尸還是另有隱情,我是刑警寧澤崇渗,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布宅广,位于F島的核電站葫掉,受9級特大地震影響跟狱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜驶臊,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一绪抛、第九天 我趴在偏房一處隱蔽的房頂上張望电禀。 院中可真熱鬧,春花似錦尖飞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荐健,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間江场,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工餐蔬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留佑附,地道東北人樊诺。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓词爬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缸夹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點贊按鈕進度條TabLayout圖標下拉刷新...
    皇小弟閱讀 46,712評論 22 664
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫蛇尚、插件芽唇、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,033評論 4 62
  • 感賞兒子今天起的很早,并且吃的飽飽的去上學研侣。中午放學回來很開心,我滿足了他的愿望給他買了想吃的東西庶诡,邊吃邊聊...
    金色陽光魏艷春閱讀 176評論 0 1
  • 感覺每天都過得很緊張咆课,因為一天的時間給到你的就那么多,怎樣讓自己能夠在這與別人一樣的時間里創(chuàng)造更多的價值书蚪。老師給到...
    問之成兮閱讀 127評論 0 0