Speed round
https://android-developers.googleblog.com/2021/03/android-dev-challenge-3.html
https://github.com/android/android-dev-challenge-compose/blob/assets/Bloom.zip
Week3
お題が出るので、お題に沿ってデザインをコードに実装していく。でもできませんでしたー。
https://github.com/dalomo-net/week3-Speed-Round
できなーい!だめだ、全然わからない。ちょっと無謀すぎたか…orz 俺の #AndroidDevChallenge はここで終わりだな~ pic.twitter.com/Mt4wU5Z7XE
— dalomo (@dalomo_dalomo) March 13, 2021
悲しい。
何ができなかったか
大変悔しいので、何ができなかったのかをまとめて、一つずつ潰していってみることにした。
全体
- ダークテーマでの色やresの切り替え
- ステータスバー・ナビゲーションバー消してない
Welcome
- 葉っぱの画像が切れてる
- Textの間隔がbaselineを意識したものになってない
- ボタンのサイズ・シェイプが変
- ボタンの背景色を変えてない
Log in
- ボタンのサイズ・シェイプが変
- ボタンの背景色を変えてない
ついで
- 入力欄にフォーカスした時、説明文字が消えない
- パスワード欄の文字入力が丸見え
Home
- Search欄にアイコンがない
- テキストの間隔が変
- 下のアプリバー
- アイコンの大きさ
- アイコンのキャプション
- 選択・非選択時の色の切り替え
- 間隔の整列
BrowseThemes
- カードが作れてない
- elevationを設定できていない
- スクロールできるリストの形になってない
Design your home garden
- テキストの間隔が変
- dividerの位置が変
- スクロールできるリストの形になってない
こんなところでしょうか…。
改善していってみる
完成しますように。とりあえず見れるようにしたい。これが正しいというわけではない。
全体
ステータスバーを透過する
themes.xmlに
<item name="android:statusBarColor" tools:targetApi="l">@android:color/transparent</item> <item name="android:windowLightStatusBar">true</item>
初っ端からJetpackCompose関係なくね、と思いつつ。
https://stackoverflow.com/questions/38382283/change-status-bar-text-color-when-primarydark-is-white
ついでにHomeでバーがバーに収まるように
ナビゲーションバー内に収まるようにする
projectのbuild.gradleに
ext.accompanist_version = '0.6.2'
appのbuild.gradleに
implementation "dev.chrisbanes.accompanist:accompanist-coil:$accompanist_version" implementation "dev.chrisbanes.accompanist:accompanist-insets:$accompanist_version"
onCreateで
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
MyTheme {
ProvideWindowInsets {
MyApp()
}
}
}
}
こんな。そんでコンテンツ全体に効くところに
modifier = Modifier.navigationBarsPadding()
てする。
https://github.com/google/accompanist
https://google.github.io/accompanist/insets/
ライト・ダークでのリソース切り替え
これ
MaterialTheme.colors.isLight
でなんか判定ができるみたいなので、ifで分岐させたり
if (MaterialTheme.colors.isLight) R.drawable.light_logo else R.drawable.dark_logo
ResourseManagerでImport Drawablesの時にdark側のQQUALIFIER TYPE-VALUEをNightMode-NightTimeにしてあげると勝手にモードに合わせて表示してくれたりするらしい。
https://developer.android.com/jetpack/compose/themes?hl=ja#color
https://developer.android.com/guide/topics/resources/providing-resources?hl=ja#Compatibility
ページごとにファイルを分割した
新しくファイル作ってコードをそっちに移しただけ。
Welcome
葉っぱが切れる
alignment = Alignment.CenterStart
を追加した。なぜこうすると上手くいくのかは謎。
https://alexzh.com/jetpack-compose-layouts/
TextをBaseline基準の間隔にする
modifier = Modifier.paddingFromBaseline(top = 32.dp, bottom = 40.dp)
とした。公式の日本語訳のページだとpaddingFromBaselineが載ってなくて迷った。原文にあたれってのはこういうことかと呪ったよね。
https://developer.android.com/jetpack/compose/layout#layout-modifier
Buttonのサイズを変える
Button(
onClick = { },
shape = MaterialTheme.shapes.medium,
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.padding(start = 16.dp,end = 16.dp)
)
潰れてたのが直った。
Buttonの背景色を変える
colors = ButtonDefaults.buttonColors(backgroundColor = MaterialTheme.colors.secondary)
これなんでこんな書き方なんだろう。探すの手間どった。
https://stackoverflow.com/questions/64376333/background-color-on-button-in-jetpack-compose
TextButtonを使う
TextButton(
onClick = { navController.navigate("login") },
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.padding(top = 8.dp)
) {
Text(
text = "Log in",
color = MaterialTheme.colors.secondary,
style = MaterialTheme.typography.button
)
}
こういうのがあるのね…。どうすれば透明になるんだ~?とかやってたわ。
https://medium.com/google-developer-experts/exploring-jetpack-compose-button-4cfb8355e50
Log in
TextをBaseline基準の間隔にする
modifier = Modifier.paddingFromBaseline(top = 184.dp, bottom = 16.dp),
先程に続き再び。これTextの下はOutlinedTextFieldの方で変えたほうがいいのかな。どっちなんだろ。
TextFieldにプレースホルダーを設定する
placeholder = {
Text(text = "Email address", style = MaterialTheme.typography.body1)
}
こうだった。これで文字入力し始めると文字が消える。
TextFieldの入力表示を隠す
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password
)
上だけで隠れる。下は知らん。
https://android–code.blogspot.com/2021/03/jetpack-compose-password-textfield.html
Buttonの形と背景色を変える
Button(
onClick = { navController.navigate("home") },
shape = MaterialTheme.shapes.medium,
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
colors = ButtonDefaults.buttonColors(backgroundColor = MaterialTheme.colors.secondary)
) {
Text(
text = "Log in",
color = MaterialTheme.colors.background,
style = MaterialTheme.typography.button
)
}
さっきと一緒。
Home
TextField内の最初にアイコンを付ける
leadingIcon = {
Icon(
imageVector = Icons.Default.Search,
contentDescription = "search",
Modifier.size(18.dp)
)
}
Iconというのがあるのだな…。頑張ってリソースに追加してたよ。。。
Browse Themesのカード作り
ひぃひぃ言いながら
@Composable
fun ThemeCard(n: String, rid: Int) {
Card(
modifier = Modifier
.size(136.dp)
.clickable { },
shape = MaterialTheme.shapes.small,
elevation = 1.dp,
backgroundColor = MaterialTheme.colors.surface
) {
Column(modifier = Modifier.fillMaxSize()) {
Image(
painter = painterResource(id = rid),
contentDescription = n,
contentScale = ContentScale.Crop,
modifier = Modifier
.height(96.dp)
)
Box() {
Text(
text = n,
style = MaterialTheme.typography.h2,
modifier = Modifier
.padding(start = 8.dp)
.paddingFromBaseline(top = 24.dp)
)
}
}
}
}
こんな感じで書いたんだけど、結果
うまくいかん。ちょっとどうやってもキレイに表示されんのでこれはもういいや…。
https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#card
あとなぜかこのあたりからCannot access class ‘androidx.compose.ui.graphics.painter.Painter’. Check your module classpath for missing or conflicting dependenciesというエラーが出るようになった。ImageとpainterResourceのところに赤波線が付いてるけどBuildは通る…。解決策が分からないのでほっといてる。
このカード達をLazyRowを使って行方向に並べているわけだけど、他の人と比べるとなんかカクカクしてしまっている。なんでなんだろう、多分何かが違うんだろうけど、その何かが分からないー。
Design your home gardenの並びにフィルターアイコンを付ける
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.paddingFromBaseline(top = 40.dp)
) {
Text(
text = "Design your home garden",
style = MaterialTheme.typography.h1,
color = MaterialTheme.colors.onPrimary,
)
Icon(
imageVector = Icons.Default.FilterList,
contentDescription = "filterlist",
modifier = Modifier.size(24.dp)
)
}
こうなった。Rowにpaddingfrombaselineに気づくのに時間かかった。
LazyColumnに2つ以上アイテムがあると落ちる
@Composable
fun LazyColumnList() {
LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp))
{
item {
PlantItem(n = "Monstera", rid = R.drawable.monstera)
}
item {
PlantItem(n = "Aglaonema", rid = R.drawable.aglaonema)
}
item {
PlantItem(n = "Peace Lily", rid = R.drawable.peace_lilly)
}
item {
PlantItem(n = "Fiddle Leaf tree", rid = R.drawable.fiddle_leaf)
}
item {
PlantItem(n = "Snake plant", rid = R.drawable.snake_plant)
}
item {
PlantItem(n = "Pothos", rid = R.drawable.pothos)
}
}
}
こうして
@Composable
fun PlantItem(n: String, rid: Int) {
Row(
modifier = Modifier
.height(64.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(id = rid),
contentDescription = n,
modifier = Modifier.clip(shape = MaterialTheme.shapes.small)
)
Column() {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(modifier = Modifier.padding(start = 16.dp)) {
Text(
text = n,
style = MaterialTheme.typography.h2,
color = MaterialTheme.colors.onPrimary,
modifier = Modifier.paddingFromBaseline(top = 24.dp)
)
Text(
text = "This is a description",
style = MaterialTheme.typography.body1,
color = MaterialTheme.colors.onPrimary
)
}
Checkbox(
checked = true,
onCheckedChange = {},
modifier = Modifier.size(24.dp)
)
}
Divider(modifier = Modifier.padding(start = 8.dp))
}
}
}
こう作ってみたんだけどLazyColumnのItemが2つ以上になるとアプリが落ちる。なんでだーと思ってPlantItemの内容を一個ずつ削って見るとImageを削ったときだけはちゃんと表示される。つーことはImageがなんか悪いのかなーといろいろ調べてたら
https://developer.android.com/jetpack/compose/libraries#image-loading
https://github.com/google/accompanist/blob/main/coil/README.md
CoilImageっていうのが使えるようになるやつがあるみたい。そんでdataには読み込みたいURLを指定するらしいんだがres/drawableに入れてる場合はどうするんだろう。
dataが対応してる型が
String (mapped to a Uri)
Uri (“android.resource”, “content”, “file”, “http”, and “https” schemes only)
HttpUrl
File
DrawableRes
Drawable
Bitmap
Drawableってのを使えばいいんだろうか。試しに
https://developer.android.com/guide/topics/graphics/drawables?hl=ja#drawables-from-images
https://stackoverflow.com/questions/58743541/how-to-get-context-in-jetpack-compose
ここらへん参考にしてみて
val context = LocalContext.current val image : Drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.desert_chic, null)!!
こんなコード書いてみたんですが、表示されませんでした…。じゃあURIとか?と思って
https://stackoverflow.com/questions/4896223/how-to-get-an-uri-of-an-image-resource-in-android
を参考に
val path: Uri = Uri.parse("android.resource://com.example.androiddevchallenge/" + R.drawable.desert_chic)
こうして、dataにpathを渡したけどこれも表示されませんでした…。他に引数に@DrawableResつけてみたりしたけど駄目だった。
contentDescription = ""
これ!これが足りなかった!
CoilImage(
data = rid,
contentDescription = "",
modifier = Modifier
.size(64.dp)
.clip(shape = MaterialTheme.shapes.small),
contentScale = ContentScale.Crop
) {}
こう!でいけたわ~。
LazyColumn, LazyRowのスクロールがカクカクする
CoilImage使うとこれも改善された。なぜかはよく分かりません。
https://stackoverflow.com/questions/63794544/lazycolumnfor-is-not-smooth-scrolling
BottomBarにLazyColumnのリストが隠れる
contentPadding = PaddingValues(bottom=56.dp)
LazyColumnにBottomBarの高さのpaddingを入れてみたけどもっとキレイなやり方ないんだろうか。
BottomAppBarとBottomNavigationの違い
さっきからBottomAppBarって言ってたような気がするが、BottomAppBarはページ内でなんらかのアクションをする際に使うやつで、BottomNavigationはページ遷移をするときに使うやつらしい。多分。で、今回の場合はBottomNavigationを使うんかな。
BottomNavigationを実装する
@Composable
fun BottomBar() {
BottomNavigation(
backgroundColor = MaterialTheme.colors.primary,
modifier = Modifier.height(56.dp)
) {
BottomNavigationItem(
selected = true,
onClick = { /*TODO*/ },
icon = { Icon(imageVector = Icons.Default.Home, contentDescription = "Home") },
label = { Text(text = "Home",style = MaterialTheme.typography.caption) }
)
BottomNavigationItem(
selected = false,
icon = { Icon(imageVector = Icons.Default.FavoriteBorder, contentDescription = "favorite") },
label = { Text(text = "Favorites",style = MaterialTheme.typography.caption) },
onClick = { /*TODO*/ }
)
BottomNavigationItem(
selected = false,
icon = { Icon(imageVector = Icons.Default.AccountCircle, contentDescription = "profile") },
label = { Text(text = "Profile",style = MaterialTheme.typography.caption) },
onClick = { /*TODO*/ }
)
BottomNavigationItem(
selected = false,
icon = { Icon(imageVector = Icons.Default.ShoppingCart, contentDescription = "cart") },
label = { Text(text = "Cart",style = MaterialTheme.typography.caption) },
onClick = { /*TODO*/ }
)
}
}
最初なぜかアイコンが上にはみ出してキャプションしかバー内に入ってなかった。けどなんか色々やって↑な感じにしたらいい感じだった。
完成
https://github.com/dalomo-net/week3-Speed-Round
いいんじゃないでしょうか…とりあえず形にはできたよね?まぁチェックボックスの初期値とかダークモードの確認全くやってない(スマホが対応してなかったしプレビューが効かん)とか詰めればきりないんだけどね。あー疲れた!ちなみに第4週は天気アプリだったけど参加はしなかった…。参加してたら天気ルーレットアプリを作りたかったかな、残念!でもまぁここまで参加できて楽しかった~(^^)あ、あと時間帯違いのWeTradeとMySootheがあるから時間あったらやってみようかなぁ~。






