Ultimas altrações

main
240408 2025-11-06 16:25:54 +00:00
parent a9da34b592
commit ef0d44647f
20 changed files with 215 additions and 83 deletions

View File

@ -2,10 +2,10 @@
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<SelectionState runConfigName="conversor">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="conversor">
<SelectionState runConfigName="conversordemoedas2">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>

View File

@ -4,12 +4,12 @@ plugins {
android {
namespace = "com.example.conversordemoedas2"
compileSdk = 36
compileSdk = 34
defaultConfig {
applicationId = "com.example.conversordemoedas2"
minSdk = 24
targetSdk = 36
targetSdk = 34
versionCode = 1
versionName = "1.0"

View File

@ -4,12 +4,19 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
// ======================= Conversor de Moedas =======================
public class Conversion {
// Identificador do registro no histórico
private int id;
// Código da moeda de origem (ex.: USD)
private String fromCurrency;
// Código da moeda de destino (ex.: BRL)
private String toCurrency;
// Valor informado pelo usuário
private double amount;
// Resultado da conversão
private double result;
// Data/hora em millis desde epoch
private long date;
public Conversion(int id, String fromCurrency, String toCurrency,
@ -39,12 +46,14 @@ public class Conversion {
public void setDate(long date) { this.date = date; }
public String getFormattedDate() {
// Formata a data no padrão dd/MM/yyyy HH:mm
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault());
return sdf.format(new Date(date));
}
@Override
public String toString() {
// String amigável para debug/listagem simples
return String.format("%.2f %s = %.2f %s (%s)",
amount, fromCurrency, result, toCurrency, getFormattedDate());
}

View File

@ -8,9 +8,13 @@ import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
// ======================= Conversor de Moedas =======================
public class ConversionHistoryAdapter extends BaseAdapter {
// Contexto para inflar layouts
private Context context;
// Lista de conversões exibidas
private List<Conversion> conversions;
// Inflater padrão para criar views da lista
private LayoutInflater inflater;
public ConversionHistoryAdapter(Context context, List<Conversion> conversions) {
@ -39,6 +43,7 @@ public class ConversionHistoryAdapter extends BaseAdapter {
ViewHolder holder;
if (convertView == null) {
// Usa layout simples com duas linhas de texto
convertView = inflater.inflate(android.R.layout.simple_list_item_2, parent, false);
holder = new ViewHolder();
holder.text1 = convertView.findViewById(android.R.id.text1);
@ -50,14 +55,14 @@ public class ConversionHistoryAdapter extends BaseAdapter {
Conversion conversion = conversions.get(position);
// Texto principal: conversão
// Linha principal: valor convertido
String mainText = String.format("%.2f %s = %.2f %s",
conversion.getAmount(),
conversion.getFromCurrency(),
conversion.getResult(),
conversion.getToCurrency());
// Texto secundário: data
// Linha secundária: data/hora
String subText = conversion.getFormattedDate();
holder.text1.setText(mainText);
@ -67,6 +72,7 @@ public class ConversionHistoryAdapter extends BaseAdapter {
}
public void updateData(List<Conversion> newConversions) {
// Atualiza a lista e notifica para redesenhar
this.conversions = newConversions;
notifyDataSetChanged();
}

View File

@ -1,10 +1,16 @@
package com.example.conversordemoedas2;
// ======================= Conversor de Moedas =======================
public class Currency {
// Identificador interno no banco
private int id;
// Código ISO da moeda (ex.: USD, BRL)
private String code;
// Nome descritivo (ex.: Dólar Americano)
private String name;
// Símbolo monetário (ex.: $, R$)
private String symbol;
// Taxa relativa ao USD (quantos USD 1 unidade desta moeda vale)
private double rateToUsd;
public Currency(int id, String code, String name, String symbol, double rateToUsd) {
@ -31,6 +37,7 @@ public class Currency {
@Override
public String toString() {
// Formato exibido nos spinners (código - nome (símbolo))
return code + " - " + name + " (" + symbol + ")";
}
}

View File

@ -3,7 +3,9 @@ package com.example.conversordemoedas2;
import android.content.Context;
import java.util.List;
// ======================= Conversor de Moedas =======================
public class CurrencyConverter {
// Acesso ao banco SQLite para moedas e histórico
private DatabaseHelper dbHelper;
public CurrencyConverter(Context context) {
@ -12,7 +14,7 @@ public class CurrencyConverter {
}
private void initializeDatabase() {
// Seed additional currencies if missing
// Insere moedas adicionais caso ainda não existam (seed)
dbHelper.seedAdditionalCurrencies();
}
@ -28,6 +30,7 @@ public class CurrencyConverter {
return amount;
}
// Obtém informações das moedas no banco
Currency fromCurrency = dbHelper.getCurrencyByCode(fromCurrencyCode);
Currency toCurrency = dbHelper.getCurrencyByCode(toCurrencyCode);
@ -35,11 +38,11 @@ public class CurrencyConverter {
throw new IllegalArgumentException("Moeda não encontrada");
}
// Converter para USD primeiro, depois para a moeda de destino
// Estratégia: normaliza para USD e depois converte para a moeda destino
double amountInUsd = amount / fromCurrency.getRateToUsd();
double result = amountInUsd * toCurrency.getRateToUsd();
// Salvar no histórico
// Salva a operação no histórico
dbHelper.insertConversion(fromCurrencyCode, toCurrencyCode, amount, result);
return result;
@ -50,6 +53,7 @@ public class CurrencyConverter {
* @return Lista de moedas
*/
public List<Currency> getAvailableCurrencies() {
// Lista todas as moedas cadastradas
return dbHelper.getAllCurrencies();
}
@ -58,6 +62,7 @@ public class CurrencyConverter {
* @return Lista de conversões
*/
public List<Conversion> getConversionHistory() {
// Retorna as últimas conversões registradas
return dbHelper.getConversionHistory();
}
@ -65,6 +70,7 @@ public class CurrencyConverter {
* Limpa o histórico de conversões
*/
public void clearHistory() {
// Limpa todos os registros de conversão
dbHelper.clearHistory();
}
@ -74,6 +80,7 @@ public class CurrencyConverter {
* @return Objeto Currency ou null se não encontrado
*/
public Currency getCurrencyByCode(String code) {
// Busca moeda pelo código (ex.: "USD")
return dbHelper.getCurrencyByCode(code);
}
@ -102,6 +109,7 @@ public class CurrencyConverter {
return 1.0;
}
// Carrega as moedas e calcula razão das taxas para USD
Currency fromCurrency = dbHelper.getCurrencyByCode(fromCurrencyCode);
Currency toCurrency = dbHelper.getCurrencyByCode(toCurrencyCode);
@ -122,6 +130,7 @@ public class CurrencyConverter {
* @return ID da conversão inserida
*/
public long insertConversion(String fromCurrency, String toCurrency, double amount, double result) {
// Insere registro manualmente no histórico
return dbHelper.insertConversion(fromCurrency, toCurrency, amount, result);
}
}

View File

@ -8,8 +8,10 @@ import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
// ======================= Conversor de Moedas =======================
public class DatabaseHelper extends SQLiteOpenHelper {
// Nome e versão do banco SQLite
private static final String DATABASE_NAME = "CurrencyConverter.db";
private static final int DATABASE_VERSION = 1;
@ -35,7 +37,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
// Criar tabela de moedas
// Cria a tabela de moedas com taxa relativa ao USD
String createCurrenciesTable = "CREATE TABLE " + TABLE_CURRENCIES + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_CODE + " TEXT UNIQUE NOT NULL, " +
@ -44,7 +46,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
COLUMN_RATE_TO_USD + " REAL NOT NULL" +
")";
// Criar tabela de conversões
// Cria a tabela de histórico de conversões
String createConversionsTable = "CREATE TABLE " + TABLE_CONVERSIONS + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_FROM_CURRENCY + " TEXT NOT NULL, " +
@ -57,7 +59,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
db.execSQL(createCurrenciesTable);
db.execSQL(createConversionsTable);
// Inserir moedas padrão
// Insere moedas padrão ao criar o banco (seed inicial)
insertDefaultCurrencies(db);
}
@ -69,6 +71,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
private void insertDefaultCurrencies(SQLiteDatabase db) {
// Lista base de moedas com símbolo e taxa para USD
String[][] currencies = {
{"USD", "Dólar Americano", "$", "1.0"},
{"BRL", "Real Brasileiro", "R$", "5.2"},
@ -94,6 +97,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// Métodos para gerenciar moedas
public List<Currency> getAllCurrencies() {
// Retorna todas as moedas ordenadas por nome
List<Currency> currencies = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_CURRENCIES, null, null, null, null, null, COLUMN_NAME);
@ -116,6 +120,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
public Currency getCurrencyByCode(String code) {
// Busca uma moeda específica pelo código
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_CURRENCIES, null, COLUMN_CODE + "=?",
new String[]{code}, null, null, null);
@ -136,6 +141,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
public void seedAdditionalCurrencies() {
// Insere moedas adicionais ignorando duplicatas (CONFLICT_IGNORE)
SQLiteDatabase db = this.getWritableDatabase();
String[][] more = new String[][]{
{"ARS","Peso Argentino","$","970.0"},
@ -173,6 +179,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// Métodos para gerenciar conversões
public long insertConversion(String fromCurrency, String toCurrency,
double amount, double result) {
// Insere um registro no histórico de conversões
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_FROM_CURRENCY, fromCurrency);
@ -187,6 +194,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
public List<Conversion> getConversionHistory() {
// Retorna até 50 conversões mais recentes (ordem decrescente por data)
List<Conversion> conversions = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_CONVERSIONS, null, null, null, null, null,
@ -211,6 +219,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
public void clearHistory() {
// Remove todos os registros da tabela de histórico
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_CONVERSIONS, null, null);
db.close();

View File

@ -27,21 +27,34 @@ import com.google.android.material.textfield.TextInputEditText;
import java.util.ArrayList;
import java.util.List;
// ======================= Conversor de Moedas =======================
public class MainActivity extends AppCompatActivity {
// Conversor de moedas (regras de negócio e acesso ao banco)
private CurrencyConverter currencyConverter;
// Campo de entrada do valor a converter
private TextInputEditText amountInput;
// Spinners para seleção de moeda de origem e destino
private Spinner fromCurrencySpinner;
private Spinner toCurrencySpinner;
// Texto do resultado formatado
private TextView resultText;
// Texto que exibe a taxa de câmbio atual entre as moedas
private TextView exchangeRateText;
// ========== DECLARAÇÃO DOS BOTÕES (variáveis de classe) ==========
// Botão para limpar o histórico de conversões
private MaterialButton clearHistoryButton;
// Lista para exibir o histórico de conversões
private ListView historyListView;
// Botão para inverter moeda de origem/destino
private ImageView swapButton;
// Botão que abre a tela do conversor de velocidade
private MaterialButton speedConverterButton;
// Lista de moedas disponíveis vindas do banco
private List<Currency> currencies;
// Adapter que renderiza os itens do histórico na ListView
private ConversionHistoryAdapter historyAdapter;
// Flag para evitar recálculo durante mudanças programáticas nos spinners
private boolean isUpdating = false;
@Override
@ -55,10 +68,15 @@ public class MainActivity extends AppCompatActivity {
return insets;
});
// Inicializa referências de UI (views)
initializeViews();
// Cria o conversor de moedas e carrega a lista de moedas do banco
initializeCurrencyConverter();
// Preenche e configura os spinners de moedas
setupSpinners();
// Registra listeners de botões e do campo de texto
setupListeners();
// Carrega e exibe o histórico salvo no banco
loadHistory();
// Executar demonstração no log (opcional)
@ -66,29 +84,36 @@ public class MainActivity extends AppCompatActivity {
}
private void initializeViews() {
// ========== INICIALIZAÇÃO DOS BOTÕES (vincula com o layout XML) ==========
// Faz o bind das views do layout com os campos da activity
amountInput = findViewById(R.id.amountInput);
fromCurrencySpinner = findViewById(R.id.fromCurrencySpinner);
toCurrencySpinner = findViewById(R.id.toCurrencySpinner);
resultText = findViewById(R.id.resultText);
exchangeRateText = findViewById(R.id.exchangeRateText);
// Botão limpar histórico - linha 95
clearHistoryButton = findViewById(R.id.clearHistoryButton);
historyListView = findViewById(R.id.historyListView);
// Botão trocar moedas - linha 98
swapButton = findViewById(R.id.swapButton);
// Botão abrir conversor de velocidade - linha 100
speedConverterButton = findViewById(R.id.speedConverterButton);
}
private void initializeCurrencyConverter() {
// Instancia o conversor e busca a lista de moedas disponíveis
currencyConverter = new CurrencyConverter(this);
currencies = currencyConverter.getAvailableCurrencies();
}
private void setupSpinners() {
// Criar lista de strings para os spinners
// Constrói a lista de textos que serão exibidos nos spinners
List<String> currencyStrings = new ArrayList<>();
for (Currency currency : currencies) {
currencyStrings.add(currency.toString());
}
// Adapter simples padrão Android para popular o spinner
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, currencyStrings);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@ -96,7 +121,7 @@ public class MainActivity extends AppCompatActivity {
fromCurrencySpinner.setAdapter(adapter);
toCurrencySpinner.setAdapter(adapter);
// Selecionar USD como padrão para origem e BRL para destino
// Define seleção inicial: USD como origem e BRL como destino
for (int i = 0; i < currencies.size(); i++) {
if (currencies.get(i).getCode().equals("USD")) {
fromCurrencySpinner.setSelection(i);
@ -106,7 +131,7 @@ public class MainActivity extends AppCompatActivity {
}
}
// Atualizar conversão quando as moedas mudarem
// Recalcula quando o usuário altera a moeda de origem
fromCurrencySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -120,6 +145,7 @@ public class MainActivity extends AppCompatActivity {
public void onNothingSelected(AdapterView<?> parent) {}
});
// Recalcula quando o usuário altera a moeda de destino
toCurrencySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -135,7 +161,8 @@ public class MainActivity extends AppCompatActivity {
}
private void setupListeners() {
// Conversão automática quando o texto muda
// ========== CONFIGURAÇÃO DOS LISTENERS DOS BOTÕES (o que acontece ao clicar) ==========
// Observa mudanças no campo de valor e recalcula automaticamente
amountInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@ -149,19 +176,19 @@ public class MainActivity extends AppCompatActivity {
}
});
// Botão de trocar moedas
// BOTÃO TROCAR MOEDAS - linha 180: ao clicar, chama swapCurrencies()
swapButton.setOnClickListener(v -> swapCurrencies());
// Botão limpar histórico
// BOTÃO LIMPAR HISTÓRICO - linha 183: ao clicar, chama clearHistory()
clearHistoryButton.setOnClickListener(v -> clearHistory());
// Botão conversor de velocidade
// BOTÃO CONVERSOR DE VELOCIDADE - linha 186: ao clicar, abre SpeedConverterActivity
speedConverterButton.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, SpeedConverterActivity.class);
startActivity(intent);
});
// Botão conversor de medidas
// BOTÃO CONVERSOR DE MEDIDAS - linha 192: ao clicar, abre MeasurementConverterActivity
MaterialButton measurementConverterButton = findViewById(R.id.measurementConverterButton);
measurementConverterButton.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, MeasurementConverterActivity.class);
@ -170,6 +197,7 @@ public class MainActivity extends AppCompatActivity {
}
private void updateConversion() {
// Validação básica do texto digitado
String amountString = amountInput.getText().toString().trim();
if (TextUtils.isEmpty(amountString)) {
@ -179,6 +207,7 @@ public class MainActivity extends AppCompatActivity {
}
try {
// Converte string para número e valida sinal
double amount = Double.parseDouble(amountString);
if (amount <= 0) {
@ -187,20 +216,21 @@ public class MainActivity extends AppCompatActivity {
return;
}
// Obtém moedas selecionadas e realiza a conversão
Currency fromCurrency = currencies.get(fromCurrencySpinner.getSelectedItemPosition());
Currency toCurrency = currencies.get(toCurrencySpinner.getSelectedItemPosition());
double result = currencyConverter.convert(amount, fromCurrency.getCode(), toCurrency.getCode());
// Mostrar resultado com animação
// Formata e exibe o resultado
String formattedResult = currencyConverter.formatCurrency(result, toCurrency.getCode());
resultText.setText(formattedResult);
resultText.setTextColor(getResources().getColor(R.color.primary_color));
// Animação suave
// Efeito visual simples para destacar atualização
resultText.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
// Salvar no histórico apenas se for uma conversão válida
// Persiste no histórico e atualiza a lista
if (amount > 0) {
currencyConverter.insertConversion(fromCurrency.getCode(), toCurrency.getCode(), amount, result);
loadHistory();
@ -216,6 +246,7 @@ public class MainActivity extends AppCompatActivity {
}
private void swapCurrencies() {
// Evita disparar listeners durante a troca programática
isUpdating = true;
int fromPosition = fromCurrencySpinner.getSelectedItemPosition();
@ -224,12 +255,12 @@ public class MainActivity extends AppCompatActivity {
fromCurrencySpinner.setSelection(toPosition);
toCurrencySpinner.setSelection(fromPosition);
// Animação do botão
// Realça o clique no botão de troca
swapButton.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
isUpdating = false;
// Atualizar conversão após a troca
// Recalcula e atualiza taxa após a troca
updateConversion();
updateExchangeRate();
@ -238,6 +269,7 @@ public class MainActivity extends AppCompatActivity {
private void updateExchangeRate() {
try {
// Calcula e exibe a taxa de câmbio 1:1 entre as moedas
Currency fromCurrency = currencies.get(fromCurrencySpinner.getSelectedItemPosition());
Currency toCurrency = currencies.get(toCurrencySpinner.getSelectedItemPosition());
@ -253,12 +285,14 @@ public class MainActivity extends AppCompatActivity {
}
private void loadHistory() {
// Consulta o banco e popula o adapter da ListView
List<Conversion> history = currencyConverter.getConversionHistory();
historyAdapter = new ConversionHistoryAdapter(this, history);
historyListView.setAdapter(historyAdapter);
}
private void clearHistory() {
// Apaga todos os registros da tabela de histórico
currencyConverter.clearHistory();
loadHistory();
Toast.makeText(this, "Histórico limpo", Toast.LENGTH_SHORT).show();

View File

@ -6,21 +6,25 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
// ======================= Conversor de Medidas =======================
public class MeasurementConverter {
// Nomes de categorias suportadas
private static final String CAT_LENGTH = "Comprimento";
private static final String CAT_WEIGHT = "Peso";
private static final String CAT_TEMPERATURE = "Temperatura";
// Unidades disponíveis por categoria
private static final List<String> LENGTH_UNITS = Arrays.asList("mm","cm","m","km","in","ft","yd","mi");
private static final List<String> WEIGHT_UNITS = Arrays.asList("mg","g","kg","t","oz","lb");
private static final List<String> TEMP_UNITS = Arrays.asList("°C","°F","K");
// Fatores para converter para a unidade base (metro e quilograma)
private static final Map<String, Double> LENGTH_TO_METER = new LinkedHashMap<>();
private static final Map<String, Double> WEIGHT_TO_KG = new LinkedHashMap<>();
static {
// Comprimento -> metros
// Comprimento -> fator para metros
LENGTH_TO_METER.put("mm", 0.001);
LENGTH_TO_METER.put("cm", 0.01);
LENGTH_TO_METER.put("m", 1.0);
@ -30,7 +34,7 @@ public class MeasurementConverter {
LENGTH_TO_METER.put("yd", 0.9144);
LENGTH_TO_METER.put("mi", 1609.344);
// Peso -> quilogramas
// Peso -> fator para quilogramas
WEIGHT_TO_KG.put("mg", 0.000001);
WEIGHT_TO_KG.put("g", 0.001);
WEIGHT_TO_KG.put("kg", 1.0);
@ -40,6 +44,7 @@ public class MeasurementConverter {
}
public List<String> getUnitsForCategory(String category) {
// Retorna a lista de unidades correspondente à categoria
if (CAT_LENGTH.equals(category)) return new ArrayList<>(LENGTH_UNITS);
if (CAT_WEIGHT.equals(category)) return new ArrayList<>(WEIGHT_UNITS);
if (CAT_TEMPERATURE.equals(category)) return new ArrayList<>(TEMP_UNITS);
@ -47,17 +52,20 @@ public class MeasurementConverter {
}
public double convert(String category, double value, String from, String to) {
// Atalho: mesma unidade não precisa converter
if (from.equals(to)) return value;
if (CAT_LENGTH.equals(category)) {
// Normaliza para metros e depois para a unidade destino
double meters = value * LENGTH_TO_METER.get(from);
return meters / LENGTH_TO_METER.get(to);
}
if (CAT_WEIGHT.equals(category)) {
// Normaliza para quilogramas e depois para a unidade destino
double kg = value * WEIGHT_TO_KG.get(from);
return kg / WEIGHT_TO_KG.get(to);
}
if (CAT_TEMPERATURE.equals(category)) {
// normalize to Celsius
// Normaliza para Celsius e reconverte
double c;
if ("°C".equals(from)) c = value;
else if ("°F".equals(from)) c = (value - 32.0) * 5.0 / 9.0;
@ -70,6 +78,7 @@ public class MeasurementConverter {
}
public double rate(String category, String from, String to) {
// Taxa unitária entre duas unidades (constante p/ comprimento/peso)
if (from.equals(to)) return 1.0;
if (CAT_LENGTH.equals(category)) {
return LENGTH_TO_METER.get(from) / LENGTH_TO_METER.get(to);
@ -78,16 +87,18 @@ public class MeasurementConverter {
return WEIGHT_TO_KG.get(from) / WEIGHT_TO_KG.get(to);
}
if (CAT_TEMPERATURE.equals(category)) {
// temperature rates aren't constant; show delta conversion for 1 unit
// Temperatura não tem fator constante; mostra conversão de 1 unidade
return convert(category, 1.0, from, to);
}
return 1.0;
}
public String format(String category, double value, String unit) {
// Formatação: temperatura com 2 casas, demais com 4
if (CAT_TEMPERATURE.equals(category)) {
return String.format("%.2f %s", value, unit);
}
return String.format("%.4f %s", value, unit);
}
}

View File

@ -22,16 +22,21 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// ======================= Conversor de Medidas =======================
public class MeasurementConverterActivity extends AppCompatActivity {
// Classe com as regras de negócio para medidas
private MeasurementConverter measurementConverter;
// Spinners para categoria (Comprimento/Peso/Temperatura) e unidades
private Spinner categorySpinner;
private Spinner fromUnitSpinner;
private Spinner toUnitSpinner;
// Campo de entrada e textos de resultado/taxa
private TextInputEditText amountInput;
private TextView resultText;
private TextView rateText;
// Lista de categorias suportadas
private List<String> categories;
@Override
@ -45,6 +50,7 @@ public class MeasurementConverterActivity extends AppCompatActivity {
return insets;
});
// Inicializa views e lógica e registra listeners
initializeViews();
initializeConverter();
setupCategorySpinner();
@ -52,6 +58,8 @@ public class MeasurementConverterActivity extends AppCompatActivity {
}
private void initializeViews() {
// ========== INICIALIZAÇÃO DOS BOTÕES (vincula com o layout XML) ==========
// Faz o bind das views do layout
categorySpinner = findViewById(R.id.categorySpinner);
fromUnitSpinner = findViewById(R.id.measureFromUnitSpinner);
toUnitSpinner = findViewById(R.id.measureToUnitSpinner);
@ -59,25 +67,31 @@ public class MeasurementConverterActivity extends AppCompatActivity {
resultText = findViewById(R.id.measureResultText);
rateText = findViewById(R.id.measureRateText);
// ========== CONFIGURAÇÃO DOS LISTENERS DOS BOTÕES (o que acontece ao clicar) ==========
// BOTÃO ABRIR CONVERSOR DE MOEDAS - linha 72: ao clicar, abre MainActivity
findViewById(R.id.openCurrencyConverterButton).setOnClickListener(v -> {
startActivity(new android.content.Intent(this, MainActivity.class));
});
// BOTÃO ABRIR CONVERSOR DE VELOCIDADE - linha 76: ao clicar, abre SpeedConverterActivity
findViewById(R.id.openSpeedConverterButton).setOnClickListener(v -> {
startActivity(new android.content.Intent(this, SpeedConverterActivity.class));
});
}
private void initializeConverter() {
// Instancia as regras e define categorias disponíveis
measurementConverter = new MeasurementConverter();
categories = new ArrayList<>(Arrays.asList("Comprimento", "Peso", "Temperatura"));
}
private void setupCategorySpinner() {
// Popula spinner de categorias
ArrayAdapter<String> categoryAdapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, categories);
categoryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
categorySpinner.setAdapter(categoryAdapter);
// Ao trocar a categoria, atualiza unidades, conversão e taxa
categorySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, android.view.View view, int position, long id) {
@ -91,6 +105,7 @@ public class MeasurementConverterActivity extends AppCompatActivity {
}
private void populateUnits() {
// Carrega unidades de acordo com a categoria selecionada e popular spinners
String category = (String) categorySpinner.getSelectedItem();
List<String> units = measurementConverter.getUnitsForCategory(category);
ArrayAdapter<String> unitsAdapter = new ArrayAdapter<>(this,
@ -98,10 +113,12 @@ public class MeasurementConverterActivity extends AppCompatActivity {
unitsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
fromUnitSpinner.setAdapter(unitsAdapter);
toUnitSpinner.setAdapter(unitsAdapter);
// Seleção inicial: primeira e segunda unidade da lista
if (!units.isEmpty()) {
fromUnitSpinner.setSelection(0);
toUnitSpinner.setSelection(Math.min(1, units.size() - 1));
}
// Reage a trocas de unidade
fromUnitSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, android.view.View view, int position, long id) {
@ -123,6 +140,7 @@ public class MeasurementConverterActivity extends AppCompatActivity {
}
private void setupListeners() {
// Observa mudanças no valor digitado e recalcula
amountInput.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {}
@ -131,6 +149,7 @@ public class MeasurementConverterActivity extends AppCompatActivity {
}
private void updateConversion() {
// Lê e valida o valor de entrada
String input = amountInput.getText() != null ? amountInput.getText().toString().trim() : "";
if (TextUtils.isEmpty(input)) {
resultText.setText("Digite um valor para converter");
@ -138,6 +157,7 @@ public class MeasurementConverterActivity extends AppCompatActivity {
return;
}
try {
// Aplica conversão conforme categoria e unidades selecionadas
double value = Double.parseDouble(input);
String category = (String) categorySpinner.getSelectedItem();
String from = (String) fromUnitSpinner.getSelectedItem();
@ -158,6 +178,7 @@ public class MeasurementConverterActivity extends AppCompatActivity {
private void updateRate() {
try {
// Exibe a taxa de conversão (constante p/ comprimento/peso e referencial p/ temperatura)
String category = (String) categorySpinner.getSelectedItem();
String from = (String) fromUnitSpinner.getSelectedItem();
String to = (String) toUnitSpinner.getSelectedItem();

View File

@ -4,8 +4,10 @@ import android.content.Context;
import java.util.ArrayList;
import java.util.List;
// ======================= Conversor de Velocidade =======================
public class SpeedConverter {
// Helper do banco (não usado para velocidade, mas mantido para consistência/expansão)
private DatabaseHelper dbHelper;
// Unidades de velocidade com fatores de conversão para m/s (metros por segundo)
@ -39,6 +41,7 @@ public class SpeedConverter {
return value;
}
// Obtém fatores de normalização para m/s
double fromFactor = getFactor(fromUnit);
double toFactor = getFactor(toUnit);
@ -46,7 +49,7 @@ public class SpeedConverter {
throw new IllegalArgumentException("Unidade não encontrada");
}
// Converter para m/s primeiro, depois para a unidade de destino
// Converte para m/s e em seguida para a unidade alvo
double valueInMs = value * fromFactor;
double result = valueInMs / toFactor;
@ -59,6 +62,7 @@ public class SpeedConverter {
* @return Fator de conversão
*/
private double getFactor(String unit) {
// Busca o fator correspondente ao símbolo informado
for (Object[] speedUnit : SPEED_UNITS) {
if (speedUnit[1].equals(unit)) {
return (Double) speedUnit[2];
@ -72,6 +76,7 @@ public class SpeedConverter {
* @return Lista de unidades
*/
public List<SpeedUnit> getAvailableUnits() {
// Constrói objetos de unidade a partir da tabela estática
List<SpeedUnit> units = new ArrayList<>();
for (Object[] speedUnit : SPEED_UNITS) {
units.add(new SpeedUnit(
@ -90,6 +95,7 @@ public class SpeedConverter {
* @return Objeto SpeedUnit ou null se não encontrado
*/
public SpeedUnit getUnitByCode(String code) {
// Retorna a unidade cujo símbolo corresponde ao código
for (Object[] speedUnit : SPEED_UNITS) {
if (speedUnit[1].equals(code)) {
return new SpeedUnit(
@ -110,6 +116,7 @@ public class SpeedConverter {
* @return String formatada
*/
public String formatSpeed(double value, String unitCode) {
// Formata com 2 casas e anexa o símbolo da unidade
SpeedUnit unit = getUnitByCode(unitCode);
if (unit != null) {
return String.format("%.2f %s", value, unit.getSymbol());
@ -128,6 +135,7 @@ public class SpeedConverter {
return 1.0;
}
// Razão direta entre fatores para m/s
double fromFactor = getFactor(fromUnit);
double toFactor = getFactor(toUnit);
@ -143,6 +151,7 @@ public class SpeedConverter {
* @return Lista de exemplos
*/
public List<String> getExamples() {
// Exemplos didáticos para demonstrar conversões comuns
List<String> examples = new ArrayList<>();
examples.add("🚗 100 km/h = 27.78 m/s");
examples.add("✈️ 500 mph = 223.52 m/s");

View File

@ -24,17 +24,25 @@ import com.google.android.material.textfield.TextInputEditText;
import java.util.ArrayList;
import java.util.List;
// ======================= Conversor de Velocidade =======================
public class SpeedConverterActivity extends AppCompatActivity {
// Classe responsável por converter valores entre unidades de velocidade
private SpeedConverter speedConverter;
// Campo de entrada do valor de velocidade
private TextInputEditText speedAmountInput;
// Spinners para selecionar unidade de origem e destino
private Spinner fromSpeedSpinner;
private Spinner toSpeedSpinner;
// Textos para exibir resultado e taxa
private TextView speedResultText;
private TextView speedRateText;
// ========== DECLARAÇÃO DOS BOTÕES (variáveis de classe) ==========
// Botão para inverter unidades
private ImageView speedSwapButton;
// Lista de unidades disponíveis (com símbolo, nome e fator)
private List<SpeedUnit> speedUnits;
// Flag de controle para evitar eventos durante trocas programáticas
private boolean isUpdating = false;
@Override
@ -47,9 +55,11 @@ public class SpeedConverterActivity extends AppCompatActivity {
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
// Removida Toolbar!
// ========== BOTÃO VOLTAR (configurado diretamente no onCreate) ==========
// Botão para voltar ao conversor de moedas (fecha a tela) - linha 58
findViewById(R.id.currencyConverterButton).setOnClickListener(v -> finish());
// Inicializa views, lógica e listeners
initializeViews();
initializeSpeedConverter();
setupSpinners();
@ -57,26 +67,31 @@ public class SpeedConverterActivity extends AppCompatActivity {
}
private void initializeViews() {
// ========== INICIALIZAÇÃO DOS BOTÕES (vincula com o layout XML) ==========
// Faz o bind das views do layout
speedAmountInput = findViewById(R.id.speedAmountInput);
fromSpeedSpinner = findViewById(R.id.speedFromUnitSpinner);
toSpeedSpinner = findViewById(R.id.speedToUnitSpinner);
speedResultText = findViewById(R.id.speedResultText);
speedRateText = findViewById(R.id.speedRateText);
// Botão trocar unidades - linha 78
speedSwapButton = findViewById(R.id.speedSwapButton);
}
private void initializeSpeedConverter() {
// Instancia o conversor e carrega unidades disponíveis
speedConverter = new SpeedConverter(this);
speedUnits = speedConverter.getAvailableUnits();
}
private void setupSpinners() {
// Criar lista de strings para os spinners
// Cria a lista textual para exibir cada unidade no spinner
List<String> unitStrings = new ArrayList<>();
for (SpeedUnit unit : speedUnits) {
unitStrings.add(unit.toString());
}
// Usa adapter simples padrão do Android
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, unitStrings);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@ -84,7 +99,7 @@ public class SpeedConverterActivity extends AppCompatActivity {
fromSpeedSpinner.setAdapter(adapter);
toSpeedSpinner.setAdapter(adapter);
// Selecionar m/s como padrão para origem e km/h para destino
// Define seleção inicial: m/s como origem e km/h como destino
for (int i = 0; i < speedUnits.size(); i++) {
if (speedUnits.get(i).getSymbol().equals("m/s")) {
fromSpeedSpinner.setSelection(i);
@ -94,7 +109,7 @@ public class SpeedConverterActivity extends AppCompatActivity {
}
}
// Atualizar conversão quando as unidades mudarem
// Recalcula quando a unidade de origem muda
fromSpeedSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -108,6 +123,7 @@ public class SpeedConverterActivity extends AppCompatActivity {
public void onNothingSelected(AdapterView<?> parent) {}
});
// Recalcula quando a unidade de destino muda
toSpeedSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -123,7 +139,8 @@ public class SpeedConverterActivity extends AppCompatActivity {
}
private void setupListeners() {
// Conversão automática quando o texto muda
// ========== CONFIGURAÇÃO DOS LISTENERS DOS BOTÕES (o que acontece ao clicar) ==========
// Observa alterações no campo de texto e recalcula automaticamente
speedAmountInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@ -137,11 +154,12 @@ public class SpeedConverterActivity extends AppCompatActivity {
}
});
// Botão de trocar unidades
// BOTÃO TROCAR UNIDADES - linha 157: ao clicar, chama swapUnits()
speedSwapButton.setOnClickListener(v -> swapUnits());
}
private void updateConversion() {
// Lê e valida o valor digitado
String amountString = speedAmountInput.getText().toString().trim();
if (TextUtils.isEmpty(amountString)) {
@ -151,6 +169,7 @@ public class SpeedConverterActivity extends AppCompatActivity {
}
try {
// Converte para número e valida sinal (não negativo)
double amount = Double.parseDouble(amountString);
if (amount < 0) {
@ -159,17 +178,18 @@ public class SpeedConverterActivity extends AppCompatActivity {
return;
}
// Obtém as unidades selecionadas e delega a conversão para a classe de regras
SpeedUnit fromUnit = speedUnits.get(fromSpeedSpinner.getSelectedItemPosition());
SpeedUnit toUnit = speedUnits.get(toSpeedSpinner.getSelectedItemPosition());
double result = speedConverter.convert(amount, fromUnit.getSymbol(), toUnit.getSymbol());
// Mostrar resultado com animação
// Formata e exibe o resultado da conversão
String formattedResult = speedConverter.formatSpeed(result, toUnit.getSymbol());
speedResultText.setText(formattedResult);
speedResultText.setTextColor(getResources().getColor(R.color.accent_color));
// Animação suave
// Efeito visual simples para indicar atualização
speedResultText.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
} catch (NumberFormatException e) {
@ -182,6 +202,7 @@ public class SpeedConverterActivity extends AppCompatActivity {
}
private void swapUnits() {
// Evita disparar eventos durante troca programática
isUpdating = true;
int fromPosition = fromSpeedSpinner.getSelectedItemPosition();
@ -190,18 +211,19 @@ public class SpeedConverterActivity extends AppCompatActivity {
fromSpeedSpinner.setSelection(toPosition);
toSpeedSpinner.setSelection(fromPosition);
// Animação do botão
// Feedback visual do clique
speedSwapButton.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
isUpdating = false;
// Atualizar conversão após a troca
// Recalcula valores e taxa após a troca
updateConversion();
updateRate();
}
private void updateRate() {
try {
// Calcula a taxa de conversão entre as unidades selecionadas
SpeedUnit fromUnit = speedUnits.get(fromSpeedSpinner.getSelectedItemPosition());
SpeedUnit toUnit = speedUnits.get(toSpeedSpinner.getSelectedItemPosition());

View File

@ -1,9 +1,14 @@
package com.example.conversordemoedas2;
// ======================= Conversor de Velocidade =======================
public class SpeedUnit {
// Identificador interno
private int id;
// Símbolo curto da unidade (ex.: km/h)
private String symbol;
// Nome descritivo (ex.: Quilômetros por hora)
private String name;
// Fator para converter para m/s
private double factorToMs;
public SpeedUnit(int id, String symbol, String name, double factorToMs) {
@ -27,6 +32,7 @@ public class SpeedUnit {
@Override
public String toString() {
// Exibe símbolo e nome, usado nos spinners
return symbol + " - " + name;
}
}
@ -34,3 +40,4 @@ public class SpeedUnit {

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/primary_color" />
<stroke android:width="2dp" android:color="@color/white" />
</shape>

View File

@ -9,3 +9,5 @@
android:pathData="M20,11H7.83l5.58-5.59L12,4l-8,8 8,8 1.41-1.41L7.83,13H20v-2z"/>
</vector>

View File

@ -13,3 +13,5 @@

View File

@ -58,40 +58,29 @@
</androidx.cardview.widget.CardView>
<!-- Botões de navegação -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<com.google.android.material.button.MaterialButton
android:id="@+id/openCurrencyConverterButton"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginBottom="8dp"
android:text="💱 Conversor de Moedas"
android:textSize="14sp"
android:textSize="16sp"
android:textStyle="bold"
android:padding="14dp"
android:padding="16dp"
app:cornerRadius="12dp"
app:backgroundTint="@color/primary_color" />
<View
android:layout_width="8dp"
android:layout_height="0dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/openSpeedConverterButton"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginBottom="20dp"
android:text="🏃 Conversor de Velocidade"
android:textSize="14sp"
android:textSize="16sp"
android:textStyle="bold"
android:padding="14dp"
android:padding="16dp"
app:cornerRadius="12dp"
app:backgroundTint="@color/accent_color" />
</LinearLayout>
<!-- Categoria -->
<androidx.cardview.widget.CardView

View File

@ -163,7 +163,7 @@
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="8dp"
android:src="@drawable/ic_swap"
android:background="@drawable/circle_background_speed"
android:background="@drawable/circle_background"
android:padding="12dp"
android:contentDescription="Trocar unidades" />