android選擇時間攻略


安卓開發過程中難免會碰到需要選擇日期時間的情況,由於大部分android初級教程都沒教怎么選擇時間,初學者碰到這種難免會有些不知所措,難道要讓用戶自己輸入日期時間?先不說用戶體驗不好,處理用戶輸入各式各樣的日期格式也要花好大一番功夫。

日期還要自己輸入?

所以當然不可能讓用戶自己輸入日期時間,筆者收集整理了一些資料,總結了一下如何實現android選擇時間的功能,方便后來者參考


android 6.0 中的運行效果
效果圖

效果圖

TimePickerDialog和DatePickerDialog介紹

系統封裝好了兩個類可以供我們直接調用,TimepickerDialog用於選擇時間,DatePickerDialog用於選擇日期。

TimePikckerDialog的構造方法

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

DatePickerDialog構造方法

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

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


具體實現

有兩種實現方式,一種是直接在Activity中使用,還有一種是通過FragmentDialog使用。
直接在Activity中使用比較簡單,不過代碼會比較亂,通過FragmentDialog管理的使用方式會比較優雅,而且便於管理。

  • 直接在Activity中使用

布局文件,里面就一個TextView用於顯示所選時間

<?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="點此選擇時間"
        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設置點擊事件
        timeText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //將timeText傳入用於顯示所選擇的時間
                showDialogPick((TextView) v);
            }
        });
    }
    //將兩個選擇時間的dialog放在該函數中
    private void showDialogPick(final TextView timeText) {
        final StringBuffer time = new StringBuffer();
        //獲取Calendar對象,用於獲取當前時間
        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);
        //實例化TimePickerDialog對象
        final TimePickerDialog timePickerDialog = new TimePickerDialog(TestActivity.this, new TimePickerDialog.OnTimeSetListener() {
            //選擇完時間后會調用該回調函數
            @Override
            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                time.append(" "  + hourOfDay + ":" + minute);
                //設置TextView顯示最終選擇的時間
                timeText.setText(time);
            }
        }, hour, minute, true);
        //實例化DatePickerDialog對象
        DatePickerDialog datePickerDialog = new DatePickerDialog(TestActivity.this, new DatePickerDialog.OnDateSetListener() {
            //選擇完日期后會調用該回調函數
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                //因為monthOfYear會比實際月份少一月所以這邊要加1
                time.append(year + "-" + (monthOfYear+1) + "-" + dayOfMonth);
                //選擇完日期后彈出選擇時間對話框
                timePickerDialog.show();
            }
        }, year, month, day);
        //彈出選擇日期對話框
        datePickerDialog.show();
    }

}

到此,點擊運行就可以看效果了:)

  • 通過FragmentDialog使用

為什么要用DialogFragment

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

通過FragmentDialog實現步驟

  • DatePickerFragment類:
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener{
    private String date;
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        //得到Calendar類實例,用於獲取當前時間
        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對象
        //因為實現了OnDateSetListener接口,所以第二個參數直接傳入this
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

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

    //實現OnTimeSetListener的onTimeSet方法
    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        //判斷activity是否是DataCallBack的一個實例
        if(getActivity() instanceof DataCallBack){
            //將activity強轉為DataCallBack
            DataCallBack dataCallBack = (DataCallBack) getActivity();
            time = time + hourOfDay + "點" + minute + "分";
            //調用activity的getData方法將數據傳回activity顯示
            dataCallBack.getData(time);
        }
    }

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

}
  • Activity的布局文件,只有一個TextView用於顯示時間
<?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="點此選擇時間"
        android:textSize="20sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

  • Activity文件:
//實現DataCallBack接口,實現與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設置點擊事件
        timeText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //實例化對象
                DatePickerFragment datePickerFragment = new DatePickerFragment();
                //調用show方法彈出對話框
                // 第一個參數為FragmentManager對象
                // 第二個為調用該方法的fragment的標簽
                datePickerFragment.show(getFragmentManager(), "date_picker");
            }
        });
    }


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

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

兼容性問題

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

重寫TimePickerDialog和DatePickerDialog的onStop()方法

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

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

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

  • 通過FragmentDialog使用的重寫方式

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

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() {
            }
        };

博主水平有限,但是保證以上代碼都是親手實現過一遍的。如果有什么不足之處歡迎大家指出_

參考

android學習筆記(十二)日期、時間組件

詳細解讀DialogFragment

解決TimePickerDialog中onTimeSet執行兩次的問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM