ia
This commit is contained in:
@@ -13,6 +13,9 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.LifeGrid">
|
||||
<activity
|
||||
android:name=".DocumentosActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".DefinicoesActivity"
|
||||
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 -> {
|
||||
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 androidx.activity.result.ActivityResultLauncher<android.net.Uri> takePictureLauncher;
|
||||
private android.net.Uri currentPhotoUri;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -70,7 +73,18 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
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);
|
||||
tvHeaderUsername = findViewById(R.id.tvHeaderUsername);
|
||||
|
||||
@@ -141,6 +155,55 @@ public class TelaInicialActivity extends AppCompatActivity {
|
||||
startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
protected void onResume() {
|
||||
|
||||
@@ -74,6 +74,15 @@ public class TransacoesFragment extends Fragment {
|
||||
Button novaTransacaoButton = root.findViewById(R.id.novaTransacaoButton);
|
||||
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);
|
||||
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
|
||||
* 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());
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_nova_transacao, null);
|
||||
builder.setView(dialogView);
|
||||
@@ -154,6 +167,9 @@ public class TransacoesFragment extends Fragment {
|
||||
btnFechar.setOnClickListener(v -> dialog.dismiss());
|
||||
|
||||
EditText etData = dialogView.findViewById(R.id.etData);
|
||||
if (!defaultData.isEmpty()) {
|
||||
etData.setText(defaultData);
|
||||
}
|
||||
etData.setOnClickListener(v -> {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
int year = calendar.get(Calendar.YEAR);
|
||||
@@ -170,7 +186,13 @@ public class TransacoesFragment extends Fragment {
|
||||
|
||||
Button btnAdicionarTransacao = dialogView.findViewById(R.id.btnAdicionarTransacao);
|
||||
EditText etValor = dialogView.findViewById(R.id.etValor);
|
||||
if (defaultValor > 0) {
|
||||
etValor.setText(String.valueOf(defaultValor));
|
||||
}
|
||||
EditText etDescricao = dialogView.findViewById(R.id.etDescricao);
|
||||
if (!defaultDescricao.isEmpty()) {
|
||||
etDescricao.setText(defaultDescricao);
|
||||
}
|
||||
Spinner spinnerCategoria = dialogView.findViewById(R.id.spinnerCategoria);
|
||||
Spinner spinnerTipo = dialogView.findViewById(R.id.spinnerTipo);
|
||||
|
||||
@@ -182,12 +204,26 @@ public class TransacoesFragment extends Fragment {
|
||||
arrayResId, android.R.layout.simple_spinner_item);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
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
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
|
||||
// Se vier da IA (geralmente despesa)
|
||||
if (!defaultDescricao.isEmpty()) {
|
||||
spinnerTipo.setSelection(1); // Despesa default para faturas
|
||||
}
|
||||
|
||||
btnAdicionarTransacao.setOnClickListener(v -> {
|
||||
String valor = etValor.getText().toString().trim();
|
||||
|
||||
@@ -196,6 +196,22 @@
|
||||
android:padding="16dp"
|
||||
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
|
||||
android:id="@+id/tvTerms"
|
||||
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>
|
||||
</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>
|
||||
@@ -21,11 +21,12 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:text="Ativos e Investimentos"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
android:textAlignment="center"
|
||||
android:textColor="#000000"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.501"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
android:layout_marginTop="50dp"
|
||||
android:text="Metas Financeiras"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="sans-serif"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.147"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:text="Transações"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.501"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -57,7 +57,7 @@
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:backgroundTint="@color/preto"
|
||||
android:text="Escanear Fatura"
|
||||
android:text="Digitalizar Fatura"
|
||||
app:cornerRadius="10sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView12" />
|
||||
|
||||
Reference in New Issue
Block a user