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 editEmail;
TextInputEditText editUserName;
TextInputEditText editConfirmPassword;
Button btnCreateAccount;
TextView txtGoLogin;
editEmail = findViewById(R.id.editEmail);
editUserName = findViewById(R.id.editUserName);
editPassword2 = findViewById(R.id.editPassword2);
editConfirmPassword = findViewById(R.id.editConfirmPassword);
btnCreateAccount = findViewById(R.id.btnCreateAccount);
@ -46,10 +48,11 @@ public class CriarContaActivity extends AppCompatActivity {
@Override
public void onClick(View v) {
String email = editEmail.getText().toString().trim();
String userName = editUserName.getText().toString().trim();
String pass = editPassword2.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();
return;
}
@ -62,10 +65,24 @@ public class CriarContaActivity extends AppCompatActivity {
FirebaseAuth auth = FirebaseAuth.getInstance();
auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this, task -> {
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 -> {
Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
startActivity(intent);
finish();
});
} else {
Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
} else {
String errorMessage = "Erro ao criar conta!";
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);
TextView textViewName = headerView.findViewById(R.id.textViewName);
TextView textViewEmail = headerView.findViewById(R.id.textView);
ImageView imageView = headerView.findViewById(R.id.imageView);
// Carregar nome
@ -79,19 +78,16 @@ public class MainActivity extends AppCompatActivity {
}
}
// Carregar email
if (textViewEmail != null && user.getEmail() != null) {
textViewEmail.setText(user.getEmail());
}
// Carregar foto de perfil
if (imageView != null && user.getPhotoUrl() != null) {
if (imageView != null) {
if (user.getPhotoUrl() != null) {
loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView);
} else {
// Tentar carregar do Storage
loadProfileImageFromStorage(imageView);
}
}
}
private void loadProfileImageInNavHeader(String imageUrl, ImageView imageView) {
new Thread(() -> {

View File

@ -1,6 +1,7 @@
package com.example.vdcscore.ui.definicoes;
import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
@ -46,8 +47,10 @@ public class ContaActivity extends AppCompatActivity {
private TextInputEditText editName;
private TextInputEditText editImageUrl;
private TextView textEmail;
private Button btnSaveName;
private Button btnSaveAll;
private Button btnLoadImageUrl;
private Button btnChangeEmail;
private Button btnChangePassword;
private Button btnLogout;
private View btnChangePhoto;
private View cardImageContainer;
@ -60,6 +63,7 @@ public class ContaActivity extends AppCompatActivity {
private ActivityResultLauncher<Intent> imagePickerLauncher;
private ActivityResultLauncher<String> permissionLauncher;
private Uri selectedImageUri;
private String imageUrlFromGoogle;
private static final String PREFS_NAME = "LoginPrefs";
@ -95,8 +99,10 @@ public class ContaActivity extends AppCompatActivity {
editName = findViewById(R.id.editName);
editImageUrl = findViewById(R.id.editImageUrl);
textEmail = findViewById(R.id.textEmail);
btnSaveName = findViewById(R.id.btnSaveName);
btnSaveAll = findViewById(R.id.btnSaveAll);
btnLoadImageUrl = findViewById(R.id.btnLoadImageUrl);
btnChangeEmail = findViewById(R.id.btnChangeEmail);
btnChangePassword = findViewById(R.id.btnChangePassword);
btnLogout = findViewById(R.id.btnLogout);
btnChangePhoto = findViewById(R.id.btnChangePhoto);
cardImageContainer = findViewById(R.id.cardImageContainer);
@ -180,8 +186,6 @@ public class ContaActivity extends AppCompatActivity {
}
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(() -> {
InputStream input = null;
try {
@ -197,7 +201,6 @@ public class ContaActivity extends AppCompatActivity {
}
});
} catch (Exception e) {
// Se falhar, tentar carregar do Storage
runOnUiThread(() -> loadProfileImageFromStorage());
} finally {
if (input != null) {
@ -230,14 +233,35 @@ public class ContaActivity extends AppCompatActivity {
if (cardImageContainer != null) {
cardImageContainer.setOnClickListener(v -> openImagePicker());
}
if (btnSaveName != null) {
btnSaveName.setOnClickListener(v -> saveUserName());
if (btnSaveAll != null) {
btnSaveAll.setOnClickListener(v -> saveAllChanges());
}
if (btnLoadImageUrl != null) {
btnLoadImageUrl.setOnClickListener(v -> loadImageFromUrl());
}
if (btnChangeEmail != null) {
btnChangeEmail.setOnClickListener(v -> sendEmailVerificationForEmailChange());
}
if (btnChangePassword != null) {
btnChangePassword.setOnClickListener(v -> sendPasswordResetEmail());
}
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();
if (bitmap != null && imageProfile != null) {
imageProfile.setImageBitmap(bitmap);
// Converter bitmap para URI e fazer upload
uploadImageFromBitmap(bitmap);
// Guardar URL para usar diretamente no perfil
imageUrlFromGoogle = imageUrl;
// Atualizar perfil com a URL diretamente
updateProfileWithImageUrl(imageUrl);
} else {
Toast.makeText(this, "Erro ao carregar imagem da URL", Toast.LENGTH_SHORT).show();
}
@ -291,13 +317,60 @@ public class ContaActivity extends AppCompatActivity {
}).start();
}
private void uploadImageFromBitmap(Bitmap bitmap) {
private void updateProfileWithImageUrl(String imageUrl) {
FirebaseUser user = mAuth.getCurrentUser();
if (user == null) return;
progressDialog.show();
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
int maxSize = 1024;
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
@ -321,121 +394,6 @@ public class ContaActivity extends AppCompatActivity {
.setPhotoUri(uri)
.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 -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
@ -470,7 +428,7 @@ public class ContaActivity extends AppCompatActivity {
}
}
private void saveUserName() {
private void saveAllChanges() {
if (editName == null) return;
String newName = editName.getText().toString().trim();
@ -495,12 +453,104 @@ public class ContaActivity extends AppCompatActivity {
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss();
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 {
Toast.makeText(this, "Erro ao atualizar nome: " +
Toast.makeText(this, "Erro ao guardar alterações: " +
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
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
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome"
android:text="Nome de Utilizador"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#1A1A1A"
@ -219,29 +219,16 @@
</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>
</com.google.android.material.card.MaterialCardView>
<!-- Email Display (Read-only) -->
<!-- Email Section -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="20dp"
app:cardElevation="4dp"
app:cardBackgroundColor="#FFFFFF"
@ -271,7 +258,94 @@
android:textColor="#757575"
android:padding="12dp"
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>

View File

@ -90,6 +90,36 @@
android:textColor="#757575"
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 -->
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"

View File

@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:background="#FFFFFF"
android:gravity="bottom"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
@ -29,14 +29,6 @@
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="#FFFFFF"
android:textColor="#212121"
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>