1+ package com.example.compose.snippets.text
2+
3+ import android.text.TextUtils
4+ import androidx.compose.foundation.layout.Column
5+ import androidx.compose.foundation.layout.padding
6+ import androidx.compose.foundation.text.BasicTextField
7+ import androidx.compose.foundation.text.KeyboardOptions
8+ import androidx.compose.foundation.text.input.InputTransformation
9+ import androidx.compose.foundation.text.input.OutputTransformation
10+ import androidx.compose.foundation.text.input.TextFieldBuffer
11+ import androidx.compose.foundation.text.input.TextFieldLineLimits
12+ import androidx.compose.foundation.text.input.TextFieldState
13+ import androidx.compose.foundation.text.input.clearText
14+ import androidx.compose.foundation.text.input.insert
15+ import androidx.compose.foundation.text.input.maxLength
16+ import androidx.compose.foundation.text.input.rememberTextFieldState
17+ import androidx.compose.foundation.text.input.selectAll
18+ import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
19+ import androidx.compose.foundation.text.input.then
20+ import androidx.compose.material.SecureTextField
21+ import androidx.compose.material.TextField
22+
23+ import androidx.compose.material3.Button
24+ import androidx.compose.material3.CircularProgressIndicator
25+ import androidx.compose.material3.Text
26+ import androidx.compose.runtime.Composable
27+ import androidx.compose.runtime.getValue
28+ import androidx.compose.runtime.mutableStateOf
29+ import androidx.compose.runtime.remember
30+ import androidx.compose.runtime.setValue
31+ import androidx.compose.ui.Modifier
32+ import androidx.compose.ui.graphics.Brush
33+ import androidx.compose.ui.graphics.Color
34+ import androidx.compose.ui.text.TextStyle
35+ import androidx.compose.ui.text.font.FontWeight
36+ import androidx.compose.ui.text.input.ImeAction
37+ import androidx.compose.ui.tooling.preview.Preview
38+ import androidx.compose.ui.unit.dp
39+ import androidx.lifecycle.ViewModel
40+ import androidx.lifecycle.viewModelScope
41+ import kotlinx.coroutines.launch
42+
43+ @Composable
44+ fun StateBasedTextSnippets () {
45+ // [START android_compose_state_text_1]
46+ BasicTextField (state = rememberTextFieldState())
47+
48+ TextField (state = rememberTextFieldState())
49+ // [END android_compose_state_text_1]
50+ }
51+
52+ @Composable
53+ fun StyleTextField () {
54+ // [START android_compose_state_text_2]
55+ TextField (
56+ state = rememberTextFieldState(),
57+ lineLimits = TextFieldLineLimits .MultiLine (maxHeightInLines = 2 ),
58+ placeholder = { Text (" " ) },
59+ textStyle = TextStyle (color = Color .Blue , fontWeight = FontWeight .Bold ),
60+ modifier = Modifier .padding(20 .dp)
61+ )
62+ // [END android_compose_state_text_2]
63+ }
64+
65+ @Composable
66+ fun ConfigureLineLimits () {
67+ // [START android_compose_state_text_3]
68+ TextField (
69+ state = rememberTextFieldState(),
70+ lineLimits = TextFieldLineLimits .SingleLine
71+ )
72+ // [END android_compose_state_text_3]
73+
74+ // [START android_compose_state_text_4]
75+ TextField (
76+ state = rememberTextFieldState(),
77+ lineLimits = TextFieldLineLimits .MultiLine (1 , 4 )
78+ )
79+ // [END android_compose_state_text_4]
80+ }
81+
82+ @Composable
83+ fun StyleWithBrush () {
84+ // [START android_compose_state_text_5]
85+ val brush = remember {
86+ Brush .linearGradient(
87+ colors = listOf (Color .Red , Color .Yellow , Color .Green , Color .Blue , Color .Magenta )
88+ )
89+ }
90+ TextField (
91+ state = rememberTextFieldState(), textStyle = TextStyle (brush = brush)
92+ )
93+ // [END android_compose_state_text_5]
94+ }
95+
96+ // [START android_compose_state_text_6]
97+ // TODO fix this snippet
98+ // val usernameState = rememberTextFieldState()
99+ // TextField(
100+ // state = usernameState,
101+ // lineLimits = TextFieldLineLimits.SingleLine,
102+ // placeholder = { Text("Enter Username") }
103+ // )
104+ val LoginRepository = " repository"
105+
106+ class LoginViewModel (val loginRepository : Repository ): ViewModel() {
107+ val username = TextFieldState ()
108+ val password = TextFieldState ()
109+
110+ val isLoginButtonEnabled: Boolean
111+ get() = ! isLoginButtonLoading && username.text.length > 6 && password.text.length > 6
112+
113+ var isLoginButtonLoading by mutableStateOf(false )
114+ private set
115+
116+ fun loginButtonClick () {
117+ viewModelScope.launch {
118+ isLoginButtonLoading = true
119+ val result = loginRepository.login(
120+ username.text.toString(),
121+ password.text.toString()
122+ )
123+ // process result
124+ isLoginButtonLoading = false
125+ }
126+ }
127+ }
128+
129+ @Composable
130+ fun LoginForm (
131+ viewModel : LoginViewModel ,
132+ modifier : Modifier
133+ ) {
134+ Column (modifier) {
135+ TextField (viewModel.username)
136+ SecureTextField (viewModel.password)
137+ Button (
138+ onClick = viewModel::loginButtonClick,
139+ enabled = viewModel.isLoginButtonEnabled
140+ ) {
141+ if (viewModel.isLoginButtonLoading) {
142+ CircularProgressIndicator ()
143+ } else {
144+ Text (" Login" )
145+ }
146+ }
147+ }
148+ }
149+ // [END android_compose_state_text_6]
150+
151+ class Repository {
152+ fun login (username : String , password : String ) {
153+
154+ }
155+ }
156+
157+ @Composable
158+ fun TextFieldPlaceholder () {
159+
160+ }
161+
162+ @Preview
163+ @Composable
164+ fun TextFieldInitialState () {
165+ // [START android_compose_state_text_7]
166+ TextField (
167+ state = rememberTextFieldState(initialText = " Username" ),
168+ lineLimits = TextFieldLineLimits .SingleLine ,
169+ )
170+ // [END android_compose_state_text_7]
171+ }
172+
173+ @Composable
174+ fun TextFieldBuffer () {
175+ // [START android_compose_state_text_8]
176+ // [END android_compose_state_text_8]
177+ // [START android_compose_state_text_9]
178+ // [END android_compose_state_text_9]
179+ }
180+
181+ @Preview
182+ @Composable
183+ fun EditTextFieldState () {
184+ // [START android_compose_state_text_10]
185+ val usernameState = rememberTextFieldState(" I love Android" )
186+ // textFieldState.text : I love Android
187+ // textFieldState.selection: TextRange(14, 14)
188+ usernameState.edit { insert(14 , " !" ) }
189+ // textFieldState.text : I love Android!
190+ // textFieldState.selection: TextRange(15, 15)
191+ usernameState.edit { replace(7 , 14 , " Compose" ) }
192+ // textFieldState.text : I love Compose!
193+ // textFieldState.selection: TextRange(15, 15)
194+ usernameState.edit { append(" !!!" ) }
195+ // textFieldState.text : I love Compose!!!!
196+ // textFieldState.selection: TextRange(18, 18)
197+ usernameState.edit { selectAll() }
198+ // textFieldState.text : I love Compose!!!!
199+ // textFieldState.selection: TextRange(0, 18)
200+ // [END android_compose_state_text_10]
201+
202+ // [END android_compose_state_text_11]
203+ usernameState.setTextAndPlaceCursorAtEnd(" I really love Android" )
204+ // textFieldState.text : I really love Android
205+ // textFieldState.selection : TextRange(21, 21)
206+ // [END android_compose_state_text_11]
207+
208+ // [END android_compose_state_text_12]
209+ usernameState.clearText()
210+ // textFieldState.text :
211+ // textFieldState.selection : TextRange(0, 0)
212+ // [END android_compose_state_text_12]
213+ }
214+
215+ class TextFieldViewModel : ViewModel () {
216+ fun validateUsername () {
217+
218+ }
219+ }
220+ val textFieldViewModel = TextFieldViewModel ()
221+ @Composable
222+ fun TextFieldKeyboardOptions () {
223+ // [START android_compose_state_text_13]
224+ BasicTextField (
225+ state = rememberTextFieldState(),
226+ keyboardOptions = KeyboardOptions (imeAction = ImeAction .Next ),
227+ onKeyboardAction = { performDefaultAction ->
228+ textFieldViewModel.validateUsername()
229+ performDefaultAction()
230+ }
231+ )
232+ // [END android_compose_state_text_13]
233+ }
234+
235+
236+
237+ @Composable
238+ fun TextFieldInputTransformation () {
239+ // [START android_compose_state_text_14]
240+ TextField (
241+ state = rememberTextFieldState(),
242+ lineLimits = TextFieldLineLimits .SingleLine ,
243+ inputTransformation = InputTransformation .maxLength(10 )
244+ )
245+ // [END android_compose_state_text_14]
246+
247+ // [START android_compose_state_text_17]
248+ TextField (
249+ state = rememberTextFieldState(),
250+ inputTransformation = InputTransformation .maxLength(6 )
251+ .then(CustomInputTransformation ()),
252+ )
253+ // [END android_compose_state_text_17]
254+
255+ }
256+
257+ // [START android_compose_state_text_15]
258+ class CustomInputTransformation : InputTransformation {
259+ override fun TextFieldBuffer.transformInput () {
260+
261+
262+ }
263+ }
264+ // [END android_compose_state_text_15]
265+
266+ // [START android_compose_state_text_16]
267+ class DigitOnlyInputTransformation : InputTransformation {
268+ override fun TextFieldBuffer.transformInput () {
269+ if (! TextUtils .isDigitsOnly(asCharSequence())) {
270+ revertAllChanges()
271+ }
272+ }
273+ }
274+ // [END android_compose_state_text_16]
275+
276+ // [START android_compose_state_text_17]
277+ class CustomOutputTransformation : OutputTransformation {
278+ override fun TextFieldBuffer.transformOutput () {
279+
280+
281+ }
282+ }
283+ // [END android_compose_state_text_17]
284+
285+ // [START android_compose_state_text_18]
286+ class PhoneNumberOutputTransformation : OutputTransformation {
287+ override fun TextFieldBuffer.transformOutput () {
288+ if (length > 0 ) insert(0 , " (" )
289+ if (length > 4 ) insert(4 , " )" )
290+ if (length > 8 ) insert(8 , " -" )
291+ }
292+ }
293+ // [END android_compose_state_text_18]
294+
295+
296+ @Composable
297+ fun TextFieldOutputTransformation () {
298+ // [START android_compose_state_text_19]
299+ TextField (
300+ state = rememberTextFieldState(),
301+ outputTransformation = PhoneNumberOutputTransformation ()
302+ )
303+ // [END android_compose_state_text_19]
304+ }
0 commit comments