graficos
This commit is contained in:
@@ -68,4 +68,5 @@ dependencies {
|
|||||||
androidTestImplementation(libs.ui.test.junit4)
|
androidTestImplementation(libs.ui.test.junit4)
|
||||||
debugImplementation(libs.ui.tooling)
|
debugImplementation(libs.ui.tooling)
|
||||||
debugImplementation(libs.ui.test.manifest)
|
debugImplementation(libs.ui.test.manifest)
|
||||||
|
implementation("com.github.PhilJay:MPAndroidChart:v3.1.0")
|
||||||
}
|
}
|
||||||
@@ -298,6 +298,9 @@ public class TelaInicialActivity extends AppCompatActivity {
|
|||||||
((HomeFragment) currentFragment).carregarDados(mesSelecionado, anoSelecionado, mesNome);
|
((HomeFragment) currentFragment).carregarDados(mesSelecionado, anoSelecionado, mesNome);
|
||||||
} else if (currentFragment instanceof TransacoesFragment) {
|
} else if (currentFragment instanceof TransacoesFragment) {
|
||||||
((TransacoesFragment) currentFragment).setFiltro(mesSelecionado, anoSelecionado);
|
((TransacoesFragment) currentFragment).setFiltro(mesSelecionado, anoSelecionado);
|
||||||
|
} else if (currentFragment instanceof GraficosFragment) {
|
||||||
|
String mesNome = meses[spinnerMes.getSelectedItemPosition()];
|
||||||
|
((GraficosFragment) currentFragment).setFiltro(mesSelecionado, anoSelecionado, mesNome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,20 +2,57 @@ package com.example.lifegrid.menu;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.lifegrid.R;
|
import com.example.lifegrid.R;
|
||||||
|
import com.example.lifegrid.models.Transacao;
|
||||||
|
import com.github.mikephil.charting.charts.BarChart;
|
||||||
|
import com.github.mikephil.charting.charts.PieChart;
|
||||||
|
import com.github.mikephil.charting.components.XAxis;
|
||||||
|
import com.github.mikephil.charting.data.BarData;
|
||||||
|
import com.github.mikephil.charting.data.BarDataSet;
|
||||||
|
import com.github.mikephil.charting.data.BarEntry;
|
||||||
|
import com.github.mikephil.charting.data.PieData;
|
||||||
|
import com.github.mikephil.charting.data.PieDataSet;
|
||||||
|
import com.github.mikephil.charting.data.PieEntry;
|
||||||
|
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
|
||||||
|
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
|
import com.google.firebase.database.DataSnapshot;
|
||||||
|
import com.google.firebase.database.DatabaseError;
|
||||||
|
import com.google.firebase.database.DatabaseReference;
|
||||||
|
import com.google.firebase.database.FirebaseDatabase;
|
||||||
|
import com.google.firebase.database.ValueEventListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GraficosFragment tem como único propósito compilar a informação da aplicação sob uma
|
* GraficosFragment tem como único propósito compilar a informação da aplicação sob uma
|
||||||
* componente puramente matemática exibida de forma ilustrativa. Tarta da visão de Dashboard de estatística.
|
* componente puramente matemática exibida de forma ilustrativa. Trata da visão de Dashboard de estatística.
|
||||||
*/
|
*/
|
||||||
public class GraficosFragment extends Fragment {
|
public class GraficosFragment extends Fragment {
|
||||||
|
|
||||||
|
private PieChart pieChartMensal;
|
||||||
|
private BarChart barChartAnual;
|
||||||
|
private TextView tvTituloMensal;
|
||||||
|
private TextView tvTituloAnual;
|
||||||
|
|
||||||
|
private List<Transacao> allTransacoesList = new ArrayList<>();
|
||||||
|
private int currentMes = -1;
|
||||||
|
private String currentAno = "";
|
||||||
|
private String currentMesNome = "";
|
||||||
|
|
||||||
public GraficosFragment() {
|
public GraficosFragment() {
|
||||||
// Construtor público vazio obrigatório
|
// Construtor público vazio obrigatório
|
||||||
}
|
}
|
||||||
@@ -25,13 +62,200 @@ public class GraficosFragment extends Fragment {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (getActivity() instanceof com.example.lifegrid.TelaInicialActivity) {
|
||||||
|
((com.example.lifegrid.TelaInicialActivity) getActivity()).atualizarDadosHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
// Inflaciona o layout para este fragmento
|
// Inflaciona o layout para este fragmento
|
||||||
View root = inflater.inflate(R.layout.fragment_graficos, container, false);
|
View root = inflater.inflate(R.layout.fragment_graficos, container, false);
|
||||||
|
|
||||||
|
pieChartMensal = root.findViewById(R.id.pieChartMensal);
|
||||||
|
barChartAnual = root.findViewById(R.id.barChartAnual);
|
||||||
|
tvTituloMensal = root.findViewById(R.id.tvTituloMensal);
|
||||||
|
tvTituloAnual = root.findViewById(R.id.tvTituloAnual);
|
||||||
|
|
||||||
|
configurarGraficos();
|
||||||
|
carregarTransacoes();
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configurarGraficos() {
|
||||||
|
// Config PieChart
|
||||||
|
pieChartMensal.getDescription().setEnabled(false);
|
||||||
|
pieChartMensal.setUsePercentValues(true);
|
||||||
|
pieChartMensal.setEntryLabelColor(android.graphics.Color.BLACK);
|
||||||
|
pieChartMensal.setEntryLabelTextSize(12f);
|
||||||
|
pieChartMensal.setCenterText("Despesas");
|
||||||
|
pieChartMensal.setCenterTextSize(18f);
|
||||||
|
|
||||||
|
// Config BarChart
|
||||||
|
barChartAnual.getDescription().setEnabled(false);
|
||||||
|
barChartAnual.setDrawGridBackground(false);
|
||||||
|
barChartAnual.getAxisRight().setEnabled(false);
|
||||||
|
XAxis xAxis = barChartAnual.getXAxis();
|
||||||
|
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
|
||||||
|
xAxis.setGranularity(1f);
|
||||||
|
xAxis.setCenterAxisLabels(true);
|
||||||
|
|
||||||
|
String[] mesesLabel = new String[]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"};
|
||||||
|
xAxis.setValueFormatter(new IndexAxisValueFormatter(mesesLabel));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void carregarTransacoes() {
|
||||||
|
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (currentUser == null) return;
|
||||||
|
|
||||||
|
String userId = currentUser.getUid();
|
||||||
|
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
|
||||||
|
|
||||||
|
databaseReference.child("users").child(userId).child("transacoes").addValueEventListener(new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
allTransacoesList.clear();
|
||||||
|
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
Transacao t = ds.getValue(Transacao.class);
|
||||||
|
if (t != null) {
|
||||||
|
t.setId(ds.getKey());
|
||||||
|
allTransacoesList.add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
atualizarGraficos();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) {
|
||||||
|
if (getContext() != null) {
|
||||||
|
Toast.makeText(getContext(), "Erro ao carregar transações.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFiltro(int mesSelecionado, String anoSelecionado, String mesNome) {
|
||||||
|
this.currentMes = mesSelecionado;
|
||||||
|
this.currentAno = anoSelecionado;
|
||||||
|
this.currentMesNome = mesNome;
|
||||||
|
|
||||||
|
if (tvTituloMensal != null) {
|
||||||
|
tvTituloMensal.setText("Resumo de " + mesNome + " " + anoSelecionado);
|
||||||
}
|
}
|
||||||
}
|
if (tvTituloAnual != null) {
|
||||||
|
tvTituloAnual.setText("Balanço Anual - " + anoSelecionado);
|
||||||
|
}
|
||||||
|
|
||||||
|
atualizarGraficos();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void atualizarGraficos() {
|
||||||
|
if (currentMes == -1 || currentAno.isEmpty()) return;
|
||||||
|
|
||||||
|
atualizarPieChart();
|
||||||
|
atualizarBarChart();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void atualizarPieChart() {
|
||||||
|
Map<String, Float> categoriasMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (Transacao t : allTransacoesList) {
|
||||||
|
if (t.getData() != null && t.getTipo() != null && t.getTipo().equalsIgnoreCase("Despesa")) {
|
||||||
|
String[] parts = t.getData().split("/");
|
||||||
|
if (parts.length == 3) {
|
||||||
|
try {
|
||||||
|
int mesTransacao = Integer.parseInt(parts[1]);
|
||||||
|
String anoTransacao = parts[2];
|
||||||
|
if (mesTransacao == currentMes && anoTransacao.equals(currentAno)) {
|
||||||
|
float valor = Float.parseFloat(t.getValor());
|
||||||
|
String cat = t.getCategoria();
|
||||||
|
categoriasMap.put(cat, categoriasMap.getOrDefault(cat, 0f) + valor);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PieEntry> entries = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, Float> entry : categoriasMap.entrySet()) {
|
||||||
|
if (entry.getValue() > 0) {
|
||||||
|
entries.add(new PieEntry(entry.getValue(), entry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PieDataSet dataSet = new PieDataSet(entries, "");
|
||||||
|
dataSet.setColors(ColorTemplate.MATERIAL_COLORS);
|
||||||
|
dataSet.setSliceSpace(3f);
|
||||||
|
dataSet.setValueTextSize(14f);
|
||||||
|
dataSet.setValueTextColor(android.graphics.Color.WHITE);
|
||||||
|
|
||||||
|
PieData data = new PieData(dataSet);
|
||||||
|
pieChartMensal.setData(data);
|
||||||
|
pieChartMensal.invalidate(); // refresh
|
||||||
|
}
|
||||||
|
|
||||||
|
private void atualizarBarChart() {
|
||||||
|
float[] receitasPorMes = new float[12];
|
||||||
|
float[] despesasPorMes = new float[12];
|
||||||
|
|
||||||
|
for (Transacao t : allTransacoesList) {
|
||||||
|
if (t.getData() != null) {
|
||||||
|
String[] parts = t.getData().split("/");
|
||||||
|
if (parts.length == 3) {
|
||||||
|
try {
|
||||||
|
int mesTransacao = Integer.parseInt(parts[1]) - 1; // 0 a 11
|
||||||
|
String anoTransacao = parts[2];
|
||||||
|
if (anoTransacao.equals(currentAno) && mesTransacao >= 0 && mesTransacao < 12) {
|
||||||
|
float valor = Float.parseFloat(t.getValor());
|
||||||
|
if (t.getTipo() != null && t.getTipo().equalsIgnoreCase("Receita")) {
|
||||||
|
receitasPorMes[mesTransacao] += valor;
|
||||||
|
} else {
|
||||||
|
despesasPorMes[mesTransacao] += valor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BarEntry> entriesReceitas = new ArrayList<>();
|
||||||
|
List<BarEntry> entriesDespesas = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
entriesReceitas.add(new BarEntry(i, receitasPorMes[i]));
|
||||||
|
entriesDespesas.add(new BarEntry(i, despesasPorMes[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
BarDataSet setReceitas = new BarDataSet(entriesReceitas, "Receitas");
|
||||||
|
setReceitas.setColor(android.graphics.Color.parseColor("#2ECC71"));
|
||||||
|
setReceitas.setValueTextSize(10f);
|
||||||
|
|
||||||
|
BarDataSet setDespesas = new BarDataSet(entriesDespesas, "Despesas");
|
||||||
|
setDespesas.setColor(android.graphics.Color.parseColor("#E74C3C"));
|
||||||
|
setDespesas.setValueTextSize(10f);
|
||||||
|
|
||||||
|
BarData data = new BarData(setReceitas, setDespesas);
|
||||||
|
|
||||||
|
// agrupar barras
|
||||||
|
float groupSpace = 0.4f;
|
||||||
|
float barSpace = 0.05f;
|
||||||
|
float barWidth = 0.25f;
|
||||||
|
|
||||||
|
data.setBarWidth(barWidth);
|
||||||
|
barChartAnual.setData(data);
|
||||||
|
barChartAnual.groupBars(0f, groupSpace, barSpace);
|
||||||
|
barChartAnual.getXAxis().setAxisMinimum(0f);
|
||||||
|
barChartAnual.getXAxis().setAxisMaximum(0f + barChartAnual.getBarData().getGroupWidth(groupSpace, barSpace) * 12);
|
||||||
|
|
||||||
|
barChartAnual.invalidate(); // refresh
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,81 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView 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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:fillViewport="true"
|
||||||
tools:context=".menu.GraficosFragment">
|
tools:context=".menu.GraficosFragment">
|
||||||
|
|
||||||
<!-- TODO: Update blank fragment layout -->
|
<LinearLayout
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/hello_blank_fragment" />
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="100dp"
|
||||||
|
android:paddingTop="16dp">
|
||||||
|
|
||||||
</FrameLayout>
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="0dp"
|
||||||
|
android:backgroundTint="#FFFFFF">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTituloMensal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Resumo Mensal"
|
||||||
|
android:textColor="#1A202C"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.github.mikephil.charting.charts.PieChart
|
||||||
|
android:id="@+id/pieChartMensal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="0dp"
|
||||||
|
android:backgroundTint="#FFFFFF">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTituloAnual"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Balanço Anual"
|
||||||
|
android:textColor="#1A202C"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.github.mikephil.charting.charts.BarChart
|
||||||
|
android:id="@+id/barChartAnual"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
@@ -19,6 +19,7 @@ dependencyResolutionManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven { url = uri("https://jitpack.io") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user