前言
阅览本文需求必定compose基础,假如没有请移步Jetpack Compose入门详解(实时更新)
接口数据来源于pokeapi
项目源代码
假如你觉得不错,请给我一个star,THKS
完成作用
闲话不多说,让我们来看看完成作用
能够看到我们完成了一个十分简洁的宝可梦图鉴,展示了一切代代的宝可梦,并提供了搜索,与宝可梦图鉴app的UI有了一些变化。
一、架构介绍
如图,展示了主要的一些文件:
本项目没有适配安卓端,iOS端和web端(假如有乐于开源的小伙伴能够联络我),因此一切中心代码都在desktop中
- http – 接口
- util -东西类
- ui -Compose组件
- viewmodels – viewmodel
二、一些的功能点的介绍
PreCompose
经过PreCompose 这个三方库,能够像写app相同写desktop,当然这儿面有一些与app运用有些差别
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import moe.tlaster.precompose.PreComposeWindow
import ui.FullScreenView
import util.EnvUtil
fun main() = application {
val windowState = rememberWindowState(size = DpSize(AppConfig.windowMinWidth, AppConfig.windowMinHeight))
PreComposeWindow(
state = windowState,
onCloseRequest = ::exitApplication,
undecorated = EnvUtil.isWindows(),
title = ""
) {
//window.minimumSize = Dimension(AppConfig.windowMinWidth.value.toInt(), AppConfig.windowMinHeight.value.toInt())
window.rootPane.apply {
rootPane.putClientProperty("apple.awt.fullWindowContent", true)
rootPane.putClientProperty("apple.awt.transparentTitleBar", true)
rootPane.putClientProperty("apple.awt.windowTitleVisible", false)
}
FullScreenView()
//CpnWindowsPlaformDecoratedButtons(windowState)
}
}
PreComposeWindow便是必备的,不然后续运用一切的与PreCompose相关的都会报错 例如初始化viewmodel
import moe.tlaster.precompose.ui.viewModel
val viewModel = viewModel { PokemonListViewModel() }
加载网络图片
桌面端加载网络图也没有安卓的原生库运用,这儿运用了compose-desktop-imageloader
package ui.common
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import org.succlz123.lib.imageloader.ImageAsyncImageFile
import org.succlz123.lib.imageloader.ImageAsyncImageUrl
import org.succlz123.lib.imageloader.ImageRes
import org.succlz123.lib.imageloader.core.ImageCallback
@Composable
fun AsyncImage(
modifier: Modifier,
url: String?,
placeHolderUrl: String? = "image/ic_pokmon.jpeg",
errorUrl: String? = "image/ic_pokmon.jpeg",
contentScale: ContentScale = ContentScale.Crop
) {
val imgUrl = url ?: "image/ic_pokmon.jpeg"
if (imgUrl.startsWith("http")) {
ImageAsyncImageUrl(url = imgUrl, imageCallback = ImageCallback(placeHolderView = {
placeHolderUrl?.let {
Image(
painter = painterResource(placeHolderUrl),
contentDescription = imgUrl,
modifier = modifier,
contentScale = contentScale
)
}
}, errorView = {
errorUrl?.let {
Image(
painter = painterResource(errorUrl),
contentDescription = imgUrl,
modifier = modifier,
contentScale = contentScale
)
}
}) {
Image(
painter = it, contentDescription = imgUrl, modifier = modifier, contentScale = contentScale
)
})
} else if (imgUrl.startsWith("/") || imgUrl.contains(":\\")) {
ImageAsyncImageFile(filePath = imgUrl, imageCallback = ImageCallback(placeHolderView = {
placeHolderUrl?.let {
Image(
painter = painterResource(placeHolderUrl),
contentDescription = imgUrl,
modifier = modifier,
contentScale = contentScale
)
}
}, errorView = {
errorUrl?.let {
Image(
painter = painterResource(errorUrl),
contentDescription = imgUrl,
modifier = modifier,
contentScale = contentScale
)
}
}) {
Image(
painter = it, contentDescription = imgUrl, modifier = modifier, contentScale = contentScale
)
})
} else {
ImageRes(resName = imgUrl, imageCallback = ImageCallback(placeHolderView = {
placeHolderUrl?.let {
Image(
painter = painterResource(placeHolderUrl),
contentDescription = imgUrl,
modifier = modifier,
contentScale = contentScale
)
}
}, errorView = {
errorUrl?.let {
Image(
painter = painterResource(errorUrl),
contentDescription = imgUrl,
modifier = modifier,
contentScale = contentScale
)
}
}) {
Image(
painter = it, contentDescription = imgUrl, modifier = modifier, contentScale = contentScale
)
})
}
}
致谢
项目中大部分技术栈都参考自NCMusicDesktop,感谢大佬