android選擇時間攻略

来源:http://www.cnblogs.com/bloglkl/archive/2016/08/14/5770279.html
-Advertisement-
Play Games

安卓開發過程中難免會碰到需要選擇日期時間的情況,由於大部分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執行兩次的問題


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Range對象之cloneRange和cloneContents 代碼效果如下 首次點擊“選擇內容“按鈕提示如下 接著會顯示 最後顯示 以下為整個代碼 看了以上代碼和效果也能知道cloneRange和cloneContents的區別了,最主要的是在實際應用中體會吧. Range對象之extractC ...
  • ...
  • 今天在學習《jQuery基礎教程》在學習編寫插件的時候,書中說利用回調函數來當參數,會極大的提高程式的靈活性。對回調函數很陌生。研究了一下給的示常式序。感覺對回調函數有了基本的瞭解。記錄下來,以備後用。 ...
  • Range對象基本用法 效果圖如下(在谷歌瀏覽器下的展示) 代碼如下 在火狐瀏覽器下的展示 為什麼會出現這種情況呢,因為火狐瀏覽器下可以針對不連續的內容多選. Range對象之SelectNode和selectNodeContents方法 效果圖如下 代碼內容如下: selectNodeConten ...
  • 自定義屬性 繪製 源碼: https://github.com/ln0491/ProgressDemo ...
  • Swift - RotateView 效果 源碼 https://github.com/YouXianMing/Swift-Animations ...
  • 介面 ...
  • 一.點擊更多按鈕 1.項目需求 點擊更多按鈕,從底部彈出一個框 2.怎麼從底部彈出一個框? 兩種方法: 一種用 UIActionSheet 另一種用 UIAlertController 2.1 使用UIActionSheet 好處: 不需要控制器,直接就能使用 缺點: 方法過期了,監聽按鈕的點擊比較 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...