Imprimir o livro todoImprimir o livro todo

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

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.
    • 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 rowscolumns 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 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 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 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 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: onProgressChangedonStartTrackingTouch 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>