<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android從0到1仿去哪兒選擇日期區(qū)間控件

          共 4159字,需瀏覽 9分鐘

           ·

          2021-05-23 03:49

          本篇學(xué)習(xí)的內(nèi)容


          第一,recyclerview的多類型item的使用;
          第二,calendar的基本使用與日期計算;
          第三,
          DialogFragment的基本使用。


          需求


          最近公司項目需要一個選擇時間區(qū)間的控件,效果跟去哪兒網(wǎng)選擇住宿時間區(qū)間非常像,先來看看最終放入我項目中的效果圖(壓縮后圖片比較不清晰,請見諒,最終在移動端顯示效果比這個更佳)如下圖:

          選擇開始后



          選擇開始與結(jié)束后




          開始與結(jié)束為同一天




          實現(xiàn)思路


          第一步,日歷主體實現(xiàn)

          首先,利用recycerview的多item布局實現(xiàn)日歷主體部分,其中,有兩種item類型;


          第一種,月份;
          這個簡單,不做過多說明


          第二種,日期。
          有GridLayoutManager實現(xiàn),設(shè)置SpanCount為7,注意空白數(shù)據(jù)的填充和每個item的樣式類型。


          既然數(shù)據(jù)itme有兩種類型,那么數(shù)據(jù)源也是會有兩種類型的,要顯示的數(shù)據(jù)體為了方便咱們可以用一個object類型,就可以匹配itme不同的數(shù)據(jù)類型了


          第二步,就是利用calendar計算出這個recyclerview的數(shù)據(jù)源

          1.先看今天所在月份的第一天為星期幾;
          2.填充空白日期;
          3.然后循環(huán)12次,也就是12個月份;
          4.每次月份循環(huán)時,看看當前月的天數(shù),然后循環(huán)天數(shù),添加數(shù)據(jù);
          5.每次天數(shù)循環(huán)后,利用calendar增加1;(最后,注意添加節(jié)日)


          另外一點

          item中的日期布局,我想講一下,每個item



          底色是兩半邊,因為選中時開始與結(jié)束的itme只需要顯示半邊顏色。


          這個布局畫一條中心線,然后從中間分開,利用在左在右的布局形式分別設(shè)置兩個view。節(jié)日在選中情況下,會變成開始字樣,這時注意變色。


          實現(xiàn)過程

          利用DialogFragment實現(xiàn)從下往上彈出框效果

          在DialogFragment的onCreateView方法中初始化view布局,并且設(shè)置相應(yīng)的參數(shù)動畫,代碼注釋已經(jīng)很清晰。

          public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {    // 去掉默認title    this.getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);    // 外部點擊是否可以收起該dialog    getDialog().setCanceledOnTouchOutside(false);
          Window window = this.getDialog().getWindow(); if (window != null) { //去掉dialog默認的padding window.getDecorView().setPadding(0, 0, 0, 0); WindowManager.LayoutParams lp = window.getAttributes(); lp.width = WindowManager.LayoutParams.MATCH_PARENT; // 設(shè)置高度為屏幕高度的四分之三 lp.height = UIUtils.getScreenHeight(getActivity()) * 3 / 4; //設(shè)置dialog的位置在底部 lp.gravity = Gravity.BOTTOM; //設(shè)置dialog的動畫 lp.windowAnimations = R.style.AnimBottom; window.setAttributes(lp); window.setBackgroundDrawable(new ColorDrawable()); }
          View view = inflater.inflate(R.layout.dialog_choose_date, container, false);
          initView(view); initRecyclerView(); initListener(); initData();
          return view;}


          初始化recyclerview

          final GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 7);layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {    @Override    public int getSpanSize(int position) {        // 這個item占有幾個位置        return (mChooseRecyclerAdapter.getItemViewType(position)                == ChooseDateRecyclerAdapter.TYPE_YEAR_MONTH ? layoutManager.getSpanCount() : 1);    }});
          mDateRecyclerView.setAdapter(mChooseRecyclerAdapter);mDateRecyclerView.setLayoutManager(layoutManager);mDateRecyclerView.setItemAnimator(new DefaultItemAnimator());


          如上所示,GridLayoutManager可以設(shè)置一行劃分為幾個區(qū)域來顯示幾個item,然后在setSpanSizeLookup方法中設(shè)置當前item類型可以占據(jù)幾個區(qū)域以此來調(diào)節(jié)item的顯示寬度。


          如果一行中顯示區(qū)域不足以顯示該item的長度,則會另起一行。所以這個控件用起來是相當靈活而且爽歪歪。


          初始化適配器數(shù)據(jù)

          這里其實是整個實現(xiàn)過程中的一個難點,咱們按照上面的思路來實現(xiàn)數(shù)據(jù)的初始化。

          設(shè)置當當前月份的第一天。

          Calendar calendar = Calendar.getInstance();calendar.set(Calendar.DAY_OF_MONTH, 1);// 添加月份數(shù)據(jù)mData.add(new ChooseDateBean(1, String.valueOf(calendar.get(Calendar.MONTH) + 1) + "月"));


          然后查看第一天是星期幾,設(shè)置相應(yīng)的空白數(shù)據(jù)。

          int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);for (int j = 1; j < dayOfWeek; j++) {    DateOfDayBean bean = new DateOfDayBean();    bean.setDayOfMonth("");    mData.add(new ChooseDateBean(2, bean));}


          獲取當前月份的天數(shù)

          private int getDayCountByYearAndMonth(int year, int month) {    int days = 30;    switch (month) {        case 1:        case 3:        case 5:        case 7:        case 8:        case 10:        case 12:            days = 31;            break;        case 4:        case 6:        case 9:        case 11:            days = 30;            break;        case 2:            if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {                days = 29;            } else {                days = 28;            }            break;    }    return days;}


          循環(huán)遍歷當前月份天數(shù),添加相應(yīng)的數(shù)據(jù)(因為代碼最終會全部上傳,所以這里只寫重要部分來講解)

          DateOfDayBean bean = new DateOfDayBean();bean.setDayOfMonth(String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)));bean.setCalendar(calendar);


          這里我遇到了一個坑,就是計算今天的時候,用了:

          calendar.compareTo(Calendar.getInstance()));

          這個方法,這個方法其實比較算了時分秒,完全相同的時間戳才會相等,后面該用判斷年月日相同就認為是同一天了。


          點擊邏輯部分


          這個部分也是難點之一,點擊分為三個部分來進行判斷顯示:

          • 選了開始,沒選結(jié)束

          • 選了開始與結(jié)束

          • 什么都沒有選


          其中選了開始與結(jié)束,還有一種樣式就是開始與結(jié)束為同一天,這種需要區(qū)分對待。詳細見代碼。


          源碼地址:

          https://github.com/zangp/ChooseDateView

          瀏覽 66
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  最大的一级A片 | 特黄AAAAAAAA片免费直播 | 婷婷五月天成人 | 国产内射一级毛片农民工 | 亚洲第一字幕 |