Alterei o design para ficar m ais fluido mas falta alterar a cor dos botões e adicionar um botão de voltar no activity_expenses_list.xml e tambem adicionei mais explicações
parent
249eb6f6f2
commit
f021060585
|
|
@ -8,12 +8,16 @@ import androidx.appcompat.app.AppCompatActivity; // Importa classe base para Act
|
|||
|
||||
import com.google.android.material.button.MaterialButton; // Importa botão Material Design
|
||||
import com.google.android.material.textfield.TextInputEditText; // Importa campo de texto Material Design
|
||||
import com.google.android.material.textfield.MaterialAutoCompleteTextView; // Campo com menu suspenso
|
||||
|
||||
import java.text.SimpleDateFormat; // Importa classe para formatação de datas
|
||||
import java.util.Date; // Importa classe para trabalhar com datas
|
||||
import java.util.Locale; // Importa classe para configurações de localização
|
||||
import java.util.Arrays; // Utilitário para trabalhar com arrays
|
||||
import java.util.ArrayList; // Lista mutável
|
||||
|
||||
import pt.epvc.gestodedespesas.data.DatabaseHelper; // DatabaseHelper movido para pacote data
|
||||
import android.widget.ArrayAdapter; // Adapter para preencher o dropdown
|
||||
|
||||
/**
|
||||
* AddExpenseActivity - Tela de Adicionar/Editar Despesas
|
||||
|
|
@ -30,7 +34,8 @@ import pt.epvc.gestodedespesas.data.DatabaseHelper; // DatabaseHelper movido par
|
|||
public class AddExpenseActivity extends AppCompatActivity { // Declara classe que estende AppCompatActivity
|
||||
|
||||
// Views da interface - campos de entrada do formulário
|
||||
private TextInputEditText etDescription, etAmount, etCategory, etDate, etNotes; // Declara campos de texto para entrada de dados
|
||||
private TextInputEditText etDescription, etAmount, etDate, etNotes; // Declara campos de texto para entrada de dados
|
||||
private MaterialAutoCompleteTextView etCategory; // Campo de categoria com dropdown
|
||||
private MaterialButton btnSave, btnCancel; // Declara botões de ação
|
||||
|
||||
// Objetos para funcionalidade
|
||||
|
|
@ -59,6 +64,8 @@ public class AddExpenseActivity extends AppCompatActivity { // Declara classe qu
|
|||
// Para nova despesa, define a data atual como padrão
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()); // Cria formato de data brasileiro
|
||||
etDate.setText(sdf.format(new Date())); // Define data atual no campo de data
|
||||
// Categoria padrão opcional (ex.: "Outros") para facilitar
|
||||
etCategory.setText("Outros", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,13 +77,26 @@ public class AddExpenseActivity extends AppCompatActivity { // Declara classe qu
|
|||
// Conecta os campos de entrada de texto
|
||||
etDescription = findViewById(R.id.etDescription); // Busca campo de descrição por ID e atribui à variável
|
||||
etAmount = findViewById(R.id.etAmount); // Busca campo de valor por ID e atribui à variável
|
||||
etCategory = findViewById(R.id.etCategory); // Busca campo de categoria por ID e atribui à variável
|
||||
etCategory = findViewById(R.id.etCategory); // Busca campo de categoria (dropdown) por ID
|
||||
etDate = findViewById(R.id.etDate); // Busca campo de data por ID e atribui à variável
|
||||
etNotes = findViewById(R.id.etNotes); // Busca campo de notas por ID e atribui à variável
|
||||
|
||||
// Conecta os botões de ação
|
||||
btnSave = findViewById(R.id.btnSave); // Busca botão salvar por ID e atribui à variável
|
||||
btnCancel = findViewById(R.id.btnCancel); // Busca botão cancelar por ID e atribui à variável
|
||||
|
||||
// Configura o dropdown de categorias com as mesmas opções do filtro
|
||||
String[] allCategories = getResources().getStringArray(R.array.expense_categories); // Inclui "Todas"
|
||||
ArrayList<String> formCategories = new ArrayList<>(Arrays.asList(allCategories));
|
||||
formCategories.remove("Todas"); // Remove "Todas" do formulário (apenas para filtro)
|
||||
ArrayAdapter<String> categoryAdapter = new ArrayAdapter<>(
|
||||
this,
|
||||
android.R.layout.simple_list_item_1,
|
||||
formCategories
|
||||
);
|
||||
etCategory.setAdapter(categoryAdapter);
|
||||
etCategory.setOnClickListener(v -> etCategory.showDropDown()); // Abre ao tocar
|
||||
etCategory.setOnFocusChangeListener((v, hasFocus) -> { if (hasFocus) etCategory.showDropDown(); });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import androidx.core.view.WindowInsetsCompat; // Insets de janela
|
|||
import androidx.recyclerview.widget.LinearLayoutManager; // Layout vertical
|
||||
import androidx.recyclerview.widget.RecyclerView; // Lista eficiente
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton; // Botão flutuante
|
||||
import com.google.android.material.button.MaterialButton; // Botão Material
|
||||
|
||||
import java.text.DecimalFormat; // Formatar valores monetários
|
||||
|
|
@ -34,13 +33,12 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
|
||||
private RecyclerView recyclerViewExpenses; // Lista de despesas
|
||||
private TextView tvTotal, tvExpenseCount, tvAverage; // Indicadores de total, contagem e média
|
||||
private FloatingActionButton fabAddExpense; // Botão flutuante para adicionar
|
||||
private MaterialButton btnFilter; // Botão para filtrar por categoria
|
||||
private DatabaseHelper databaseHelper; // Acesso ao SQLite
|
||||
private ExpenseAdapter expenseAdapter; // Adapter do RecyclerView
|
||||
private List<Expense> expenseList; // Dados das despesas
|
||||
private DecimalFormat currencyFormat = new DecimalFormat("€#,##0.00"); // Formatação em euro
|
||||
private boolean isShowingEmptyState = false; // Controle de qual layout está visível (lista ou estado vazio)
|
||||
private View emptyStateView; // Container do empty state incluído no layout
|
||||
|
||||
/**
|
||||
* onCreate: configura layout, Edge-to-Edge e listeners de insets, inicializa
|
||||
|
|
@ -50,8 +48,19 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
protected void onCreate(Bundle savedInstanceState) { // Ciclo de vida: criação da Activity
|
||||
super.onCreate(savedInstanceState); // Chama implementação base
|
||||
EdgeToEdge.enable(this); // Ativa layout de ponta a ponta
|
||||
databaseHelper = new DatabaseHelper(this); // Instancia acesso ao DB (SQLiteHelper)
|
||||
renderLayoutByData(); // Decide e aplica o layout conforme existência de despesas
|
||||
setContentView(R.layout.activity_expenses_list); // Usa layout principal sempre
|
||||
try {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
} catch (Exception ignored) {}
|
||||
databaseHelper = new DatabaseHelper(this); // Instancia acesso ao DB
|
||||
initializeViews(); // Faz bind das views (inclui empty state)
|
||||
setupRecyclerView(); // Configura lista
|
||||
setupClickListeners(); // Configura cliques (filtro e empty state)
|
||||
loadExpenses(); // Carrega dados iniciais
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -63,8 +72,8 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
tvTotal = findViewById(R.id.tvTotal); // Texto do total gasto
|
||||
tvExpenseCount = findViewById(R.id.tvExpenseCount); // Texto da contagem
|
||||
tvAverage = findViewById(R.id.tvAverage); // Texto da média
|
||||
fabAddExpense = findViewById(R.id.fabAddExpense); // FAB adicionar
|
||||
btnFilter = findViewById(R.id.btnFilter); // Botão filtrar
|
||||
emptyStateView = findViewById(R.id.emptyStateContainer); // Empty state incluído
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, "Erro ao inicializar views: " + e.getMessage(), Toast.LENGTH_LONG).show(); // Feedback de erro
|
||||
}
|
||||
|
|
@ -92,16 +101,6 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
*/
|
||||
private void setupClickListeners() {
|
||||
try {
|
||||
if (fabAddExpense != null) { // Verifica se a view foi encontrada
|
||||
fabAddExpense.setOnClickListener(new View.OnClickListener() { // Clique do FAB
|
||||
@Override
|
||||
public void onClick(View v) { // Ação ao clicar
|
||||
Intent intent = new Intent(ExpensesListActivity.this, AddExpenseActivity.class); // Ir para adicionar
|
||||
startActivityForResult(intent, 1); // Abrir aguardando resultado
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (btnFilter != null) { // Verifica existência do botão
|
||||
btnFilter.setOnClickListener(new View.OnClickListener() { // Clique do filtro
|
||||
@Override
|
||||
|
|
@ -110,6 +109,18 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
}
|
||||
});
|
||||
}
|
||||
// Botões do empty state (se presentes no include)
|
||||
View add = findViewById(R.id.btnAddFirstExpense);
|
||||
if (add != null) {
|
||||
add.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(ExpensesListActivity.this, AddExpenseActivity.class);
|
||||
startActivityForResult(intent, 1);
|
||||
});
|
||||
}
|
||||
View back = findViewById(R.id.btnBackFromEmpty);
|
||||
if (back != null) {
|
||||
back.setOnClickListener(v -> finish());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, "Erro ao configurar click listeners: " + e.getMessage(), Toast.LENGTH_LONG).show(); // Feedback de erro
|
||||
}
|
||||
|
|
@ -122,20 +133,15 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
private void loadExpenses() {
|
||||
try {
|
||||
expenseList = databaseHelper.getAllExpenses(); // Puxa despesas do DB
|
||||
boolean hasData = expenseList != null && !expenseList.isEmpty();
|
||||
if (!hasData) {
|
||||
if (!isShowingEmptyState) {
|
||||
renderEmptyLayout();
|
||||
}
|
||||
return; // Nada para atualizar no layout vazio
|
||||
}
|
||||
if (isShowingEmptyState) {
|
||||
renderMainLayout();
|
||||
}
|
||||
if (expenseAdapter != null) { // Garante adapter existente
|
||||
expenseAdapter.updateExpenses(expenseList); // Atualiza lista na UI
|
||||
if (expenseAdapter != null) { // Atualiza a lista
|
||||
expenseAdapter.updateExpenses(expenseList);
|
||||
}
|
||||
updateTotal(); // Recalcula indicadores
|
||||
// Mostra/oculta o empty state no fim da tela
|
||||
boolean isEmpty = expenseList == null || expenseList.isEmpty();
|
||||
if (emptyStateView != null) {
|
||||
emptyStateView.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, "Erro ao carregar despesas: " + e.getMessage(), Toast.LENGTH_LONG).show(); // Feedback de erro
|
||||
}
|
||||
|
|
@ -178,14 +184,11 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
} else { // Categoria específica
|
||||
String category = categories[which]; // Nome da categoria
|
||||
expenseList = databaseHelper.getExpensesByCategory(category); // Busca filtrada
|
||||
if (expenseList == null || expenseList.isEmpty()) {
|
||||
renderEmptyLayout();
|
||||
} else {
|
||||
if (isShowingEmptyState) {
|
||||
renderMainLayout();
|
||||
}
|
||||
expenseAdapter.updateExpenses(expenseList); // Atualiza adapter
|
||||
expenseAdapter.updateExpenses(expenseList); // Atualiza adapter (lista pode ficar vazia)
|
||||
updateTotal(); // Recalcula totais com filtro
|
||||
boolean isEmpty = expenseList == null || expenseList.isEmpty();
|
||||
if (emptyStateView != null) {
|
||||
emptyStateView.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -230,54 +233,5 @@ public class ExpensesListActivity extends AppCompatActivity implements ExpenseAd
|
|||
.show(); // Exibe diálogo
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide qual layout usar com base nos dados atuais do DB.
|
||||
*/
|
||||
private void renderLayoutByData() { // Decide qual layout mostrar com base nos dados
|
||||
try {
|
||||
List<Expense> initial = databaseHelper.getAllExpenses(); // Consulta inicial ao DB
|
||||
if (initial == null || initial.isEmpty()) { // Sem dados?
|
||||
renderEmptyLayout(); // Mostra estado vazio
|
||||
} else { // Há dados
|
||||
expenseList = initial; // Mantém em memória
|
||||
renderMainLayout(); // Mostra lista principal
|
||||
}
|
||||
} catch (Exception e) { // Qualquer erro
|
||||
renderEmptyLayout(); // Fallback: evita crash mostrando estado vazio
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mostra o layout principal de lista, inicializa views/adapter e listeners.
|
||||
*/
|
||||
private void renderMainLayout() { // Exibe layout principal de lista
|
||||
setContentView(R.layout.activity_expenses_list); // Aplica XML de lista
|
||||
isShowingEmptyState = false; // Marca que a lista está ativa
|
||||
try {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { // Listener de insets
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); // Áreas das barras
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); // Padding seguro
|
||||
return insets; // Continua propagação
|
||||
});
|
||||
} catch (Exception ignored) { } // Se não existir view com id main, ignora
|
||||
initializeViews(); // Associa views do layout
|
||||
setupRecyclerView(); // Configura RecyclerView e adapter
|
||||
setupClickListeners(); // Registra cliques (FAB e filtro)
|
||||
updateTotal(); // Atualiza totais na UI
|
||||
}
|
||||
|
||||
/**
|
||||
* Mostra o layout de estado vazio e configura o botão de adicionar.
|
||||
*/
|
||||
private void renderEmptyLayout() { // Exibe layout de estado vazio
|
||||
setContentView(R.layout.empty_state); // Aplica XML vazio
|
||||
isShowingEmptyState = true; // Marca que estado vazio está ativo
|
||||
View add = findViewById(R.id.btnAddFirstExpense); // Botão "Adicionar Despesa"
|
||||
if (add != null) { // Se existir no layout
|
||||
add.setOnClickListener(v -> { // Ao clicar
|
||||
Intent intent = new Intent(ExpensesListActivity.this, AddExpenseActivity.class); // Abre tela de adição
|
||||
startActivityForResult(intent, 1); // Aguarda resultado para recarregar
|
||||
});
|
||||
}
|
||||
}
|
||||
// Métodos de alternância de layout foram substituídos por um include do empty state no XML
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ public class MainActivity extends AppCompatActivity { // Declara classe que este
|
|||
btnViewExpenses.setOnClickListener(new View.OnClickListener() { // Define listener de clique para o botão "Ver Despesas"
|
||||
@Override // Sobrescreve método da interface
|
||||
public void onClick(View v) { // Método chamado quando botão é clicado
|
||||
// Navega para a tela simplificada de lista de despesas
|
||||
Intent intent = new Intent(MainActivity.this, SimpleExpensesActivity.class); // Cria Intent para navegar para SimpleExpensesActivity
|
||||
// Navega para a tela avançada de lista de despesas (usa empty_state e activity_expenses_list)
|
||||
Intent intent = new Intent(MainActivity.this, ExpensesListActivity.class); // Cria Intent para ExpensesListActivity
|
||||
startActivity(intent); // Inicia Activity sem esperar resultado
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import android.database.Cursor; // Onde ficam os resultados de uma consulta
|
|||
import android.database.sqlite.SQLiteDatabase; // Objeto que permite ler/escrever no banco
|
||||
import android.database.sqlite.SQLiteOpenHelper; // Classe que ajuda a criar e atualizar o banco
|
||||
|
||||
import java.util.ArrayList; // Lista de tamanho variável
|
||||
import java.util.List; // Tipo "lista" em Java
|
||||
import java.util.ArrayList; // Lista de tamanho variável (pode crescer conforme necessário)
|
||||
import java.util.List; // Tipo "lista" em Java (coleção de itens)
|
||||
|
||||
import pt.epvc.gestodedespesas.Expense; // Nossa classe que representa uma despesa
|
||||
|
||||
|
|
@ -23,24 +23,24 @@ public class DatabaseHelper extends SQLiteOpenHelper { // Helper do SQLite
|
|||
private static final int DATABASE_VERSION = 1; // Versão do banco (muda quando a estrutura mudar)
|
||||
|
||||
// Nome da tabela e das colunas (os "campos" da tabela)
|
||||
private static final String TABLE_EXPENSES = "expenses";
|
||||
private static final String COLUMN_ID = "id";
|
||||
private static final String COLUMN_DESCRIPTION = "description";
|
||||
private static final String COLUMN_AMOUNT = "amount";
|
||||
private static final String COLUMN_CATEGORY = "category";
|
||||
private static final String COLUMN_DATE = "date";
|
||||
private static final String COLUMN_NOTES = "notes";
|
||||
private static final String TABLE_EXPENSES = "expenses"; // Nome da tabela no banco
|
||||
private static final String COLUMN_ID = "id"; // Coluna: identificador único da despesa
|
||||
private static final String COLUMN_DESCRIPTION = "description"; // Coluna: descrição do gasto
|
||||
private static final String COLUMN_AMOUNT = "amount"; // Coluna: valor do gasto
|
||||
private static final String COLUMN_CATEGORY = "category"; // Coluna: categoria do gasto
|
||||
private static final String COLUMN_DATE = "date"; // Coluna: data do gasto (texto formatado)
|
||||
private static final String COLUMN_NOTES = "notes"; // Coluna: notas/opcional
|
||||
|
||||
// Comando que cria a tabela de despesas (rodado somente na primeira vez)
|
||||
private static final String CREATE_TABLE_EXPENSES =
|
||||
"CREATE TABLE " + TABLE_EXPENSES + "(" +
|
||||
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
COLUMN_DESCRIPTION + " TEXT NOT NULL," +
|
||||
COLUMN_AMOUNT + " REAL NOT NULL," +
|
||||
COLUMN_CATEGORY + " TEXT NOT NULL," +
|
||||
COLUMN_DATE + " TEXT NOT NULL," +
|
||||
COLUMN_NOTES + " TEXT" +
|
||||
")";
|
||||
private static final String CREATE_TABLE_EXPENSES = // Texto do comando para criar a tabela
|
||||
"CREATE TABLE " + TABLE_EXPENSES + "(" + // Começa criando a tabela "expenses"
|
||||
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + // id numérico que cresce sozinho
|
||||
COLUMN_DESCRIPTION + " TEXT NOT NULL," + // descrição obrigatória
|
||||
COLUMN_AMOUNT + " REAL NOT NULL," + // valor obrigatório (número)
|
||||
COLUMN_CATEGORY + " TEXT NOT NULL," + // categoria obrigatória
|
||||
COLUMN_DATE + " TEXT NOT NULL," + // data obrigatória (guardada como texto)
|
||||
COLUMN_NOTES + " TEXT" + // notas opcionais
|
||||
")"; // fecha o comando
|
||||
|
||||
public DatabaseHelper(Context context) { // Chamado quando precisamos usar o banco
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION); // Diz o nome e a versão do banco
|
||||
|
|
@ -73,11 +73,11 @@ public class DatabaseHelper extends SQLiteOpenHelper { // Helper do SQLite
|
|||
|
||||
public Expense getExpense(int id) { // Busca uma despesa específica pelo id
|
||||
SQLiteDatabase db = this.getReadableDatabase(); // Abre o banco para leitura
|
||||
Cursor cursor = db.query(
|
||||
TABLE_EXPENSES,
|
||||
new String[]{COLUMN_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_CATEGORY, COLUMN_DATE, COLUMN_NOTES},
|
||||
COLUMN_ID + "=?",
|
||||
new String[]{String.valueOf(id)}, null, null, null, null
|
||||
Cursor cursor = db.query( // Faz uma consulta procurando pelo id
|
||||
TABLE_EXPENSES, // na tabela de despesas
|
||||
new String[]{COLUMN_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_CATEGORY, COLUMN_DATE, COLUMN_NOTES}, // colunas desejadas
|
||||
COLUMN_ID + "=?", // condição: id igual ao informado
|
||||
new String[]{String.valueOf(id)}, null, null, null, null // valor do id
|
||||
);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) { // Se achou o registro
|
||||
|
|
@ -100,9 +100,9 @@ public class DatabaseHelper extends SQLiteOpenHelper { // Helper do SQLite
|
|||
|
||||
public List<Expense> getAllExpenses() { // Busca todas as despesas, mais recentes primeiro
|
||||
List<Expense> expenseList = new ArrayList<>(); // Cria uma lista vazia
|
||||
String selectQuery = "SELECT * FROM " + TABLE_EXPENSES + " ORDER BY " + COLUMN_DATE + " DESC"; // Consulta
|
||||
String selectQuery = "SELECT * FROM " + TABLE_EXPENSES + " ORDER BY " + COLUMN_DATE + " DESC"; // Consulta: tudo, ordenado pela data (mais recente primeiro)
|
||||
SQLiteDatabase db = this.getWritableDatabase(); // Abre o banco
|
||||
Cursor cursor = db.rawQuery(selectQuery, null); // Executa a consulta
|
||||
Cursor cursor = db.rawQuery(selectQuery, null); // Executa a consulta e devolve um "cursor" para navegar
|
||||
|
||||
if (cursor.moveToFirst()) { // Se tem pelo menos uma linha
|
||||
do { // Repete para cada linha
|
||||
|
|
@ -157,10 +157,10 @@ public class DatabaseHelper extends SQLiteOpenHelper { // Helper do SQLite
|
|||
List<Expense> expenseList = new ArrayList<>(); // Lista vazia
|
||||
SQLiteDatabase db = this.getReadableDatabase(); // Abre para leitura
|
||||
Cursor cursor = db.query( // Faz a consulta com filtro de categoria
|
||||
TABLE_EXPENSES,
|
||||
new String[]{COLUMN_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_CATEGORY, COLUMN_DATE, COLUMN_NOTES},
|
||||
COLUMN_CATEGORY + "=?",
|
||||
new String[]{category}, null, null, COLUMN_DATE + " DESC", null
|
||||
TABLE_EXPENSES, // tabela "expenses"
|
||||
new String[]{COLUMN_ID, COLUMN_DESCRIPTION, COLUMN_AMOUNT, COLUMN_CATEGORY, COLUMN_DATE, COLUMN_NOTES}, // colunas
|
||||
COLUMN_CATEGORY + "=?", // condição de filtro
|
||||
new String[]{category}, null, null, COLUMN_DATE + " DESC", null // valor do filtro e ordenação
|
||||
);
|
||||
|
||||
if (cursor.moveToFirst()) { // Se achou resultados
|
||||
|
|
|
|||
|
|
@ -89,14 +89,17 @@
|
|||
android:hint="Categoria"
|
||||
app:startIconDrawable="@drawable/ic_category"
|
||||
app:boxStrokeColor="@color/primary_color"
|
||||
app:hintTextColor="@color/primary_color">
|
||||
app:hintTextColor="@color/primary_color"
|
||||
app:endIconMode="dropdown_menu">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/etCategory"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:textColor="@color/text_primary" />
|
||||
android:inputType="none"
|
||||
android:textColor="@color/text_primary"
|
||||
android:hint="Selecione uma categoria"
|
||||
android:entries="@array/expense_categories" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -225,23 +225,16 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="80dp" />
|
||||
|
||||
<!-- Empty state embutido (mostrado quando não há despesas) -->
|
||||
<include
|
||||
android:id="@+id/emptyStateContainer"
|
||||
layout="@layout/empty_state"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<!-- Floating Action Button -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabAddExpense"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_add_white"
|
||||
app:backgroundTint="@color/primary_color"
|
||||
app:borderWidth="0dp"
|
||||
app:elevation="12dp"
|
||||
app:fabSize="normal"
|
||||
app:tint="@color/white"
|
||||
app:rippleColor="@color/primary_dark" />
|
||||
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
|
|
@ -33,40 +33,40 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp"
|
||||
android:gravity="center">
|
||||
android:padding="32dp">
|
||||
|
||||
<!-- Ícone principal -->
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:src="@drawable/ic_wallet"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:background="@drawable/welcome_icon_background"
|
||||
android:padding="24dp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
android:src="@drawable/ic_wallet" />
|
||||
|
||||
<!-- Título principal -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="💰 Gestão de Despesas"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="12dp" />
|
||||
android:text="💰 Gestão de Despesas"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- Subtítulo -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Controle seus gastos de forma inteligente e organizada"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="4dp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
android:text="Controle seus gastos de forma inteligente e organizada"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<!-- Botão principal -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
|
@ -74,14 +74,14 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:text="🚀 Começar Agora"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18sp"
|
||||
app:backgroundTint="@color/primary_color"
|
||||
app:cornerRadius="28dp"
|
||||
app:elevation="6dp"
|
||||
app:icon="@drawable/ic_rocket"
|
||||
app:iconTint="@color/white"
|
||||
app:iconSize="24dp"
|
||||
app:elevation="6dp" />
|
||||
app:iconTint="@color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -45,4 +45,16 @@
|
|||
app:icon="@drawable/ic_add_white"
|
||||
app:iconTint="@color/white" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnBackFromEmpty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="🔙 Voltar"
|
||||
android:textColor="@color/primary_color"
|
||||
app:backgroundTint="@android:color/transparent"
|
||||
app:strokeColor="@color/primary_color"
|
||||
app:strokeWidth="2dp"
|
||||
app:cornerRadius="20dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
<resources>
|
||||
<string name="app_name">Gestão de Despesas</string>
|
||||
|
||||
<string-array name="expense_categories">
|
||||
<item>Todas</item>
|
||||
<item>Alimentação</item>
|
||||
<item>Transporte</item>
|
||||
<item>Entretenimento</item>
|
||||
<item>Saúde</item>
|
||||
<item>Compras</item>
|
||||
<item>Outros</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
Loading…
Reference in New Issue