2025年2月27日 星期四

Android app 程式設計-畫面底部 有三個按鈕 -1

 

 目標

  • 畫面底部 有三個按鈕 (Option1, Option2, Option3)
  • 點擊按鈕時,顯示 Toast 訊息
  • 使用 Jetpack Compose 來設計 UI
MainActivity.kt(完整程式碼 + 註解)

package com.example.myapplication  // 定義這個 Kotlin 檔案的 package 名稱

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

// `MainActivity` 繼承 `ComponentActivity`,是應用的主要活動 (Activity)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) { // `onCreate` 是 Activity 的進入點
        super.onCreate(savedInstanceState)
        setContent { // 使用 Jetpack Compose 來設定 UI
            MyApp() // 呼叫 `MyApp()` 來顯示畫面
        }
    }
}

// `MyApp` 是 Compose 函式 (Composable),用來定義畫面內容
@Composable
fun MyApp() {
    val context = LocalContext.current // 取得當前的 Context (用來顯示 Toast)

    // `Box` 是一個容器,它會填滿整個畫面,並讓內容對齊底部
    Box(
        modifier = Modifier.fillMaxSize(), // `fillMaxSize()` 讓 Box 佔滿整個螢幕
        contentAlignment = Alignment.BottomCenter // 讓內容對齊到畫面底部
    ) {
        // `Row` 用來水平排列三個按鈕
        Row(
            modifier = Modifier
                .fillMaxWidth() // 讓 Row 佔滿整個寬度
                .padding(16.dp), // 設定四周的間距
            horizontalArrangement = Arrangement.SpaceEvenly // 讓按鈕均分寬度
        ) {
            // 第一個按鈕:Option 1
            Button(onClick = {
                Toast.makeText(context, "Option 1 Clicked!", Toast.LENGTH_SHORT).show()
            }) {
                Text("Option 1") // 按鈕內的文字
            }

            // 第二個按鈕:Option 2
            Button(onClick = {
                Toast.makeText(context, "Option 2 Clicked!", Toast.LENGTH_SHORT).show()
            }) {
                Text("Option 2")
            }

            // 第三個按鈕:Option 3
            Button(onClick = {
                Toast.makeText(context, "Option 3 Clicked!", Toast.LENGTH_SHORT).show()
            }) {
                Text("Option 3")
            }
        }
    }
}

// `PreviewMyApp()` 用來預覽 `MyApp()` 的畫面 (在 Android Studio 預覽模式中可見)
@Preview(showBackground = true)
@Composable
fun PreviewMyApp() {
    MyApp()
}




📌 程式碼解析

1️⃣ setContent { MyApp() }

  • 這是 Jetpack Compose 的進入點,取代了傳統 setContentView(R.layout.activity_main)
  • MyApp() 是一個 @Composable 函式,負責畫面設計。

2️⃣ 使用 BoxRow 來排列 UI

  • Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter)
    • 所有內容填滿整個畫面,並對齊到底部。
  • Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly)
    • 讓三個按鈕水平排列,並且 平均分配寬度

3️⃣ 使用 Button(onClick = { ... }) 來建立按鈕

  • 當使用者點擊按鈕時,會顯示 Toast 訊息,例如:
    kotlin
    Toast.makeText(context, "Option 1 Clicked!", Toast.LENGTH_SHORT).show()
  • 這樣當按鈕被點擊時,就會在螢幕下方彈出「Option 1 Clicked!」的提示。

4️⃣ @Preview 提供畫面預覽

  • @Preview 讓你可以在 Android Studio 預覽 UI,不需要每次都執行 App。

2025年2月21日 星期五

Hello Android! 進階版 -2

再加第二個按扭,按一下就顯示“Hello world !”


package com.example.myapplication


import android.os.Bundle

import androidx.activity.ComponentActivity

import androidx.activity.compose.setContent

import androidx.compose.foundation.layout.*

import androidx.compose.material3.*

import androidx.compose.runtime.*

import androidx.compose.ui.Alignment

import androidx.compose.ui.Modifier

import androidx.compose.ui.unit.dp

import com.example.myapplication.ui.theme.MyApplicationTheme


// 將 enum class 移到 @Composable 函數外部

enum class DisplayText { NONE, ANDROID, WORLD }


class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContent {

            MyApplicationTheme {

                Greeting()

            }

        }

    }

}


@Composable

fun Greeting(modifier: Modifier = Modifier) {

    // 使用 enum 狀態

    var displayedText by remember { mutableStateOf(DisplayText.NONE) }


    Column(

        modifier = modifier.fillMaxSize().padding(16.dp),

        verticalArrangement = Arrangement.Center,

        horizontalAlignment = Alignment.CenterHorizontally

    ) {

        Button(

            onClick = {

                displayedText = if (displayedText == DisplayText.ANDROID) DisplayText.NONE 

                               else DisplayText.ANDROID

            },

            modifier = Modifier.padding(bottom = 8.dp)

        ) {

            Text(text = if (displayedText == DisplayText.ANDROID) "Hide Android" 

                       else "Show Android")

        }


        Button(

            onClick = {

                displayedText = if (displayedText == DisplayText.WORLD) DisplayText.NONE 

                               else DisplayText.WORLD

            },

            modifier = Modifier.padding(bottom = 8.dp)

        ) {

            Text(text = if (displayedText == DisplayText.WORLD) "Hide World" 

                       else "Show World")

        }


        when (displayedText) {

            DisplayText.ANDROID -> Text("Hello Android!", Modifier.padding(top = 16.dp))

            DisplayText.WORLD -> Text("Hello World!", Modifier.padding(top = 16.dp))

            DisplayText.NONE -> {} // 不顯示任何文本

        }

    }

}






運行效果:

  1. 初始畫面有兩個按鈕:

    • "Show Android" 和 "Show World"。

  2. 點擊按鈕後:

    • 點擊 "Show Android" → 顯示 "Hello Android!",按鈕文字變為 "Hide Android"。

    • 點擊 "Show World" → 顯示 "Hello World!",按鈕文字變為 "Hide World"。

  3. 再次點擊按鈕 → 隱藏對應的文本。


////////////// 程式說明 ////////////////////




總結:

1 fun Greeting(modifier: Modifier = Modifier) 是一個可組合函數,用於定義一個 UI 元件。

2 modifier 參數允許外部呼叫者靈活調整 UI 的外觀。

3 內部使用 Column 佈局來排列按鈕和文本。

4 使用 remember 和 mutableStateOf 來管理狀態,實現動態 UI 更新。

 

2025年2月20日 星期四

Hello Android! 進階版-1

實現按一個按鈕才顯示 "Hello Android!" 的功能

以使用 Jetpack Compose 的狀態管理來控制文本的顯示與隱藏。以下是改寫後的程式碼:


  1. 首先,你需要在 Greeting 函數中加入一個按鈕,並使用 MutableState 來控制文本的顯示與隱藏。

  2. 當按鈕被點擊時,切換狀態以顯示或隱藏文本。



package com.example.myapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment // 導入 Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.myapplication.ui.theme.MyApplicationTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            MyApplicationTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Greeting(
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }
}

@Composable
fun Greeting(modifier: Modifier = Modifier) {
    // 使用 remember 來保存狀態
    var showText by remember { mutableStateOf(false) }

    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally // 使用 Alignment
    ) {
        // 當 showText 為 true 時顯示文本
        if (showText) {
            Text(
                text = "Hello Android!",
                modifier = Modifier.padding(bottom = 16.dp)
            )
        }

        // 按鈕,點擊時切換 showText 的值
        Button(onClick = { showText = !showText }) {
            Text(text = if (showText) "Hide Text" else "Show Text")
        }
    }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme {
        Greeting()
    }
}


程式碼說明:

1 導入 Alignment:

在檔案頂部加入 import androidx.compose.ui.Alignment。

Alignment 是 Compose UI 中用於對齊的類別,例如 Alignment.CenterHorizontally 用於水平居中對齊。

2 showText 狀態:使用 remember { mutableStateOf(false) } 來創建一個可觀察的狀態 showText,初始值為 false,表示文本一開始是隱藏的。

3 條件渲染:在 Column 中,使用 if (showText) 來判斷是否顯示 "Hello Android!" 文本。

4 按鈕點擊事件:按鈕的 onClick 事件會切換 showText 的值,從而控制文本的顯示與隱藏。按鈕的文本也會根據 showText 的值動態變化。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 Column(
        modifier = modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally // 使用 Alignment
    ) 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


這段程式碼的效果是:

  • Column 會佔滿父容器的全部空間,並設置 16 dp 的內邊距。

  • Column 中的所有子元素會在垂直方向上居中排列。

  • 每個子元素會在水平方向上居中對齊。



運行效果:

  • 1 當你運行這個應用程式時,一開始只會看到一個按鈕,點擊按鈕後會顯示 "Hello Android!" 文本。

  • 2 再次點擊按鈕,文本會隱藏。



      





Hello Android! 的原始碼

Hello Android! 的原始碼。

package com.example.myapplication


import android.os.Bundle

import androidx.activity.ComponentActivity

import androidx.activity.compose.setContent

import androidx.activity.enableEdgeToEdge

import androidx.compose.foundation.layout.fillMaxSize

import androidx.compose.foundation.layout.padding

import androidx.compose.material3.Scaffold

import androidx.compose.material3.Text

import androidx.compose.runtime.Composable

import androidx.compose.ui.Modifier

import androidx.compose.ui.tooling.preview.Preview

import com.example.myapplication.ui.theme.MyApplicationTheme


class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        enableEdgeToEdge()

        setContent {

            MyApplicationTheme {

                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->

                    Greeting(

                        name = "Android",

                        modifier = Modifier.padding(innerPadding)

                    )

                }

            }

        }

    }

}


@Composable

fun Greeting(name: String, modifier: Modifier = Modifier) {

    Text(

        text = "Hello $name!",

        modifier = modifier

    )

}


@Preview(showBackground = true)

@Composable

fun GreetingPreview() {

    MyApplicationTheme {

        Greeting("Android")

    }

}