Livro 2 - Projeto da Mini-Calculadora
Site: | Moodle - IFSC |
Curso: | 2022-1 - FIC - Programação para Dispositivos Móveis - Prof. Bruno Calegaro |
Livro: | Livro 2 - Projeto da Mini-Calculadora |
Impresso por: | Usuário visitante |
Data: | segunda, 25 Nov 2024, 00:35 |
Índice
1. Apresentação
Prezados alunos,
Neste livro, conheceremos novos componentes gráficos para a construção de aplicativos Android exemplificando com a construção de um aplicativo chamado MiniCalculadora.
O aplicativo aplica uma taxa de serviço a um valor digitado para mostrar o valor da taxa e o valor total. Quando se toca no teclado numérico para digitar o valor, o aplicativo já aplica a taxa de serviço (por padrão com o valor 15%) no valor total da conta, não necessitando de um botão para disparar a ação (cálculo). O valor da taxa de serviço é uma porcentagem que pode variar de 0% a 30 % e será configurado através de uma barra de progresso (SeekBar). Mudanças no valor da conta ou na taxa de serviço irão automaticamente recalcular os demais valores na tela. Também é apresentado esses valores no formato de moeda (R$, por exemplo) dependendo da localidade do dispositivo Android.
Bons estudos!
2. Recursos Envolvidos
Nesse projeto usaremos os seguintes recursos na construção do aplicativo MiniCalculadora:
- Classe Activity
- Um aplicativo Android possui quatro tipos de componentes executáveis: activities, services, content providers e broadcast receivers. Neste projeto discutiremos activities que são subclasses da classe Activity (pacote android.app).
- Todo aplicativo possui diversas activities, cada uma vinculada a uma tela do aplicativo. Ao se clicar em uma View (componentes da interface) o usuário consegue interagir com a Activity.
- As Activities possuem um ciclo de vida onde passam por diferentes estados: em execução (active), pausado (paused) ou parado (stopped). A Activity muda de estados em resposta a diferentes tipos de eventos:
- Uma Activity ativa é visível e possui foco de toda tela.
- Uma Activity pausada é visível na tela, mas não possui foco, por exemplo, quando uma mensagem de alerta é mostrada.
- Uma Activity parada não é visível na tela, está no plano de fundo e pode ser encerrada pelo Android para poupar memória. Uma Activity é parada quando outra Activity se torna ativa. Por exemplo, durante o uso de um aplicativo se recebe uma chamada de telefone, o aplicativo das chamadas telefônicas se torna ativo e o anterior é parado.
- Quando uma Activity é iniciada (estado starting) ela sempre executa o método onCreate. É nesse método que definimos as configurações iniciais dos aplicativos.
- Outros tipos de método podem ser invocados de acordo com o clico de vida da Activity: onStart, onPause, onRestart, onResume, onStop e onDestroy.
- GridLayout
- GridLayout é um tipo de layout que organiza os componentes (Views) em células de uma grade com linhas e colunas. Cada célula pode ocupar mais de uma linha e coluna ou ainda conter outros layouts, o que permite a construção de layouts mais complexos.
- TextViews, EditText e SeekBar
- Usando a ferramenta gráfica de desenho do Android Studio, iremos usar os componentes: TextView (já utilizado no projeto 1), EditText e SeekBar.
- EditText - em outras tecnologias esse elemento é chamado de text box ou text field - trata-se de uma caixa de texto que aceita a entrada do usuário. Neste projeto vamos especificar a EditText para aceitar apenas números e restringir o máximo de números que podem ser digitados.
- SeekBar é uma barra de progresso que representa um valor inteiro de 0 a 100 por padrão. O usuário pode interagir com a barra e aumentar ou diminuir seu valor. Neste projeto, vamos usar a SeekBar para representar o valor da taxa de serviço e limitá-la para aceitar valores entre 0 e 30.
- Classe NumberFormat
- Vamos usar a classe NumberFormat (pacote java.text) para formatar os valores da aplicação para o padrão da moeda (R$, U$, etc.) de acordo com a localidade do aplicativo - uma parte importante da internacionalização de aplicativos. Além disso, também será aplicada formatação para mostrar a porcentagem da taxa de serviço.
- Interface TextWatcher
- Para fazer o tratamento de eventos de uma EditText é preciso implementar a interface TextWatcher (pacote android.text). Em particular, usaremos o método da interface onTextChanged para mostrar em moeda o novo valor inserido e (re) calcular o valor da taxa de serviço e valor total da conta, toda vez que for digitado ou alterado um número da EditText.
- Interface OnSeekBarChangeListener
- Para fazer o tratamento de eventos de uma SeekBar temos que implementar a interface SeekBar.OnSeekBarChangeListener (pacote android.widget). Em particular, usaremos o método onProgressChanged para mostrar a taxa de serviço em porcentagem e (re) calcular o valor da taxa de serviço e o total da conta toda vez que o usuário interagir com a barra de progresso.
- Material Design
-
- O Android segue as diretrizes de Material Design do Google para a construção de interfaces gráficas. Essas diretrizes especificam o comportamento dos componentes como elevação e sobra, cores, entre outros recursos.
- Material Themes
- O tema de um aplicativo se refere a toda uma construção visual da aplicação. O Android oferece uma série de tema pré-definidos de acordo com o Material Design:
- Tema light - possui uma app bar branca, um plano de fundo branco e texto em preto ou cinza escuro
- Tema light com app bar preta e texto branco
- Tema dark - app bar preta, plano de fundo cinza escuro e texto em branco ou cinza claro
- Ao construir uma interface gráfica, podemos escolher entre esses temas pré-definidos ou personalizar com novas cores os estilos. Para este projeto,iremos usar o tema padrão utilizado nas templates do Android Studio e,posteriormente, modificá-lo com cores personalizadas.
- O tema de um aplicativo se refere a toda uma construção visual da aplicação. O Android oferece uma série de tema pré-definidos de acordo com o Material Design:
- Material Design: Elevation e Shadows
- Por especificações do Material Design, sombras (shadows) são aplicadas aos componentes de uma interface de acordo com a sua elevação com a ideia de imitar o mundo real. Logo, ao se especificar a propriedade elevation de uma View, o Android irá automaticamente aplicar um efeito de sombra ao componente.
- Segundo as diretrizes do Material Design, cada tipo de componente possui uma elevação recomendada, por exemplo, para um menu é 8dp e uma caixa de diálogo é 24dp.
- Material Design: Colors
- O Google também recomenda uma paleta de cores para ser usada em aplicativos. Cada cor possui versões de diferentes tonalidades, de tons mais claros a escuros, o que permite a construção de aplicativos com cores harmoniosas.
- O Android Studio oferece uma editor de temas (Theme Editor) para ajudar na escolha dessas cores.
- AndroidManifest.xml
- O arquivo AndroidManifest.xml é criado pelo Android Studio na inicialização do projeto. Esse arquivo contém diversas configuração do aplicativo como: nome do aplicativo, nome do pacote, Activity principal e mais. Neste projeto iremos configurar esse arquivo para que o aplicativo force o uso do teclado numérico ao se abrir e rode apenas em modo retrato (portrait).
3. Criando o projeto
Para começar o Projeto 2 vamos criar o projeto base de maneira similar ao Projeto 1. Siga os mesmos passos do Capitulo 3 do Livro 1 mas coloque as seguintes configurações:
- Escolha a template do projeto como Empty Activity.
- Defina o nome do projeto para MiniCalculadora
- Especifique o campo Package name de acordo com as regras apresentadas no Livro 1
- Modifique o local de criação do projeto se achar necessário (Save Location)
- Na opção Language certifique-se de estar selecionado a linguagem Java
- O mesmo com campo Mininum SDK. Certifique-se que está selecionada a API 23 na caixa de seleção.
- Clique em Finish e aguarde a criação do novo projeto.
4. Desenhando a tela do aplicativo
Para criar a tela do aplicativo usamos a ferramenta de desenho do Android Studio onde selecionamos os elementos gráficos na janela Palette e o arrastamos até a posição desejada na tela. Neste projeto serão utilizados os componentes EditText, TextView e SeekBar. Mas antes de arrasta-los, configuraremos o layout da tela.
GridLayout é um tipo de layout que organiza a tela como uma grade retangular com linhas e colunas. Cada célula da grade ocupa uma linha e coluna, mas também pode ser configurada para usar mais de uma linha e coluna (propriedades span). É possível especificar as propriedades rows e columns do GridLayout para definir quantas linhas e colunas a grade possui. Cada célula da grade pode estar em branco, possuir uma ou mais Views, ou ainda incluir outro layout com outras views. A altura de uma linha é definida pela view mais alta da linha, similarmente, a largura de uma coluna é definida pela largura da maior view.
Cada view pode especificar em qual linha e coluna se encontra, como mostrado na Tabela 1. A View1 possui as propriedades row e column como 0, a View2 possui as propriedades row 0 e column 1. Já a View3, além especificar as propriedades row 1 e column 0, ela se expande por mais uma coluna. Esse comportamento é atingido através da propriedade layout:columnSpan 1.
Na construção da tela para o aplicativo MiniCalculadora iremos criar um GridLayout de duas colunas e organizar os elementos em quatro linhas. Nesse layout cada célula irá possuir um componente, exceto a primeira linha onde haverá um EditText e TextView sobreescritos e ocupando toda a primeira linha.
4.1. Configurando o layout da tela
A template Empty Activity do Android Studio cria um arquivo activity_main.xml com o ConstrantLayout. Logo, primeiramente precisamos alterar esse arquivo para usar o GridLayout e adicionar duas novas propriedades. O primeiro passo é similar ao realizado no projeto 1 para a configuração do LinearLayout e a inclusão da duas novas propriedades pode ser feita direto no arquivo XML ou na janela gráfica.
- Abra o arquivo activity_main.xml localizado dentro da pasta res/layout.
- Para modificar modificar o ConstantLayout para o GridLayout você deve entrar no modo de edição textual (Code), por padrão o Android Studio vai abrir inicialmente no modo visual (Design). Para alternar entre o modo Design e Code clique em um dos botões na barra superior à direita.
- No modo textual substitua androidx.constraintlayout.widget.ConstraintLayout por GridLayout
- Volte ao modo Design
- Apague o elemento TextView ("Hello World") pré-criado
- Selecione o GridLayout na janela de componentes (Component Tree)
- Localize e modifique as seguintes propriedades do GridLayout:
- columnCount – mude o valor para 2
- useDefaultMargins – mude o valor para true – essa propriedade faz com o layout use as margens definidas pelo Material Design (8dp).
- No final o arquivo activity_main.xml deve ficar como:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="2"
android:useDefaultMargins="true"
tools:context=".MainActivity" />
4.2. Adicionando EditText, TextViews e SeekBar
Agora com o layout configurado para uma grade de duas colunas podemos adicionar os elementos gráficos para o aplicativo. Comece arrastando e soltando os referidos elementos e modificando as propriedades para os valores indicados.
Primeira linha
A primeira linha consiste de dois componentes: amountEditText e amountTextView, respectivamente um EditText e TextView. Toda vez que se incluir um novo elemento a grade, o Android Studio tenta deduzir em qual linha e coluna incluir o componente, mas isso pode ser manualmente especificado com as propriedades row e column. Vamos fazer esse processo manualmente pois tanto a EditText quanto a TextView devem ficar nas mesmas células sobrepondo um ao outro (o porquê disso veremos nas próximas etapas, vai ser um pequeno "truque").
Realize os seguintes passos para configuração da primeira linha da grade:
- Procure na janela Palette a seção Text
- A janela de paleta do Android permite o uso de EditText para diferentes finalidades (texto, senha, e-mail, etc.), assim, selecione Number e coloque na primeira linha e coluna da grade. Configure as seguintes propriedades para o novo elemento gráfico:
- id: amountEditText
- layout:column: 0
- layout:columnSpan: 2
-
- Arraste um componente TextView em cima do componente EdiText criado. Configure as seguintes propriedades para o novo elemento gráfico:
- id: amountTextView
- layout:row: 0
- layout:column: 0
- layout:columnSpan: 2
Segunda linha
Realize os seguintes passos para configuração da segunda linha da grade:
- Adicione uma TextView para a segunda linha da grade com o idpercentTextView.
- Arraste um componente SeekBar (aba Widget da paleta) para a célula ao lado do componente anterior e coloque seu id como percentSeekBar
Terceira linha
Realize os seguintes passos para configuração da terceira linha da grade:
- Adicione uma TextView para a terceira linha da grade com o id tipLabelTextView
- Arraste um componente TextView para a célula ao lado do componente anterior e coloque o id como tipTextView.
Quarta linha
Realize os seguintes passos para configuração da quarta linha da grade:
- Adicione uma TextView para a terceira linha da grade com o id totalLabelTextView.
- Arraste um componente TextView para a célula ao lado do componente anterior e coloque o id totalTextView
A nomeação dos componentes da interface gráfica deve ficar de acordo com a figura abaixo:
Por fim, o resultado da configuração inicial da tela deve ficar como:
Se o seu aplicativo apresenta os resultados como mostrado nas figuras você concluiu a primeira etapa da construção do layout do aplicativo usando a grade, os elementos gráficos foram criados e posicionados corretamente. No próximo capítulo vamos configurar o visual de cada componente e finalizar o desenho da tela.
5. Configurando os componentes da tela
Com as posições inicias das views bem definidas, iremos agora configurar todas as demais propriedades como textos, cores e espaçamento.
5.1. Especificando os recursos strings
Para a configuração dos textos na tela iremos adicionar recursos strings no arquivo strings.xml como detalhado no projeto 1. No caso do EditText um nova propriedade hint deve ser configurada também, pois é ela que apresenta uma “dica” do que deve ser inserido na caixa de texto.
Assim, vá a propriedade text (ou hint no caso do EditText) de cada componente TextView e adicione um novo recurso string a cada elemento. A lista dos recursos e sua View relacionada se encontra na lista da tabela a seguir:
Observe que são omissas as strings para as views amountTextView, tipTextView e totalTextView. Isso ocorre porque os seus valores serão calculados e apresentados dinamicamente.
Adicionando novos recursos strings
Para adicionar os novos recursos strings ao elementos gráficos da tela procure a propriedade text e clique no botão branco ao lado. Observe que a posição exata da propriedade pode variar dependendo do tipo de elemento sendo configurado (TextView, EditText, SeekBar). Use como referência a figura:
Na janela Pick a resource clique no botão + localizado na parte superior esquerda da janela e selecione a opção String Value.
Na janela New String Value complete os campos com as informações adequadas, por exemplo:
Clique em OK para confirmar a criação do novo valor e em seguida selecione o valor correto e confirme novamente com o botão OK.
Repita esses passos em todos os elementos para adicionar seus textos como informado na tabela no início dessa seção.
5.2. Alinhando a direita os componentes da primeira coluna
Para alinhar os componentes da primeira coluna à direita deve ser modificada a propriedade layout:gravity. Logo, realize as etapas abaixo:
- Na janela de componentes, selecione o componente percentTextView, segure CTRL e selecione os demais componentes tipLabelTextView e totalLabelTextView para modificar todos ao mesmo tempo.
- Localize a propriedade layout:gravity e marque a opção end
5.3. Configurando os elementos EditText e TextView
Configurando amountEditText
Nas configurações do EditText iremos fazer com que ele aceite apenas números e tenha um tamanho máximo. Para isso, localize as propriedades abaixo nesse componente e coloque os valores adequados:
- digits: 0123456789 – isso fará com que sejam aceitos apenas números, e não símbolos numéricos com -, “,” ou “.” presentes no teclado numérico.
- maxLenght: 6 – logo o valor mais alto aceito é 999999
Configurando amountTextView
Nas configurações dessa view. localize as propriedades abaixo e coloque os valores adequados:
- layout:gravity: fill_horizontal – para indicar que a view deve ocupar todo o espaço
- restante na linha
- background: #BBDEFB – essa propriedade especifica a cor de fundo com componente
- padding – essa propriedade especifica o espaçamento em volta do conteúdo da view. Nesse caso iremos selecionar a opção geral e alocar um novo tipo de recurso (similar as strings criadas no arquivo strings.xml) clicando no botão branco ao lado da caixa de entrada. Similar a quando se cria um novo recurso string, crie um novo recurso com o nome textview_padding e coloque seu valor como 12dp.
- elevation –propriedade para adicionar o efeito de sombra a view. Novamente crie um novo recurso e coloque o nome textview_elevation com o valor 4dp.
Note que, ambos recursos criados nessa etapa (padding e elevation) serão usados nos demais componentes da tela por isso é necessário criar eles dessa forma ao invés de digitar manualmente pois seus valores serão compartilhados. Isto é, se eu modificar futuramente o valor de elevação então todos os componentes serão automaticamente configurados também.
Configurando percentTextView
Configure o alinhamento do componente percentTextView para ficar mais alinhado com a SeekBar, incluindo na propriedade layout:gravity a opção center_vertical. Note que isso fará a view ficar tanto alinhado à direita (etapa realizada anteriormente) quanto verticalmente, isto é, mais de uma opção pode ser selecionada na propriedade layout:gravity.
Configurando percentSeekBar
Por padrão o componente SeekBar possui a margem de valor de 0 a 100, iremos modificar essa barra para ir de 0 a 30. Também iremos definir o valor inicial como 15. Assim, selecione esse componente e localize as propriedades abaixo para colocar os valores adequados:
- max: 30
- progress: 15 – essa propriedade especifica a cor de fundo com componente
- layout:gravity: fill_horizontal – faz com que a barra de progresso se expanda horizontalmente para preencher visualmente o restante da coluna
- layout:height: 40dp
Configurando tipTextView e TotalTextView
Selecione esses componentes e localize as propriedades abaixo para colocar os valores adequados:
- layout:gravity: fill_horizontal
- background: #FFE0B2
- gravity: center - essa propriedade faz com que o texto seja centralizado no meio do componente
- padding: selecione o recurso textview_padding
- elevation: selecione o recurso textview_elevation
Resultado final
Se você executou com exatidão os passos acima terá como resultado final a seguinte tela do aplicativo:
No próximo capítulo iremos incrementar a tela do aplicativo com o uso de temas e cores personalizadas.
6. Personalizando o tema do aplicativo
Criar um tema para um aplicativo é a tarefa de dar uma identidade visual ao aplicativo. O Android Studio oferece alguns temas pré-definidos que são incluídos pelas templates. Neste projeto iremos agora aprender como editar o tema do aplicativo para personalizar a nossa aplicação.
O tema padrão incluído na Empty Activity e demais templates, configura a tela com propriedades especificas no arquivo styles.xml. Algumas modificações podem ser aplicadas ao estilo apenas mudando as cores usadas por esses elementos. Ao se mudar a cor secondária diversos componentes gráficos na tela irão se adaptar à nova cor declarada, por exemplo, a cor da SeekBar.
6.1. Modificando as cores do tema
Para customizar as cores do tema do aplicativo MiniCalculadora primeiramente abra o arquivo styles.xml como ilustrado na figura abaixo:
Dentro deste arquivo estão todas as configurações para alterar o estilo do aplicativo. Ao se fazer mudanças nesse arquivo isso refletirá na aparência do seu aplicativo. Se o valor da cor primária for modificado a cor da AppBar vai mudar, se a cor secundária mudar alguns elementos gráficos também vão se adaptar as mudanças, como é o caso da SeekBar presente em nosso projeto.
O valor para cada cor é um código em hexadecimal (ex, #B2FAC3) e pode ser obtido através de diferentes fontes. Como referência você pode usar o conjunto de cores do Material Design para pintar seus aplicativos através do site https://materialuicolors.co/ ou escolher sua própria preferência.
Para este aplicativo vamos adicionar novos recursos de cor ao arquivo colors.xml. Para tanto, abra o arquivo e adicione as seguintes cores:
- Cor primária - colorPrimary - #2196F3
- Cor primária escura - colorPrimaryVariant- #1976D2
- Cor de realce - colorSecondary - #FF9100
O arquivo colors.xml deve ficar como:
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<color name="colorPrimary">#2196F3</color>
<color name="colorPrimaryVariant">#1976D2</color>
<color name="colorSecondary">#FF9100</color>
</resources>
Agora precisamos configurar o tema do aplicativo para fazer o uso destas novas cores. Assim, abra o arquivo styles.xml e modifique as propriedades para usar os valores corretamente:
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MiniCalculadora" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryVariant">@color/colorPrimaryVariant</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/colorSecondary</item>
...
</style>
</resources>
O resultado final é o seguinte visual:
7. Adicionado a Lógica da Aplicação
No projeto da MiniCalculadora temos um campo de entrada para se inserir valores e uma barra de progresso para escolher uma taxa de serviço de 0 a 30. A MiniCalculadora deve pegar os valores de entrada, calcular o valor da taxa de serviço e o valor total final. Também, todos os valores na tela do aplicativo devem ser mostrados no formato correto: porcentagem (%) e moeda (R$, U$, ou outros). Toda essa lógica da aplicação será criada no arquivo MainActivity.java.
7.1. Pacotes utilizados
Faz parte do cabeçalho de qualquer arquivo Java, a declaração dos pacotes que serão necessários para a execução do código. Para este projeto iremos precisar importar diversas classes do Android para conseguir o acesso aos elementos da tela (as views) e implementar o tratamento de eventos. Também, para tratar a formatação dos valores numéricos em moeda e porcentagem, é utilizada uma classe proveniente do próprio Java – a classe NumberFormat (pacote java.text).
7.2. Atributos da classe
Boas práticas de programação indicam a criação de todos os atributos em uma classe em Java na parte de cima do arquivo. Nessa parte devem estar declaradas todas as variáveis e constantes que serão utilizadas pela aplicação.
No caso desse projeto, iremos criar as constantes currencyFormat e percentFormat, duas instâncias da classe NumberFormat, que vão cuidar da formatação da moeda e porcentagem. A especificação do tipo de formatação que irá ser usada é obtida através da invocação do método getCurrecyInstance() e getPercentInstance() respectivamente. Fica a cargo da classe NumberFormat descobrir qual o tipo de moeda deve ser usado, informações essa que depende da localidade do dispositivo. Logo, a formatação da moeda é adaptável a reais (R$) ou dólares (U$), por exemplo, dependendo das configurações do dispositivo Android. Para satisfazer os requisitos da aplicação, são declaradas duas variáveis billAmount (representará o valor inserido pelo usuário – inicialmente 0) e percent (representará a taxa de serviço – inicialmente 0.15). Ao se interagir com as views da tela, esses valores irão ser modificados e usados nos cálculos. Também devem ser declarados no inicio da classe todos os componentes gráficos que serão manipulados na aplicação. Neste projeto é necessário obter a referência das views amoutTextView, percentTextView, tipTextView e totalTextView.
package br.com.bcalegaro.minicalculadora;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TextView;
import java.text.NumberFormat;
public class MainActivity extends AppCompatActivity {
//objetos de formatação da MOEDA e da PORCENTAGEM
private static NumberFormat currecyFormat = NumberFormat.getCurrencyInstance();
private static NumberFormat percentFormat = NumberFormat.getPercentInstance();
//variáveis para a lógica de aplicação
private double billAmount = 0.0;
private double percent = 0.15;
//variavéis com as referências aos elementos da interface gráfica
private TextView amountTextView;
private TextView percentTextView;
private TextView tipTextView;
private TextView totalTextView;
7.3. Programando a Inicialização da Aplicação
No ato de criação de uma Activity é invocado o método onCreate. É nesse método que devem ser declaradas as configurações iniciais do aplicativo, comumente a ligação com os elementos na tela e configuração do tratamento de eventos.
Para obter acesso a um elemento da tela, invoca-se o método findViewById, que através de seu parâmetro retorna uma referência (objeto) do referido elemento na tela. Nesse ponto, a classe R ocupa um papel importante, pois ela consegue através do id da view localizar corretamente o elemento na tela e retornar sua refência.
No que tange o tratamento de eventos, o aplicativo vai precisar instânciar classes anônimas para dois tipos de interfaces: TextWatcher (usada para reagir na inserção de textos) e SeekBarListener (reage ao movimento na barra de progresso). Para a inclusão de um tratamento de eventos no EditText, adicionamos a classe anônima (que será criada futuramente) que implementa um TextWatcher com o método addTextChangedListener(). No tratamento de eventos para a SeekBar, adicionamos a classe anônima (que será criada futuramente também) que implementa um SeekBarListener com o método setOnSeekBarChangeListener ().
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//configurando as referências as TextViews da tela
amountTextView = findViewById(R.id.amountTextView);
percentTextView = findViewById(R.id.percentTextView);
tipTextView = findViewById(R.id.tipTextView);
totalTextView = findViewById(R.id.totalTextView);
//configura os valores iniciais da taxa e total
tipTextView.setText(currecyFormat.format(0));//R$ 0,00 U$ 0.00
totalTextView.setText(currecyFormat.format(0));
//configura o tratamento de eventos para a caixa de texto
EditText amountEditText = findViewById(R.id.amountEditText);
amountEditText.addTextChangedListener(amountEditTextWatcher);
//configura o tratamento de eventos para a barra seekBar
SeekBar percentSeekBar = findViewById(R.id.percentSeekBar);
percentSeekBar.setOnSeekBarChangeListener(seekBarListener);
}
7.4. O método calculate()
Para fazer os cálculos da lógica da aplicação da MiniCalculadora, iremos criar um método calculate() para pegar os valores salvos e calcular o valor da taxa de serviço e total da conta. Esse método deve ser invocado após a alteração do valor de entrada e a porcentagem da taxa de serviço. Sua lógica é bem simples, pois apenas recebe os valores, aplica as fórmulas e atualiza os novos valores na tela com método setText de cada view. Contudo, não se coloca o valor numérico bruto na tela, assim é usada as constantes currencyFormat e percentFormat que através do método format recebe um valor numérico e retorna a apresentação correta. Por exemplo, invocar o método com o valor 102.35 retornará R$102,35.
Prevenção de Erros: tome cuidado com números reais no Java possui ele usa o padrão americano, ou seja, definir billAmount = 10,50; gera um erro, pois o correto é billAmount = 10.50
private void calculate(){
//calcula a gorjeta e o total final da conta
double tip = billAmount * percent;
double total = billAmount + tip;
//mostra os resultados formatados no padrão da moeda
tipTextView.setText(currecyFormat.format(tip));
totalTextView.setText(currecyFormat.format(total));
}
7.5. Implementação da interface SeekBarListener
De acordo com a iteração do usuário, o tratamento de eventos de uma SeekBar dispara três métodos: onProgressChanged, onStartTrackingTouch e onStopTrackingTouch. Para o nosso caso, é necessário implementar apenas o primeiro, o resto fica em branco. Assim, a se mover a barra de progresso o programa deve atualizar o novo valor da porcentagem. Contudo, lembre que o valor da barra de progresso na SeekBar varia de 0 a 30, assim o novo valor de porcentagem deve receber o valor inteiro da barra de progresso e converter em %, isto é, dividir por 100. Por fim, invoca-se o método calculate() para refazer os cálculos da aplicação.
private final SeekBar.OnSeekBarChangeListener seekBarListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
//atualiza o valor da porcentagem com o novo valor selecionado
percent = i/100.0;
//mostrar o valor da porcentagem atualizado na tela
percentTextView.setText(percentFormat.format(percent));
//manda (re)calcular os valores
calculate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};
7.6. Implementação da interface TextWatcher
O tratamento de eventos de um EditText dispara três métodos: onTextChanged, beforeTextChanged e afterTextChanged. Para o nosso caso, é necessário implementar apenas o primeiro, o resto fica em branco. Ao se inserir ou apagar um digito na caixa de entrada, o método observa o valor digitado, o converte para representação em moeda e manda atualizar a amountTextView com o novo valor. Dessa forma, por mais que o usuário insira apenas números, a TextView faz com que apareça a visualização em formato de moeda.
Contudo, no caso de um valor em branco ou não numérico, a conversão do valor bruto em moeda irá dar errado e disparar uma exceção do tipo NumberFormatException. Assim, é necessário criar um tratamento de exceções (implementado através dos comandos try/catch) para caso aconteça esse erro e o programa não trave. Dessa forma, o método faz a tentativa de conversão normal, e em caso de erro, configura os valores como em branco. Independente do disparo ou não de uma exceção, a última etapa do tratamento de eventos é invocar o método -se o calculate() para refazer os cálculos da aplicação.
private final TextWatcher amountEditTextWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
try{
//faz a leitura do valor da caixa de texto e converte em número real (double)
billAmount = Double.parseDouble(charSequence.toString())/100.0;
amountTextView.setText(currecyFormat.format(billAmount));
}
catch (NumberFormatException e) {
//se a entrada for um valor em branco (o usuário apagou o que digitou por exemplo)
//dispara uma exceção. Então o programa seta o valor da conta como ZERO
billAmount = 0.0;
//reseta a entrada com a mensagem de dica inicial
amountTextView.setText(R.string.enter_amount);
}
//manda (re)calcular os valores
calculate();
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {}
};
8. Configurações finais do arquivo AndroidManifest.xml
Para finalizar o aplicativo, vamos configurar o arquivo do AndroidManifest.xml para forçar a inicialização do aplicativo numérico e orientação em forma de retrato (portrait). Para tanto, realize as etapas a seguir:
- Abra o arquivo AndroidManifest.xml
- Adicione nas propriedades da activity os campos:
- android:screenOrientation=”portrait”
- android:windowSoftInputMode=”stateAlwaysVisible”
O arquivo AndroidManifest.xml irá ficar como na figura a seguir.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.bcalegaro.minicalculadora">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MiniCalculadora">
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateAlwaysVisible">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>