CoreGraphics

Usando CoreGraphics na criação de gráfico de colunas

Quando estamos desenvolvendo é muito comum nos depararmos com a necessidade de exibir dados para o usuário. E qual a melhor forma de fazer isso senão usando gráficos?

Nesse tutorial você vai aprender a construir um gráfico de barras.

Abra o Xcode e crie um novo projeto, selecione iOS e Single View App. 
A seguir dê um nome para o seu app e escolha o diretório onde deseja salvá-lo.

Abra o arquivo Main.storyboard. A partir da Object Library, clique e arraste para levar os itens até a tela.

Você precisará de uma View, 5 Text Fields e um botão. 
Sua storyboard deverá ficar mais ou menos assim:

No canto superior direito, clique no ícone que habilita o Assistant editor.

Segurando a tecla control, clique e arraste a partir da View até abaixo da linha 11 no código. Dê um nome para o seu outlet.

Depois, faça o mesmo com os 4 text fields.

Clique e arraste com o control selecionado a partir do botão até a linha do código anterior ao fechamento da ultima chave. Esse outlet será ativado quando o botão for tocado e servirá para atualizar o gráfico com os valores inseridos nos text fields. Mude o tipo de conexão para Action e dê um nome.

Sua classe ViewController deve se parecer com isso:

Agora vamos criar a classe que será responsável por construir a view do gráfico.

Adicione um novo arquivo ao projeto.
Selecione a opção Cocoa Touch Class.
Dê um nome para a sua classe e escolha UIView como sendo a classe mãe.

Os atributos da classe serão: dados = [0,0,0,0,0] (para conter os 5 valores do gráfico) e context: CGContext! (Para armazenar o CGContext).

O CGContext é necessário pois “dentro” dele realizaremos todos os desenhos, ou melhor dizendo, criaremos paths. Os paths são a maneira como o CoreGraphics armazena formas e linhas que serão desenhadas.

Dentro do método draw() adicione o seguinte:

Essas linhas servem para chamar o construtor da classe mãe e também identificar o context e armazena-lo na nossa variável.

Abaixo do método draw() adicione essas linhas:

Aqui você está criando uma função para desenhar os eixos do gráfico.
Nas linhas 24–26 estamos configurando o context. Definimos que a cor da linha será cinza claro e que ela terá uma largura de 0.5. Também iniciamos o path, o que é necessário para começarmos.

A variável espacoEntreOsEixos representa quando haverá entre cada linha. No caso queremos deixar 5% livre em cima e em baixo, portanto, dividimos a altura de 90% da view por 5.

O eixoAtual representa um eixo que será desenhado, o primeiro estará a 5% do topo da view.

Importante notar que o sistema de coordenados é configurado assim:

Para desenharmos uma linha usamos o método move para escolher o ponto inicial e a seguir addLine define o ponto final. Cada vez que usamos o método addLine adicionamos um sub-path ao desenho atual.

Dentro do while esse processo é repetido até que não haja mais espaço para adicionarmos linhas horizontais. Ai então usamos context.strokePath() para desenharmos todo o path (que é limpo após o desenho).

Adicione desenharOsEixos() ao final do método draw().

Abra o storyboard. Selecione a view do grafico.

No inspector mude a classe para aquela que você acabou de criar. No outlet da view dentro da classe ViewController também é necessário alterar o tipo, assim:

Execute o código. Seu app deve estar assim:

Agora é a vez das linhas verticais.

Adicione o seguinte ao final do método desenharOsEixos:

A lógica utilizada é a mesma para desenhar as linhas horizontais: iniciamos um novo path, confiarmos as linhas (agora tracejadas), definimos qual será o espaço entre os eixos e o eixo inicial. Movemos o referencial do context para o inicio de cada linhas e às adicionamos repetidamente, até que não haja mais espaço.

Agora já temos o fundo para o gráfico:

Vamos então criar a função que irá construir as barras verticais. Adicione o código abaixo da função desenharOsEixos.

Começamos mais uma vez preparando o context:

  • Definimos que a cor da linha será laranja.
  • Determinamos a largura de cada linha.
  • Precisamos indicar que a linha não será tracejada.

Criamos um for que itera pelos dados adicionando um sub-path para cada um deles. E por fim desenhamos o path.

Não se preocupe com o erro, corrigiremos ele em breve.

Para testarmos nosso gráfico precisamos pegar as informações digitadas nos textFields, para isso, acrescente o seguinte no método atualizarGrafico do ViewController:

Criamos 5 variáveis para conter os números digitados, verificamos cada textField e se ele contiver algum texto convertemos para inteiro e salvamos na variável adequada, depois passamos esses dados para o método atualizar que construiremos a seguir.

Volte para a classe do grafico.
Depois do método desenharAsBarras adicione o seguinte:

Essa rotina ira mudar o atributo dados para aqueles que foram passados como parâmetro, remove as subviews e reconstrói a view.

Abra o storyboard.

Selecione cada um dos text fields e altere o tipo do teclado para numérico, isso impedirá que seja digitado algum texto.

Selecione um Tap Gesture recognizer e o arraste até à view principal. 
Depois o crie um outlet do mesmo:

Usaremos esse outlet para ocultar o teclado ao tocar na view de fundo.

Vá a classe ViewController e adicione UITextFieldDelegate à assinatura:

class ViewController: UIViewController, UITextFieldDelegate {

Altere o método ocultarGrafico:

resignFirstResponder fará com que caso o teclado de algum text field esteja ativo, deixe de ser exibido.

Agora volte à classe do gráfico e crie essa função:

Essa função encontra o maior numero entre os dados (desde que ele seja maior do que 5) e se ele não for múltiplo de 5, aumenta seu valor até que o seja. Esse valor será o do eixo mais alto.

No final do método draw() adicione desenharAsBarras().

Rode o aplicativo. Teste com alguns valores.

Agora vamos para a última parte: colocar as legendas dos valores.

Adicione essa função depois daquela responsável por atualizar o gráfico.
O que é estamos fazendo é primeiro, definindo uma fonte e um tamanho para as legendas, e a seguir criamos um loop que irá construir todas e as adicionará ao gráfico.

Adicione escreverLegendas() ao método draw e rode mais uma vez o aplicativo.

Seu gráfico está pronto!