2021年5月6日 星期四

Android Basics in Kotlin - Unit 2: Layouts

Kotlin 簡介

  • 層次結構
    將類別(Class)以父類子類的層次架構進行編排。

    • 子類別 (SubClass)
      屬於其他類別底下的任何類別。

    • 父類別(SuperClass)
      具有仔類別的任何類別。

    • 頂層類別(Top-level Class)
      層次結構中最上層的類別。

    • 繼承
      子類別可繼承其父類別的屬性與函數,使得開發者可以在程式中共享或重複使用代碼。

    • 抽象(Abstract)

      • 抽象類別沒有被完全付諸於實現,是一種不能被實例化的類別,但可以用來建構其他類別;有點類似於設計草圖的概念(可以利用草圖去描繪藍圖,但不能利用草圖直接蓋房子)。

      • 抽象函數不需要在類別中進行實作,但必須在子類別中覆寫進行實作。

    • 覆寫(Override)
      在子類別中覆蓋其父類別中定義的屬性與函數。

    • 宣告 (final)
      透過 final 關鍵字 讓屬性與函數不可在仔類別中被覆寫。

    • 調用父類別 (super)
      利用 super 關鍵字可引用父類別中的屬性與函數。

    • Open 關鍵字 
      透過 open 來表示類別可以被繼承,或讓函數得以被覆寫。

    • 私有屬性 (private property)
      透過 private 關鍵字,讓屬性只能在類別內部使用。

    • with 關鍵字
      透過with 對同一個物件實例作多次調用。

    • 類別範例程式碼
import kotlin.math.PI
import kotlin.math.sqrt

fun main() {

   val squareCabin = SquareCabin(6, 50.0)
   val roundHut = RoundHut(3, 10.0)
   val roundTower = RoundTower(4, 15.5)

   with(squareCabin) {
       println("\nSquare Cabin\n============")
       println("Capacity: ${capacity}")
       println("Material: ${buildingMaterial}")
       println("Floor area: ${floorArea()}")
   }

   with(roundHut) {
       println("\nRound Hut\n=========")
       println("Material: ${buildingMaterial}")
       println("Capacity: ${capacity}")
       println("Floor area: ${floorArea()}")
       println("Has room? ${hasRoom()}")
       getRoom()
       println("Has room? ${hasRoom()}")
       getRoom()
       println("Carpet size: ${calculateMaxCarpetSize()}")
   }

   with(roundTower) {
       println("\nRound Tower\n==========")
       println("Material: ${buildingMaterial}")
       println("Capacity: ${capacity}")
       println("Floor area: ${floorArea()}")
       println("Carpet size: ${calculateMaxCarpetSize()}")
   }
}

abstract class Dwelling(private var residents: Int) {

   abstract val buildingMaterial: String
   abstract val capacity: Int
   abstract fun floorArea(): Double

   fun hasRoom(): Boolean { return residents < capacity }
   fun getRoom() {
       if (capacity > residents) {
           residents++
           println("You got a room!")
       } else {
           println("Sorry, at capacity and no rooms left.")
       }
   }

}

class SquareCabin(residents: Int, val length: Double) : Dwelling(residents) {

   override val buildingMaterial = "Wood"
   override val capacity = 6
   override fun floorArea(): Double { return length * length}

}

open class RoundHut( val residents: Int, val radius: Double) : Dwelling(residents) {

   override val buildingMaterial = "Straw"
   override val capacity = 4
   override fun floorArea(): Double { return PI * radius * radius }

   fun calculateMaxCarpetSize(): Double {
       val diameter = 2 * radius
       return sqrt(diameter * diameter / 2)
   }

}

class RoundTower(residents: Int, radius: Double, val floors: Int = 2) : RoundHut(residents, radius) {

   override val buildingMaterial = "Stone"
   override val capacity = floors * 4
   override fun floorArea(): Double { return super.floorArea() * floors }

}

 


  • XML (eXtensible Markup Language) 由標籤、元素與屬性組成,可用來定義 Android 應用程式的佈局。

  • 使用 EditText 元件使用戶可以輸入或編輯文字

    • EditText 元件可以提示使用者須輸入的資料類型。

    • 透過屬性 android:inputType 可以限制用戶輸入至EditText的內容類型。

  • 使用 RadioButton 元件來建立單選鈕的介面。

    • 選擇鈕的群組可藉由 RadioGroup 元件建立,其排版可依喜好垂直或水平分布。

    • 透過 RadioGroup 的 checkRadioButtonId 屬性可以知道目前被選中的RadioButton是哪一個。

  • 使用 Switch 元件讓用戶可以切換開關。


  • 所有在 ConstraintLayout 內元件皆需設定垂直或水平約束

    • 因各個語言的書寫方向不同,各方向的約束的定義為"起始到結束",非"左到右"。

    • 若要讓 View 的寬度與其所在的 ConstraintLayout 一樣寬,其layout_constraintBottom_toBottomOf 與 layout_constraintStart_toStartOf 皆須設置為 ConstraintLayout  並將寬度設定為0dp。

  • App中檔案
    • MainActivity.kt
      存放所有 Kotlin 程式碼檔案。

    • activity_main.xml
      App的佈局檔案。

    • strings.xml
      App內使用到的字串資源。

    • Gradle
      Android Studio 使用的自動建構系統,當開發人員更改程式碼或匯入資源時,Gradle 會找出以更改的內容並採取必要的措施以重新建構程式。

  • 視圖綁定 (View binding)
    透過視圖綁定,開發者可更加輕鬆地與 App 中的介面元素進行互動。

    • 綁定類別的名稱是透過將 XML 文件的名稱轉換為駝峰式大小寫的格式並將單詞 "Binding" 添加到後面而生成的。例如: activity_main.xml 變成 ActivityMainBinding 。

  • 格式化輸出 (Formatter)
    透過 NumberFormat.getCurrencyInstance(),我們可將數字格式化為貨幣形式。

  • 動態字串
    可透過%s創建動態字串。

  • 可使用 Android Studio 中的 Logcat 排除問題,堆疊追蹤會顯示程式碼中產生異常訊息的部份。

  • Null 代表沒有值
    • 並非所有程式碼都可以處理 Null。

  • 透過 Android Studio 的 Analyze > Inspect Code,可以獲取改進程式碼的建議。

  • 使用 Material Color 工具來選擇App主題的顏色,或是利用調色盤工具選擇色調。

  • 在colors.xml 中建立顏色資源,以便重覆調用。

  • 主題分為一般與深色主題,深色主題可以減少功耗並利於光源較低的環境下觀看。

  • 盡可能使用 Material Design Components 以符合質感設計指南。

  • 添加圖示讓 App 中操作起來更加直觀。

  • 須注意佈局是否出現超出邊界的情形。

  • 圖示應放置在mipmap資源目錄中,並提供各個解析度的圖示檔案(mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi)。

  • 向量繪製圖像是Android 對於向量圖的實現,可以任意縮放而不受解析度影響,圖像背後為XML中對於點、線、面與其顏色的定義。

  • 自適應圖像在 API 26 之後被引入 Android 平台,透過符合某些要求的前景與背景層堆疊產生。

  • 利用 Android Studio 中的 Image Asset Studio工具產生就版或自適應圖像。

  • Kotlin 中的集合有 list, set 與 map

    • List 是特定元素的有序集合

      • 索引(Index)是反映元素所在的整數位置。

      • 列表的第一個元素,其索引為 0 。

      • Type
        • List
          唯讀,一但初始化即無法變更。

        • MutableList
          可在創建後進行修改。

  • Loop

    • While
      while (expression) {
      While the expression is true, execute this code block
      }

    • For
      for (item in myList) {
      Execute this code block for each element of the list
      }


  • vararg
    定義函數時使用 vararg 宣告參數,可允許傳遞不等量的參數進函數,但 vararg 的宣告只能放在最後的參數上。

  • RecyclerView


    • RecycleView元件內建 LayoutManagers,可透過Adapter的模式來顯示列表數據。

    • Adapter的構成

      • 為 Adapter 創建 ItemAdapter 類別以容納列表數據。

      • 創建ItemViewHolder (繼承自RecyclerView.ViewHolder),用來表示單個列表元素的View。

      • 在 ItemAdapter 中實現getItemsCount()、 onCreateViewHolder() 與 onBindViewHolder() 方法

        • getItemsCount()
          回傳列表元素個數。

        • onCreateViewHolder()
          LayoutManager 需要為 RecyclerView 創建 ItemViewHolder 時呼叫的函數。

        • onBindViewHolder()
          LayoutManager 需要置換 ItemViewHolder 內容時呼叫的函數。
  • MaterialCardView
    透過 MaterialCardView 組件讓物件於其中顯示。



                                                                                                                                                                                                              沒有留言:

                                                                                                                                                                                                              張貼留言