1. 程式人生 > >android中DatePickerDialog只顯示年月

android中DatePickerDialog只顯示年月

今天專案中碰到一個需求,就是在填信用卡的時候,需要填信用卡的有效期(包括年月,沒有日),但是正常的日期選擇器都是有日的。。。。另外專案中希望彈出個dialog來顯示日期選擇器,所以這裡採用DatePickerDialog。

實現的效果是:無論在什麼語言的系統下,都只顯示年月,並且月在前,年在後(在英文的系統中,是mmddyy的順序,但是在中文系統中是yymmdd的順序)

看下程式碼:

        final Calendar calendar = Calendar.getInstance();
        int yy = calendar.get(Calendar.YEAR);
        int mm = calendar.get(Calendar.MONTH);
        int dd = calendar.get(Calendar.DAY_OF_MONTH);

        DatePickerDialog dlg = new DatePickerDialog(new ContextThemeWrapper(getActivity(),
                android.R.style.Theme_Holo_Light_Dialog_NoActionBar), null, yy, mm, dd) {
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                LinearLayout mSpinners = (LinearLayout) findViewById(getContext().getResources().getIdentifier("android:id/pickers", null, null));
                if (mSpinners != null) {
                    NumberPicker mMonthSpinner = (NumberPicker) findViewById(getContext().getResources().getIdentifier("android:id/month", null, null));
                    NumberPicker mYearSpinner = (NumberPicker) findViewById(getContext().getResources().getIdentifier("android:id/year", null, null));
                    mSpinners.removeAllViews();
                    if (mMonthSpinner != null) {
                        mSpinners.addView(mMonthSpinner);
                    }
                    if (mYearSpinner != null) {
                        mSpinners.addView(mYearSpinner);
                    }
                }
                View dayPickerView = findViewById(getContext().getResources().getIdentifier("android:id/day", null, null));
                if(dayPickerView != null){
                    dayPickerView.setVisibility(View.GONE);
                }
            }

            @Override
            public void onDateChanged(DatePicker view, int year, int month, int day) {
                super.onDateChanged(view, year, month, day);
                setTitle("請選擇信用卡有效期");
            }
        };
        dlg.setTitle("請選擇信用卡有效期");

執行上述程式碼的效果是這樣的:

怎麼樣,是不是好看了很多?效果的變化來源於在宣告DatePickerDialog的時候,傳了一個主題theme給它:

new ContextThemeWrapper(getActivity(),android.R.style.Theme_Holo_Light_Dialog_NoActionBar)

如果沒有傳入style的話,長這個樣子:


現在再來看看,是如何做到隱藏日的選擇器,只顯示年和月的,並且讓月顯示在年前面的。

在DatePickerDialog中,也是有一個DatePicker的,現在來看下DatePicker的程式碼,我找到了他引用的layout資源:


開啟該資原始檔:

<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->

<!-- Layout of date picker-->

<!-- Warning: everything within the "pickers" layout is removed and re-ordered
     depending on the date format selected by the user.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="center_horizontal"
    android:orientation="horizontal"
    android:gravity="center">

    <LinearLayout android:id="@+id/pickers"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:gravity="center">

        <!-- Month -->
        <NumberPicker
            android:id="@+id/month"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="1dip"
            android:layout_marginEnd="1dip"
            android:focusable="true"
            android:focusableInTouchMode="true"
            />

        <!-- Day -->
        <NumberPicker
            android:id="@+id/day"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="1dip"
            android:layout_marginEnd="1dip"
            android:focusable="true"
            android:focusableInTouchMode="true"
            />

        <!-- Year -->
        <NumberPicker
            android:id="@+id/year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="1dip"
            android:layout_marginEnd="1dip"
            android:focusable="true"
            android:focusableInTouchMode="true"
            />

    </LinearLayout>

    <!-- calendar view -->
    <CalendarView
        android:id="@+id/calendar_view"
        android:layout_width="245dip"
        android:layout_height="280dip"
        android:layout_marginStart="44dip"
        android:layout_weight="1"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:visibility="gone"
        />

</LinearLayout>
preview的效果是:


看到了吧,其實內部是三個NumberPicker,外部的佈局是LinearLayout,橫向排列。那我在想隱藏日的選擇器很簡單,直接獲取該view,然後設定為gone就好了。(看上面的程式碼你就懂了,這裡不說明了)

但是再一看程式碼,發現該layout原來的順序就是month-day-year,那為什麼中文系統中會修改順序呢?繼續找程式碼!

往下翻找,找到了一個reorderSpinner的方法,原來就是這段程式碼,根據當前系統的語言,來重排序了!

/**
         * Reorders the spinners according to the date format that is
         * explicitly set by the user and if no such is set fall back
         * to the current locale's default format.
         */
        private void reorderSpinners() {
            mSpinners.removeAllViews();
            // We use numeric spinners for year and day, but textual months. Ask icu4c what
            // order the user's locale uses for that combination. http://b/7207103.
            String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
            char[] order = ICU.getDateFormatOrder(pattern);
            final int spinnerCount = order.length;
            for (int i = 0; i < spinnerCount; i++) {
                switch (order[i]) {
                    case 'd':
                        mSpinners.addView(mDaySpinner);
                        setImeOptions(mDaySpinner, spinnerCount, i);
                        break;
                    case 'M':
                        mSpinners.addView(mMonthSpinner);
                        setImeOptions(mMonthSpinner, spinnerCount, i);
                        break;
                    case 'y':
                        mSpinners.addView(mYearSpinner);
                        setImeOptions(mYearSpinner, spinnerCount, i);
                        break;
                    default:
                        throw new IllegalArgumentException(Arrays.toString(order));
                }
            }
        }
看完這段程式碼,我就大概知道怎麼重排年和月了,看最上面我提供的實現程式碼,你就應該知道了,不再贅述了。