melhoramento da app

main
230421 2025-12-06 22:26:42 +00:00
parent 460b719785
commit 4b766067f4
6 changed files with 332 additions and 173 deletions

View File

@ -30,12 +30,14 @@ public class CriarContaActivity extends AppCompatActivity {
}); });
TextInputEditText editPassword2; TextInputEditText editPassword2;
TextInputEditText editEmail; TextInputEditText editEmail;
TextInputEditText editUserName;
TextInputEditText editConfirmPassword; TextInputEditText editConfirmPassword;
Button btnCreateAccount; Button btnCreateAccount;
TextView txtGoLogin; TextView txtGoLogin;
editEmail = findViewById(R.id.editEmail); editEmail = findViewById(R.id.editEmail);
editUserName = findViewById(R.id.editUserName);
editPassword2 = findViewById(R.id.editPassword2); editPassword2 = findViewById(R.id.editPassword2);
editConfirmPassword = findViewById(R.id.editConfirmPassword); editConfirmPassword = findViewById(R.id.editConfirmPassword);
btnCreateAccount = findViewById(R.id.btnCreateAccount); btnCreateAccount = findViewById(R.id.btnCreateAccount);
@ -46,10 +48,11 @@ public class CriarContaActivity extends AppCompatActivity {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
String email = editEmail.getText().toString().trim(); String email = editEmail.getText().toString().trim();
String userName = editUserName.getText().toString().trim();
String pass = editPassword2.getText().toString().trim(); String pass = editPassword2.getText().toString().trim();
String conf = editConfirmPassword.getText().toString().trim(); String conf = editConfirmPassword.getText().toString().trim();
if (email.isEmpty() || pass.isEmpty() || conf.isEmpty()) { if (email.isEmpty() || userName.isEmpty() || pass.isEmpty() || conf.isEmpty()) {
Toast.makeText(CriarContaActivity.this, "Preencha todos os campos!", Toast.LENGTH_SHORT).show(); Toast.makeText(CriarContaActivity.this, "Preencha todos os campos!", Toast.LENGTH_SHORT).show();
return; return;
} }
@ -62,10 +65,24 @@ public class CriarContaActivity extends AppCompatActivity {
FirebaseAuth auth = FirebaseAuth.getInstance(); FirebaseAuth auth = FirebaseAuth.getInstance();
auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this, task -> { auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this, task -> {
if (task.isSuccessful()) { if (task.isSuccessful()) {
// Atualizar nome de utilizador
com.google.firebase.auth.FirebaseUser user = auth.getCurrentUser();
if (user != null) {
com.google.firebase.auth.UserProfileChangeRequest profileUpdates =
new com.google.firebase.auth.UserProfileChangeRequest.Builder()
.setDisplayName(userName)
.build();
Intent intent= new Intent(CriarContaActivity.this, MainActivity.class); user.updateProfile(profileUpdates).addOnCompleteListener(updateTask -> {
startActivity(intent); Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
finish(); startActivity(intent);
finish();
});
} else {
Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
} else { } else {
String errorMessage = "Erro ao criar conta!"; String errorMessage = "Erro ao criar conta!";
if (task.getException() != null && task.getException().getMessage() != null) { if (task.getException() != null && task.getException().getMessage() != null) {

View File

@ -67,7 +67,6 @@ public class MainActivity extends AppCompatActivity {
View headerView = binding.navView.getHeaderView(0); View headerView = binding.navView.getHeaderView(0);
TextView textViewName = headerView.findViewById(R.id.textViewName); TextView textViewName = headerView.findViewById(R.id.textViewName);
TextView textViewEmail = headerView.findViewById(R.id.textView);
ImageView imageView = headerView.findViewById(R.id.imageView); ImageView imageView = headerView.findViewById(R.id.imageView);
// Carregar nome // Carregar nome
@ -79,17 +78,14 @@ public class MainActivity extends AppCompatActivity {
} }
} }
// Carregar email
if (textViewEmail != null && user.getEmail() != null) {
textViewEmail.setText(user.getEmail());
}
// Carregar foto de perfil // Carregar foto de perfil
if (imageView != null && user.getPhotoUrl() != null) { if (imageView != null) {
loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView); if (user.getPhotoUrl() != null) {
} else { loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView);
// Tentar carregar do Storage } else {
loadProfileImageFromStorage(imageView); // Tentar carregar do Storage
loadProfileImageFromStorage(imageView);
}
} }
} }

View File

@ -1,6 +1,7 @@
package com.example.vdcscore.ui.definicoes; package com.example.vdcscore.ui.definicoes;
import android.Manifest; import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -46,8 +47,10 @@ public class ContaActivity extends AppCompatActivity {
private TextInputEditText editName; private TextInputEditText editName;
private TextInputEditText editImageUrl; private TextInputEditText editImageUrl;
private TextView textEmail; private TextView textEmail;
private Button btnSaveName; private Button btnSaveAll;
private Button btnLoadImageUrl; private Button btnLoadImageUrl;
private Button btnChangeEmail;
private Button btnChangePassword;
private Button btnLogout; private Button btnLogout;
private View btnChangePhoto; private View btnChangePhoto;
private View cardImageContainer; private View cardImageContainer;
@ -60,6 +63,7 @@ public class ContaActivity extends AppCompatActivity {
private ActivityResultLauncher<Intent> imagePickerLauncher; private ActivityResultLauncher<Intent> imagePickerLauncher;
private ActivityResultLauncher<String> permissionLauncher; private ActivityResultLauncher<String> permissionLauncher;
private Uri selectedImageUri; private Uri selectedImageUri;
private String imageUrlFromGoogle;
private static final String PREFS_NAME = "LoginPrefs"; private static final String PREFS_NAME = "LoginPrefs";
@ -95,8 +99,10 @@ public class ContaActivity extends AppCompatActivity {
editName = findViewById(R.id.editName); editName = findViewById(R.id.editName);
editImageUrl = findViewById(R.id.editImageUrl); editImageUrl = findViewById(R.id.editImageUrl);
textEmail = findViewById(R.id.textEmail); textEmail = findViewById(R.id.textEmail);
btnSaveName = findViewById(R.id.btnSaveName); btnSaveAll = findViewById(R.id.btnSaveAll);
btnLoadImageUrl = findViewById(R.id.btnLoadImageUrl); btnLoadImageUrl = findViewById(R.id.btnLoadImageUrl);
btnChangeEmail = findViewById(R.id.btnChangeEmail);
btnChangePassword = findViewById(R.id.btnChangePassword);
btnLogout = findViewById(R.id.btnLogout); btnLogout = findViewById(R.id.btnLogout);
btnChangePhoto = findViewById(R.id.btnChangePhoto); btnChangePhoto = findViewById(R.id.btnChangePhoto);
cardImageContainer = findViewById(R.id.cardImageContainer); cardImageContainer = findViewById(R.id.cardImageContainer);
@ -180,8 +186,6 @@ public class ContaActivity extends AppCompatActivity {
} }
private void loadProfileImage(String imageUrl) { private void loadProfileImage(String imageUrl) {
// Usar uma biblioteca de imagens seria ideal aqui (Glide/Picasso)
// Por agora, vamos usar uma abordagem simples com Thread
new Thread(() -> { new Thread(() -> {
InputStream input = null; InputStream input = null;
try { try {
@ -197,7 +201,6 @@ public class ContaActivity extends AppCompatActivity {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
// Se falhar, tentar carregar do Storage
runOnUiThread(() -> loadProfileImageFromStorage()); runOnUiThread(() -> loadProfileImageFromStorage());
} finally { } finally {
if (input != null) { if (input != null) {
@ -230,14 +233,35 @@ public class ContaActivity extends AppCompatActivity {
if (cardImageContainer != null) { if (cardImageContainer != null) {
cardImageContainer.setOnClickListener(v -> openImagePicker()); cardImageContainer.setOnClickListener(v -> openImagePicker());
} }
if (btnSaveName != null) { if (btnSaveAll != null) {
btnSaveName.setOnClickListener(v -> saveUserName()); btnSaveAll.setOnClickListener(v -> saveAllChanges());
} }
if (btnLoadImageUrl != null) { if (btnLoadImageUrl != null) {
btnLoadImageUrl.setOnClickListener(v -> loadImageFromUrl()); btnLoadImageUrl.setOnClickListener(v -> loadImageFromUrl());
} }
if (btnChangeEmail != null) {
btnChangeEmail.setOnClickListener(v -> sendEmailVerificationForEmailChange());
}
if (btnChangePassword != null) {
btnChangePassword.setOnClickListener(v -> sendPasswordResetEmail());
}
if (btnLogout != null) { if (btnLogout != null) {
btnLogout.setOnClickListener(v -> logoutUser()); btnLogout.setOnClickListener(v -> showLogoutConfirmation());
}
}
private void openImagePicker() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imagePickerLauncher.launch(intent);
} else {
String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imagePickerLauncher.launch(intent);
} else {
permissionLauncher.launch(permission);
}
} }
} }
@ -272,8 +296,10 @@ public class ContaActivity extends AppCompatActivity {
progressDialog.dismiss(); progressDialog.dismiss();
if (bitmap != null && imageProfile != null) { if (bitmap != null && imageProfile != null) {
imageProfile.setImageBitmap(bitmap); imageProfile.setImageBitmap(bitmap);
// Converter bitmap para URI e fazer upload // Guardar URL para usar diretamente no perfil
uploadImageFromBitmap(bitmap); imageUrlFromGoogle = imageUrl;
// Atualizar perfil com a URL diretamente
updateProfileWithImageUrl(imageUrl);
} else { } else {
Toast.makeText(this, "Erro ao carregar imagem da URL", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Erro ao carregar imagem da URL", Toast.LENGTH_SHORT).show();
} }
@ -291,13 +317,60 @@ public class ContaActivity extends AppCompatActivity {
}).start(); }).start();
} }
private void uploadImageFromBitmap(Bitmap bitmap) { private void updateProfileWithImageUrl(String imageUrl) {
FirebaseUser user = mAuth.getCurrentUser(); FirebaseUser user = mAuth.getCurrentUser();
if (user == null) return; if (user == null) return;
progressDialog.show(); progressDialog.show();
try { try {
Uri imageUri = Uri.parse(imageUrl);
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setPhotoUri(imageUri)
.build();
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this, "Foto de perfil atualizada com sucesso!", Toast.LENGTH_SHORT).show();
editImageUrl.setText("");
loadProfileImage(imageUrl);
} else {
Toast.makeText(this, "Erro ao atualizar foto: " +
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao processar URL: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void uploadProfileImage() {
if (selectedImageUri == null) return;
FirebaseUser user = mAuth.getCurrentUser();
if (user == null) return;
progressDialog.show();
InputStream inputStream = null;
try {
inputStream = getContentResolver().openInputStream(selectedImageUri);
if (inputStream == null) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao abrir imagem", Toast.LENGTH_SHORT).show();
return;
}
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap == null) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao processar imagem", Toast.LENGTH_SHORT).show();
return;
}
// Redimensionar se muito grande // Redimensionar se muito grande
int maxSize = 1024; int maxSize = 1024;
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) { if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
@ -321,121 +394,6 @@ public class ContaActivity extends AppCompatActivity {
.setPhotoUri(uri) .setPhotoUri(uri)
.build(); .build();
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this, "Foto de perfil atualizada com sucesso!", Toast.LENGTH_SHORT).show();
editImageUrl.setText("");
loadProfileImage(uri.toString());
} else {
Toast.makeText(this, "Erro ao atualizar foto: " +
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
Toast.LENGTH_SHORT).show();
}
});
}).addOnFailureListener(e -> {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao obter URL da imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
}).addOnFailureListener(e -> {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao fazer upload: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
} catch (Exception e) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao processar imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void logoutUser() {
// Limpar credenciais guardadas
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.apply();
// Fazer logout do Firebase
mAuth.signOut();
Toast.makeText(this, "Sessão terminada", Toast.LENGTH_SHORT).show();
// Voltar para o login
Intent intent = new Intent(ContaActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
private void openImagePicker() {
// No Android 13+ (API 33+), ACTION_PICK não requer permissão
// Mas vamos verificar e pedir permissão se necessário para versões anteriores
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// Android 13+ - não precisa de permissão para ACTION_PICK
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imagePickerLauncher.launch(intent);
} else {
// Android 12 e anteriores - precisa de permissão
String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imagePickerLauncher.launch(intent);
} else {
permissionLauncher.launch(permission);
}
}
}
private void uploadProfileImage() {
if (selectedImageUri == null) return;
FirebaseUser user = mAuth.getCurrentUser();
if (user == null) return;
progressDialog.show();
InputStream inputStream = null;
try {
// Comprimir imagem
inputStream = getContentResolver().openInputStream(selectedImageUri);
if (inputStream == null) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao abrir imagem", Toast.LENGTH_SHORT).show();
return;
}
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap == null) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao processar imagem", Toast.LENGTH_SHORT).show();
return;
}
// Redimensionar se muito grande (max 1024x1024)
int maxSize = 1024;
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
float scale = Math.min((float) maxSize / bitmap.getWidth(), (float) maxSize / bitmap.getHeight());
int newWidth = Math.round(bitmap.getWidth() * scale);
int newHeight = Math.round(bitmap.getHeight() * scale);
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] imageData = baos.toByteArray();
// Upload para Firebase Storage
StorageReference profileImageRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
UploadTask uploadTask = profileImageRef.putBytes(imageData);
uploadTask.addOnSuccessListener(taskSnapshot -> {
// Obter URL da imagem
profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> {
// Atualizar perfil do utilizador com a URL da foto
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setPhotoUri(uri)
.build();
user.updateProfile(profileUpdates).addOnCompleteListener(task -> { user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss(); progressDialog.dismiss();
if (task.isSuccessful()) { if (task.isSuccessful()) {
@ -470,7 +428,7 @@ public class ContaActivity extends AppCompatActivity {
} }
} }
private void saveUserName() { private void saveAllChanges() {
if (editName == null) return; if (editName == null) return;
String newName = editName.getText().toString().trim(); String newName = editName.getText().toString().trim();
@ -495,12 +453,104 @@ public class ContaActivity extends AppCompatActivity {
user.updateProfile(profileUpdates).addOnCompleteListener(task -> { user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss(); progressDialog.dismiss();
if (task.isSuccessful()) { if (task.isSuccessful()) {
Toast.makeText(this, "Nome atualizado com sucesso!", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Alterações guardadas com sucesso!", Toast.LENGTH_SHORT).show();
} else { } else {
Toast.makeText(this, "Erro ao atualizar nome: " + Toast.makeText(this, "Erro ao guardar alterações: " +
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"), (task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} }
}); });
} }
private void sendPasswordResetEmail() {
FirebaseUser user = mAuth.getCurrentUser();
if (user == null || user.getEmail() == null) {
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
return;
}
progressDialog.show();
mAuth.sendPasswordResetEmail(user.getEmail())
.addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this,
"Email de alteração de password enviado! Verifique a sua caixa de entrada.",
Toast.LENGTH_LONG).show();
} else {
String errorMessage = "Erro ao enviar email!";
if (task.getException() != null && task.getException().getMessage() != null) {
errorMessage = "Erro: " + task.getException().getMessage();
}
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
}
});
}
private void sendEmailVerificationForEmailChange() {
FirebaseUser user = mAuth.getCurrentUser();
if (user == null || user.getEmail() == null) {
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
return;
}
progressDialog.show();
// Enviar email de verificação para alterar email
user.sendEmailVerification()
.addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this,
"Email de verificação enviado! Verifique a sua caixa de entrada para alterar o email.",
Toast.LENGTH_LONG).show();
} else {
// Se não conseguir enviar email de verificação, enviar email de reset de password
// que pode ser usado para alterar o email através do Firebase Console
mAuth.sendPasswordResetEmail(user.getEmail())
.addOnCompleteListener(resetTask -> {
if (resetTask.isSuccessful()) {
Toast.makeText(this,
"Email enviado! Verifique a sua caixa de entrada para instruções de alteração.",
Toast.LENGTH_LONG).show();
} else {
String errorMessage = "Erro ao enviar email!";
if (resetTask.getException() != null && resetTask.getException().getMessage() != null) {
errorMessage = "Erro: " + resetTask.getException().getMessage();
}
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
}
});
}
});
}
private void showLogoutConfirmation() {
new AlertDialog.Builder(this)
.setTitle("Terminar Sessão")
.setMessage("Tem a certeza que deseja terminar a sessão?")
.setPositiveButton("Sim", (dialog, which) -> logoutUser())
.setNegativeButton("Cancelar", null)
.show();
}
private void logoutUser() {
// Limpar credenciais guardadas
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.apply();
// Fazer logout do Firebase
mAuth.signOut();
Toast.makeText(this, "Sessão terminada", Toast.LENGTH_SHORT).show();
// Voltar para o login
Intent intent = new Intent(ContaActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
} }

View File

@ -184,7 +184,7 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Nome" android:text="Nome de Utilizador"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1A1A1A" android:textColor="#1A1A1A"
@ -219,29 +219,16 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<!-- Save Name Button -->
<Button
android:id="@+id/btnSaveName"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="16dp"
android:backgroundTint="#424242"
android:text="Guardar Nome"
android:textColor="#FFFFFF"
android:textSize="16sp"
android:textStyle="bold"
android:elevation="2dp"
android:stateListAnimator="@null" />
</LinearLayout> </LinearLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
<!-- Email Display (Read-only) --> <!-- Email Section -->
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/cardEmail" android:id="@+id/cardEmail"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="20dp" app:cardCornerRadius="20dp"
app:cardElevation="4dp" app:cardElevation="4dp"
app:cardBackgroundColor="#FFFFFF" app:cardBackgroundColor="#FFFFFF"
@ -271,7 +258,94 @@
android:textColor="#757575" android:textColor="#757575"
android:padding="12dp" android:padding="12dp"
android:background="#F5F5F5" android:background="#F5F5F5"
android:layout_marginTop="4dp" /> android:layout_marginBottom="16dp" />
<Button
android:id="@+id/btnChangeEmail"
android:layout_width="match_parent"
android:layout_height="48dp"
android:backgroundTint="#616161"
android:text="Alterar Email"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:textStyle="bold"
android:elevation="2dp"
android:stateListAnimator="@null" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Password Section -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="20dp"
app:cardElevation="4dp"
app:cardBackgroundColor="#FFFFFF"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Password"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#1A1A1A"
android:layout_marginBottom="16dp" />
<Button
android:id="@+id/btnChangePassword"
android:layout_width="match_parent"
android:layout_height="48dp"
android:backgroundTint="#616161"
android:text="Alterar Password"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:textStyle="bold"
android:elevation="2dp"
android:stateListAnimator="@null" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Save All Changes Button -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardSaveAll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="20dp"
app:cardElevation="4dp"
app:cardBackgroundColor="#FFFFFF"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<Button
android:id="@+id/btnSaveAll"
android:layout_width="match_parent"
android:layout_height="56dp"
android:backgroundTint="#424242"
android:text="Guardar Alterações"
android:textColor="#FFFFFF"
android:textSize="16sp"
android:textStyle="bold"
android:elevation="2dp"
android:stateListAnimator="@null" />
</LinearLayout> </LinearLayout>

View File

@ -90,6 +90,36 @@
android:textColor="#757575" android:textColor="#757575"
android:layout_marginBottom="32dp" /> android:layout_marginBottom="32dp" />
<!-- Nome de Utilizador Input -->
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:hint="Nome de Utilizador"
app:boxCornerRadiusTopStart="12dp"
app:boxCornerRadiusTopEnd="12dp"
app:boxCornerRadiusBottomStart="12dp"
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="1dp"
app:boxStrokeColor="#BDBDBD"
app:startIconDrawable="@android:drawable/ic_menu_myplaces"
app:startIconTint="#616161"
app:boxBackgroundMode="outline"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editUserName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:textColor="#212121"
android:textColorHint="#9E9E9E"
android:textSize="16sp"
android:padding="18dp"
android:background="@android:color/transparent" />
</com.google.android.material.textfield.TextInputLayout>
<!-- Email Input --> <!-- Email Input -->
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height" android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar" android:background="#FFFFFF"
android:gravity="bottom" android:gravity="bottom"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin"
@ -29,14 +29,6 @@
android:paddingTop="@dimen/nav_header_vertical_spacing" android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/nav_header_title" android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="#FFFFFF" android:textColor="#212121"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nav_header_subtitle"
android:textColor="#FFFFFF"
android:alpha="0.9" />
</LinearLayout> </LinearLayout>