Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
TextField 表示スタイル変更の 有効活用例 5 選
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
akkiee76
November 30, 2023
Technology
770
0
Share
TextField 表示スタイル変更の 有効活用例 5 選
「DroidKaigi.collect { #7@Tokyo }」で発表した資料になります。
https://droidkaigi.connpass.com/event/301886/
akkiee76
November 30, 2023
More Decks by akkiee76
See All by akkiee76
Graph Art with Charts API – Beyond Data Visualization
akkie76
0
230
Meet the Translation API
akkie76
0
470
コードレビューで開発を加速させるAIコードレビュー
akkie76
1
730
Android Target SDK 35 (Android 15) 対応の概要
akkie76
0
6.1k
コードレビューを支援するAI技術の応用
akkie76
5
1.2k
オブジェクト指向コードレビューの新しいアプローチ
akkie76
3
9.8k
Jetpack Compose で Adaptive Layout に対応しよう
akkie76
0
1.2k
Observationではじめる値監視
akkie76
4
4.9k
rememberUpdatedState の使いどころを考える
akkie76
0
690
Other Decks in Technology
See All in Technology
拝啓、あの夏の僕へ〜あなたも知っているApp Runnerの世界〜
news_it_enj
0
230
SREの仕事は「壊さないこと」ではなくなった 〜自律化していくシステムに、責任と判断を与えるという価値〜 / 20260515 Naoki Shimada
shift_evolve
PRO
1
100
生成AIはソフトウェア開発の革命か、ソフトウェア工学の宿題再提出なのか -ソフトウェア品質特性の追加提案-
kyonmm
PRO
2
870
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
15
100k
10サービス以上のメール到達率改善を地道に継続的に進めている話 / Continue to improve email delivery rates across multiple services
yamaguchitk333
3
130
20260516_SecJAWS_Days
takuyay0ne
0
110
100マイクロサービスのTerraform/Kubernetes管理地獄から抜け出すためのAI活用術
markie1009
0
110
Tachikawa.any 運営挨拶
daitasu
0
140
AI時代の品質はテストプロセスの作り直し #scrumniigata
kyonmm
PRO
4
1.4k
Oracle Exadata Database Service on Cloud@Customer X11M (ExaDB-C@C) サービス概要
oracle4engineer
PRO
2
8k
20260507-ACL-seminar
satoshi5884
0
100
Purview Endpoint DLP 動かしてみた
kozakigh
0
150
Featured
See All Featured
GitHub's CSS Performance
jonrohan
1032
470k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Making Projects Easy
brettharned
120
6.6k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.4k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.1k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.2k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
340
Art, The Web, and Tiny UX
lynnandtonic
304
21k
Raft: Consensus for Rubyists
vanstee
141
7.4k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.5k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Transcript
©2023 RAKUS Co., Ltd. TextField 表示スタイル変更の 有効活用例 5 選 DroidKaigi.collect
{ #7@Tokyo } 2023/12/01 @akkiee76
自己紹介 • Akihiko Sato • Rakus Inc. • 楽楽精算 •
@akkiee76 / X 2
表示スタイル変更の有効活用 5 選 1. パスワード入力 2. クレジットカード番号入力 3. カンマ区切り数値入力 4.
PINコード入力 5. プレフィックス文字入力 3
表示スタイル変更の有効活用 5 3 選 1. パスワード入力 2. クレジットカード番号入力 3. カンマ区切り数値入力
4. PINコード入力 5. プレフィックス文字入力 4
TextField カスタマイズの基本 • VisualTransformation(TextField / 表示スタイル変更) • decorationBox(BasicTextField / カスタムデザイン)
@Composable fun TextField( value: String, onValueChange: (String) -> Unit, modifier: Modifier = Modifier, ・・・ visualTransformation: VisualTransformation = VisualTransformation.None, ・・・ colors: TextFieldColors = TextFieldDefaults.colors() ) 5
VisualTransformation class OriginalVisualTransformation: VisualTransformation { override fun filter(text: AnnotatedString): TransformedText
{ return TransformedText( text = AnnotatedString(buildString { TODO("表示形式へ変換処理") }), object : OffsetMapping { override fun originalToTransformed(offset: Int): Int { TODO("入力文字列の位置から表示文字列の位置へのマッピング") } override fun transformedToOriginal(offset: Int): Int { TODO("表示文字列の位置から入力文字列の位置へのマッピング") } } ) VisualTransformation の拡張クラスを利用することで表示形式の変換を行うことができます 6
decorationBox(BasicTextField) @Composable fun BasicTextField( value: String, onValueChange: (String) -> Unit,
modifier: Modifier = Modifier, ・・・ decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit = @Composable { innerTextField -> innerTextField() } ) 独自の Composable を設定し、入力欄のカスタマイズを行うことができます 7
表示スタイル変更の有効活用 5 選 1. パスワード入力 2. クレジットカード番号入力 3. カンマ区切り数値入力 4.
PINコード入力 5. プレフィックス文字入力 8
1. パスワード入力: TextField val visualTransformation = PasswordVisualTransformation('*') TextField( value =
text, onValueChange = { value -> if (value.isDigitsOnly()) { text = value } }, modifier = modifier, visualTransformation = visualTransformation, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Number ) ) 9
1. パスワード入力: VisualTransformation class PasswordVisualTransformation(val mask: Char = '\u2022') :
VisualTransformation { override fun filter(text: AnnotatedString): TransformedText { return TransformedText( // 文字数分の mask に変換 AnnotatedString(mask.toString().repeat(text.text.length)), OffsetMapping.Identity ) } } 10
表示スタイル変更の有効活用 5 選 1. パスワード入力 2. クレジットカード番号入力 3. カンマ区切り数値入力 4.
PINコード入力 5. プレフィックス文字入力 11
2. クレジットカード番号入力: TextField val visualTransformation = CreditCardVisualTransformation() TextField( value =
text, onValueChange = { value -> if (value.isDigitsOnly()) { text = value } }, modifier = modifier, visualTransformation = visualTransformation, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Number ) ) TextFieldはパスワード入力と同様の実装 12
class CreditCardNumberVisualTransformation : VisualTransformation { override fun filter(text: AnnotatedString): TransformedText
{ val trimmed = if (text.text.length >= 16) { text.text.substring(0..15) } else { text.text } var output = "" for (i in trimmed.indices) { output += trimmed[i] if (i % 4 == 3 && i != 15) output += "-" } val creditCardOffsetTranslator = object : OffsetMapping { ・・・ } return TransformedText(AnnotatedString(output), creditCardOffsetTranslator) 2. クレジットカード番号入力: VisualTransformation https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose 13
2. クレジットカード番号入力: VisualTransformation class CreditCardNumberVisualTransformation : VisualTransformation { override fun
filter(text: AnnotatedString): TransformedText { val creditCardOffsetTranslator = object : OffsetMapping { override fun originalToTransformed(offset: Int): Int { if (offset <= 3) return offset if (offset <= 7) return offset + 1 if (offset <= 11) return offset + 2 if (offset <= 16) return offset + 3 return 19 } override fun transformedToOriginal(offset: Int): Int { if (offset <= 4) return offset if (offset <= 9) return offset - 1 if (offset <= 14) return offset - 2 if (offset <= 19) return offset - 3 return 16 } } return TransformedText(AnnotatedString(output), creditCardOffsetTranslator) 14
表示スタイル変更の有効活用 5 選 1. パスワード入力 2. クレジットカード番号入力 3. カンマ区切り数値入力 4.
PINコード入力 5. プレフィックス文字入力 15
3. カンマ区切り数値入力: TextField val visualTransformation = CommaSeparatorTransformation() TextField( value =
text, onValueChange = { value -> if (value.isDigitsOnly()) { text = value } }, modifier = modifier, visualTransformation = visualTransformation, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Number ) ) TextFieldは同様の実装 16
class CommaSeparatorTransformation : VisualTransformation { override fun filter(text: AnnotatedString): TransformedText
{ val output = buildString { val reversed = text.text.reversed() for (index in reversed.indices) { if (index > 0 && index % 3 == 0) { append(',') } append(reversed[index]) } }.reversed() val offsetMapping = object : OffsetMapping { ・・・ } return TransformedText(text = AnnotatedString(output), offsetMapping = offsetMapping) } } 3. カンマ区切り数値入力: VisualTransformation 17
class CommaSeparatorTransformation : VisualTransformation { override fun filter(text: AnnotatedString): TransformedText
{ val offsetMapping = object : OffsetMapping { override fun originalToTransformed(offset: Int): Int { val totalSeparatorCount = (text.length - 1) / 3 val rightSeparatorCount = (text.length - 1 - offset) / 3 val leftSeparatorCount = totalSeparatorCount - rightSeparatorCount return offset + leftSeparatorCount } override fun transformedToOriginal(offset: Int): Int { val totalSeparatorCount = (text.length - 1) / 3 val rightSeparatorCount = (output.length - offset) / 4 val leftSeparatorCount = totalSeparatorCount - rightSeparatorCount return offset - leftSeparatorCount } } return TransformedText(text = AnnotatedString(output), offsetMapping = offsetMapping) 3. カンマ区切り数値入力: VisualTransformation 18
表示スタイル変更の有効活用 5 選 1. パスワード入力 2. クレジットカード番号入力 3. カンマ区切り数値入力 4.
PINコード入力 5. プレフィックス文字入力 19
4. PINコード入力: TextField BasicTextField( value = text, onValueChange = {
newValue -> if (newValue.length <= MaxDigits) { text = newValue } }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword), interactionSource = interactionSource, modifier = modifier.border(1.dp, contentColor, RoundedCornerShape(8.dp)) ) { CompositionLocalProvider(LocalContentColor provides contentColor) { PinDigits(text, interactionSource.collectIsFocusedAsState().value) } } 20
@Composable fun PinDigits() { Row(horizontalArrangement = Arrangement.spacedBy(16.dp), modifier = modifier.padding(16.dp))
{ repeat(MaxDigits) { i -> Text( text = text.getOrNull(i)?.toString() ?: " ", modifier = Modifier.drawWithContent { if (i == text.length && focused) { drawRect(color = focusedColor) } drawContent() if (i >= text.length) { drawLine(・・・) } } 4. PINコード入力: decorationBox 21
表示スタイル変更の有効活用 5 選 1. パスワード入力 2. クレジットカード番号入力 3. カンマ区切り数値入力 4.
PINコード入力 5. プレフィックス文字入力 22
5. プレフィックス文字入力: TextField val visualTransformation = PrefixVisualTransformation() TextField( value =
text, onValueChange = { value -> if (value.isDigitsOnly() && value.length <= MAX_LENGTH) { text = value } }, modifier = modifier, visualTransformation = visualTransformation, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Number ) ) TextFieldはパスワード入力と同様の実装 23
class PrefixVisualTransformation: VisualTransformation { override fun filter(text: AnnotatedString): TransformedText {
return TransformedText( text = AnnotatedString(buildString { text.forEachIndexed { i, char -> if (i == 0) { append('X') } append(char) } }), object : OffsetMapping { override fun originalToTransformed(offset: Int): Int { return if (offset < 1) offset else offset + 1 } override fun transformedToOriginal(offset: Int): Int { return if (offset < 1) offset else offset - 1 } } 5. プレフィックス文字入力: VisualTransformation 24
まとめ • VisualTransformation で自由に表示テキストの変更が可能 • dacorationBox を使うとデザインの幅も広がる 25
Thank you ! 26