一個超高自定義度又簡單使用的頁面狀態管理庫

檸檬茶就是力量發表於2019-07-23

StatusLayout : 一個超高自定義度又簡單的頁面狀態管理庫

業務場景需求:

在日常開發App的過程中,我們少不了對Activity/Fragment 等做一些不同狀態不同UI的狀態管理邏輯,比如空頁面 錯誤重試頁面 等等,網上也有很多作者寫了開源庫來處理這些問題 但是我看了一下這些庫,個人認為有以下幾個小問題

  • 大部分都是隻定義了錯誤 空資料 loading等3-5個左右的狀態,並且切換的時候也是已經規定好呼叫哪些方法,這樣就會大大限制了擴充性以及對一些複雜的業務場景的適配
  • 對於一些點選事件或者view的處理也不是很到位,比如錯誤重試等大多數都是傳入一個id
  • 多個地方需要同樣的設定的時候,需要不斷copy程式碼過去
以上幾個小問題相信有些開發者也有發現,在用的時候也會覺得還有改進的空間
我在公司的專案中也發現了這些問題,所以在空閒時間寫了一個管理庫用來管理頁面,接下來就給大家介紹一下,相信能給大家在日常開發中帶來更多便利,更少的程式碼,更多的可操作性

StatusLayout有以下幾個優點

  • 自由定製需要的狀態以及對應佈局,只需要一行程式碼
  • 可以定製動畫效果
  • 可以用在舊專案上,不需要修改原有xml檔案
  • 可設定全域性屬性避免重複勞動

Github地址: github.com/Colaman0/St…


效果圖:

一個超高自定義度又簡單使用的頁面狀態管理庫

效果圖來看比起普通的庫多了一個淡入淡出的動畫效果,這部分可以自定義,這裡只給大家展現一個最基本的效果

依賴 :

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
複製程式碼
	dependencies {
	        implementation 'com.github.Colaman0:StatusLayout:1.0.8'
	}
複製程式碼

具體使用步驟如下:

1.第一步先把StatusLayout作為根佈局,這裡有以下兩種寫法

  • StatusLayout作為根佈局在activity/fragment/view 中使用

    在xml內直接把StatusLayout作為根佈局,注意StatusLayout內部子view數量不能超過1個, 所以如果UI上需求需要排列多個View的時候,需要多套一層佈局,比如:

    <StatusLayout>
        <LinearLayout>    
            <View/>        
            <View/>
            <View/>
        </LinearLayout>
    </StatusLayout>
    
    複製程式碼
  • 通過 StatusLayout.init()方法傳入Context以及你要顯示到的layout資原始檔,這個方法會返回一個StatusLayout物件,所以大家可以在封裝BaseActivity的時候這樣寫:
    // 後續可以通過mStatusLayout新增不同狀態對應的UI  
    StatusLayout mStatusLayout = StatusLayout.init(this, R.layout.activity_main);   
    setContentView(mStatusLayout);
    複製程式碼

2. 新增不同狀態對應的UI以及響應點選事件

通過add(statusconfig : StatusConfig)方法來新增一種狀態佈局,傳入StatusConfig引數類,給大家講一下每個引數的作用
  • status : 作為一個狀態佈局的status標記,比如空頁面 錯誤頁面 等等你想要新增進去的頁面,設定一下自己想要新增的status

  • layoutRes : 對應上面的status, 一個status對應一個view,一個佈局,比如上面status傳入了一個empty,那我們這裡對應可以新增一個空頁面的layout資原始檔id

  • view : 跟layoutRes相似,考慮到有時候業務需求,某個狀態下的頁面可能按鈕或者一些需要寫的邏輯比較多比較複雜, 這個時候可以讓開發者自己寫一個view傳進來,對應的一些邏輯判斷則讓view內部去處理 ,StatusLayout只負責切換

  • clickRes :每一個佈局,可以傳遞一個id進來,比如錯誤重試頁面 可以傳一個button的id進來,這樣在button被點選的時候,可以通過回撥來接收到點選事件

      data class StatusConfig(        
              var status: String?,        
              @field:LayoutRes        
              var layoutRes: Int = -1,        
              var view: View? = null,       
              @field:IdRes       
              var clickRes: Int = -1)
    
    
    複製程式碼

3. 切換佈局

通過switchLayout()/showDefaultContent()兩種方法來切換佈局
  • switchLayout(status : String)方法是用於切換你add進去的佈局,只要傳入你前面add佈局的時候傳入的status就可以了
  • showDefaultContent()用於切換回你預設的UI,比如在切到error狀態的UI時,你點選了重試按鈕請求成功之後,通過showDefaultContent()方法切換正常的佈局,可能是你在xml裡預設的一個佈局,也可以是通過add方法新增進去的佈局,通過add新增進去的佈局需要statusSTATUS_NORMAL才會被StatusLayout認為是預設的佈局。總體來說切換回正常狀態佈局呼叫這個方法就可以了,具體可以參考下面關於回撥的程式碼

4. 不同佈局點選的回撥

上面在add方法中講到了StatusConfig中一個clickRes變數,相當於告訴StatusLayout我要監聽這個id的view的點選事件,當它被點選的時候告訴我,可以通過setLayoutClickListener()方法來設定監聽

            setLayoutClickListener(new StatusLayout.OnLayoutClickListener() {
                @Override
                public void OnLayoutClick(View view, String status) {
                     // View: 對應status的rootView  
                     // status:當前status,可以判斷當前頁面處於哪個status
                    switch (status) {
                        case LOADING:
                            Toast.makeText(MainActivity.this, LOADING, Toast.LENGTH_SHORT).show();
                            break;
                        case EMPTY:
                            Toast.makeText(MainActivity.this, EMPTY, Toast.LENGTH_SHORT).show();
                            break;
                        case ERROR:  
                             // 這裡通過showDefaultContent()方法展示預設的佈局
                            mStatusLayout.showDefaultContent();
                            break;
                    }
                }
            });
            
複製程式碼

講解一下上面的程式碼,設定一個layout點選的回撥監聽,當layout/clickRes 對應的view被點選的時候,會回撥當前是哪一個status的頁面,以及對應的佈局view,當我們的clickRes不傳的時候,預設是整個頁面響應點選事件,所以在add的時候比較靈活的處理了關於點選事件的處理,比較複雜的頁面建議就在add的時候傳入一個view然後在內部做處理比較合適了,避免擴充出一大堆方法。

5. 設定顯示/隱藏的動畫

通過setAnimation() 來設定頁面顯示/隱藏的的動畫, 也可以通過setGlobalAnim()來設定一個全域性的動畫效果,setAnimation()的優先順序比setGlobalAnim()更高

6.設定全域性屬性

考慮到APP裡常見的空頁面 loading 之類的頁面都是比較統一的,這個時候可以通過StatusLayout.setGlobalData()方法來設定全域性的屬性,這個時候可以設定全域性屬性來避免重複新增的程式碼,後續可以通過add()方法來覆蓋全域性屬性。 setGlobalData方法傳入的引數和通過add()方法傳入的引數值是一樣的,可以參考一下程式碼,並且這裡考慮到有些地方沒有機會用到這些佈局或者說不需要這些佈局,所以StatusLayout只有在切換佈局的時候才會去載入這些全域性屬性佈局。

StatusLayout.setGlobalData(        
    StatusConfig(status = StatusLayout.STATUS_EMPTY, layoutRes = R.layout.include_empty),        
    StatusConfig(status = StatusLayout.STATUS_ERROR, layoutRes = R.layout.include_error, clickRes = R.id.btn_retry))
複製程式碼

總結

以上六點就講解完了StatusLayout的一個使用,在我一開始寫的時候,是想著能儘量適應多種場景以及儘可能少的程式碼邏輯

  • 比如電商APP中一個訂單支付成功失敗loading等場景,可以通過StatusLayout去對應新增布局,並且對於一些通用的狀態,可以設定全域性屬性避免不同地方出現一樣的程式碼,並且以後需要更換佈局的時候只要在設定全域性屬性的地方修改一下layout就可以了。
  • 點選回撥通過setLayoutClickListener 去處理不同狀態下的點選事件回撥,不需要寫不同的回撥事件,也可以更好的對於多種多樣的佈局來做一個適應

整個庫的核心想法就是通過status來管理頁面,StatusLayout只負責管理你新增進來的佈局,以及對應切換某個status的佈局。並不會限制得很死要呼叫某個方法,所以你可以盡情得自定義你的頁面,新增各種各樣的佈局進去,然後通過switchLayout()來切換佈局就可以了。


Github地址: github.com/Colaman0/St…

相關文章