507 字
3 分鐘
08行動應用開發筆記
行動應用開發筆記
Table of Contents
[TOC]
Android (Jetpack Compose)
可用套件
Gson
com.google.code.gson:gson:2.10OkHttp
com.squareup.okhttp3:okhttp:5.0.0XML 解析
fun parseXml(parser: XmlPullParser): List<String> { var eventType = parser.eventType val list = mutableListOf<String>() var item = ""
while (eventType != XmlPullParser.END_DOCUMENT) { when (eventType) { XmlPullParser.START_TAG -> { // <xxx> when (parser.name) { "xxx" -> item = parser.nextText() } }
XmlPullParser.END_TAG -> { // <xxx/> when (parser.name) { "xxx" -> list.add(item) } }
} eventType = parser.next() } return list}
parseXml(context.resources.getXml(R.xml.resourceId))讀res/raw資料
通常用來讀取靜態JSON
context.resources.openRawResource(R.raw.xxx).bufferedReader().use { it.readText() }頁面導航
因 Navigation 元件需要套件安裝,所以可用下列方法代替 (取自學長)
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() val viewModel by viewModels<MainViewModel>() setContent { Crossfade(viewModel.screen, label = "") { screen -> //若screen為空就退出App screen?.invoke() ?: finish() } // 處理返回鍵 BackHandler(onBack = viewModel::pop) } }}class MainViewModel : ViewModel() { private val screens = mutableStateListOf<@Composable () -> Unit>({ FirstScreen(this) })
// 用getter保持最新 val screen get() = screens.lastOrNull()
fun push(targetScreen: @Composable () -> Unit) { screens += targetScreen }
fun pushReplacement(targetScreen: @Composable () -> Unit) { pop() screens += targetScreen }
fun pop() { screens.removeLastOrNull() }}Drawer
val drawerState = rememberDrawerState(DrawerValue.Closed) // Closed, OpenModalNavigationDrawer( drawerContent = { ModalDrawerSheet { NavigationDrawerItem( icon = { Icon(painterResource..., "") }, label = { Text("...") }, selected = false, onClick = {} ) } }, drawerState = drawerState, gesturesEnabled = true //右滑打開Drawer的手勢)NOTEdrawerState.open() / close() 為 suspend 方法
Pager
HorizontalPager(水平) 適合用來公告輪播 亦有 VerticalPager (垂直)
val pagerState = rememberPagerState( initialPage = 0, //Optional pageCount = { 2 })HorizontalPager(pagerState) { page -> when (page) { 0 -> .. }}WebView讀取本機HTML
var webView: WebView? = nullAndroidView( factory = { context -> WebView(context).apply { loadUrl("file:///android_asset/xxx") webView = this } },)
//返回鍵回到上一頁BackHandler(onBack = { webView!!.goBack()})NOTEfile://android_asset 指向 assets 資料夾
Gson
toJson
OkHttp
GET
val client = OkHttpClient().newBuilder().build()
val request = Request.Builder() .url("http://10.0.2.2:8000/reminders/1") .addHeader("accept","application/json") .addHeader("X-API-KEY","KEY1") .build()
val call = client.newCall(request)
call.enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { println(e.message) }
override fun onResponse(call: Call, response: Response) { println(response.body.string()) }
})POST (PATCH)
val client = OkHttpClient().newBuilder().build()
val request = Request.Builder() .url("http://10.0.2.2:8000/reminders/1") .patch(Gson().toJson( mapOf("enabled" to true) ).toRequestBody("application/json".toMediaType())) //.post() or .patch() .addHeader("accept","application/json") .addHeader("X-API-KEY","KEY1") .build()
val call = client.newCall(request)
call.enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { println(e.message) }
override fun onResponse(call: Call, response: Response) { println(response.body.string()) }
})NOTE可用 call.execute() 做同步請求 (不能在UI線程上)
NOTE10.0.2.2 指向 Host IP
Flutter
漸層 Paint
final paint = Paint() ..strokeWidth = 5 ..shader = LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0x552196F3), Colors.black], ).createShader( Rect.fromLTRB(0, 0, size.width, size.height), );