Kotlin入門(20)幾種常見的對話框

来源:https://www.cnblogs.com/aqi00/archive/2018/09/27/9716207.html
-Advertisement-
Play Games

提醒對話框手機上的App極大地方便了人們的生活,很多業務只需用戶拇指一點即可輕鬆辦理,然而這也帶來了一定的風險,因為有時候用戶並非真的想這麼做,只是不小心點了一下而已,如果App不做任何提示的話,繼續吭哧吭哧兀自辦完業務,比如轉錯錢了、誤刪資料了,往往令用戶追悔莫及。所以對於部分關鍵業務,App為了 ...


提醒對話框
手機上的App極大地方便了人們的生活,很多業務只需用戶拇指一點即可輕鬆辦理,然而這也帶來了一定的風險,因為有時候用戶並非真的想這麼做,只是不小心點了一下而已,如果App不做任何提示的話,繼續吭哧吭哧兀自辦完業務,比如轉錯錢了、誤刪資料了,往往令用戶追悔莫及。所以對於部分關鍵業務,App為了避免用戶的誤操作,很有必要彈出消息對話框,提醒用戶是否真的要進行此項操作。這個提醒對話框便是App開發常見的AlertDialog,說起這個AlertDialog,安卓開發者都有所耳聞,該對話框不外乎消息標題、消息內容、確定按鈕、取消按鈕這四個要素,使用Java編碼顯示提醒對話框,基本跟下麵的示例代碼大同小異:

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("尊敬的用戶");
    builder.setMessage("你真的要卸載我嗎?");
    builder.setPositiveButton("殘忍卸載", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            tv_alert.setText("雖然依依不捨,但是只能離開了");
        }
    });
    builder.setNegativeButton("我再想想", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            tv_alert.setText("讓我再陪你三百六十五個日夜");
        }
    });
    AlertDialog alert = builder.create();
    alert.show();

 

顯而易見上述代碼非常冗長,特別是兩個按鈕的點擊事件,又是匿名類又是函數重載,令人不堪卒讀。嘗試將以上Java代碼轉換為Kotlin代碼,則改寫後的Kotlin代碼如下所示:

    val builder = AlertDialog.Builder(this)
    builder.setTitle("尊敬的用戶")
    builder.setMessage("你真的要卸載我嗎?")
    builder.setPositiveButton("殘忍卸載") { dialog, which -> tv_alert.text = "雖然依依不捨,還是只能離開了" }
    builder.setNegativeButton("我再想想") { dialog, which -> tv_alert.text = "讓我再陪你三百六十五個日夜" }
    val alert = builder.create()
    alert.show()

 

這下看來點擊事件的代碼在很大程度上簡化了,不過除此之外,整塊代碼依然顯得有些臃腫,尤其是運用了建造者模式的Builder類,雖然錶面上增強了安全性,但對於編碼來說其實是累贅。因此,Anko庫將其做了進一步的封裝,給Context類添加了一個擴展函數,即“alert(消息內容, 消息標題) { 幾個按鈕及其點擊事件 }”,簡化後的alert彈窗代碼舉例如下:

    alert("你真的要卸載我嗎?", "尊敬的用戶") {
        positiveButton("殘忍卸載") { tv_alert.text = "雖然依依不捨,還是只能離開了" }
        negativeButton("我再想想") { tv_alert.text = "讓我再陪你三百六十五個日夜" }
    }.show()

 

現在的Kotlin代碼相比之下更方便閱讀了,並且代碼量還不到原來Java代碼的三分之一。當然,為了正常地使用這麼好的擴展函數,不要忘了在代碼文件頭部加上下麵一行導入語句:

import org.jetbrains.anko.alert

 

這麼精簡的Kotlin代碼,功能上可是一點都沒偷工減料的,它的提醒對話框效果與Java編碼一模一樣,都如下圖所示。

 

下拉選擇框
對於某些固定值的條件選擇,比如紅綠藍三原色選擇其一,一月份到十二月份選擇其中一個月份等等,這些情況在Android中用到了下拉框Spinner。界面上的Spinner控制項一開始是個右側帶向下箭頭的文本,點擊該文本會彈出一個選擇對話框,選中某一項之後,對話框消失,同時界面上的文本替換為剛纔選中的文本內容。光看下拉框的功能其實挺簡單的,可是若用Java代碼實現的話,就得費一番功夫了,下麵便是Spinner控制項的調用代碼例子:

    private void initSpinner() {
        ArrayAdapter<String> starAdapter = new ArrayAdapter<String>(this,
                R.layout.item_select, starArray);
        starAdapter.setDropDownViewResource(R.layout.item_dropdown);
        Spinner sp = (Spinner) findViewById(R.id.sp_dialog);
        sp.setPrompt("請選擇行星");
        sp.setAdapter(starAdapter);
        sp.setSelection(0);
        sp.setOnItemSelectedListener(new MySelectedListener());
    }

    private String[] starArray = {"水星", "金星", "地球", "火星", "木星", "土星"};
    class MySelectedListener implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            Toast.makeText(SpinnerDialogActivity.this, "你選擇的行星是"+starArray[arg2], Toast.LENGTH_LONG).show();
        }

        public void onNothingSelected(AdapterView<?> arg0) {}
    }

不出所料這再次體現了Java編碼的尾大不掉,簡簡單單的功能在Java代碼中被分解為以下幾個專門的處理:

1、首先要定義一個數組適配器ArrayAdapter,指定待選擇的字元串數組,以及每項文本的佈局文件;
2、其次要定義一個選擇監聽器OnItemSelectedListener,在用戶選中某項時觸發,響應文本項的選中事件;
3、最後Spinner控制項依次設置選擇對話框的標題、數組適配器、選擇監聽器、預設選項等等;
我的天,這也太專業了吧,在產品經理看來,這隻是個下拉框而已,有必要搞這麼複雜嗎?然而Java代碼就是這麼錯綜複雜,要想開發Android,只能這麼搗騰,不然還有更好的法子嗎?不信的話換成Kotlin試試?說時遲那時快,在Android Studio上面把Spinner上述的Java代碼轉換為Kotlin,不一會兒就生成瞭如下的Kotlin代碼: 

    private fun initSpinner() {
        val starAdapter = ArrayAdapter(this, R.layout.item_select, starArray)
        starAdapter.setDropDownViewResource(R.layout.item_dropdown)
        val sp = findViewById(R.id.sp_dialog) as Spinner
        sp.prompt = "請選擇行星"
        sp.adapter = starAdapter
        sp.setSelection(0)
        sp.onItemSelectedListener = MySelectedListener()
    }

    private val starArray = arrayOf("水星", "金星", "地球", "火星", "木星", "土星")
    internal inner class MySelectedListener : OnItemSelectedListener {
        override fun onItemSelected(arg0: AdapterView<*>, arg1: View, arg2: Int, arg3: Long) {
            toast("你選擇的行星是${starArray[arg2]}")
        }

        override fun onNothingSelected(arg0: AdapterView<*>) {}
    }

瞧瞧,號稱終結者的Kotlin也不過爾爾,整體代碼量跟Java相比是半斤八兩,絲毫不見了往日的威風。由於這裡的Java代碼邏輯實在拐彎抹角,又是數組適配器又是選擇監聽器的,因此Kotlin對這種玩意確實沒有好辦法。既然此路不通,那就試試別的辦法唄,前面提到Spinner其實由兩部分組成,一部分是直接顯示在界面上的帶箭頭文本,另一部分是點擊後彈出的選擇對話框,所以能不能繞過Spinner,運用所見即所得的理念,乾脆把下拉框分離成兩個控制項好了。倘若僅僅是一個帶箭頭的文本,毫無疑問使用文本視圖TextView就可以了,箭頭圖標可以在佈局文件中通過drawableRight屬性來指定。於是佈局文件中的下麵Spinner節點: 

    <Spinner
        android:id="@+id/sp_dialog"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_toRightOf="@+id/tv_dialog"
        android:gravity="left|center"
        android:spinnerMode="dialog" />

 

錶面上完全可以被下麵這個TextView節點所取代:

    <TextView
        android:id="@+id/tv_spinner"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_toRightOf="@+id/tv_dialog"
        android:gravity="center"
        android:drawableRight="@drawable/arrow_down"
        android:textColor="@color/black"
        android:textSize="17sp" />

如果再來一個選擇對話框,這樣只要給該文本視圖添加點擊事件,點擊TextView彈出選擇框,豈不是萬事大吉?正巧Anko庫已經提供了這股東風,與alert一樣來自於Context的擴展函數,它便是“selector(對話框標題, 字元串隊列) { i -> 第i項的選中處理代碼 }”,那麼將其與前面的文本視圖相結合,即可無縫實現原來的下拉框功能,具體的Kotlin代碼如下所示: 

    val satellites = listOf("水星", "金星", "地球", "火星", "木星", "土星")
    tv_spinner.text = satellites[0]
    tv_spinner.setOnClickListener {
        selector("請選擇行星", satellites) { i ->
            tv_spinner.text = satellites[i]
            toast("你選擇的行星是${tv_spinner.text}")
        }
    }

 

看看這幾行代碼,完全不見了數組適配器和選擇監聽器的蹤影,故而代碼量一下劇減到對應Java代碼的三分之一。當然,為了正常地使用selector函數,不要忘了在代碼文件頭部加上下麵一行導入語句:

import org.jetbrains.anko.selector

 

雖然把佈局文件裡面的Spinner控制項換成TextView,但是二者在功能使用上是沒什麼區別的,同樣支持點擊文本彈出選擇框,也同樣支持選中某項的回調。改造後下拉框的界面效果如下圖所示。

如此方便易用的selector,竟然撇開了數組適配器和選擇監聽器,那麼它又是怎麼實現的呢?認真閱讀Anko庫裡面的selector源碼,發現原來該函數利用了AlertDialog的setItems方法,通過setItems方法指定一串文本,並且定義了每項的點擊事件,其運行結果竟然與Spinner的選擇對話框殊途同歸。下麵給出AlertDialog對應selector函數的Java實現代碼,方便讀者理解它的本質:

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("請選擇行星");
    builder.setItems(satellites, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            Toast.makeText(SpinnerDialogActivity.this, "你選擇的行星是"+starArray[arg2], Toast.LENGTH_LONG).show();
        }
    });
    builder.create().show();

  


進度對話框
App載入網頁之類的請求服務端行為,經常屬於耗時操作,往往要過好幾秒才能載入完畢,在此期間為了減少用戶的等待焦灼感,界面需要展示正在載入的動畫,一方面避免造成App卡死的錯覺,另一方面提示用戶耐心等待。這時就用到了進度對話框,在載入開始前彈出進度框,載入結束後關閉進度框,從而改善了載入交互的用戶體驗。
進度對話框分兩種,一種是水平進度對話框,另一種是圓圈進度對話框,下麵分別進行介紹。
水平進度對話框
水平進度對話框允許實時刷新當前進度,方便用戶知曉已處理的進展百分比。它主要包含幾個元素,包括消息標題、消息內容、對話框樣式(水平還是圓圈)、當前進度這四種,如果使用Java代碼實現該對話框,則是很常規的編碼風格,具體的Java代碼例子如下:

    ProgressDialog dialog = new ProgressDialog(this);
    dialog.setTitle("請稍候");
    dialog.setMessage("正在努力載入頁面");
    dialog.setMax(100);
    dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    dialog.show();

 

水平進度對話框的Java編碼,看起來十分中規中矩,可是仍然顯得拖泥帶水,很簡單的功能也花費了六行Java代碼。倘若使用Kotlin書寫,則藉助於Anko庫只需下麵兩行代碼:

    val dialog = progressDialog("正在努力載入頁面", "請稍候")
    dialog.show()

 

瞧瞧,水平進度對話框的實現代碼頓時變得清爽了許多,其界面效果與Java是完全一樣的。當然,因為用到了Anko庫的擴展函數,所以務必在代碼頭部加上一行導入語句:

import org.jetbrains.anko.progressDialog

 

在水平進度對話框彈出之後,若想更新水平條的進度值,則可調用以下代碼設置當前進度:

    dialog.progress = 進度值(取值為0到100)

當進度值達到100,意味著處理完成,此時即可調用對話框對象的dismiss函數關閉對話框,下圖展示了水平進度對話框的進度變化效果。

圓圈進度對話框
圓圈進度對話框僅僅展示轉圈的動畫效果,不支持實時刷新處理進度,自然在編碼上比水平對話框會簡化一些,可是用Java來顯示圓圈進度對話框,依舊需要下列的五行代碼:

    ProgressDialog dialog = new ProgressDialog(this);
    dialog.setTitle("請稍候");
    dialog.setMessage("正在努力載入頁面");
    dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    dialog.show();

 

如果用Kotlin實現該對話框的話,有了水平進度對話框的的先例,不出意料只需以下的兩行Kotlin代碼就行了:

    val dialog = indeterminateProgressDialog("正在努力載入頁面", "請稍候")
    dialog.show()

 

註意到上面的Kotlin函數採取了首碼indeterminate,該單詞意思是“模糊的、不定的”,表示這種對話框的處理進度是不確定的,不像水平進度對話框可以明確指定當前進度,據此開發者能夠將progressDialog與indeterminateProgressDialog兩個函數區分開。由於該函數同樣來自於Anko庫,因此不要忘了在用到的代碼文件頭部加入下麵這行語句:

import org.jetbrains.anko.indeterminateProgressDialog

 

Kotlin實現的圓圈進度對話框,轉圈效果等同於Java實現的效果,具體的對話框界面如下圖所示。


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

-Advertisement-
Play Games
更多相關文章
  • 最近內部的 mysql 資料庫發生了一件奇怪的事,其中有一個表 users625 突然出現問題, 所有對它的操作都報錯誤 。 它還顯示在列表裡,在 mysql 數據目錄中也可以找到對應的表文件,也沒有 進行過刪除操作,突然出現這樣的錯誤非常奇怪。 <! more 內部運行環境: | 名稱 | 值 | ...
  • 報錯現象: 從mysql5.5資料庫導出的數據結構放到mysql5.7.10 報錯create_time timestamp NOT NULL DEFAULT ‘0000-00-00 00:00:00’ 則會出現以下的異常: Invalid default value for ‘create_tim ...
  • 工作中遇到的問題,小結一下 查詢今日添加的記錄: select * from [表名] where datediff(day,CONVERT(VARCHAR(20),DATEADD(SECOND,[時間欄位],'1970-01-01 00:00:00'),120),getdate())=0 這裡的 ...
  • 創建主XML索引註意事項 若要創建主 XML 索引,請使用 CREATE INDEX (Transact-SQL) Transact-SQL DDL 語句。 XML 索引不完全支持可用於非 XML 索引的所有選項。 創建 XML 索引時註意下列事項: 若要創建主 XML 索引,含有被索引的 XML ...
  • Hadoop版本演變 Apache Hadoop的四大分支構成了三個系列的Hadoop版本: 0.20.X系列 主要有兩個特征:Append與Security 0.21.0/0.22.X系列 整個Hadoop項目被分割成三個獨立的模塊: 1.Common模塊 2.HDFS模塊 3.Mapreduce ...
  • mysql 正常運行的時候,[查看 table 的結構][show create table doc]並不是困難的事。 但是有時 mysql 發生故障,這種方法便不再可行。 當遇到故障,通常使用新的 mysql 實例來恢復當前的數據。 建表是非常重要的步驟,我們必須有其它的方法來尋找 table 的 ...
  • 在使用lepus3.7監控MySQL資料庫的時候,碰到了以下幾個問題,本博客給出了這些問題產生的原因,以及相應的解決辦法。 1. 問題1:php頁面無法連接資料庫 直接使用php程式執行php文件,可以連接mysql,但是在httpd中同樣的php頁面無法連接mysql。 lepus的web程式(P ...
  • 之前一直以為Linux和Windows差不多,但是學習了Linux基礎入門之後才發現兩種操作系統之間差距非常大。 Linux只是在硬體之上的內核和系統調用,就連我們在Windows里習以為常的圖形界面都是Linux上的軟體。在使用Linux的時候,我們都習慣於使用終端和命令行進行操作,而不是像Win ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...