Construindo o Formulário de Atualização de Perfil - Android M-Commerce

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Construindo o Formulário de Atualização de Perfil - Android M-Commerce

Construindo o Formulário de Atualização de Perfil - Android M-Commerce

Vinícius Thiengo
(3478)
Go-ahead
"O método consciente de tentativa e erro é mais bem-sucedido que o planejamento de um gênio isolado."
Peter Skillman
Prototipagem Android
Capa do curso Prototipagem Profissional de Aplicativos
TítuloAndroid: Prototipagem Profissional de Aplicativos
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
Acessar Curso
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Lendo
TítuloTest-Driven Development: Teste e Design no Mundo Real
CategoriaEngenharia de Software
Autor(es)Mauricio Aniche
EditoraCasa do Código
Edição1
Ano2012
Páginas194
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Tudo bem?

Neste artigo vamos a construção da tela de atualização de dados de perfil de usuário, tela do projeto Android mobile-commerce, app BlueShoes.

Animação da tela de atualização de dados de perfil de usuário

O desenvolvimento será simples, principalmente devido a quantidade de códigos já encapsulados em outras aulas, mas também teremos de enfrentar um problema em relação a necessidade de mantermos alguns códigos repetidos devido a atualizações em layout que devem ocorrer em código dinâmico.

Antes de continuar, não deixe de se inscrever ðŸ“«na lista de emails do Blog para ter acesso exclusivo às novas aulas do projeto e também a outros conteúdos restritos somente ao Blog.

A seguir os tópicos abordados:

Conhecendo agora no projeto Android mobile-commerce

Você chegou ao projeto Android mobile-commerce somente agora? Então não deixe de primeiro conferir todas as aulas anteriores a esta nova aula.

Antes de lhe apresentar os links das aulas, saiba que nesta primeira parte do projeto o nosso foco é na construção de toda a interface gráfica do aplicativo.

Seguem as aulas que devem ser consumidas antes desta 13ª aula:

Lembrando que as aulas são liberadas semanalmente para a lista de e-mails 📩 do Blog, logo, não esqueça de se inscrever nela, é gratuito.

Estratégia para a tela de atualização de perfil

Como já definido em outras aulas, incluindo as aulas de refatoração de código, vamos iniciar o desenvolvimento da tela de atualização de dados de perfil pelos códigos estáticos, códigos XML. Segue roteiro:

  • Primeiro vamos ao desenvolvimento de todos os códigos estáticos, da tela de atualização perfil, que são independentes de códigos dinâmicos;
  • Depois vamos ao desenvolvimento dos códigos dinâmicos da atividade de atualização de dados de perfil;
  • Por fim vamos às atualizações de códigos de outras entidades que permitem o acesso a atividade de perfil.

Antes de prosseguir, o projeto Android BlueShoes está por completo disponível no repositório dele em: https://github.com/viniciusthiengo/blueshoes-kotlin-android.

Protótipo estático

A seguir o protótipo estático da tela de atualização de dados de perfil de usuário:

Formulário de perfil

Formulário de perfil

Load - atualização em back-end Web

Load - atualização em back-end Web

Erro na atualização

Erro na atualização

Atualização bem sucedida

Atualização bem sucedida

Trabalhando a atividade de dados de perfil

Como informado anteriormente: vamos iniciar pelos códigos estáticos e assim seguir para os códigos dinâmicos, códigos Kotlin.

Arquivo de Strings

Nossa primeira atualização é no arquivo de Strings, com dados que são passíveis de serem obtidos diretamente do protótipo estático do app BlueShoes.

Em /res/values/strings.xml adicione os códigos em destaque:

<resources>
...

<!-- ConfigProfileActivity -->
<string name="title_activity_config_profile">
Perfil
</string>

<string name="info_profile_photo">
Toque na foto para abrir a galeria ou fotografia.
</string>

<string name="name_label">Nome:</string>
<string name="config_profile">Atualizar perfil</string>
<string name="config_profile_going">Atualizando&#8230;</string>

<string name="invalid_name">
Nome inválido.
</string>

<string name="invalid_config_profile">
Um nome válido deve ser fornecido
</string>
</resources>

Drawable para o campo de imagem de perfil

O campo para mudança de imagem de perfil na verdade é apenas um ImageView com um ícone centralizado e um background personalizado:

Campo de imagem de perfil

Para o background personalizado, que por sinal é bem simples, no folder /res/drawable crie o arquivo XML bg_image_view_profile.xml com o código a seguir:

<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">

<!--
Definindo a cor de backgrund da View alvo.
-->
<solid android:color="@color/colorTextBox" />

<!--
Definindo bordas de 1dp de espessura e na
cor cinza escuro.
-->
<stroke
android:color="@color/colorViewLine"
android:width="1dp" />
</shape>

 

Note que as referências de cores são pouco genéricas até o momento, pois elas foram criadas em outros contextos. Por exemplo: o cinza escuro de borda está com o rótulo colorViewLine. A cor de fundo está com o rótulo colorTextBox.

Posteriormente, em novas refatorações, vamos corrigir também este ponto em projeto, pois querendo ou não isso atrapalha a leitura do código por parte de outros desenvolvedores, leitura dos futuros developers do app.

Ícone para o campo de imagem de perfil

O ícone, diferente de muitos outros já utilizados em projeto, foi baixado diretamente do protótipo estático no MarvelApp:

Ícone do campo de imagem de perfil

Sendo assim, a melhor maneira de te-lo, exatamente como em protótipo, é baixa-lo direto do repositório e então coloca-lo em sua versão de projeto, dentro de sua instalação do Android Studio.

A seguir os links para download do ícone de campo de imagem de perfil:

Não esqueça de coloca-los em seus respectivos folders drawable.

Ok, Thiengo. Mas enquanto você não utiliza o VectorDrawable como você fez para obter essa imagem nas versões drawable necessárias dela?

  • Primeiro temos de realizar o download da imagem pelo MarvelApp (como apresentado na imagem anterior);
  • Depois é carrega-la no Android Asset Studio, mais precisamente em Generic icon generator, e assim colocar as configurações:
    • Trim whitespace: Trim;
    • Padding: 0%;
    • Asset size: 24dp;
    • Asset padding: 0dp;
    • Color: Black;
    • Name: ic_photo_black_24dp.
  • Por fim realizar o download do pacote.

Se você quiser prosseguir com outro ícone, até mesmo algum do Material Design Icons, sem problemas quanto a isso. Aqui estou buscando ao máximo ter um projeto final igual ao projeto definido em protótipo estático.

Layout do formulário de perfil

Como estamos trabalhando com uma atividade de formulário, é evidente que estaremos reaproveitando inúmeros códigos já criados em outras aulas de telas com formulários.

Sendo assim é certo que a atividade FormActivity estará sim na hierarquia da atividade de atualização de dados de perfil de usuário.

Com isso, temos de desenvolver somente um layout principal para a nossa nova tela que contém o formulário de configurações de perfil.

Em /res/layout crie o XML content_config_profile.xml com o código a seguir:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="36dp">

<ImageView
android:id="@+id/iv_profile"
android:layout_width="108dp"
android:layout_height="108dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:src="@drawable/ic_photo_black_24dp"
android:tint="@color/colorLightGrey"
android:scaleType="centerInside"
android:background="@drawable/bg_image_view_profile"
android:onClick="callGallery" />

<TextView
android:id="@+id/tv_photo_info"
style="@style/TextViewOrangeInfo"
android:layout_width="90dp"
app:layout_constraintTop_toTopOf="@+id/iv_profile"
app:layout_constraintBottom_toBottomOf="@+id/iv_profile"
app:layout_constraintLeft_toRightOf="@+id/iv_profile"
android:maxLines="10"
android:text="@string/info_profile_photo" />

<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/et_name"
app:layout_constraintLeft_toLeftOf="@+id/et_name"
android:text="@string/name_label" />

<EditText
android:id="@+id/et_name"
style="@style/EditTextFormField"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:background="@drawable/bg_form_field"
android:inputType="textPersonName"
android:imeOptions="actionDone" />

<Button
android:id="@+id/bt_send_profile"
style="@style/ButtonForm"
app:layout_constraintTop_toBottomOf="@+id/et_name"
app:layout_constraintRight_toRightOf="@+id/et_name"
android:text="@string/config_profile"
android:onClick="mainAction" />

</android.support.constraint.ConstraintLayout>

 

Diferente de outros formulário, desta vez não teremos hint (placeholder) no EditText em tela, isso, pois o campo de ID et_name sempre terá um valor e assim o rótulo acima do campo facilita ao usuário o entendimento de para que esse campo é utilizado.

No primeiro TextView do XML anterior tivemos de definir android:maxLines="10", pois o estilo TextViewOrangeInfo tem a definição de maxLines sendo de uma linha. Qualquer valor igual ou maior do que 10 é seguro para nós, pois o texto presente neste TextView é longo e terá quebras de linhas - nunca igual ou maior do que 10 linhas.

Note também que já adiantamos aqui alguns pontos do código dinâmico da atividade de atualização de dados de perfil, pois já foram definidos todos os atributos android:onClick. Não há problemas quanto a isso.

A seguir o diagrama do layout anterior:

Diagrama do layout content_config_profile.xml

Criando a ConfigProfileActivity

A atividade de atualização de dados de perfil será bem simples. Ao invés de seguir todo o conhecido protocolo de criação de atividade, isso pelo menu de contexto do Android Studio, vamos apenas copiar e colar, no mesmo pacote, a atividade ForgotPasswordActivity.

Porém coloque como nome da nova atividade: ConfigProfileActivity.

O código inicial da ConfigProfileActivity será como a seguir:

class ConfigProfileActivity :
FormActivity() {

override fun onCreate( savedInstanceState: Bundle? ) {
super.onCreate( savedInstanceState )

et_name.validate(
{
it.length > 1
},
getString( R.string.invalid_name )
)
et_name.setOnEditorActionListener( this )

/*
* Name é um dos dados de banco de dados, e campo de
* formulário, que nunca poderá estar vazio.
* */
val user = intent.getParcelableExtra<User>( User.KEY )
et_name.setText( user.name )
}

override fun getLayoutResourceID()
= R.layout.content_config_profile

override fun backEndFakeDelay(){
backEndFakeDelay(
false,
getString( R.string.invalid_config_profile )
)
}

override fun blockFields( status: Boolean ){
iv_profile.isEnabled = !status
et_name.isEnabled = !status
bt_send_profile.isEnabled = !status
}

override fun isMainButtonSending( status: Boolean ){
bt_send_profile.text =
if( status )
getString( R.string.config_profile_going )
else
getString( R.string.config_profile )
}

fun callGallery( view: View ){
Toast
.makeText( this, "TODO", Toast.LENGTH_SHORT )
.show()
}
}

 

Primeiro, note no onCreate() que será necessário o envio do objeto user também para a ConfigProfileActivity. Tendo em mente que ele já está presente em AccountSettingsActivity.

Todo o restante do código é bem simples, com métodos obrigatórios sendo implementados, métodos encapsulados e isolados em aulas anteriores de nosso projeto.

O método listener de clique no campo de imagem, callGallery(), já está pré-implementado (terá uma aula somente sobre a galeria de imagens, incluindo a possibilidade de tirar fotografias).

Mas ainda há um problema nesta tela.

O problema de campo sobrepondo outro campo

É isso mesmo, novamente o problema de sobreposição de campos de formulário, problema que "deveria" ter sido solucionado de uma vez por todas.

Se já estivéssemos com todas as configurações desta aula finalizadas, exceto o algoritmo de correção do problema de sobreposição de campos, teríamos na tela de atualização de dados de usuário:

Animação do problema de sobreposição de campos de formulário

Ai você pergunta: mas Thiengo, nós já temos um algoritmo em FormEmailAndPasswordActivity que resolve este problema certo?

Quase certo!

O algoritmo em FormEmailAndPasswordActivity é específico para um TextView de políticas de privacidade.

Nosso foco agora é no ImageView que representa o campo de imagem de perfil, pois ele é o que exigirá menos alteração em código dinâmico para mantermos a tela, independente do status dela, com a configuração correta de acordo com o que foi definido em protótipo estático.

Sendo assim a nossa melhor alternativa agora é reproduzir todo o código de atualização de constraints já presente em FormEmailAndPasswordActivity, em LoginActivity e em SignUpActivity, reproduzir esse código com alterações pontuais para então, em futuras refatorações, ser possível melhorarmos todo o script com facilidade.

Correção da sobreposição de campos

Em ConfigProfileActivity vamos primeiro adicionar todo o código listener de mudança de status de teclado virtual:

class ConfigProfileActivity :
FormActivity(),
KeyboardUtils.OnSoftInputChangedListener {

override fun onCreate( ... ) {
super.onCreate( ... )

KeyboardUtils.registerSoftInputChangedListener(
this,
this
)

...
}
...

override fun onDestroy() {
KeyboardUtils.unregisterSoftInputChangedListener( this )
super.onDestroy()
}

override fun onSoftInputChanged( height: Int ) {
/* TODO */
}
}

 

Para os códigos de atualização direta nas configurações do ImageView de campo de imagem de perfil, vamos tentar manter o máximo possível igual aos códigos já isolados em FormEmailAndPasswordActivity, pois esse comportamento agora provavelmente nos ajudará em novas refatorações.

Ainda em ConfigProfileActivity acrescente o código em destaque:

class ConfigProfileActivity :
FormActivity(),
KeyboardUtils.OnSoftInputChangedListener {
...

override fun onSoftInputChanged( ... ) {
if( isAbleToCallChangeTargetViewConstraints() ){
changeTargetViewConstraints(
KeyboardUtils.isSoftInputVisible( this )
)
}
}

private fun isAbleToCallChangeTargetViewConstraints()
= true

private fun changeTargetViewConstraints(
isKeyBoardOpened: Boolean
){

val photoProfileId = iv_profile.id
val parent = iv_profile.parent as ConstraintLayout
val constraintSet = ConstraintSet()
val size = (108 * ScreenUtils.getScreenDensity()).toInt()

/*
* Definindo a largura e a altura da View em
* mudança de constraints, caso contrário ela
* fica com largura e altura em 0dp.
* */
constraintSet.constrainWidth(
photoProfileId,
size
)
constraintSet.constrainHeight(
photoProfileId,
size
)

/*
* Centralizando a View horizontalmente no
* ConstraintLayout.
* */
constraintSet.centerHorizontally(
photoProfileId,
ConstraintLayout.LayoutParams.PARENT_ID
)

if( isConstraintToSiblingView( isKeyBoardOpened ) ){
setConstraintsRelativeToSiblingView( constraintSet, photoProfileId )
}
else{
constraintSet.connect(
photoProfileId,
ConstraintLayout.LayoutParams.TOP,
ConstraintLayout.LayoutParams.PARENT_ID,
ConstraintLayout.LayoutParams.TOP
)
}

constraintSet.applyTo( parent )
}

private fun isConstraintToSiblingView(
isKeyBoardOpened: Boolean
): Boolean {

return isKeyBoardOpened || ScreenUtils.isLandscape()
}

private fun setConstraintsRelativeToSiblingView(
constraintSet: ConstraintSet,
targetViewId: Int
) {

constraintSet.connect(
targetViewId,
ConstraintLayout.LayoutParams.BOTTOM,
tv_name.id,
ConstraintLayout.LayoutParams.TOP,
(30 * ScreenUtils.getScreenDensity()).toInt()
)
}
}

 

Problema de sobreposição de campos: resolvido, com muito código repetido, mas resolvido.

Atualização no AndroidManifest

Ainda é preciso adicionarmos a nova atividade ao AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest
...>

<application
...>

...

<activity
android:name=".view.ConfigProfileActivity"
android:label="@string/title_activity_config_profile"
android:theme="@style/AppTheme.NoActionBar"/>
</application>
</manifest>

Atualizando as entidades de configuração de conta

Vamos agora a atualizações necessárias em projeto para que seja possível acessar a nossa nova tela de atualização de dados de perfil de usuário.

Ops! Configuração atual do Gradle Nível de Projeto

Antes de iniciarmos as atualizações em entidades diretamente ligadas a tela de configuração perfil, vamos primeiro ver como está a configuração atual do Gradle Nível de Projeto, ou build.gradle (Project: BlueShoes), do aplicativo:

buildscript {
ext.kotlin_version = '1.3.31'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

allprojects {
repositories {
google()
jcenter()
mavenCentral() /* Para acesso a API RoundedImageView */
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

 

Se necessário em seu caso, atualize ext.kotlin_version = '1.3.31'classpath 'com.android.tools.build:gradle:3.4.1' e então sincronize o projeto. Todas as APIs em uso continuarão funcionando sem problemas.

Ampliando a AccountSettingItem

Nossa classe de domínio responsável por representar os itens da tela de configurações de conta tem de passar por uma atualização, simples, mas necessária, pois será em cada um dos objetos desta classe que também haverá a referência a atividade que deverá ser aberta quando houver o acionamento do item.

Em AccountSettingItem adicione o trecho em destaque:

class AccountSettingItem(
val label: String,
val description: String,
val activityClass: Class<out FormActivity>
)

 

Agora em AccountSettingItem podemos passar como terceiro argumento valores no seguinte formato: ConfigProfileActivity::class.java. Exatamente como esperamos no segundo argumento de Intent para invocarmos o startActivity() - ainda nesta aula chegaremos a esta parte.

<out FormActivity> nos permite passar como argumento qualquer tipo Class de uma subclasse de FormActivity.

Corrigindo a AccountSettingsItemsDataBase

Agora é preciso corrigir as inicializações de objetos AccountSettingItem em AccountSettingsItemsDataBase:

class AccountSettingsItemsDataBase {

companion object{

fun getItems( context: Context )
= listOf(
AccountSettingItem(
context.getString( R.string.setting_item_profile ),
context.getString( R.string.setting_item_profile_desc ),
ConfigProfileActivity::class.java
),
AccountSettingItem(
context.getString( R.string.setting_item_login ),
context.getString( R.string.setting_item_login_desc ),
ConfigProfileActivity::class.java
),
AccountSettingItem(
context.getString( R.string.setting_item_address ),
context.getString( R.string.setting_item_address_desc ),
ConfigProfileActivity::class.java
),
AccountSettingItem(
context.getString( R.string.setting_item_credit_cards ),
context.getString( R.string.setting_item_credit_cards_desc ),
ConfigProfileActivity::class.java
)
)
}
}

 

Vamos prosseguir nesta aula sempre utilizando o objeto ConfigProfileActivity::class.java como terceiro argumento de AccountSettingItem. Em aulas futuras, onde criaremos as outras telas de configurações de conta, nós atualizaremos os pontos necessários em AccountSettingsItemsDataBase.

Atualizando a AccountSettingsActivity

O objeto user que teremos de acessar também em ConfigProfileActivity está presente na AccountSettingsActivity.

Esse objeto user será necessário também em outras telas de atualização de configurações de conta, não somente na tela de atualização de dados de perfil.

Sendo assim é correto afirmar que no código acionador de atividades de configuração, que estará presente na classe adaptadora de itens do RecyclerView de AccountSettingsActivity, sempre haverá o algoritmo de acesso ao objeto user em AccountSettingsActivity.

Com isso, em AccountSettingsActivity, podemos criar um método simples que acessa esse objeto direto da fonte dele, o objeto intent.

Em AccountSettingsActivity adicione o método getUser(), e atualizações necessárias, como em destaque a seguir:

...
override fun onCreate( ... ) {
...

val user = getUser()
tv_user_connected.text = String.format(
"%s %s",
getString( R.string.connected ),
user.name
)

...
}

/*
* Método que permitirá o acesso ao User em Intent
* também por parte de outros objetos dependentes de
* AccountSettingsActivity.
* */
fun getUser()
= intent.getParcelableExtra<User>( User.KEY )
...

 

Assim podemos partir para a criação do listener de clique em classe adaptadora.

Listener de clique no adapter de AccountSettings

Com um código ainda simples, em AccountSettingsItemsAdapter adicione o trecho em destaque:

...
inner class ViewHolder( itemView: View ) :
RecyclerView.ViewHolder( itemView ),
View.OnClickListener {
...

init{
itemView.setOnClickListener( this )

...
}
...

override fun onClick( view: View ) {
val activity = view.context as AccountSettingsActivity
val user = activity.getUser()
val intent = Intent(
activity,
items[ adapterPosition ].activityClass
)

intent.putExtra( User.KEY, user )
activity.startActivity( intent )
}
}
...

 

Veja como a nova propriedade activityClass de AccountSettingItem alivia em muito a necessidade de termos em código um bloco condicional para sabermos qual atividade invocar.

Com essa última atualização em projeto, os toques em itens de configurações de conta passam a ser funcionais e o objeto user é sempre enviado a atividade acionada.

Testes e resultados

Em sua instalação do Android Studio, vá ao menu de topo e acesse "Build", então clique em "Rebuid project". Ao final do rebuild execute o aplicativo em seu emulador Android.

Não esqueça de colocar o objeto user como um "usuário conectado". Este objeto está na MainActivity:

...
val user = User(
"Thiengo Vinícius",
R.drawable.user,
true /* Usuário conectado. */
)
...

 

Acessando a tela de atualização de dados de perfil, temos:

Animação da navegação na tela de atualização de dados de perfil

Com isso finalizamos mais um importante trecho de interface gráfica de nosso projeto Android mobile-commerce. Ainda temos de trabalhar, para esta área do app, a parte de seleção de imagem... conteúdo de uma próxima aula.

Antes de prosseguir, não esqueça de se inscrever na ðŸ“« lista de emails do Blog para receber todas as aulas do projeto Android BlueShoes.

Se inscreva também no canal do Blog em: YouTube Thiengo.

Vídeos

Abaixo os vídeos com o passo a passo da construção da nova tela de atualização de dados de perfil e também com o passo a passo das atualizações necessárias em projeto para que a nova tela possa ser acionada:

O código do projeto pode ser acessado pelo GitHub dele em: https://github.com/viniciusthiengo/blueshoes-kotlin-android.

Conclusão

Ainda com foco em telas que contêm formulários, demos continuidade a área de configurações de conta construindo desta vez a tela que permite a atualização de dados de perfil de usuário, mais precisamente a atualização do nome e imagem de perfil.

Muitos códigos foram reaproveitados, principalmente os códigos de FormActivity, mas foi inevitável, ao menos neste ponto do projeto, a repetição dos códigos de atualização de constraints em script dinâmico, mas certamente esses códigos passarão por melhorias para resolver isso: duplicação.

A parte de acesso a galeria e a câmera do aparelho será discutida em outra aula, pois ainda é preciso definirmos a API que será utilizada além de como ficarão os códigos de solicitação de permissão em tempo de execução.

Caso você tenha dúvidas ou dicas para este projeto, não hesite em deixar logo abaixo nos comentários.

Curtiu o conteúdo? Não deixe de compartilha-lo. E, por fim, se inscreva na 📩 lista de emails, respondo às suas dúvidas também por lá.

Abraço.

Fontes

Kotlin Generics

MyClass.class syntax in Kotlin

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Kotlin Android, Entendendo e Primeiro ProjetoKotlin Android, Entendendo e Primeiro ProjetoAndroid
Como Criar Protótipos AndroidComo Criar Protótipos AndroidAndroid
Trabalhando Análise Qualitativa em seu Aplicativo AndroidTrabalhando Análise Qualitativa em seu Aplicativo AndroidAndroid
Android Mobile-Commerce, Apresentação e Protótipo do ProjetoAndroid Mobile-Commerce, Apresentação e Protótipo do ProjetoAndroid

Compartilhar

Comentários Facebook

Comentários Blog

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...