ia
This commit is contained in:
@@ -58,6 +58,8 @@ dependencies {
|
|||||||
implementation(libs.ui.tooling.preview)
|
implementation(libs.ui.tooling.preview)
|
||||||
implementation(libs.material3)
|
implementation(libs.material3)
|
||||||
implementation(libs.material3.adaptive.navigation.suite)
|
implementation(libs.material3.adaptive.navigation.suite)
|
||||||
|
implementation("com.google.ai.client.generativeai:generativeai:0.7.0")
|
||||||
|
implementation("com.google.guava:guava:31.1-android")
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.LifeGrid">
|
android:theme="@style/Theme.LifeGrid">
|
||||||
|
<activity
|
||||||
|
android:name=".DocumentosActivity"
|
||||||
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".DefinicoesActivity"
|
android:name=".DefinicoesActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|||||||
@@ -108,6 +108,14 @@ public class DefinicoesActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextView tvDocuments = findViewById(R.id.tvDocuments);
|
||||||
|
if (tvDocuments != null) {
|
||||||
|
tvDocuments.setOnClickListener(v -> {
|
||||||
|
Intent intent = new Intent(DefinicoesActivity.this, DocumentosActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> {
|
btnBack.setOnClickListener(v -> {
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package com.example.lifegrid;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
|
public class DocumentosActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private ImageView btnBack;
|
||||||
|
private LinearLayout llDocumentsList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
setContentView(R.layout.activity_documentos);
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
|
||||||
|
btnBack = findViewById(R.id.btnBack);
|
||||||
|
llDocumentsList = findViewById(R.id.llDocumentsList);
|
||||||
|
|
||||||
|
btnBack.setOnClickListener(v -> finish());
|
||||||
|
|
||||||
|
loadDocuments();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadDocuments() {
|
||||||
|
SharedPreferences prefs = getSharedPreferences("LifeGridDocs", Context.MODE_PRIVATE);
|
||||||
|
int count = prefs.getInt("doc_count", 0);
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
TextView emptyText = new TextView(this);
|
||||||
|
emptyText.setText("Nenhum documento guardado.");
|
||||||
|
emptyText.setPadding(32, 32, 32, 32);
|
||||||
|
llDocumentsList.addView(emptyText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
String uriString = prefs.getString("doc_uri_" + i, "");
|
||||||
|
String desc = prefs.getString("doc_desc_" + i, "Sem descrição");
|
||||||
|
String data = prefs.getString("doc_data_" + i, "Sem data");
|
||||||
|
|
||||||
|
LinearLayout itemLayout = new LinearLayout(this);
|
||||||
|
itemLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
itemLayout.setPadding(16, 16, 16, 16);
|
||||||
|
|
||||||
|
ImageView ivDoc = new ImageView(this);
|
||||||
|
ivDoc.setLayoutParams(new LinearLayout.LayoutParams(200, 200));
|
||||||
|
ivDoc.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||||
|
try {
|
||||||
|
ivDoc.setImageURI(Uri.parse(uriString));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearLayout textLayout = new LinearLayout(this);
|
||||||
|
textLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
textLayout.setPadding(16, 0, 0, 0);
|
||||||
|
|
||||||
|
TextView tvDesc = new TextView(this);
|
||||||
|
tvDesc.setText(desc);
|
||||||
|
tvDesc.setTextSize(16);
|
||||||
|
tvDesc.setTypeface(null, android.graphics.Typeface.BOLD);
|
||||||
|
|
||||||
|
TextView tvData = new TextView(this);
|
||||||
|
tvData.setText(data);
|
||||||
|
|
||||||
|
textLayout.addView(tvDesc);
|
||||||
|
textLayout.addView(tvData);
|
||||||
|
|
||||||
|
itemLayout.addView(ivDoc);
|
||||||
|
itemLayout.addView(textLayout);
|
||||||
|
|
||||||
|
llDocumentsList.addView(itemLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package com.example.lifegrid;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.ai.client.generativeai.GenerativeModel;
|
||||||
|
import com.google.ai.client.generativeai.java.GenerativeModelFutures;
|
||||||
|
import com.google.ai.client.generativeai.type.Content;
|
||||||
|
import com.google.ai.client.generativeai.type.GenerateContentResponse;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class InvoiceScannerHelper {
|
||||||
|
|
||||||
|
private static final String API_KEY = "YOUR_GEMINI_API_KEY_HERE"; // Substitua pela sua chave API
|
||||||
|
private static final String PROMPT = "Analisa esta fatura. Devolve APENAS um objeto JSON com os campos: 'valor' (Double, apenas números e ponto decimal), 'descricao' (String curta, nome do estabelecimento ou produto), 'categoria' (String, ex: Alimentação, Transporte, Lazer, Saúde, Casa, Educação, Outros), e 'data' (String formato DD/MM/AAAA). Se não conseguires ler algum, coloca valor padrão ou string vazia.";
|
||||||
|
|
||||||
|
public interface ScanCallback {
|
||||||
|
void onSuccess(double valor, String descricao, String categoria, String data);
|
||||||
|
void onError(String error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void scanInvoice(Context context, Uri imageUri, ScanCallback callback) {
|
||||||
|
if (API_KEY.equals("YOUR_GEMINI_API_KEY_HERE")) {
|
||||||
|
callback.onError("Chave API do Gemini não configurada.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
InputStream imageStream = context.getContentResolver().openInputStream(imageUri);
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
|
||||||
|
|
||||||
|
GenerativeModel gm = new GenerativeModel(
|
||||||
|
"gemini-1.5-flash",
|
||||||
|
API_KEY
|
||||||
|
);
|
||||||
|
GenerativeModelFutures model = GenerativeModelFutures.from(gm);
|
||||||
|
|
||||||
|
Content content = new Content.Builder()
|
||||||
|
.addText(PROMPT)
|
||||||
|
.addImage(bitmap)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
|
||||||
|
|
||||||
|
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(GenerateContentResponse result) {
|
||||||
|
try {
|
||||||
|
String textResponse = result.getText();
|
||||||
|
if (textResponse != null) {
|
||||||
|
textResponse = textResponse.replace("```json", "").replace("```", "").trim();
|
||||||
|
JSONObject json = new JSONObject(textResponse);
|
||||||
|
double valor = json.optDouble("valor", 0.0);
|
||||||
|
String descricao = json.optString("descricao", "");
|
||||||
|
String categoria = json.optString("categoria", "Outros");
|
||||||
|
String data = json.optString("data", "");
|
||||||
|
callback.onSuccess(valor, descricao, categoria, data);
|
||||||
|
} else {
|
||||||
|
callback.onError("Resposta vazia da IA.");
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e("InvoiceScanner", "Erro ao fazer parse do JSON: " + result.getText(), e);
|
||||||
|
callback.onError("Erro ao ler dados da fatura.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
Log.e("InvoiceScanner", "Falha na API do Gemini", t);
|
||||||
|
callback.onError("Falha ao comunicar com a IA: " + t.getMessage());
|
||||||
|
}
|
||||||
|
}, executor);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
callback.onError("Erro ao processar imagem: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,9 @@ public class TelaInicialActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private String[] meses = {"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"};
|
private String[] meses = {"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"};
|
||||||
|
|
||||||
|
private androidx.activity.result.ActivityResultLauncher<android.net.Uri> takePictureLauncher;
|
||||||
|
private android.net.Uri currentPhotoUri;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -70,6 +73,17 @@ public class TelaInicialActivity extends AppCompatActivity {
|
|||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
takePictureLauncher = registerForActivityResult(
|
||||||
|
new androidx.activity.result.contract.ActivityResultContracts.TakePicture(),
|
||||||
|
success -> {
|
||||||
|
if (success) {
|
||||||
|
processInvoiceImage(currentPhotoUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
com.google.android.material.floatingactionbutton.FloatingActionButton fabScanInvoice = findViewById(R.id.fabScanInvoice);
|
||||||
|
fabScanInvoice.setOnClickListener(v -> startInvoiceScan());
|
||||||
|
|
||||||
ivHeaderProfilePicture = findViewById(R.id.ivHeaderProfilePicture);
|
ivHeaderProfilePicture = findViewById(R.id.ivHeaderProfilePicture);
|
||||||
tvHeaderUsername = findViewById(R.id.tvHeaderUsername);
|
tvHeaderUsername = findViewById(R.id.tvHeaderUsername);
|
||||||
@@ -142,6 +156,55 @@ public class TelaInicialActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startInvoiceScan() {
|
||||||
|
java.io.File photoFile = new java.io.File(getFilesDir(), "invoice_" + System.currentTimeMillis() + ".jpg");
|
||||||
|
currentPhotoUri = androidx.core.content.FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile);
|
||||||
|
takePictureLauncher.launch(currentPhotoUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processInvoiceImage(android.net.Uri imageUri) {
|
||||||
|
Toast.makeText(this, "A processar fatura com IA...", Toast.LENGTH_LONG).show();
|
||||||
|
InvoiceScannerHelper.scanInvoice(this, imageUri, new InvoiceScannerHelper.ScanCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(double valor, String descricao, String categoria, String data) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
|
||||||
|
TransacoesFragment transFragment;
|
||||||
|
if (currentFragment instanceof TransacoesFragment) {
|
||||||
|
transFragment = (TransacoesFragment) currentFragment;
|
||||||
|
} else {
|
||||||
|
updateNavSelection(findViewById(R.id.carteiraImageView));
|
||||||
|
transFragment = new TransacoesFragment();
|
||||||
|
getSupportFragmentManager().beginTransaction()
|
||||||
|
.replace(R.id.fragmentContainerView, transFragment)
|
||||||
|
.commit();
|
||||||
|
getSupportFragmentManager().executePendingTransactions();
|
||||||
|
}
|
||||||
|
transFragment.showNovaTransacaoDialog(valor, descricao, categoria, data);
|
||||||
|
|
||||||
|
// Save document to shared preferences or database
|
||||||
|
saveDocument(imageUri.toString(), descricao, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(String error) {
|
||||||
|
runOnUiThread(() -> Toast.makeText(TelaInicialActivity.this, error, Toast.LENGTH_LONG).show());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveDocument(String uriString, String descricao, String data) {
|
||||||
|
SharedPreferences prefs = getSharedPreferences("LifeGridDocs", Context.MODE_PRIVATE);
|
||||||
|
int count = prefs.getInt("doc_count", 0);
|
||||||
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
editor.putString("doc_uri_" + count, uriString);
|
||||||
|
editor.putString("doc_desc_" + count, descricao);
|
||||||
|
editor.putString("doc_data_" + count, data);
|
||||||
|
editor.putInt("doc_count", count + 1);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|||||||
@@ -74,6 +74,15 @@ public class TransacoesFragment extends Fragment {
|
|||||||
Button novaTransacaoButton = root.findViewById(R.id.novaTransacaoButton);
|
Button novaTransacaoButton = root.findViewById(R.id.novaTransacaoButton);
|
||||||
novaTransacaoButton.setOnClickListener(v -> showNovaTransacaoDialog());
|
novaTransacaoButton.setOnClickListener(v -> showNovaTransacaoDialog());
|
||||||
|
|
||||||
|
Button escanearTransacaoButton = root.findViewById(R.id.escanearTransacaoButton);
|
||||||
|
if (escanearTransacaoButton != null) {
|
||||||
|
escanearTransacaoButton.setOnClickListener(v -> {
|
||||||
|
if (getActivity() instanceof com.example.lifegrid.TelaInicialActivity) {
|
||||||
|
((com.example.lifegrid.TelaInicialActivity) getActivity()).startInvoiceScan();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
rvTransacoes = root.findViewById(R.id.rvTransacoes);
|
rvTransacoes = root.findViewById(R.id.rvTransacoes);
|
||||||
tvEmptyState = root.findViewById(R.id.textView13);
|
tvEmptyState = root.findViewById(R.id.textView13);
|
||||||
|
|
||||||
@@ -136,11 +145,15 @@ public class TransacoesFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showNovaTransacaoDialog() {
|
||||||
|
showNovaTransacaoDialog(0.0, "", "", "");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cria e monta manualmente uma janela Modal (Pop-up) a fim do utilizador preencher
|
* Cria e monta manualmente uma janela Modal (Pop-up) a fim do utilizador preencher
|
||||||
* os detalhes referentes a uma recém aquisição de receita ou encargo para alimentar a base de dados.
|
* os detalhes referentes a uma recém aquisição de receita ou encargo para alimentar a base de dados.
|
||||||
*/
|
*/
|
||||||
private void showNovaTransacaoDialog() {
|
public void showNovaTransacaoDialog(double defaultValor, String defaultDescricao, String defaultCategoria, String defaultData) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_nova_transacao, null);
|
View dialogView = getLayoutInflater().inflate(R.layout.dialog_nova_transacao, null);
|
||||||
builder.setView(dialogView);
|
builder.setView(dialogView);
|
||||||
@@ -154,6 +167,9 @@ public class TransacoesFragment extends Fragment {
|
|||||||
btnFechar.setOnClickListener(v -> dialog.dismiss());
|
btnFechar.setOnClickListener(v -> dialog.dismiss());
|
||||||
|
|
||||||
EditText etData = dialogView.findViewById(R.id.etData);
|
EditText etData = dialogView.findViewById(R.id.etData);
|
||||||
|
if (!defaultData.isEmpty()) {
|
||||||
|
etData.setText(defaultData);
|
||||||
|
}
|
||||||
etData.setOnClickListener(v -> {
|
etData.setOnClickListener(v -> {
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
int year = calendar.get(Calendar.YEAR);
|
int year = calendar.get(Calendar.YEAR);
|
||||||
@@ -170,7 +186,13 @@ public class TransacoesFragment extends Fragment {
|
|||||||
|
|
||||||
Button btnAdicionarTransacao = dialogView.findViewById(R.id.btnAdicionarTransacao);
|
Button btnAdicionarTransacao = dialogView.findViewById(R.id.btnAdicionarTransacao);
|
||||||
EditText etValor = dialogView.findViewById(R.id.etValor);
|
EditText etValor = dialogView.findViewById(R.id.etValor);
|
||||||
|
if (defaultValor > 0) {
|
||||||
|
etValor.setText(String.valueOf(defaultValor));
|
||||||
|
}
|
||||||
EditText etDescricao = dialogView.findViewById(R.id.etDescricao);
|
EditText etDescricao = dialogView.findViewById(R.id.etDescricao);
|
||||||
|
if (!defaultDescricao.isEmpty()) {
|
||||||
|
etDescricao.setText(defaultDescricao);
|
||||||
|
}
|
||||||
Spinner spinnerCategoria = dialogView.findViewById(R.id.spinnerCategoria);
|
Spinner spinnerCategoria = dialogView.findViewById(R.id.spinnerCategoria);
|
||||||
Spinner spinnerTipo = dialogView.findViewById(R.id.spinnerTipo);
|
Spinner spinnerTipo = dialogView.findViewById(R.id.spinnerTipo);
|
||||||
|
|
||||||
@@ -182,6 +204,15 @@ public class TransacoesFragment extends Fragment {
|
|||||||
arrayResId, android.R.layout.simple_spinner_item);
|
arrayResId, android.R.layout.simple_spinner_item);
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
spinnerCategoria.setAdapter(adapter);
|
spinnerCategoria.setAdapter(adapter);
|
||||||
|
|
||||||
|
if (!defaultCategoria.isEmpty()) {
|
||||||
|
for (int i = 0; i < adapter.getCount(); i++) {
|
||||||
|
if (adapter.getItem(i).toString().equalsIgnoreCase(defaultCategoria)) {
|
||||||
|
spinnerCategoria.setSelection(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -189,6 +220,11 @@ public class TransacoesFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Se vier da IA (geralmente despesa)
|
||||||
|
if (!defaultDescricao.isEmpty()) {
|
||||||
|
spinnerTipo.setSelection(1); // Despesa default para faturas
|
||||||
|
}
|
||||||
|
|
||||||
btnAdicionarTransacao.setOnClickListener(v -> {
|
btnAdicionarTransacao.setOnClickListener(v -> {
|
||||||
String valor = etValor.getText().toString().trim();
|
String valor = etValor.getText().toString().trim();
|
||||||
String descricao = etDescricao.getText().toString().trim();
|
String descricao = etDescricao.getText().toString().trim();
|
||||||
|
|||||||
@@ -196,6 +196,22 @@
|
|||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:layout_marginBottom="32dp">
|
android:layout_marginBottom="32dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDocuments"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Meus Documentos (Faturas)"
|
||||||
|
android:textColor="@color/preto"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:paddingVertical="8dp" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#E0E0E0"
|
||||||
|
android:layout_marginVertical="4dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTerms"
|
android:id="@+id/tvTerms"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
58
app/src/main/res/layout/activity_documentos.xml
Normal file
58
app/src/main/res/layout/activity_documentos.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/branco"
|
||||||
|
tools:context=".DocumentosActivity">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/headerLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/btnBack"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:src="@drawable/diagonalarrowleftdownoutline_110924"
|
||||||
|
app:tint="@color/preto"
|
||||||
|
android:rotation="45"
|
||||||
|
android:padding="4dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Meus Documentos"
|
||||||
|
android:textColor="@color/preto"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/headerLayout">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llDocumentsList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp" />
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -229,6 +229,16 @@
|
|||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/fabScanInvoice"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
android:src="@android:drawable/ic_menu_camera"
|
||||||
|
app:backgroundTint="@color/preto"
|
||||||
|
app:tint="@color/branco"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -21,11 +21,12 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="32dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
android:text="Ativos e Investimentos"
|
android:text="Ativos e Investimentos"
|
||||||
android:textSize="25sp"
|
android:textAlignment="center"
|
||||||
android:textStyle="bold"
|
android:textColor="#000000"
|
||||||
|
android:textSize="24sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.501"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
android:layout_marginTop="50dp"
|
android:layout_marginTop="50dp"
|
||||||
android:text="Metas Financeiras"
|
android:text="Metas Financeiras"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold"
|
android:fontFamily="sans-serif"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.147"
|
app:layout_constraintHorizontal_bias="0.147"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|||||||
@@ -30,9 +30,9 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="32dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
android:text="Transações"
|
android:text="Transações"
|
||||||
android:textSize="25sp"
|
android:textSize="25sp"
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.501"
|
app:layout_constraintHorizontal_bias="0.501"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
android:layout_marginEnd="25dp"
|
android:layout_marginEnd="25dp"
|
||||||
android:backgroundTint="@color/preto"
|
android:backgroundTint="@color/preto"
|
||||||
android:text="Escanear Fatura"
|
android:text="Digitalizar Fatura"
|
||||||
app:cornerRadius="10sp"
|
app:cornerRadius="10sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/textView12" />
|
app:layout_constraintTop_toBottomOf="@+id/textView12" />
|
||||||
|
|||||||
Reference in New Issue
Block a user