android選擇時(shí)間攻略

<big>安卓開發(fā)過(guò)程中難免會(huì)碰到需要選擇日期時(shí)間的情況,由于大部分android初級(jí)教程都沒教怎么選擇時(shí)間,初學(xué)者碰到這種難免會(huì)有些不知所措,難道要讓用戶自己輸入日期時(shí)間?先不說(shuō)用戶體驗(yàn)不好,處理用戶輸入各式各樣的日期格式也要花好大一番功夫。</big>

日期還要自己輸入?

<big>所以當(dāng)然不可能讓用戶自己輸入日期時(shí)間,筆者收集整理了一些資料,總結(jié)了一下如何實(shí)現(xiàn)android選擇時(shí)間的功能,方便后來(lái)者參考</big>


android 6.0 中的運(yùn)行效果

效果圖

效果圖

TimePickerDialog和DatePickerDialog介紹

系統(tǒng)封裝好了兩個(gè)類可以供我們直接調(diào)用,TimepickerDialog用于選擇時(shí)間,DatePickerDialog用于選擇日期。

TimePikckerDialog的構(gòu)造方法

public TimePickerDialog(Context context, OnTimeSetListener listener, int hourOfDay, int minute, boolean is24HourView)
  • 第一個(gè)參數(shù)接受一個(gè)context信息
  • 第二個(gè)參數(shù)為當(dāng)選擇時(shí)間完成后執(zhí)行的回調(diào)接口
  • 第三個(gè)參數(shù)和第四個(gè)參數(shù)為初始化的時(shí)間
  • 第四個(gè)參數(shù)選擇true代表24小時(shí)制,false代表12小時(shí)制

DatePickerDialog構(gòu)造方法

public DatePickerDialog(Context context, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth)
  • 第一個(gè)參數(shù)接受context信息
  • 第二個(gè)參數(shù)為日期選擇完成后的回掉接口
  • 最后三個(gè)參數(shù)分別為初始化的年月日

可以看出兩者的構(gòu)造方法基本相差不多,由于兩者都是繼承自AlertDialog,所以得到兩者對(duì)象后只要調(diào)用它們的show()方法即可將選擇框彈出。


具體實(shí)現(xiàn)

有兩種實(shí)現(xiàn)方式,一種是直接在Activity中使用,還有一種是通過(guò)FragmentDialog使用。
直接在Activity中使用比較簡(jiǎn)單,不過(guò)代碼會(huì)比較亂,通過(guò)FragmentDialog管理的使用方式會(huì)比較優(yōu)雅,而且便于管理。

  • 直接在Activity中使用

布局文件,里面就一個(gè)TextView用于顯示所選時(shí)間

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.testdemo.TestActivity">

    <TextView
        android:layout_centerInParent="true"
        android:textSize="20sp"
        android:id="@+id/time_text"
        android:text="點(diǎn)此選擇時(shí)間"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

Activity文件:

public class TestActivity extends AppCompatActivity {

    private TextView timeText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        timeText = (TextView) findViewById(R.id.time_text);
        //為TextView設(shè)置點(diǎn)擊事件
        timeText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //將timeText傳入用于顯示所選擇的時(shí)間
                showDialogPick((TextView) v);
            }
        });
    }
    //將兩個(gè)選擇時(shí)間的dialog放在該函數(shù)中
    private void showDialogPick(final TextView timeText) {
        final StringBuffer time = new StringBuffer();
        //獲取Calendar對(duì)象,用于獲取當(dāng)前時(shí)間
        final Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        //實(shí)例化TimePickerDialog對(duì)象
        final TimePickerDialog timePickerDialog = new TimePickerDialog(TestActivity.this, new TimePickerDialog.OnTimeSetListener() {
            //選擇完時(shí)間后會(huì)調(diào)用該回調(diào)函數(shù)
            @Override
            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                time.append(" "  + hourOfDay + ":" + minute);
                //設(shè)置TextView顯示最終選擇的時(shí)間
                timeText.setText(time);
            }
        }, hour, minute, true);
        //實(shí)例化DatePickerDialog對(duì)象
        DatePickerDialog datePickerDialog = new DatePickerDialog(TestActivity.this, new DatePickerDialog.OnDateSetListener() {
            //選擇完日期后會(huì)調(diào)用該回調(diào)函數(shù)
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                //因?yàn)閙onthOfYear會(huì)比實(shí)際月份少一月所以這邊要加1
                time.append(year + "-" + (monthOfYear+1) + "-" + dayOfMonth);
                //選擇完日期后彈出選擇時(shí)間對(duì)話框
                timePickerDialog.show();
            }
        }, year, month, day);
        //彈出選擇日期對(duì)話框
        datePickerDialog.show();
    }

}

到此,點(diǎn)擊運(yùn)行就可以看效果了:)

  • 通過(guò)FragmentDialog使用

為什么要用DialogFragment

  1. 用DialogFragment管理對(duì)話框是官方推介的使用方式。
  2. 使用DialogFragment管理對(duì)話框也方便代碼的重用。
  3. 如果你想了解更多可以看看詳細(xì)解讀DialogFragment,里面講的很詳細(xì)。

通過(guò)FragmentDialog實(shí)現(xiàn)步驟

  • DatePickerFragment類:
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener{
    private String date;
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        //得到Calendar類實(shí)例,用于獲取當(dāng)前時(shí)間
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        //返回DatePickerDialog對(duì)象
        //因?yàn)閷?shí)現(xiàn)了OnDateSetListener接口,所以第二個(gè)參數(shù)直接傳入this
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    //實(shí)現(xiàn)OnDateSetListener接口的onDateSet()方法
    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        //這樣子寫就將選擇時(shí)間的fragment和選擇日期的fragment完全綁定在一起
        //使用的時(shí)候只需直接調(diào)用DatePickerFragment的show()方法
        //即可選擇完日期后選擇時(shí)間
        TimePickerFragment timePicker = new TimePickerFragment();
        timePicker.show(getFragmentManager(), "time_picker");
        //將用戶選擇的日期傳到TimePickerFragment
        date = year + "年" + (monthOfYear+1) + "月" + dayOfMonth + "日";
        timePicker.setTime(date);
    }
}
  • TimePickerFragment類:
//實(shí)現(xiàn)OnTimeSetListener接口
public class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener{
    private String time = "";
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        //新建日歷類用于獲取當(dāng)前時(shí)間
        Calendar calendar = Calendar.getInstance();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        //返回TimePickerDialog對(duì)象
        //因?yàn)閷?shí)現(xiàn)了OnTimeSetListener接口,所以第二個(gè)參數(shù)直接傳入this
        return new TimePickerDialog(getActivity(), this, hour, minute, true);
    }

    //實(shí)現(xiàn)OnTimeSetListener的onTimeSet方法
    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        //判斷activity是否是DataCallBack(這是自己定義的一個(gè)接口)的一個(gè)實(shí)例
        if(getActivity() instanceof DataCallBack){
            //將activity強(qiáng)轉(zhuǎn)為DataCallBack
            DataCallBack dataCallBack = (DataCallBack) getActivity();
            time = time + hourOfDay + "點(diǎn)" + minute + "分";
            //調(diào)用activity的getData方法將數(shù)據(jù)傳回activity顯示
            dataCallBack.getData(time);
        }
    }

    public void setTime(String date){
        time += date;
    }

}
  • Activity的布局文件,只有一個(gè)TextView用于顯示時(shí)間
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.testdemo.TestActivityActivity">

    <TextView
        android:id="@+id/time_text"
        android:layout_centerInParent="true"
        android:text="點(diǎn)此選擇時(shí)間"
        android:textSize="20sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

  • DataCallBack接口:
public interface DataCallBack {
    void getData(String data);
}

  • Activity文件:
//實(shí)現(xiàn)DataCallBack接口,實(shí)現(xiàn)與Fragment的通信
public class TestActivityActivity extends AppCompatActivity implements DataCallBack{

    TextView timeText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test2);
        timeText = (TextView) findViewById(R.id.time_text);
        //為timeText設(shè)置點(diǎn)擊事件
        timeText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //實(shí)例化對(duì)象
                DatePickerFragment datePickerFragment = new DatePickerFragment();
                //調(diào)用show方法彈出對(duì)話框
                // 第一個(gè)參數(shù)為FragmentManager對(duì)象
                // 第二個(gè)為調(diào)用該方法的fragment的標(biāo)簽
                datePickerFragment.show(getFragmentManager(), "date_picker");
            }
        });
    }


    //實(shí)現(xiàn)DataCallBack的getData方法
    @Override
    public void getData(String data) {
        //data即為fragment調(diào)用該函數(shù)傳回的日期時(shí)間
        timeText.setText(data);
    }
}

由于TimePickerFragment對(duì)話框是在DatePickerFragment類里面啟動(dòng)的,所以這樣寫只能日期和時(shí)間都選擇,如果要單獨(dú)選擇日期或者時(shí)間,只需要重寫onTimeSet()或者onDateSet()方法即可

兼容性問(wèn)題

不同的android版本顯示的效果不同,在android6.0效果很好,不過(guò)在一些低版本android(如4.0,筆者沒有每個(gè)版本都測(cè)試)會(huì)出現(xiàn)調(diào)用兩次回掉函數(shù)的情況,導(dǎo)致選擇兩次時(shí)間。解決的辦法有很多,只要保證回調(diào)函數(shù)里面的邏輯只執(zhí)行一次就可以。這里提供一種比較通用的方法。

重寫TimePickerDialog和DatePickerDialog的onStop()方法

  • 直接在Activity中使用的重寫方法
final TimePickerDialog timePickerDialog = new TimePickerDialog(TestActivity.this, new TimePickerDialog.OnTimeSetListener() {
            //選擇完時(shí)間后會(huì)調(diào)用該回調(diào)函數(shù)
            @Override
            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                time.append(" "  + hourOfDay + ":" + minute);
                //設(shè)置TextView顯示最終選擇的時(shí)間
                timeText.setText(time);
            }
        }, hour, minute, true){
          // 重寫onStop()
            @Override
            protected void onStop() {

            }
        };
        //實(shí)例化DatePickerDialog對(duì)象
        DatePickerDialog datePickerDialog = new DatePickerDialog(TestActivity.this, new DatePickerDialog.OnDateSetListener() {
            //選擇完日期后會(huì)調(diào)用該回調(diào)函數(shù)
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                //因?yàn)閙onthOfYear會(huì)比實(shí)際月份少一月所以這邊要加1
                time.append(year + "-" + (monthOfYear+1) + "-" + dayOfMonth);
                //選擇完日期后彈出選擇時(shí)間對(duì)話框
                timePickerDialog.show();
            }
        }, year, month, day){
           //重寫onstop
            @Override
            protected void onStop() {
            }
        };

上面的寫法看起來(lái)會(huì)比較亂,也可以另外新建一個(gè)類繼承TimePickerDialog或者DatePickerDialog然后重寫onStop()方法

  • 通過(guò)FragmentDialog使用的重寫方式

只需在onCreateDialog()方法里面重寫即可,下面的代碼會(huì)比較清晰

return new DatePickerDialog(getActivity(), this, year, month, day){
           // 重寫onStop
            @Override
            protected void onStop() {
            }
        };
 return new TimePickerDialog(getActivity(), this, hour, minute, true){
            //重寫onStop
            @Override
            protected void onStop() {
            }
        };

筆者水平有限,但是保證以上代碼都是親手實(shí)現(xiàn)過(guò)一遍的。如果有什么不足之處歡迎大家指出_。

參考

android學(xué)習(xí)筆記(十二)日期、時(shí)間組件

詳細(xì)解讀DialogFragment

解決TimePickerDialog中onTimeSet執(zhí)行兩次的問(wèn)題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,940評(píng)論 25 709
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 47,147評(píng)論 22 665
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 7,321評(píng)論 0 17
  • 曾經(jīng)有一個(gè)這樣的貼子: “一位女作家27歲,名校畢業(yè),在著名公關(guān)公司做項(xiàng)目總監(jiān),夫婦兩人月收入4萬(wàn),經(jīng)過(guò)種種曲折,...
    深圳房友圈閱讀 393評(píng)論 0 0
  • 有的人過(guò)于強(qiáng)調(diào)自己的主觀性,如此以來(lái),他的內(nèi)在世界就會(huì)變得與現(xiàn)實(shí)完全脫節(jié)。在此情況下,我們把這個(gè)人稱為瘋子。 另一...
    七月的小七閱讀 228評(píng)論 0 0

友情鏈接更多精彩內(nèi)容