1. 程式人生 > >Android-仿支付寶的日期選擇頁

Android-仿支付寶的日期選擇頁

描述

參考支付寶所製作的日期選擇頁,效果如下:

效果展示

知識點與難點

1、獲取指定月份有多少天

public static int getDayCountOfMonth(int year, int month) {
    int[] arr = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int days = 0;
    //如果是閏年,二月= 29天
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
        arr[1] = 29
; } try { days = arr[month - 1]; } catch (Exception e) { e.printStackTrace(); } return days; }

2、計算指定日期是周幾

/**
 * 計算指定日期是周幾
 * 1為週日,2為週一,3為週二,4為週三,5為週四,6為週五,7為週六
 */
public static int getDayOfWeekInMonth(int year, int month, int day) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, month - 1
); calendar.set(Calendar.DATE, day); return calendar.get(Calendar.DAY_OF_WEEK); }

3、基礎架構

整個專案的結構是RecyclerView巢狀RecyclerView:
專案結構

紅色為外層RecyclerView,藍色為內部RecyclerView。

外層RecyclerView包含了固定頭部條目與月份RecyclerView。

每個月份RecyclerView對應了一個月份的日期展示。

4、資料儲存

關於日期資料,我們需要考慮到很多情況。

因為日期資料可能很大,幾年的資料甚至更多,如果傳遞來傳遞去會在記憶體中產生多份資料(根據引用地址不同可以看出)。

為了節省記憶體,我選擇使用單例模式來實現,並且是懶漢式單例模式,因為此功能使用者不一定每次開啟App都會使用。

這樣做的好處不僅是節省了記憶體、減少了來回傳遞資料的繁瑣操作,還有就是很方便地讓我們實現了回顯功能,從上面的Gif圖中也可以看出回顯功能。

那麼還有一個問題就是,什麼時候銷燬資料?

我的想法是,在使用者第一次開啟日期選擇頁時,進行資料的初始化,接著使用者反覆在結果展示頁和日期選擇頁來回切換時,用的都是這一批資料。

當用戶離開結果展示頁(提交、或者放棄)時,就要銷燬資料,清理記憶體,具體建立、銷燬邏輯可以檢視程式碼。

5、重新整理

關於每個日期的狀態初始化以及選擇後的重新整理,是比較麻煩的。

尤其是跨月、跨年選擇日期!因為我們的每個月是獨立的巢狀RecyclerView,當你跨月選擇時,你就需要重新整理多條內部RecyclerView。

為了解決這種情況,我在程式碼中使用了外部Adapter來進行條目的重新整理,並且不會呼叫全域性重新整理:adapter.notifyDataSetChanged();

選擇使用區域性重新整理:

adapter.notifyItemRangeChanged(int position, int count);
adapter.notifyItemChanged(int position);

不會去重新整理無關的條目。

還有一點要說的是,巢狀RecyclerView的高度是不固定的:可能有5行、6行,也可能有7行。

關於巢狀RecyclerView的高度問題,確實已經無需計算高度了,可以直接將內部RecyclerView的高度設定為wrap_content

之前需要動態計算高度,是因為RecyclerView相容包的Bug,不過已經在23.2.0之後修復了,具體參考這裡

不過我在巢狀RecyclerView還是計算了高度,我嘗試了不計算高度,感覺效能遠不如計算高度,具體就需要看看原始碼了。

至此,難點基本已經介紹完了。

不過專案當中因為上述高度不固定的原因,產生了一個小問題:

在呼叫adapter.notifyItemChanged(int position)時,當position為0或1時,有時會導致螢幕自動滾動至頂部,目前還沒有找到合適的解決方案,各位看官可以自己試一試,找找解決方案。

感謝