Compare commits
41 Commits
66d019d9b6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 894c9a845c | |||
| 337440eb91 | |||
| 421ba7c2e2 | |||
| 2087572fa9 | |||
| e797216506 | |||
| 695e8cac2e | |||
| beede716c6 | |||
| e2c3d0badd | |||
| 7e70721c6c | |||
| e1150b3bf0 | |||
| e7aa23bbec | |||
| 2d27e4a227 | |||
| 24acb90d58 | |||
| 371a298636 | |||
| cd527224bf | |||
| 214d51d36e | |||
| 750e91538c | |||
| f034364a41 | |||
| a70395f258 | |||
| 1dbbcb9a78 | |||
| 47a436c97d | |||
| 66746a459a | |||
| e06b4be7bf | |||
| 6618e27afe | |||
| ae62000ff3 | |||
| 62d2a6bb51 | |||
| fc4f786739 | |||
| ca26b8e146 | |||
| b297ff0e6e | |||
| 2e47ced7c7 | |||
| fe0dbed813 | |||
| f2ece221b6 | |||
| 743ddeb3db | |||
| 85a1907ef8 | |||
| 2d4d229eac | |||
| 4b766067f4 | |||
| 460b719785 | |||
| 81eb71bd46 | |||
| 49ba834e96 | |||
| 4d80a9a27d | |||
| 9875c82e65 |
8
.idea/deploymentTargetSelector.xml
generated
@@ -4,14 +4,6 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-11-26T09:17:18.598825Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230421/.android/avd/Medium_Phone.avd" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
|
||||
7
.idea/misc.xml
generated
@@ -6,4 +6,11 @@
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
<component name="VisualizationToolProject">
|
||||
<option name="state">
|
||||
<ProjectState>
|
||||
<option name="scale" value="0.2492626953125" />
|
||||
</ProjectState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -54,4 +54,5 @@ dependencies {
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "89853204936",
|
||||
"firebase_url": "https://vdcscore-default-rtdb.firebaseio.com",
|
||||
"project_id": "vdcscore",
|
||||
"storage_bucket": "vdcscore.firebasestorage.app"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
@@ -30,12 +30,13 @@ 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 +47,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;
|
||||
}
|
||||
@@ -60,21 +62,35 @@ public class CriarContaActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||
auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this, task -> {
|
||||
if (task.isSuccessful()) {
|
||||
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);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
} else {
|
||||
String errorMessage = "Erro ao criar conta!";
|
||||
if (task.getException() != null && task.getException().getMessage() != null) {
|
||||
errorMessage = "Erro: " + task.getException().getMessage();
|
||||
}
|
||||
Toast.makeText(CriarContaActivity.this, errorMessage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
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) {
|
||||
errorMessage = "Erro: " + task.getException().getMessage();
|
||||
}
|
||||
Toast.makeText(CriarContaActivity.this, errorMessage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.example.vdcscore;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -15,11 +17,17 @@ public class LoginActivity extends AppCompatActivity {
|
||||
|
||||
TextInputEditText editEmail, editPassword;
|
||||
Button btnLogin;
|
||||
CheckBox checkRememberMe;
|
||||
FirebaseAuth mAuth;
|
||||
|
||||
private TextView criarContaTextView;
|
||||
private TextView txtForgotPassword;
|
||||
|
||||
private static final String PREFS_NAME = "LoginPrefs";
|
||||
private static final String KEY_EMAIL = "email";
|
||||
private static final String KEY_PASSWORD = "password";
|
||||
private static final String KEY_REMEMBER = "remember";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -28,6 +36,7 @@ public class LoginActivity extends AppCompatActivity {
|
||||
editEmail = findViewById(R.id.editEmail);
|
||||
editPassword = findViewById(R.id.editPassword2);
|
||||
btnLogin = findViewById(R.id.btnLogin);
|
||||
checkRememberMe = findViewById(R.id.checkRememberMe);
|
||||
criarContaTextView = findViewById(R.id.txtRegister);
|
||||
txtForgotPassword = findViewById(R.id.txtForgotPassword);
|
||||
|
||||
@@ -36,6 +45,45 @@ public class LoginActivity extends AppCompatActivity {
|
||||
btnLogin.setOnClickListener(v -> loginUser());
|
||||
criarContaTextView.setOnClickListener(view -> criarConta());
|
||||
txtForgotPassword.setOnClickListener(view -> recuperarPassword());
|
||||
|
||||
// Carregar credenciais guardadas
|
||||
loadSavedCredentials();
|
||||
}
|
||||
|
||||
private void loadSavedCredentials() {
|
||||
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
||||
boolean remember = prefs.getBoolean(KEY_REMEMBER, false);
|
||||
|
||||
if (remember) {
|
||||
String savedEmail = prefs.getString(KEY_EMAIL, "");
|
||||
String savedPassword = prefs.getString(KEY_PASSWORD, "");
|
||||
|
||||
if (!savedEmail.isEmpty() && !savedPassword.isEmpty()) {
|
||||
editEmail.setText(savedEmail);
|
||||
editPassword.setText(savedPassword);
|
||||
checkRememberMe.setChecked(true);
|
||||
|
||||
// Tentar login automático
|
||||
autoLogin(savedEmail, savedPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void autoLogin(String email, String password) {
|
||||
mAuth.signInWithEmailAndPassword(email, password)
|
||||
.addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
// Login automático bem-sucedido
|
||||
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
} else {
|
||||
// Se o login automático falhar, apenas limpar a password do campo
|
||||
// O utilizador pode tentar fazer login manualmente
|
||||
editPassword.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void criarConta() {
|
||||
@@ -60,11 +108,19 @@ public class LoginActivity extends AppCompatActivity {
|
||||
mAuth.signInWithEmailAndPassword(email, password)
|
||||
.addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
// Guardar credenciais se "Lembrar-me" estiver marcado
|
||||
if (checkRememberMe.isChecked()) {
|
||||
saveCredentials(email, password);
|
||||
} else {
|
||||
clearSavedCredentials();
|
||||
}
|
||||
|
||||
Toast.makeText(this, "Login efetuado!", Toast.LENGTH_SHORT).show();
|
||||
|
||||
// Abre a tua página principal
|
||||
startActivity(new Intent(LoginActivity.this, MainActivity.class));
|
||||
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
|
||||
} else {
|
||||
@@ -77,12 +133,31 @@ public class LoginActivity extends AppCompatActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void saveCredentials(String email, String password) {
|
||||
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString(KEY_EMAIL, email);
|
||||
editor.putString(KEY_PASSWORD, password);
|
||||
editor.putBoolean(KEY_REMEMBER, true);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private void clearSavedCredentials() {
|
||||
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.clear();
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
// Verificar se já está autenticado (caso o login automático não tenha funcionado)
|
||||
if (FirebaseAuth.getInstance().getCurrentUser() != null){
|
||||
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.example.vdcscore;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Menu;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
@@ -15,45 +19,203 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.example.vdcscore.databinding.ActivityMainBinding;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
|
||||
import java.io.InputStream;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.InputType;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import com.google.firebase.storage.StorageReference;
|
||||
import com.google.firebase.storage.UploadTask;
|
||||
import com.google.firebase.auth.UserProfileChangeRequest;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private AppBarConfiguration mAppBarConfiguration;
|
||||
private ActivityMainBinding binding;
|
||||
private ActivityResultLauncher<String> mGetContent;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Carregar preferência do Dark Mode
|
||||
android.content.SharedPreferences prefs = getSharedPreferences("SettingsPrefs",
|
||||
android.content.Context.MODE_PRIVATE);
|
||||
boolean isDarkMode = prefs.getBoolean("dark_mode", false);
|
||||
if (isDarkMode) {
|
||||
androidx.appcompat.app.AppCompatDelegate
|
||||
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES);
|
||||
} else {
|
||||
androidx.appcompat.app.AppCompatDelegate
|
||||
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO);
|
||||
}
|
||||
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
setSupportActionBar(binding.appBarMain.toolbar);
|
||||
binding.appBarMain.fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null)
|
||||
.setAnchorView(R.id.fab).show();
|
||||
}
|
||||
});
|
||||
|
||||
DrawerLayout drawer = binding.drawerLayout;
|
||||
NavigationView navigationView = binding.navView;
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
// menu should be considered as top level destinations.
|
||||
mAppBarConfiguration = new AppBarConfiguration.Builder(
|
||||
R.id.nav_home, R.id.nav_gallery, R.id.nav_definicoes)
|
||||
R.id.nav_home, R.id.nav_gallery, R.id.nav_definicoes,
|
||||
R.id.nav_live_games, R.id.nav_clubs)
|
||||
.setOpenableLayout(drawer)
|
||||
.build();
|
||||
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
|
||||
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
|
||||
NavigationUI.setupWithNavController(navigationView, navController);
|
||||
|
||||
// Initialize Gallery Launcher
|
||||
mGetContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
|
||||
uri -> {
|
||||
if (uri != null) {
|
||||
uploadImageToStorage(uri);
|
||||
}
|
||||
});
|
||||
|
||||
// Carregar dados do utilizador no menu lateral
|
||||
loadUserDataInNavHeader();
|
||||
}
|
||||
|
||||
private void loadUserDataInNavHeader() {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
View headerView = binding.navView.getHeaderView(0);
|
||||
TextView textViewName = headerView.findViewById(R.id.textViewName);
|
||||
ImageView imageView = headerView.findViewById(R.id.imageView);
|
||||
|
||||
// Carregar nome
|
||||
if (textViewName != null) {
|
||||
if (user.getDisplayName() != null && !user.getDisplayName().isEmpty()) {
|
||||
textViewName.setText(user.getDisplayName());
|
||||
} else {
|
||||
textViewName.setText("Utilizador");
|
||||
}
|
||||
}
|
||||
|
||||
// Carregar foto de perfil
|
||||
if (imageView != null) {
|
||||
imageView.setOnClickListener(v -> showChangeProfilePhotoDialog());
|
||||
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(() -> {
|
||||
InputStream input = null;
|
||||
try {
|
||||
java.net.URL url = new java.net.URL(imageUrl);
|
||||
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.connect();
|
||||
input = connection.getInputStream();
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(input);
|
||||
runOnUiThread(() -> {
|
||||
if (bitmap != null && imageView != null) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
imageView.setScaleType(android.widget.ImageView.ScaleType.CENTER_CROP);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
// Se falhar, tentar carregar do Storage
|
||||
runOnUiThread(() -> loadProfileImageFromStorage(imageView));
|
||||
} finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (Exception e) {
|
||||
// Ignorar erro ao fechar
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void loadProfileImageFromStorage(ImageView imageView) {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null || imageView == null)
|
||||
return;
|
||||
|
||||
com.google.firebase.storage.FirebaseStorage.getInstance()
|
||||
.getReference()
|
||||
.child("profile_images/" + user.getUid() + ".jpg")
|
||||
.getDownloadUrl()
|
||||
.addOnSuccessListener(uri -> {
|
||||
loadProfileImageInNavHeader(uri.toString(), imageView);
|
||||
})
|
||||
.addOnFailureListener(e -> {
|
||||
// Manter imagem padrão
|
||||
});
|
||||
}
|
||||
|
||||
private void showChangeProfilePhotoDialog() {
|
||||
mGetContent.launch("image/*");
|
||||
}
|
||||
|
||||
private void uploadImageToStorage(Uri imageUri) {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
StorageReference storageRef = com.google.firebase.storage.FirebaseStorage.getInstance().getReference();
|
||||
StorageReference profileRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
|
||||
|
||||
Toast.makeText(this, "A carregar imagem...", Toast.LENGTH_SHORT).show();
|
||||
|
||||
profileRef.putFile(imageUri)
|
||||
.addOnSuccessListener(taskSnapshot -> {
|
||||
profileRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
||||
updateUserProfile(uri);
|
||||
});
|
||||
})
|
||||
.addOnFailureListener(e -> {
|
||||
Toast.makeText(MainActivity.this, "Erro ao carregar imagem: " + e.getMessage(), Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUserProfile(Uri photoUri) {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
|
||||
.setPhotoUri(photoUri)
|
||||
.build();
|
||||
|
||||
user.updateProfile(profileUpdates)
|
||||
.addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
Toast.makeText(MainActivity.this, "Foto de perfil atualizada!", Toast.LENGTH_SHORT).show();
|
||||
loadUserDataInNavHeader(); // Refresh UI
|
||||
} else {
|
||||
Toast.makeText(MainActivity.this, "Erro ao atualizar perfil.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
// getMenuInflater().inflate(R.menu.main, menu);
|
||||
// getMenuInflater().inflate(R.menu.main, menu);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -63,4 +225,11 @@ public class MainActivity extends AppCompatActivity {
|
||||
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|
||||
|| super.onSupportNavigateUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// Atualizar dados do utilizador quando voltar à activity
|
||||
loadUserDataInNavHeader();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.example.vdcscore.data;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.example.vdcscore.models.Club;
|
||||
import com.example.vdcscore.models.Jornada;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FirebaseRepository {
|
||||
|
||||
private final DatabaseReference mDatabase;
|
||||
private static FirebaseRepository instance;
|
||||
|
||||
private FirebaseRepository() {
|
||||
mDatabase = FirebaseDatabase.getInstance().getReference();
|
||||
}
|
||||
|
||||
public static synchronized FirebaseRepository getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new FirebaseRepository();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// --- Clubs ---
|
||||
|
||||
public void addClub(Club club, OnCompleteListener<Void> onCompleteListener) {
|
||||
String key = String.valueOf(club.getId());
|
||||
if (key == null || key.isEmpty()) {
|
||||
key = mDatabase.child("clubs").push().getKey();
|
||||
club.setId(Integer.parseInt(key));
|
||||
}
|
||||
mDatabase.child("clubs").child(key).setValue(club).addOnCompleteListener(onCompleteListener);
|
||||
}
|
||||
|
||||
public void getClubs(final DataCallback<List<Club>> callback) {
|
||||
mDatabase.child("clubs").addListenerForSingleValueEvent(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
List<Club> clubs = new ArrayList<>();
|
||||
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
|
||||
Club club = postSnapshot.getValue(Club.class);
|
||||
if (club != null) {
|
||||
club.setId(Integer.parseInt(postSnapshot.getKey()));
|
||||
clubs.add(club);
|
||||
}
|
||||
}
|
||||
callback.onSuccess(clubs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
callback.onFailure(error.toException());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- Jornadas ---
|
||||
|
||||
public void addJornada(Jornada jornada, OnCompleteListener<Void> onCompleteListener) {
|
||||
String key = jornada.getId();
|
||||
if (key == null || key.isEmpty()) {
|
||||
key = mDatabase.child("jornadas").push().getKey();
|
||||
jornada.setId(key);
|
||||
}
|
||||
mDatabase.child("jornadas").child(key).setValue(jornada).addOnCompleteListener(onCompleteListener);
|
||||
}
|
||||
|
||||
public void getJornadas(final DataCallback<List<Jornada>> callback) {
|
||||
mDatabase.child("jornadas").addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
List<Jornada> jornadas = new ArrayList<>();
|
||||
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
|
||||
Jornada jornada = postSnapshot.getValue(Jornada.class);
|
||||
if (jornada != null) {
|
||||
jornada.setId(postSnapshot.getKey());
|
||||
jornadas.add(jornada);
|
||||
}
|
||||
}
|
||||
callback.onSuccess(jornadas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
callback.onFailure(error.toException());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface DataCallback<T> {
|
||||
void onSuccess(T data);
|
||||
|
||||
void onFailure(Exception e);
|
||||
}
|
||||
}
|
||||
136
app/src/main/java/com/example/vdcscore/models/Club.java
Normal file
@@ -0,0 +1,136 @@
|
||||
package com.example.vdcscore.models;
|
||||
|
||||
import com.google.firebase.database.PropertyName;
|
||||
import java.util.ArrayList;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Club implements Serializable {
|
||||
@PropertyName("id")
|
||||
private int id;
|
||||
|
||||
@PropertyName("nome")
|
||||
private String name;
|
||||
|
||||
@PropertyName("imagem")
|
||||
private String imageUrl;
|
||||
|
||||
@PropertyName("campo")
|
||||
private String stadium;
|
||||
|
||||
@PropertyName("ano fundacao")
|
||||
private int foundationYear;
|
||||
|
||||
@PropertyName("morada")
|
||||
private String address;
|
||||
|
||||
@PropertyName("presidente")
|
||||
private String president;
|
||||
|
||||
@PropertyName("jogadores")
|
||||
private ArrayList<Player> players;
|
||||
|
||||
public Club() {
|
||||
// Default constructor for Firebase
|
||||
players = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Club(int id, String name, String imageUrl, String stadium, int foundationYear, String address,
|
||||
String president) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.imageUrl = imageUrl;
|
||||
this.stadium = stadium;
|
||||
this.foundationYear = foundationYear;
|
||||
this.address = address;
|
||||
this.president = president;
|
||||
this.players = new ArrayList<>();
|
||||
}
|
||||
|
||||
@PropertyName("id")
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@PropertyName("id")
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@PropertyName("nome")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@PropertyName("nome")
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@PropertyName("imagem")
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
@PropertyName("imagem")
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
@PropertyName("campo")
|
||||
public String getStadium() {
|
||||
return stadium;
|
||||
}
|
||||
|
||||
@PropertyName("campo")
|
||||
public void setStadium(String stadium) {
|
||||
this.stadium = stadium;
|
||||
}
|
||||
|
||||
@PropertyName("ano fundacao")
|
||||
public int getFoundationYear() {
|
||||
return foundationYear;
|
||||
}
|
||||
|
||||
@PropertyName("ano fundacao")
|
||||
public void setFoundationYear(int foundationYear) {
|
||||
this.foundationYear = foundationYear;
|
||||
}
|
||||
|
||||
@PropertyName("morada")
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@PropertyName("morada")
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
@PropertyName("presidente")
|
||||
public String getPresident() {
|
||||
return president;
|
||||
}
|
||||
|
||||
@PropertyName("presidente")
|
||||
public void setPresident(String president) {
|
||||
this.president = president;
|
||||
}
|
||||
|
||||
@PropertyName("jogadores")
|
||||
public ArrayList<Player> getPlayersMap() {
|
||||
return players;
|
||||
}
|
||||
|
||||
@PropertyName("jogadores")
|
||||
public void setPlayersMap(ArrayList<Player> players) {
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
public List<Player> getPlayersList() {
|
||||
if (players == null)
|
||||
return new ArrayList<>();
|
||||
return new ArrayList<>(players);
|
||||
}
|
||||
}
|
||||
102
app/src/main/java/com/example/vdcscore/models/Game.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package com.example.vdcscore.models;
|
||||
|
||||
public class Game {
|
||||
private String id;
|
||||
private String homeTeamId;
|
||||
private String awayTeamId;
|
||||
private String homeTeamName;
|
||||
private String awayTeamName;
|
||||
private int homeScore;
|
||||
private int awayScore;
|
||||
private boolean isFinished;
|
||||
private long timestamp;
|
||||
|
||||
public Game() {
|
||||
// Required for Firebase
|
||||
}
|
||||
|
||||
public Game(String id, String homeTeamId, String awayTeamId, String homeTeamName, String awayTeamName,
|
||||
long timestamp) {
|
||||
this.id = id;
|
||||
this.homeTeamId = homeTeamId;
|
||||
this.awayTeamId = awayTeamId;
|
||||
this.homeTeamName = homeTeamName;
|
||||
this.awayTeamName = awayTeamName;
|
||||
this.timestamp = timestamp;
|
||||
this.isFinished = false;
|
||||
this.homeScore = 0;
|
||||
this.awayScore = 0;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getHomeTeamId() {
|
||||
return homeTeamId;
|
||||
}
|
||||
|
||||
public void setHomeTeamId(String homeTeamId) {
|
||||
this.homeTeamId = homeTeamId;
|
||||
}
|
||||
|
||||
public String getAwayTeamId() {
|
||||
return awayTeamId;
|
||||
}
|
||||
|
||||
public void setAwayTeamId(String awayTeamId) {
|
||||
this.awayTeamId = awayTeamId;
|
||||
}
|
||||
|
||||
public String getHomeTeamName() {
|
||||
return homeTeamName;
|
||||
}
|
||||
|
||||
public void setHomeTeamName(String homeTeamName) {
|
||||
this.homeTeamName = homeTeamName;
|
||||
}
|
||||
|
||||
public String getAwayTeamName() {
|
||||
return awayTeamName;
|
||||
}
|
||||
|
||||
public void setAwayTeamName(String awayTeamName) {
|
||||
this.awayTeamName = awayTeamName;
|
||||
}
|
||||
|
||||
public int getHomeScore() {
|
||||
return homeScore;
|
||||
}
|
||||
|
||||
public void setHomeScore(int homeScore) {
|
||||
this.homeScore = homeScore;
|
||||
}
|
||||
|
||||
public int getAwayScore() {
|
||||
return awayScore;
|
||||
}
|
||||
|
||||
public void setAwayScore(int awayScore) {
|
||||
this.awayScore = awayScore;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return isFinished;
|
||||
}
|
||||
|
||||
public void setFinished(boolean finished) {
|
||||
isFinished = finished;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
55
app/src/main/java/com/example/vdcscore/models/Jornada.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.example.vdcscore.models;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Jornada {
|
||||
private String id;
|
||||
private int number;
|
||||
private List<Game> games;
|
||||
private boolean isCurrent;
|
||||
|
||||
public Jornada() {
|
||||
// Required for Firebase
|
||||
this.games = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Jornada(String id, int number) {
|
||||
this.id = id;
|
||||
this.number = number;
|
||||
this.games = new ArrayList<>();
|
||||
this.isCurrent = false;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public List<Game> getGames() {
|
||||
return games;
|
||||
}
|
||||
|
||||
public void setGames(List<Game> games) {
|
||||
this.games = games;
|
||||
}
|
||||
|
||||
public boolean isCurrent() {
|
||||
return isCurrent;
|
||||
}
|
||||
|
||||
public void setCurrent(boolean current) {
|
||||
isCurrent = current;
|
||||
}
|
||||
}
|
||||
40
app/src/main/java/com/example/vdcscore/models/Player.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package com.example.vdcscore.models;
|
||||
|
||||
import com.google.firebase.database.PropertyName;
|
||||
|
||||
public class Player {
|
||||
@PropertyName("id")
|
||||
private int id;
|
||||
|
||||
@PropertyName("nome")
|
||||
private String nome;
|
||||
|
||||
public Player() {
|
||||
// Default constructor required for calls to DataSnapshot.getValue(Player.class)
|
||||
}
|
||||
|
||||
public Player(int id, String nome) {
|
||||
this.id = id;
|
||||
this.nome = nome;
|
||||
}
|
||||
|
||||
@PropertyName("id")
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@PropertyName("id")
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@PropertyName("nome")
|
||||
public String getNome() {
|
||||
return nome;
|
||||
}
|
||||
|
||||
@PropertyName("nome")
|
||||
public void setNome(String nome) {
|
||||
this.nome = nome;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.example.vdcscore.ui.clubs;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.example.vdcscore.R;
|
||||
import com.example.vdcscore.models.Club;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ClubAdapter extends RecyclerView.Adapter<ClubAdapter.ClubViewHolder> {
|
||||
|
||||
private final List<Club> mClubs;
|
||||
private final OnItemClickListener mListener;
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(Club club);
|
||||
}
|
||||
|
||||
public ClubAdapter(List<Club> clubs, OnItemClickListener listener) {
|
||||
mClubs = clubs;
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ClubViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_club, parent, false);
|
||||
return new ClubViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ClubViewHolder holder, int position) {
|
||||
Club club = mClubs.get(position);
|
||||
holder.bind(club, mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mClubs.size();
|
||||
}
|
||||
|
||||
static class ClubViewHolder extends RecyclerView.ViewHolder {
|
||||
private final TextView name;
|
||||
private final TextView stadium;
|
||||
private final ImageView image_detail_logo;
|
||||
|
||||
public ClubViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
name = itemView.findViewById(R.id.text_club_name);
|
||||
stadium = itemView.findViewById(R.id.text_club_stadium);
|
||||
image_detail_logo = itemView.findViewById(R.id.image_club_logo);
|
||||
}
|
||||
|
||||
public void bind(final Club club, final OnItemClickListener listener) {
|
||||
name.setText(club.getName());
|
||||
stadium.setText(club.getStadium());
|
||||
|
||||
Glide.with(itemView.getContext())
|
||||
.load(club.getImageUrl())
|
||||
.into(image_detail_logo);
|
||||
|
||||
itemView.setOnClickListener(v -> listener.onItemClick(club));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.example.vdcscore.ui.clubs;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
import com.example.vdcscore.databinding.FragmentClubDetailBinding;
|
||||
import com.example.vdcscore.models.Club;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
import com.bumptech.glide.Glide;
|
||||
|
||||
public class ClubDetailFragment extends Fragment {
|
||||
|
||||
private FragmentClubDetailBinding binding;
|
||||
private DatabaseReference mDatabase;
|
||||
private String clubId;
|
||||
private String escalao;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
clubId = getArguments().getString("clubId");
|
||||
escalao = getArguments().getString("escalao");
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentClubDetailBinding.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getArguments() != null) {
|
||||
Club clubeRecebido = (Club) getArguments().getSerializable("clube_selecionado");
|
||||
|
||||
if (clubeRecebido != null) {
|
||||
// Preencher views diretamente
|
||||
binding.textDetailClubName.setText(clubeRecebido.getName());
|
||||
binding.textDetailFoundation.setText(String.valueOf(clubeRecebido.getFoundationYear()));
|
||||
binding.textDetailPresident.setText(clubeRecebido.getPresident());
|
||||
binding.textDetailAddress.setText(clubeRecebido.getAddress());
|
||||
|
||||
if (getContext() != null) {
|
||||
Glide.with(this)
|
||||
.load(clubeRecebido.getImageUrl())
|
||||
.placeholder(R.mipmap.ic_launcher_round)
|
||||
.error(R.mipmap.ic_launcher)
|
||||
.into(binding.imageDetailLogo);
|
||||
}
|
||||
|
||||
// Configurar o botão para ver jogadores
|
||||
binding.btnPlayers.setOnClickListener(v -> {
|
||||
Bundle bundle = new Bundle();
|
||||
// Passar o 'clube_selecionado' também para a lista de jogadores se necessário,
|
||||
// ou passar o ID como antes se o fragmento de jogadores esperar ID
|
||||
bundle.putString("clubId", String.valueOf(clubeRecebido.getId()));
|
||||
bundle.putString("escalao", escalao);
|
||||
// Se o ClubPlayersFragment esperar "clube_selecionado" tambem, poderiamos
|
||||
// passar:
|
||||
// bundle.putSerializable("clube_selecionado", clubeRecebido);
|
||||
|
||||
Navigation.findNavController(view).navigate(R.id.action_nav_club_detail_to_nav_club_players,
|
||||
bundle);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadClubDetails() {
|
||||
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
Club club = snapshot.getValue(Club.class);
|
||||
if (club != null) {
|
||||
binding.textDetailClubName.setText(club.getName());
|
||||
binding.textDetailFoundation.setText(String.valueOf(club.getFoundationYear()));
|
||||
binding.textDetailPresident.setText(club.getPresident());
|
||||
binding.textDetailAddress.setText(club.getAddress());
|
||||
// binding.textDetailStadium.setText(club.getStadium()); // Hidden for now
|
||||
|
||||
// binding.imageDetailLogo.setImageResource(R.mipmap.ic_launcher_round);
|
||||
if (getContext() != null) {
|
||||
Glide.with(ClubDetailFragment.this)
|
||||
.load(club.getImageUrl())
|
||||
.placeholder(R.mipmap.ic_launcher_round)
|
||||
.error(R.mipmap.ic_launcher)
|
||||
.into(binding.imageDetailLogo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Failed to load club details.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.example.vdcscore.ui.clubs;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.example.vdcscore.databinding.FragmentClubPlayersBinding;
|
||||
import com.example.vdcscore.models.Club;
|
||||
import com.example.vdcscore.models.Player;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ClubPlayersFragment extends Fragment {
|
||||
|
||||
private FragmentClubPlayersBinding binding;
|
||||
private DatabaseReference mDatabase;
|
||||
private String clubId;
|
||||
private String escalao;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
clubId = getArguments().getString("clubId");
|
||||
escalao = getArguments().getString("escalao");
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentClubPlayersBinding.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
binding.recyclerPlayersList.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
binding.progressBarPlayers.setVisibility(View.VISIBLE);
|
||||
|
||||
if (clubId != null && escalao != null) {
|
||||
mDatabase = FirebaseDatabase.getInstance().getReference().child("clubes").child(escalao).child(clubId);
|
||||
loadPlayers();
|
||||
} else {
|
||||
binding.progressBarPlayers.setVisibility(View.GONE);
|
||||
binding.textNoPlayers.setVisibility(View.VISIBLE);
|
||||
binding.textNoPlayers.setText("Erro: Clube ou escalão não identificado.");
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPlayers() {
|
||||
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
Club club = snapshot.getValue(Club.class);
|
||||
binding.progressBarPlayers.setVisibility(View.GONE);
|
||||
|
||||
if (club != null) {
|
||||
List<Player> playerList = club.getPlayersList();
|
||||
if (playerList != null && !playerList.isEmpty()) {
|
||||
PlayerAdapter adapter = new PlayerAdapter(playerList);
|
||||
binding.recyclerPlayersList.setAdapter(adapter);
|
||||
binding.textNoPlayers.setVisibility(View.GONE);
|
||||
} else {
|
||||
binding.textNoPlayers.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
binding.textNoPlayers.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Failed to load players.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
binding.progressBarPlayers.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.example.vdcscore.ui.clubs;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
import com.example.vdcscore.databinding.FragmentClubsBinding;
|
||||
import com.example.vdcscore.models.Club;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ClubsFragment extends Fragment {
|
||||
|
||||
private FragmentClubsBinding binding;
|
||||
private DatabaseReference mDatabase;
|
||||
private ValueEventListener mValueEventListener;
|
||||
private static final String TAG = "ClubsFragment";
|
||||
private String currentEscalao = "seniores"; // Default selection
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
binding = FragmentClubsBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
RecyclerView recyclerView = binding.recyclerClubs;
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
ProgressBar progressBar = binding.progressBar;
|
||||
|
||||
// Set up toggle listener
|
||||
binding.toggleGroupEscalao.addOnButtonCheckedListener((group, checkedId, isChecked) -> {
|
||||
if (isChecked) {
|
||||
if (checkedId == R.id.btnJuniores) {
|
||||
currentEscalao = "juniores";
|
||||
} else if (checkedId == R.id.btnSeniores) {
|
||||
currentEscalao = "seniores";
|
||||
}
|
||||
loadClubsData(recyclerView, progressBar);
|
||||
}
|
||||
});
|
||||
|
||||
// Initial Data Load
|
||||
loadClubsData(recyclerView, progressBar);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void loadClubsData(RecyclerView recyclerView, ProgressBar progressBar) {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
mDatabase = FirebaseDatabase.getInstance().getReference().child("clubes").child(currentEscalao);
|
||||
|
||||
// Remove previous listener to avoid duplicate data or leaks
|
||||
if (mValueEventListener != null) {
|
||||
mDatabase.removeEventListener(mValueEventListener);
|
||||
}
|
||||
|
||||
mValueEventListener = new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
List<Club> clubs = new ArrayList<>();
|
||||
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
|
||||
Club club = postSnapshot.getValue(Club.class);
|
||||
if (club != null) {
|
||||
clubs.add(club);
|
||||
}
|
||||
}
|
||||
ClubAdapter adapter = new ClubAdapter(clubs, club -> {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("clube_selecionado", club);
|
||||
bundle.putString("escalao", currentEscalao);
|
||||
androidx.navigation.fragment.NavHostFragment.findNavController(ClubsFragment.this)
|
||||
.navigate(R.id.action_nav_clubs_to_nav_club_detail, bundle);
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
if (clubs.isEmpty()) {
|
||||
// Keep UI empty but don't show mock data automatically to avoid confusion
|
||||
// Toast.makeText(getContext(), "No clubs found.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
Log.w(TAG, "loadClubs:onCancelled", error.toException());
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Failed to load clubs.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
if (binding != null) {
|
||||
binding.progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mDatabase.addValueEventListener(mValueEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (mDatabase != null && mValueEventListener != null) {
|
||||
mDatabase.removeEventListener(mValueEventListener);
|
||||
}
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.example.vdcscore.ui.clubs;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
import com.example.vdcscore.models.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlayerAdapter extends RecyclerView.Adapter<PlayerAdapter.PlayerViewHolder> {
|
||||
|
||||
private final List<Player> mPlayers;
|
||||
|
||||
public PlayerAdapter(List<Player> players) {
|
||||
mPlayers = players;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PlayerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_player, parent, false);
|
||||
return new PlayerViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PlayerViewHolder holder, int position) {
|
||||
Player player = mPlayers.get(position);
|
||||
holder.bind(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mPlayers.size();
|
||||
}
|
||||
|
||||
static class PlayerViewHolder extends RecyclerView.ViewHolder {
|
||||
private final TextView name;
|
||||
|
||||
public PlayerViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
name = itemView.findViewById(R.id.text_player_name);
|
||||
}
|
||||
|
||||
public void bind(Player player) {
|
||||
if (player != null){
|
||||
name.setText(player.getNome());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
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;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
@@ -21,12 +23,12 @@ import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.example.vdcscore.LoginActivity;
|
||||
import com.example.vdcscore.R;
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
@@ -42,12 +44,13 @@ import java.io.InputStream;
|
||||
|
||||
public class ContaActivity extends AppCompatActivity {
|
||||
|
||||
private static final int PERMISSION_REQUEST_CODE = 100;
|
||||
|
||||
private ImageView imageProfile;
|
||||
private TextInputEditText editName;
|
||||
private TextView textEmail;
|
||||
private Button btnSaveName;
|
||||
private Button btnSaveAll;
|
||||
private Button btnChangeEmail;
|
||||
private Button btnChangePassword;
|
||||
private Button btnLogout;
|
||||
private View btnChangePhoto;
|
||||
private View cardImageContainer;
|
||||
|
||||
@@ -57,8 +60,11 @@ public class ContaActivity extends AppCompatActivity {
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
private ActivityResultLauncher<Intent> imagePickerLauncher;
|
||||
private ActivityResultLauncher<String> permissionLauncher;
|
||||
private Uri selectedImageUri;
|
||||
|
||||
private static final String PREFS_NAME = "LoginPrefs";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -75,6 +81,7 @@ public class ContaActivity extends AppCompatActivity {
|
||||
initViews();
|
||||
initFirebase();
|
||||
setupImagePicker();
|
||||
setupPermissionLauncher();
|
||||
loadUserData();
|
||||
setupListeners();
|
||||
}
|
||||
@@ -82,18 +89,35 @@ public class ContaActivity extends AppCompatActivity {
|
||||
private void initViews() {
|
||||
MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
toolbar.setNavigationOnClickListener(v -> finish());
|
||||
if (toolbar != null) {
|
||||
toolbar.setNavigationOnClickListener(v -> finish());
|
||||
}
|
||||
|
||||
imageProfile = findViewById(R.id.imageProfile);
|
||||
editName = findViewById(R.id.editName);
|
||||
// In XML it is present as @+id/textEmail inside cardSecurity.
|
||||
textEmail = findViewById(R.id.textEmail);
|
||||
btnSaveName = findViewById(R.id.btnSaveName);
|
||||
btnChangePhoto = findViewById(R.id.btnChangePhoto);
|
||||
|
||||
btnSaveAll = findViewById(R.id.btnSaveAll);
|
||||
btnChangeEmail = findViewById(R.id.btnChangeEmail);
|
||||
btnChangePassword = findViewById(R.id.btnChangePassword);
|
||||
btnLogout = findViewById(R.id.btnLogout);
|
||||
|
||||
// New FAB for editing photo
|
||||
btnChangePhoto = findViewById(R.id.fabEditPhoto);
|
||||
// Also allow clicking the text
|
||||
View btnChangePhotoText = findViewById(R.id.btnChangePhoto);
|
||||
|
||||
cardImageContainer = findViewById(R.id.cardImageContainer);
|
||||
|
||||
progressDialog = new ProgressDialog(this);
|
||||
progressDialog.setMessage("A processar...");
|
||||
progressDialog.setCancelable(false);
|
||||
|
||||
// Setup listeners here or in setupListeners()
|
||||
if (btnChangePhotoText != null) {
|
||||
btnChangePhotoText.setOnClickListener(v -> openImagePicker());
|
||||
}
|
||||
}
|
||||
|
||||
private void initFirebase() {
|
||||
@@ -104,33 +128,54 @@ public class ContaActivity extends AppCompatActivity {
|
||||
|
||||
private void setupImagePicker() {
|
||||
imagePickerLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
|
||||
selectedImageUri = result.getData().getData();
|
||||
if (selectedImageUri != null) {
|
||||
try {
|
||||
InputStream inputStream = getContentResolver().openInputStream(selectedImageUri);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||
imageProfile.setImageBitmap(bitmap);
|
||||
uploadProfileImage();
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, "Erro ao carregar imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
|
||||
selectedImageUri = result.getData().getData();
|
||||
if (selectedImageUri != null) {
|
||||
try {
|
||||
InputStream inputStream = getContentResolver().openInputStream(selectedImageUri);
|
||||
if (inputStream != null) {
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||
inputStream.close();
|
||||
if (bitmap != null) {
|
||||
imageProfile.setImageBitmap(bitmap);
|
||||
// Não fazemos upload até clicar em Gravar
|
||||
} else {
|
||||
Toast.makeText(this, "Erro ao carregar imagem", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, "Erro ao carregar imagem: " + e.getMessage(), Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void setupPermissionLauncher() {
|
||||
permissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
isGranted -> {
|
||||
if (isGranted) {
|
||||
openImagePicker();
|
||||
} else {
|
||||
Toast.makeText(this, "Permissão necessária para selecionar imagem", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadUserData() {
|
||||
FirebaseUser user = mAuth.getCurrentUser();
|
||||
if (user != null) {
|
||||
// Carregar email
|
||||
textEmail.setText(user.getEmail());
|
||||
if (textEmail != null) {
|
||||
textEmail.setText(user.getEmail() != null ? user.getEmail() : "");
|
||||
}
|
||||
|
||||
// Carregar nome
|
||||
if (user.getDisplayName() != null && !user.getDisplayName().isEmpty()) {
|
||||
if (editName != null && user.getDisplayName() != null && !user.getDisplayName().isEmpty()) {
|
||||
editName.setText(user.getDisplayName());
|
||||
}
|
||||
|
||||
@@ -148,31 +193,38 @@ 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 {
|
||||
java.net.URL url = new java.net.URL(imageUrl);
|
||||
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.connect();
|
||||
InputStream input = connection.getInputStream();
|
||||
input = connection.getInputStream();
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(input);
|
||||
runOnUiThread(() -> {
|
||||
if (bitmap != null) {
|
||||
if (bitmap != null && imageProfile != null) {
|
||||
imageProfile.setImageBitmap(bitmap);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
// Se falhar, tentar carregar do Storage
|
||||
runOnUiThread(() -> loadProfileImageFromStorage());
|
||||
} finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (Exception e) {
|
||||
// Ignorar erro ao fechar
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void loadProfileImageFromStorage() {
|
||||
FirebaseUser user = mAuth.getCurrentUser();
|
||||
if (user == null) return;
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
StorageReference profileImageRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
|
||||
profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
||||
@@ -183,114 +235,49 @@ public class ContaActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void setupListeners() {
|
||||
btnChangePhoto.setOnClickListener(v -> openImagePicker());
|
||||
cardImageContainer.setOnClickListener(v -> openImagePicker());
|
||||
|
||||
btnSaveName.setOnClickListener(v -> saveUserName());
|
||||
if (btnChangePhoto != null) {
|
||||
btnChangePhoto.setOnClickListener(v -> openImagePicker());
|
||||
}
|
||||
if (cardImageContainer != null) {
|
||||
cardImageContainer.setOnClickListener(v -> openImagePicker());
|
||||
}
|
||||
if (btnSaveAll != null) {
|
||||
btnSaveAll.setOnClickListener(v -> saveAllChanges());
|
||||
}
|
||||
if (btnChangeEmail != null) {
|
||||
btnChangeEmail.setOnClickListener(v -> sendEmailVerificationForEmailChange());
|
||||
}
|
||||
if (btnChangePassword != null) {
|
||||
btnChangePassword.setOnClickListener(v -> sendPasswordResetEmail());
|
||||
}
|
||||
if (btnLogout != null) {
|
||||
btnLogout.setOnClickListener(v -> showLogoutConfirmation());
|
||||
}
|
||||
}
|
||||
|
||||
private void openImagePicker() {
|
||||
if (checkPermissions()) {
|
||||
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 {
|
||||
requestPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkPermissions() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
} else {
|
||||
return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
}
|
||||
|
||||
private void requestPermissions() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.READ_MEDIA_IMAGES},
|
||||
PERMISSION_REQUEST_CODE);
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||
PERMISSION_REQUEST_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == PERMISSION_REQUEST_CODE) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
openImagePicker();
|
||||
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 {
|
||||
Toast.makeText(this, "Permissão necessária para selecionar imagem", Toast.LENGTH_SHORT).show();
|
||||
permissionLauncher.launch(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadProfileImage() {
|
||||
if (selectedImageUri == null) return;
|
||||
private void saveAllChanges() {
|
||||
if (editName == null)
|
||||
return;
|
||||
|
||||
FirebaseUser user = mAuth.getCurrentUser();
|
||||
if (user == null) return;
|
||||
|
||||
progressDialog.show();
|
||||
|
||||
try {
|
||||
// Comprimir imagem
|
||||
InputStream inputStream = getContentResolver().openInputStream(selectedImageUri);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||
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()) {
|
||||
Toast.makeText(this, "Foto de perfil atualizada com sucesso!", Toast.LENGTH_SHORT).show();
|
||||
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 saveUserName() {
|
||||
String newName = editName.getText().toString().trim();
|
||||
|
||||
if (newName.isEmpty()) {
|
||||
Toast.makeText(this, "Por favor, insira um nome", Toast.LENGTH_SHORT).show();
|
||||
if (newName.isEmpty() && selectedImageUri == null) {
|
||||
Toast.makeText(this, "Nenhuma alteração a guardar", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -302,6 +289,21 @@ public class ContaActivity extends AppCompatActivity {
|
||||
|
||||
progressDialog.show();
|
||||
|
||||
// Se tiver foto nova, primeiro faz upload
|
||||
if (selectedImageUri != null) {
|
||||
uploadNewProfileImageAndSaveName(user, newName);
|
||||
} else {
|
||||
// Só muda o nome
|
||||
saveNameOnly(user, newName);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveNameOnly(FirebaseUser user, String newName) {
|
||||
if (newName.isEmpty()) {
|
||||
progressDialog.dismiss();
|
||||
return; // Se não houver nome para trocar nem imagem, já barrámos em saveAllChanges.
|
||||
}
|
||||
|
||||
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
|
||||
.setDisplayName(newName)
|
||||
.build();
|
||||
@@ -309,12 +311,181 @@ 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 uploadNewProfileImageAndSaveName(FirebaseUser user, String newName) {
|
||||
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
|
||||
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();
|
||||
|
||||
StorageReference profileImageRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
|
||||
UploadTask uploadTask = profileImageRef.putBytes(imageData);
|
||||
|
||||
uploadTask.addOnSuccessListener(taskSnapshot -> {
|
||||
profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
||||
|
||||
UserProfileChangeRequest.Builder builder = new UserProfileChangeRequest.Builder();
|
||||
builder.setPhotoUri(uri);
|
||||
if (!newName.isEmpty()) {
|
||||
builder.setDisplayName(newName);
|
||||
}
|
||||
UserProfileChangeRequest profileUpdates = builder.build();
|
||||
|
||||
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
|
||||
progressDialog.dismiss();
|
||||
if (task.isSuccessful()) {
|
||||
Toast.makeText(this, "As definições foram guardadas!", Toast.LENGTH_SHORT).show();
|
||||
loadProfileImage(uri.toString());
|
||||
selectedImageUri = null; // reset
|
||||
} else {
|
||||
Toast.makeText(this, "Erro ao atualizar perfil", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}).addOnFailureListener(e -> {
|
||||
progressDialog.dismiss();
|
||||
Toast.makeText(this, "Erro ao obter URL: " + 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: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,14 @@ public class DefinicoesFragment extends Fragment {
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentDefinicoesBinding.inflate(inflater, container, false);
|
||||
setupUi();
|
||||
return binding.getRoot();
|
||||
}
|
||||
//teste
|
||||
|
||||
// teste
|
||||
private void setupUi() {
|
||||
binding.cardConta.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -44,14 +45,35 @@ public class DefinicoesFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
binding.switchNotifications.setOnCheckedChangeListener((buttonView, isChecked) ->
|
||||
binding.textNotificationsStatus.setText(
|
||||
binding.switchNotifications
|
||||
.setOnCheckedChangeListener((buttonView, isChecked) -> binding.textNotificationsStatus.setText(
|
||||
isChecked ? "Ativadas" : "Desativadas"));
|
||||
|
||||
binding.switchDarkMode.setOnCheckedChangeListener((buttonView, isChecked) ->
|
||||
binding.textDarkModeStatus.setText(
|
||||
isChecked ? "Ativo" : "Inativo"));
|
||||
// Obter SharedPreferences
|
||||
android.content.SharedPreferences prefs = requireActivity().getSharedPreferences("SettingsPrefs",
|
||||
android.content.Context.MODE_PRIVATE);
|
||||
boolean isDarkMode = prefs.getBoolean("dark_mode", false);
|
||||
|
||||
binding.switchDarkMode.setChecked(isDarkMode);
|
||||
binding.textDarkModeStatus.setText(isDarkMode ? "Ativo" : "Inativo");
|
||||
|
||||
binding.switchDarkMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
binding.textDarkModeStatus.setText(isChecked ? "Ativo" : "Inativo");
|
||||
|
||||
// Guardar preferência
|
||||
android.content.SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putBoolean("dark_mode", isChecked);
|
||||
editor.apply();
|
||||
|
||||
// Aplicar modo escuro
|
||||
if (isChecked) {
|
||||
androidx.appcompat.app.AppCompatDelegate
|
||||
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES);
|
||||
} else {
|
||||
androidx.appcompat.app.AppCompatDelegate
|
||||
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO);
|
||||
}
|
||||
});
|
||||
|
||||
binding.btnOpenSystemSettings.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(Settings.ACTION_SETTINGS);
|
||||
@@ -66,4 +88,3 @@ public class DefinicoesFragment extends Fragment {
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,31 +4,82 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.example.vdcscore.databinding.FragmentGalleryBinding;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GalleryFragment extends Fragment {
|
||||
|
||||
private FragmentGalleryBinding binding;
|
||||
private MatchdaysAdapter adapter;
|
||||
private DatabaseReference mDatabase;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
GalleryViewModel galleryViewModel =
|
||||
new ViewModelProvider(this).get(GalleryViewModel.class);
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentGalleryBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
final TextView textView = binding.textGallery;
|
||||
galleryViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
|
||||
// Initialize RecyclerView
|
||||
adapter = new MatchdaysAdapter();
|
||||
binding.recyclerMatchdays.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
binding.recyclerMatchdays.setAdapter(adapter);
|
||||
|
||||
// Initialize Firebase
|
||||
mDatabase = FirebaseDatabase.getInstance().getReference("matchdays");
|
||||
|
||||
// Fetch Data
|
||||
fetchMatchdays();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void fetchMatchdays() {
|
||||
mDatabase.addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
List<Matchday> matchdays = new ArrayList<>();
|
||||
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
|
||||
Matchday matchday = new Matchday();
|
||||
matchday.setId(postSnapshot.getKey());
|
||||
matchday.setName(postSnapshot.child("name").getValue(String.class));
|
||||
|
||||
List<Match> matches = new ArrayList<>();
|
||||
for (DataSnapshot matchSnapshot : postSnapshot.child("matches").getChildren()) {
|
||||
Match match = matchSnapshot.getValue(Match.class);
|
||||
if (match != null) {
|
||||
match.setId(matchSnapshot.getKey());
|
||||
matches.add(match);
|
||||
}
|
||||
}
|
||||
matchday.setMatches(matches);
|
||||
matchdays.add(matchday);
|
||||
}
|
||||
adapter.setMatchdays(matchdays);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Erro ao carregar jornadas: " + error.getMessage(), Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
88
app/src/main/java/com/example/vdcscore/ui/gallery/Match.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package com.example.vdcscore.ui.gallery;
|
||||
|
||||
public class Match {
|
||||
private String id;
|
||||
private String homeTeam;
|
||||
private String awayTeam;
|
||||
private int homeScore;
|
||||
private int awayScore;
|
||||
private String date;
|
||||
private String time;
|
||||
private String status; // "Scheduled", "Finished", "Live"
|
||||
|
||||
public Match() {
|
||||
}
|
||||
|
||||
public Match(String homeTeam, String awayTeam, String date, String time) {
|
||||
this.homeTeam = homeTeam;
|
||||
this.awayTeam = awayTeam;
|
||||
this.date = date;
|
||||
this.time = time;
|
||||
this.status = "Scheduled";
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getHomeTeam() {
|
||||
return homeTeam;
|
||||
}
|
||||
|
||||
public void setHomeTeam(String homeTeam) {
|
||||
this.homeTeam = homeTeam;
|
||||
}
|
||||
|
||||
public String getAwayTeam() {
|
||||
return awayTeam;
|
||||
}
|
||||
|
||||
public void setAwayTeam(String awayTeam) {
|
||||
this.awayTeam = awayTeam;
|
||||
}
|
||||
|
||||
public int getHomeScore() {
|
||||
return homeScore;
|
||||
}
|
||||
|
||||
public void setHomeScore(int homeScore) {
|
||||
this.homeScore = homeScore;
|
||||
}
|
||||
|
||||
public int getAwayScore() {
|
||||
return awayScore;
|
||||
}
|
||||
|
||||
public void setAwayScore(int awayScore) {
|
||||
this.awayScore = awayScore;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(String date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(String time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.example.vdcscore.ui.gallery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Matchday {
|
||||
private String id;
|
||||
private String name; // e.g., "Jornada 1"
|
||||
private List<Match> matches;
|
||||
|
||||
public Matchday() {
|
||||
}
|
||||
|
||||
public Matchday(String name, List<Match> matches) {
|
||||
this.name = name;
|
||||
this.matches = matches;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Match> getMatches() {
|
||||
return matches;
|
||||
}
|
||||
|
||||
public void setMatches(List<Match> matches) {
|
||||
this.matches = matches;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.example.vdcscore.ui.gallery;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MatchdaysAdapter extends RecyclerView.Adapter<MatchdaysAdapter.ViewHolder> {
|
||||
|
||||
private List<Matchday> matchdays = new ArrayList<>();
|
||||
private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
|
||||
|
||||
public void setMatchdays(List<Matchday> matchdays) {
|
||||
this.matchdays = matchdays;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_matchday, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Matchday matchday = matchdays.get(position);
|
||||
holder.textName.setText(matchday.getName());
|
||||
|
||||
// Setup nested RecyclerView
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(
|
||||
holder.recyclerMatches.getContext(),
|
||||
LinearLayoutManager.VERTICAL,
|
||||
false);
|
||||
layoutManager.setInitialPrefetchItemCount(matchday.getMatches().size());
|
||||
|
||||
MatchesAdapter matchesAdapter = new MatchesAdapter(matchday.getMatches());
|
||||
holder.recyclerMatches.setLayoutManager(layoutManager);
|
||||
holder.recyclerMatches.setAdapter(matchesAdapter);
|
||||
holder.recyclerMatches.setRecycledViewPool(viewPool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return matchdays.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public final TextView textName;
|
||||
public final RecyclerView recyclerMatches;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
textName = view.findViewById(R.id.text_matchday_name);
|
||||
recyclerMatches = view.findViewById(R.id.recycler_matches);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.example.vdcscore.ui.gallery;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MatchesAdapter extends RecyclerView.Adapter<MatchesAdapter.ViewHolder> {
|
||||
|
||||
private List<Match> matches;
|
||||
|
||||
public MatchesAdapter(List<Match> matches) {
|
||||
this.matches = matches;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_match, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Match match = matches.get(position);
|
||||
holder.textHomeTeam.setText(match.getHomeTeam());
|
||||
holder.textAwayTeam.setText(match.getAwayTeam());
|
||||
|
||||
if ("Finished".equals(match.getStatus())) {
|
||||
holder.textScore.setText(match.getHomeScore() + " - " + match.getAwayScore());
|
||||
holder.textTime.setText("Final");
|
||||
} else {
|
||||
holder.textScore.setText("Vs");
|
||||
holder.textTime.setText(match.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return matches == null ? 0 : matches.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public final TextView textHomeTeam;
|
||||
public final TextView textAwayTeam;
|
||||
public final TextView textScore;
|
||||
public final TextView textTime;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
textHomeTeam = view.findViewById(R.id.text_home_team);
|
||||
textAwayTeam = view.findViewById(R.id.text_away_team);
|
||||
textScore = view.findViewById(R.id.text_score);
|
||||
textTime = view.findViewById(R.id.text_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,31 +4,90 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.example.vdcscore.databinding.FragmentHomeBinding;
|
||||
import com.google.firebase.database.DataSnapshot;
|
||||
import com.google.firebase.database.DatabaseError;
|
||||
import com.google.firebase.database.DatabaseReference;
|
||||
import com.google.firebase.database.FirebaseDatabase;
|
||||
import com.google.firebase.database.ValueEventListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class HomeFragment extends Fragment {
|
||||
|
||||
private FragmentHomeBinding binding;
|
||||
private StandingsAdapter adapter;
|
||||
private DatabaseReference mDatabase;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
HomeViewModel homeViewModel =
|
||||
new ViewModelProvider(this).get(HomeViewModel.class);
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
binding = FragmentHomeBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
final TextView textView = binding.textHome;
|
||||
homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
|
||||
// Initialize RecyclerView
|
||||
adapter = new StandingsAdapter();
|
||||
binding.recyclerStandings.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
binding.recyclerStandings.setAdapter(adapter);
|
||||
|
||||
// Initialize Firebase
|
||||
mDatabase = FirebaseDatabase.getInstance().getReference("standings");
|
||||
|
||||
// Fetch Data
|
||||
fetchStandings();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void fetchStandings() {
|
||||
mDatabase.addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
List<Team> teams = new ArrayList<>();
|
||||
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
|
||||
Team team = postSnapshot.getValue(Team.class);
|
||||
if (team != null) {
|
||||
// If ID is missing, set it from the key
|
||||
if (team.getId() == null) {
|
||||
team.setId(postSnapshot.getKey());
|
||||
}
|
||||
teams.add(team);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by Points (Descending), then Goal Difference, then Goals For
|
||||
Collections.sort(teams, new Comparator<Team>() {
|
||||
@Override
|
||||
public int compare(Team t1, Team t2) {
|
||||
if (t1.getPoints() != t2.getPoints()) {
|
||||
return t2.getPoints() - t1.getPoints(); // Descending points
|
||||
}
|
||||
return t2.getGoalDifference() - t1.getGoalDifference(); // Descending GD
|
||||
}
|
||||
});
|
||||
|
||||
adapter.setTeams(teams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Erro ao carregar classificação: " + error.getMessage(),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.example.vdcscore.ui.home;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class StandingsAdapter extends RecyclerView.Adapter<StandingsAdapter.ViewHolder> {
|
||||
|
||||
private List<Team> mTeams;
|
||||
|
||||
public StandingsAdapter() {
|
||||
this.mTeams = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void setTeams(List<Team> teams) {
|
||||
this.mTeams = teams;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_standing, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Team team = mTeams.get(position);
|
||||
|
||||
holder.textPosition.setText(String.valueOf(position + 1));
|
||||
holder.textTeamName.setText(team.getName());
|
||||
holder.textPlayed.setText(String.valueOf(team.getPlayed()));
|
||||
holder.textPoints.setText(String.valueOf(team.getPoints()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mTeams.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public final TextView textPosition;
|
||||
public final TextView textTeamName;
|
||||
public final TextView textPlayed;
|
||||
public final TextView textPoints;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
textPosition = view.findViewById(R.id.text_position);
|
||||
textTeamName = view.findViewById(R.id.text_team_name);
|
||||
textPlayed = view.findViewById(R.id.text_played);
|
||||
textPoints = view.findViewById(R.id.text_points);
|
||||
}
|
||||
}
|
||||
}
|
||||
106
app/src/main/java/com/example/vdcscore/ui/home/Team.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package com.example.vdcscore.ui.home;
|
||||
|
||||
public class Team {
|
||||
private String id;
|
||||
private String name;
|
||||
private int points;
|
||||
private int played;
|
||||
private int won;
|
||||
private int drawn;
|
||||
private int lost;
|
||||
private int goalsFor;
|
||||
private int goalsAgainst;
|
||||
private int goalDifference;
|
||||
|
||||
public Team() {
|
||||
// Required empty constructor for Firebase
|
||||
}
|
||||
|
||||
public Team(String id, String name, int points, int played) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.points = points;
|
||||
this.played = played;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public void setPoints(int points) {
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
public int getPlayed() {
|
||||
return played;
|
||||
}
|
||||
|
||||
public void setPlayed(int played) {
|
||||
this.played = played;
|
||||
}
|
||||
|
||||
public int getWon() {
|
||||
return won;
|
||||
}
|
||||
|
||||
public void setWon(int won) {
|
||||
this.won = won;
|
||||
}
|
||||
|
||||
public int getDrawn() {
|
||||
return drawn;
|
||||
}
|
||||
|
||||
public void setDrawn(int drawn) {
|
||||
this.drawn = drawn;
|
||||
}
|
||||
|
||||
public int getLost() {
|
||||
return lost;
|
||||
}
|
||||
|
||||
public void setLost(int lost) {
|
||||
this.lost = lost;
|
||||
}
|
||||
|
||||
public int getGoalsFor() {
|
||||
return goalsFor;
|
||||
}
|
||||
|
||||
public void setGoalsFor(int goalsFor) {
|
||||
this.goalsFor = goalsFor;
|
||||
}
|
||||
|
||||
public int getGoalsAgainst() {
|
||||
return goalsAgainst;
|
||||
}
|
||||
|
||||
public void setGoalsAgainst(int goalsAgainst) {
|
||||
this.goalsAgainst = goalsAgainst;
|
||||
}
|
||||
|
||||
public int getGoalDifference() {
|
||||
return goalDifference;
|
||||
}
|
||||
|
||||
public void setGoalDifference(int goalDifference) {
|
||||
this.goalDifference = goalDifference;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.example.vdcscore.ui.livegames;
|
||||
|
||||
public class Game {
|
||||
private String id;
|
||||
private String homeTeam;
|
||||
private String awayTeam;
|
||||
private int homeScore;
|
||||
private int awayScore;
|
||||
private String time;
|
||||
private int homePossession;
|
||||
private int awayPossession;
|
||||
private int homeShots;
|
||||
private int awayShots;
|
||||
|
||||
public Game(String id, String homeTeam, String awayTeam, int homeScore, int awayScore, String time) {
|
||||
this.id = id;
|
||||
this.homeTeam = homeTeam;
|
||||
this.awayTeam = awayTeam;
|
||||
this.homeScore = homeScore;
|
||||
this.awayScore = awayScore;
|
||||
this.time = time;
|
||||
// Default mocked stats
|
||||
this.homePossession = 50;
|
||||
this.awayPossession = 50;
|
||||
this.homeShots = 5;
|
||||
this.awayShots = 3;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getHomeTeam() {
|
||||
return homeTeam;
|
||||
}
|
||||
|
||||
public String getAwayTeam() {
|
||||
return awayTeam;
|
||||
}
|
||||
|
||||
public int getHomeScore() {
|
||||
return homeScore;
|
||||
}
|
||||
|
||||
public int getAwayScore() {
|
||||
return awayScore;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public int getHomePossession() {
|
||||
return homePossession;
|
||||
}
|
||||
|
||||
public int getAwayPossession() {
|
||||
return awayPossession;
|
||||
}
|
||||
|
||||
public int getHomeShots() {
|
||||
return homeShots;
|
||||
}
|
||||
|
||||
public int getAwayShots() {
|
||||
return awayShots;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.example.vdcscore.ui.livegames;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GameAdapter extends RecyclerView.Adapter<GameAdapter.GameViewHolder> {
|
||||
|
||||
private final List<Game> mGames;
|
||||
private final OnGameClickListener mListener;
|
||||
|
||||
public interface OnGameClickListener {
|
||||
void onGameClick(Game game);
|
||||
}
|
||||
|
||||
public GameAdapter(List<Game> games, OnGameClickListener listener) {
|
||||
mGames = games;
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public GameViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_live_game, parent, false);
|
||||
return new GameViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull GameViewHolder holder, int position) {
|
||||
Game game = mGames.get(position);
|
||||
holder.bind(game, mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mGames.size();
|
||||
}
|
||||
|
||||
static class GameViewHolder extends RecyclerView.ViewHolder {
|
||||
private final TextView time;
|
||||
private final TextView homeTeam;
|
||||
private final TextView awayTeam;
|
||||
private final TextView score;
|
||||
|
||||
public GameViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
time = itemView.findViewById(R.id.text_game_time);
|
||||
homeTeam = itemView.findViewById(R.id.text_home_team);
|
||||
awayTeam = itemView.findViewById(R.id.text_away_team);
|
||||
score = itemView.findViewById(R.id.text_score);
|
||||
}
|
||||
|
||||
public void bind(final Game game, final OnGameClickListener listener) {
|
||||
time.setText(game.getTime());
|
||||
homeTeam.setText(game.getHomeTeam());
|
||||
awayTeam.setText(game.getAwayTeam());
|
||||
score.setText(game.getHomeScore() + " - " + game.getAwayScore());
|
||||
|
||||
itemView.setOnClickListener(v -> listener.onGameClick(game));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.example.vdcscore.ui.livegames;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GameViewModel extends ViewModel {
|
||||
|
||||
private final MutableLiveData<List<Game>> mGames;
|
||||
private final MutableLiveData<Game> mSelectedGame;
|
||||
|
||||
public GameViewModel() {
|
||||
mGames = new MutableLiveData<>();
|
||||
mSelectedGame = new MutableLiveData<>();
|
||||
loadMockGames();
|
||||
}
|
||||
|
||||
public LiveData<List<Game>> getGames() {
|
||||
return mGames;
|
||||
}
|
||||
|
||||
public LiveData<Game> getSelectedGame() {
|
||||
return mSelectedGame;
|
||||
}
|
||||
|
||||
public void selectGame(Game game) {
|
||||
mSelectedGame.setValue(game);
|
||||
}
|
||||
|
||||
private void loadMockGames() {
|
||||
List<Game> games = new ArrayList<>();
|
||||
games.add(new Game("1", "VDC", "Benfica", 2, 1, "45'"));
|
||||
games.add(new Game("2", "Sporting", "Porto", 0, 0, "12'"));
|
||||
games.add(new Game("3", "Braga", "V. Guimarães", 1, 3, "88'"));
|
||||
mGames.setValue(games);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.example.vdcscore.ui.livegames;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
import com.example.vdcscore.databinding.FragmentLiveGameDetailBinding;
|
||||
|
||||
public class LiveGameDetailFragment extends Fragment {
|
||||
|
||||
private FragmentLiveGameDetailBinding binding;
|
||||
private GameViewModel gameViewModel;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
gameViewModel = new ViewModelProvider(requireActivity()).get(GameViewModel.class);
|
||||
|
||||
binding = FragmentLiveGameDetailBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
gameViewModel.getSelectedGame().observe(getViewLifecycleOwner(), game -> {
|
||||
if (game != null) {
|
||||
binding.detailGameTime.setText(game.getTime());
|
||||
binding.detailHomeTeam.setText(game.getHomeTeam());
|
||||
binding.detailAwayTeam.setText(game.getAwayTeam());
|
||||
binding.detailScore.setText(game.getHomeScore() + " - " + game.getAwayScore());
|
||||
|
||||
binding.progressPossession.setProgress(game.getHomePossession());
|
||||
binding.textPossessionHome.setText(game.getHomePossession() + "%");
|
||||
binding.textPossessionAway.setText(game.getAwayPossession() + "%");
|
||||
|
||||
binding.textShotsHome.setText(String.valueOf(game.getHomeShots()));
|
||||
binding.textShotsAway.setText(String.valueOf(game.getAwayShots()));
|
||||
}
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.example.vdcscore.ui.livegames;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.example.vdcscore.R;
|
||||
import com.example.vdcscore.databinding.FragmentLiveGamesBinding;
|
||||
|
||||
public class LiveGamesFragment extends Fragment {
|
||||
|
||||
private FragmentLiveGamesBinding binding;
|
||||
private GameViewModel gameViewModel;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
gameViewModel = new ViewModelProvider(requireActivity()).get(GameViewModel.class);
|
||||
|
||||
binding = FragmentLiveGamesBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
RecyclerView recyclerView = binding.recyclerLiveGames;
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
||||
gameViewModel.getGames().observe(getViewLifecycleOwner(), games -> {
|
||||
GameAdapter adapter = new GameAdapter(games, game -> {
|
||||
gameViewModel.selectGame(game);
|
||||
Navigation.findNavController(root).navigate(R.id.action_nav_live_games_to_nav_live_game_detail);
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
7
app/src/main/res/drawable/bg_bottom_sheet_curve.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF" />
|
||||
<corners
|
||||
android:topLeftRadius="30dp"
|
||||
android:topRightRadius="30dp" />
|
||||
</shape>
|
||||
9
app/src/main/res/drawable/bg_input_field.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#F5F5F5" />
|
||||
<corners android:radius="12dp" />
|
||||
<stroke
|
||||
android:width="0dp"
|
||||
android:color="#E0E0E0" />
|
||||
</shape>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#667eea" />
|
||||
<solid android:color="#616161" />
|
||||
<size
|
||||
android:width="36dp"
|
||||
android:height="36dp" />
|
||||
|
||||
17
app/src/main/res/drawable/custom_progress_bg.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<corners android:radius="6dp" />
|
||||
<solid android:color="#E0E0E0" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<corners android:radius="6dp" />
|
||||
<solid android:color="@color/secondary_color" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
5
app/src/main/res/drawable/header_background.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/primary_color"/>
|
||||
<corners android:radius="8dp"/>
|
||||
</shape>
|
||||
10
app/src/main/res/drawable/ic_calendar.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,4h-1V2h-2v2H8V2H6v2H5c-1.11,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2zM19,20H5V10h14v10zM19,8H5V6h14v2z"/>
|
||||
</vector>
|
||||
11
app/src/main/res/drawable/ic_header_login_bg.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="412dp"
|
||||
android:height="300dp"
|
||||
android:viewportWidth="412"
|
||||
android:viewportHeight="300">
|
||||
|
||||
<path
|
||||
android:fillColor="#121212"
|
||||
android:pathData="M0,0 L412,0 L412,220 C412,220 300,300 0,220 L0,0 Z" />
|
||||
</vector>
|
||||
11
app/src/main/res/drawable/ic_header_signup_bg.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="412dp"
|
||||
android:height="200dp"
|
||||
android:viewportWidth="412"
|
||||
android:viewportHeight="200">
|
||||
|
||||
<path
|
||||
android:fillColor="#121212"
|
||||
android:pathData="M0,0 L412,0 L412,150 C300,200 100,200 0,150 L0,0 Z" />
|
||||
</vector>
|
||||
BIN
app/src/main/res/drawable/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 191 KiB |
@@ -1,30 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_location.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_person.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_soccer.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-0.96 -0.78,-1.85 -1.35,-2.68 1.69,0.25 3.19,1.21 4.3,2.68zM14.53,7.69c-0.23,-0.69 -0.52,-1.36 -0.86,-1.99 -0.87,-0.3 -1.8,-0.48 -2.77,-0.48 -0.41,0 -0.81,0.04 -1.2,0.1 0.72,0.92 1.25,2.02 1.51,3.22h3.32zM8.33,5.32c-0.58,0.83 -1.04,1.72 -1.35,2.68H4.08c1.11,-1.47 2.61,-2.43 4.25,-2.68zM4.26,16h3.1c0.41,1.12 1.05,2.15 1.87,3.01 -1.97,-0.47 -3.67,-1.55 -4.97,-3.01zM4,12c0,-1.39 0.42,-2.68 1.13,-3.76 0.18,0.07 0.36,0.13 0.53,0.21 0.42,1.38 1.1,2.63 2,3.7 -0.85,1.02 -1.5,2.2 -1.92,3.5 0,0 -0.01,0 -0.01,0 -1.05,-1.03 -1.73,-2.45 -1.73,-4.06zM11.9,16.5c-1.3,0 -2.48,-0.62 -3.26,-1.59 0.73,-0.89 1.27,-1.93 1.57,-3.06h3.76l0,0c0.3,1.13 0.85,2.17 1.56,3.06 -0.78,0.97 -1.96,1.59 -3.26,1.59zM14.77,19.01c0.82,-0.86 1.46,-1.89 1.88,-3.01h3.1c-1.3,1.46 -3.01,2.54 -4.98,3.01zM17.16,11.94c0.42,-1.29 1.07,-2.48 1.92,-3.5 1.04,1.06 1.72,2.49 1.72,4.06 0,0.15 -0.01,0.29 -0.02,0.44 -1.13,-1.47 -2.62,-2.55 -4.26,-2.81 -0.19,0.64 -0.46,1.25 -0.78,1.82 0.5,0.38 0.98,0.81 1.42,1.29v-1.3z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/shape_circle_live.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/live_indicator" />
|
||||
</shape>
|
||||
6
app/src/main/res/drawable/shape_score_bg.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/primary_light" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@@ -6,7 +6,7 @@
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5"
|
||||
android:background="@color/background_light"
|
||||
tools:context=".ui.definicoes.ContaActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
@@ -20,11 +20,11 @@
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@drawable/bg_gradient"
|
||||
android:background="@color/primary_color"
|
||||
app:title="Definições de Conta"
|
||||
app:titleTextColor="#FFFFFF"
|
||||
app:titleTextColor="@color/white"
|
||||
app:navigationIcon="@drawable/ic_arrow_back"
|
||||
app:navigationIconTint="#FFFFFF" />
|
||||
app:navigationIconTint="@color/white" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
@@ -45,10 +45,10 @@
|
||||
android:id="@+id/cardProfilePhoto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:cardCornerRadius="20dp"
|
||||
app:cardElevation="4dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
android:layout_marginBottom="20dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="@color/surface_card"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<LinearLayout
|
||||
@@ -64,56 +64,61 @@
|
||||
android:text="Foto de Perfil"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1A1A1A"
|
||||
android:layout_marginBottom="20dp" />
|
||||
android:textColor="@color/primary_color"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Profile Image -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/cardImageContainer"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
app:cardCornerRadius="60dp"
|
||||
app:cardElevation="6dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageProfile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="Foto de perfil"
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
android:background="#E0E0E0" />
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/cardImageContainer"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
app:cardCornerRadius="60dp"
|
||||
app:cardElevation="6dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless">
|
||||
|
||||
<!-- Edit Icon Overlay -->
|
||||
<ImageView
|
||||
android:id="@+id/iconEditPhoto"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="8dp"
|
||||
android:src="@android:drawable/ic_menu_edit"
|
||||
android:background="@drawable/circle_edit_background"
|
||||
android:padding="8dp"
|
||||
android:contentDescription="Editar foto" />
|
||||
<ImageView
|
||||
android:id="@+id/imageProfile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="Foto de perfil"
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
android:background="#E0E0E0" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabEditPhoto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fabSize="mini"
|
||||
app:backgroundTint="@color/secondary_color"
|
||||
app:tint="@color/white"
|
||||
android:src="@android:drawable/ic_menu_edit"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/cardImageContainer"
|
||||
app:layout_constraintEnd_toEndOf="@+id/cardImageContainer"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnChangePhoto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Alterar Foto"
|
||||
android:textColor="#667eea"
|
||||
android:textSize="15sp"
|
||||
android:text="Toque para alterar"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="12dp"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -125,10 +130,10 @@
|
||||
android:id="@+id/cardName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:cardCornerRadius="20dp"
|
||||
app:cardElevation="4dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
android:layout_marginBottom="20dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="@color/surface_card"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<LinearLayout
|
||||
@@ -140,10 +145,10 @@
|
||||
<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"
|
||||
android:textColor="@color/primary_color"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Name Input -->
|
||||
@@ -151,17 +156,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Nome completo"
|
||||
app:boxCornerRadiusTopStart="16dp"
|
||||
app:boxCornerRadiusTopEnd="16dp"
|
||||
app:boxCornerRadiusBottomStart="16dp"
|
||||
app:boxCornerRadiusBottomEnd="16dp"
|
||||
app:boxStrokeWidth="2dp"
|
||||
app:boxStrokeWidthFocused="2dp"
|
||||
app:boxStrokeColor="#E0E0E0"
|
||||
app:boxStrokeColorFocused="#667eea"
|
||||
app:boxCornerRadiusTopStart="12dp"
|
||||
app:boxCornerRadiusTopEnd="12dp"
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeWidth="1dp"
|
||||
app:boxStrokeColor="@color/divider"
|
||||
app:startIconDrawable="@android:drawable/ic_menu_myplaces"
|
||||
app:startIconTint="#667eea"
|
||||
app:hintTextColor="#667eea"
|
||||
app:startIconTint="@color/text_secondary"
|
||||
app:boxBackgroundMode="outline"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
@@ -170,40 +172,38 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPersonName"
|
||||
android:textColor="#1A1A1A"
|
||||
android:textColorHint="#9E9E9E"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_secondary"
|
||||
android:textSize="16sp"
|
||||
android:padding="18dp"
|
||||
android:padding="16dp"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Save Name Button -->
|
||||
<Button
|
||||
android:id="@+id/btnSaveName"
|
||||
android:id="@+id/btnSaveAll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/button_modern"
|
||||
android:text="Guardar Nome"
|
||||
android:textColor="#FFFFFF"
|
||||
android:backgroundTint="@color/primary_color"
|
||||
android:text="Guardar Alterações"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:elevation="4dp"
|
||||
android:stateListAnimator="@null" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Email Display (Read-only) -->
|
||||
<!-- Security Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/cardEmail"
|
||||
android:id="@+id/cardSecurity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="20dp"
|
||||
app:cardElevation="4dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="@color/surface_card"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<LinearLayout
|
||||
@@ -215,22 +215,80 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Email"
|
||||
android:text="Segurança"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1A1A1A"
|
||||
android:layout_marginBottom="12dp" />
|
||||
android:textColor="@color/primary_color"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Email"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textEmail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="email@exemplo.com"
|
||||
android:textSize="16sp"
|
||||
android:textColor="#757575"
|
||||
android:textColor="@color/text_primary"
|
||||
android:padding="12dp"
|
||||
android:background="#F5F5F5"
|
||||
android:layout_marginTop="4dp" />
|
||||
android:background="@drawable/shape_score_bg"
|
||||
android:backgroundTint="@color/background_light"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnChangeEmail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/text_secondary"
|
||||
android:text="Alterar Email"
|
||||
android:textColor="@color/white" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnChangePassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:backgroundTint="@color/text_secondary"
|
||||
android:text="Alterar Password"
|
||||
android:textColor="@color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Logout Section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/cardLogout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="@color/surface_card"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnLogout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/live_time"
|
||||
android:text="Terminar Sessão"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -3,275 +3,189 @@
|
||||
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="@drawable/bg_gradient"
|
||||
android:id="@+id/main"
|
||||
android:padding="0dp">
|
||||
android:background="#FFFFFF">
|
||||
|
||||
<!-- Decorative circles for modern look -->
|
||||
<View
|
||||
android:id="@+id/circle1"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
android:background="@drawable/circle_decoration"
|
||||
android:alpha="0.1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
<!-- Header Background -->
|
||||
<ImageView
|
||||
android:id="@+id/headerBg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_header_signup_bg"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_margin="-80dp"
|
||||
app:layout_constraintTop_margin="-80dp" />
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/circle2"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="150dp"
|
||||
android:background="@drawable/circle_decoration"
|
||||
android:alpha="0.15"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_margin="-60dp"
|
||||
app:layout_constraintBottom_margin="100dp" />
|
||||
|
||||
<!-- Logo/Title Section -->
|
||||
<LinearLayout
|
||||
android:id="@+id/headerSection"
|
||||
<!-- Header Title (as per design image, showing "Sign Up" in header) or Body?
|
||||
The image shows "Sign Up" text in the header area. -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:text="Sign Up"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginTop="60dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_margin="60dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="VdcScore"
|
||||
android:textSize="48sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:letterSpacing="0.05"
|
||||
android:elevation="4dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="Criar Conta"
|
||||
android:textSize="18sp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:alpha="0.95"
|
||||
android:fontFamily="sans-serif-light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Main Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/cardRegister"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:elevation="12dp"
|
||||
app:cardCornerRadius="28dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
app:cardUseCompatPadding="true"
|
||||
app:strokeWidth="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/headerSection">
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ScrollView
|
||||
<!-- Back Button (Optional, not in Java but good for UX) -->
|
||||
|
||||
|
||||
<!-- Sign Up Form Container -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:fillViewport="true"
|
||||
android:layout_marginTop="160dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true">
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="32dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:background="@drawable/bg_bottom_sheet_curve"> <!-- Implicit white background from activity, but layout structure follows scrolling -->
|
||||
|
||||
<!-- User Name Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Nome de Utilizador"
|
||||
android:textColor="#212121"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editUserName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:background="@drawable/bg_input_field"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:inputType="textPersonName"
|
||||
android:hint="Tony"
|
||||
android:textColor="#424242"
|
||||
android:textColorHint="#BDBDBD"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Email Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Email"
|
||||
android:textColor="#212121"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editEmail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:background="@drawable/bg_input_field"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:inputType="textEmailAddress"
|
||||
android:hint="email@exemplo.com"
|
||||
android:textColor="#424242"
|
||||
android:textColorHint="#BDBDBD"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Password Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Password"
|
||||
android:textColor="#212121"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editPassword2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:background="@drawable/bg_input_field"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:inputType="textPassword"
|
||||
android:hint="********"
|
||||
android:textColor="#424242"
|
||||
android:textColorHint="#BDBDBD"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Confirm Password Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Confirmar Password"
|
||||
android:textColor="#212121"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editConfirmPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:background="@drawable/bg_input_field"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:inputType="textPassword"
|
||||
android:hint="********"
|
||||
android:textColor="#424242"
|
||||
android:textColorHint="#BDBDBD"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="32dp" />
|
||||
|
||||
|
||||
<!-- Sign Up Button -->
|
||||
<Button
|
||||
android:id="@+id/btnCreateAccount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="55dp"
|
||||
android:text="Sign Up"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:backgroundTint="#000000"
|
||||
app:cornerRadius="12dp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Login Link -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp">
|
||||
|
||||
<!-- Title inside card -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Registo"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1A1A1A"
|
||||
android:layout_marginBottom="8dp" />
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Cria a tua conta para começar"
|
||||
android:textSize="15sp"
|
||||
android:textColor="#757575"
|
||||
android:layout_marginBottom="32dp" />
|
||||
android:text="Já tem uma conta? "
|
||||
android:textColor="#757575" />
|
||||
|
||||
<!-- Email Input -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
<TextView
|
||||
android:id="@+id/txtGoLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:hint="Email"
|
||||
app:boxCornerRadiusTopStart="16dp"
|
||||
app:boxCornerRadiusTopEnd="16dp"
|
||||
app:boxCornerRadiusBottomStart="16dp"
|
||||
app:boxCornerRadiusBottomEnd="16dp"
|
||||
app:boxStrokeWidth="2dp"
|
||||
app:boxStrokeWidthFocused="2dp"
|
||||
app:boxStrokeColor="#E0E0E0"
|
||||
app:boxStrokeColorFocused="#667eea"
|
||||
app:startIconDrawable="@android:drawable/ic_dialog_email"
|
||||
app:startIconTint="#667eea"
|
||||
app:hintTextColor="#667eea"
|
||||
app:boxBackgroundMode="outline"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editEmail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textEmailAddress"
|
||||
android:textColor="#1A1A1A"
|
||||
android:textColorHint="#9E9E9E"
|
||||
android:textSize="16sp"
|
||||
android:padding="18dp"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Password Input -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:hint="Password"
|
||||
app:boxCornerRadiusTopStart="16dp"
|
||||
app:boxCornerRadiusTopEnd="16dp"
|
||||
app:boxCornerRadiusBottomStart="16dp"
|
||||
app:boxCornerRadiusBottomEnd="16dp"
|
||||
app:boxStrokeWidth="2dp"
|
||||
app:boxStrokeWidthFocused="2dp"
|
||||
app:boxStrokeColor="#E0E0E0"
|
||||
app:boxStrokeColorFocused="#667eea"
|
||||
app:startIconDrawable="@android:drawable/ic_lock_lock"
|
||||
app:startIconTint="#667eea"
|
||||
app:hintTextColor="#667eea"
|
||||
app:endIconMode="password_toggle"
|
||||
app:endIconTint="#667eea"
|
||||
app:boxBackgroundMode="outline"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editPassword2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword"
|
||||
android:textColor="#1A1A1A"
|
||||
android:textColorHint="#9E9E9E"
|
||||
android:textSize="16sp"
|
||||
android:padding="18dp"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Confirm Password Input -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:hint="Confirmar Password"
|
||||
app:boxCornerRadiusTopStart="16dp"
|
||||
app:boxCornerRadiusTopEnd="16dp"
|
||||
app:boxCornerRadiusBottomStart="16dp"
|
||||
app:boxCornerRadiusBottomEnd="16dp"
|
||||
app:boxStrokeWidth="2dp"
|
||||
app:boxStrokeWidthFocused="2dp"
|
||||
app:boxStrokeColor="#E0E0E0"
|
||||
app:boxStrokeColorFocused="#667eea"
|
||||
app:startIconDrawable="@android:drawable/ic_lock_lock"
|
||||
app:startIconTint="#667eea"
|
||||
app:hintTextColor="#667eea"
|
||||
app:endIconMode="password_toggle"
|
||||
app:endIconTint="#667eea"
|
||||
app:boxBackgroundMode="outline"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editConfirmPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword"
|
||||
android:textColor="#1A1A1A"
|
||||
android:textColorHint="#9E9E9E"
|
||||
android:textSize="16sp"
|
||||
android:padding="18dp"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Create Account Button -->
|
||||
<Button
|
||||
android:id="@+id/btnCreateAccount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="@drawable/button_modern"
|
||||
android:text="Criar Conta"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="17sp"
|
||||
android:text="Sign In"
|
||||
android:textColor="#000000"
|
||||
android:textStyle="bold"
|
||||
android:letterSpacing="0.05"
|
||||
android:elevation="6dp"
|
||||
android:stateListAnimator="@null"
|
||||
android:layout_marginTop="12dp" />
|
||||
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Login Link -->
|
||||
<LinearLayout
|
||||
android:id="@+id/loginSection"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cardRegister"
|
||||
app:layout_constraintTop_margin="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Já tens conta? "
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="15sp"
|
||||
android:alpha="0.9" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtGoLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Entrar"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textStyle="bold"
|
||||
android:textSize="15sp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -5,247 +5,177 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/bg_gradient"
|
||||
android:padding="0dp">
|
||||
android:background="#FFFFFF">
|
||||
|
||||
<!-- Decorative circles for modern look -->
|
||||
<View
|
||||
android:id="@+id/circle1"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
android:background="@drawable/circle_decoration"
|
||||
android:alpha="0.1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
<!-- Header Background -->
|
||||
<ImageView
|
||||
android:id="@+id/headerBg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_header_login_bg"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_margin="-80dp"
|
||||
app:layout_constraintTop_margin="-80dp" />
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/circle2"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="150dp"
|
||||
android:background="@drawable/circle_decoration"
|
||||
android:alpha="0.15"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_margin="-60dp"
|
||||
app:layout_constraintBottom_margin="100dp" />
|
||||
|
||||
<!-- Logo/Title Section -->
|
||||
<LinearLayout
|
||||
android:id="@+id/headerSection"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
<!-- Logo -->
|
||||
<ImageView
|
||||
android:id="@+id/logoImage"
|
||||
android:layout_width="77dp"
|
||||
android:layout_height="80dp"
|
||||
android:layout_marginTop="60dp"
|
||||
android:elevation="4dp"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_margin="80dp">
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="VdcScore"
|
||||
android:textSize="48sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:letterSpacing="0.05"
|
||||
android:elevation="4dp" />
|
||||
<!-- Login Form Container -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:fillViewport="true"
|
||||
android:layout_marginTop="-40dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/headerBg"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="Bem-vindo de volta"
|
||||
android:textSize="18sp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:alpha="0.95"
|
||||
android:fontFamily="sans-serif-light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Main Card -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/cardLogin"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:elevation="12dp"
|
||||
app:cardCornerRadius="28dp"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
app:cardUseCompatPadding="true"
|
||||
app:strokeWidth="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/headerSection">
|
||||
|
||||
<LinearLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp">
|
||||
android:paddingHorizontal="32dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp">
|
||||
|
||||
<!-- Title inside card -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Login"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1A1A1A"
|
||||
android:layout_marginBottom="8dp" />
|
||||
android:textColor="#212121"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="40dp" />
|
||||
|
||||
<!-- Email Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Entre na sua conta para continuar"
|
||||
android:textSize="15sp"
|
||||
android:textColor="#757575"
|
||||
android:layout_marginBottom="32dp" />
|
||||
android:text="Email"
|
||||
android:textColor="#212121"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
|
||||
<!-- Email Input -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editEmail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:hint="Email"
|
||||
app:boxCornerRadiusTopStart="16dp"
|
||||
app:boxCornerRadiusTopEnd="16dp"
|
||||
app:boxCornerRadiusBottomStart="16dp"
|
||||
app:boxCornerRadiusBottomEnd="16dp"
|
||||
app:boxStrokeWidth="2dp"
|
||||
app:boxStrokeWidthFocused="2dp"
|
||||
app:boxStrokeColor="#E0E0E0"
|
||||
app:boxStrokeColorFocused="#667eea"
|
||||
app:startIconDrawable="@android:drawable/ic_dialog_email"
|
||||
app:startIconTint="#667eea"
|
||||
app:hintTextColor="#667eea"
|
||||
app:boxBackgroundMode="outline"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
android:layout_height="50dp"
|
||||
android:background="@drawable/bg_input_field"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:inputType="textEmailAddress"
|
||||
android:hint="email@exemplo.com"
|
||||
android:textColor="#424242"
|
||||
android:textColorHint="#BDBDBD"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editEmail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textEmailAddress"
|
||||
android:textColor="#1A1A1A"
|
||||
android:textColorHint="#9E9E9E"
|
||||
android:textSize="16sp"
|
||||
android:padding="18dp"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Password Input -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:hint="Password"
|
||||
app:boxCornerRadiusTopStart="16dp"
|
||||
app:boxCornerRadiusTopEnd="16dp"
|
||||
app:boxCornerRadiusBottomStart="16dp"
|
||||
app:boxCornerRadiusBottomEnd="16dp"
|
||||
app:boxStrokeWidth="2dp"
|
||||
app:boxStrokeWidthFocused="2dp"
|
||||
app:boxStrokeColor="#E0E0E0"
|
||||
app:boxStrokeColorFocused="#667eea"
|
||||
app:startIconDrawable="@android:drawable/ic_lock_lock"
|
||||
app:startIconTint="#667eea"
|
||||
app:hintTextColor="#667eea"
|
||||
app:endIconMode="password_toggle"
|
||||
app:endIconTint="#667eea"
|
||||
app:boxBackgroundMode="outline"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editPassword2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword"
|
||||
android:textColor="#1A1A1A"
|
||||
android:textColorHint="#9E9E9E"
|
||||
android:textSize="16sp"
|
||||
android:padding="18dp"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Forgot Password Link -->
|
||||
<!-- Password Label -->
|
||||
<TextView
|
||||
android:id="@+id/txtForgotPassword"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginBottom="28dp"
|
||||
android:text="Esqueceu a palavra-passe?"
|
||||
android:textColor="#667eea"
|
||||
android:textSize="14sp"
|
||||
android:text="Password"
|
||||
android:textColor="#212121"
|
||||
android:textStyle="bold"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless" />
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
|
||||
<!-- Password Input -->
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editPassword2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:background="@drawable/bg_input_field"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:inputType="textPassword"
|
||||
android:hint="********"
|
||||
android:textColor="#424242"
|
||||
android:textColorHint="#BDBDBD"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Remember Me & Forgot Password -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="32dp">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkRememberMe"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Lembrar"
|
||||
android:textColor="#757575"/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtForgotPassword"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Esqueceu a senha?"
|
||||
android:textColor="#757575"
|
||||
android:textStyle="bold"
|
||||
android:textSize="12sp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Login Button -->
|
||||
<Button
|
||||
android:id="@+id/btnLogin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="@drawable/button_modern"
|
||||
android:text="Entrar"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="17sp"
|
||||
android:layout_height="55dp"
|
||||
android:text="Login"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:letterSpacing="0.05"
|
||||
android:elevation="6dp"
|
||||
android:stateListAnimator="@null"
|
||||
android:layout_marginTop="4dp" />
|
||||
android:textColor="#FFFFFF"
|
||||
android:backgroundTint="#000000"
|
||||
app:cornerRadius="12dp"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Sign Up Link -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Não tem uma conta? "
|
||||
android:textColor="#757575" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtRegister"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Criar Conta"
|
||||
android:textColor="#000000"
|
||||
android:textStyle="bold"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- Register Link -->
|
||||
<LinearLayout
|
||||
android:id="@+id/registerSection"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cardLogin"
|
||||
app:layout_constraintTop_margin="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Não tens conta? "
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="15sp"
|
||||
android:alpha="0.9" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtRegister"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Criar conta"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textStyle="bold"
|
||||
android:textSize="15sp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:drawablePadding="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:fitsSystemWindows="true"
|
||||
android:background="@color/white"
|
||||
app:itemTextColor="@color/black"
|
||||
app:itemIconTint="@color/black"
|
||||
app:headerLayout="@layout/nav_header_main"
|
||||
app:menu="@menu/activity_main_drawer" />
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
@@ -85,7 +85,6 @@
|
||||
app:boxCornerRadiusBottomStart="12dp"
|
||||
app:boxCornerRadiusBottomEnd="12dp"
|
||||
app:boxStrokeWidth="0dp"
|
||||
app:boxStrokeWidthFocused="0dp"
|
||||
app:startIconDrawable="@android:drawable/ic_dialog_email"
|
||||
app:startIconTint="#667eea"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
@@ -9,26 +9,21 @@
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/Theme.VdcScore.AppBarOverlay">
|
||||
android:background="@color/white"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Light"> <!-- Light theme for dark text -->
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:background="@color/white"
|
||||
app:titleTextColor="@color/black"
|
||||
app:popupTheme="@style/Theme.VdcScore.PopupOverlay" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="@dimen/fab_margin"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:srcCompat="@android:drawable/ic_dialog_email" />
|
||||
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
232
app/src/main/res/layout/fragment_club_detail.xml
Normal file
@@ -0,0 +1,232 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:background="@color/white"
|
||||
tools:context=".ui.clubs.ClubDetailFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<!-- Club Logo (Circular) -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardLogo"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
app:cardCornerRadius="100dp"
|
||||
app:cardElevation="8dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_detail_logo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:padding="0dp"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- CLUBE Label -->
|
||||
<TextView
|
||||
android:id="@+id/label_club"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CLUBE:"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#616161"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/cardLogo"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<!-- Club Name -->
|
||||
<TextView
|
||||
android:id="@+id/text_detail_club_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Inter Freguesias Vila do Conde"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#0D47A1"
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/label_club"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<!-- President Section -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_president"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_detail_club_name"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_person"
|
||||
app:tint="#455A64"
|
||||
android:background="@drawable/circle_edit_background"
|
||||
android:backgroundTint="#ECEFF1"
|
||||
android:padding="8dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginStart="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PRESIDENTE:"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#616161"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_detail_president"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="João Silva"
|
||||
android:textSize="16sp"
|
||||
android:textColor="#263238"
|
||||
android:textStyle="bold"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Address Section -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_president"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_location"
|
||||
app:tint="#455A64"
|
||||
android:background="@drawable/circle_edit_background"
|
||||
android:backgroundTint="#ECEFF1"
|
||||
android:padding="8dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginStart="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="MORADA:"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#616161"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_detail_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Rua Desportiva 123"
|
||||
android:textSize="16sp"
|
||||
android:textColor="#263238"
|
||||
android:textStyle="bold"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Foundation Section -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_foundation"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_address"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_calendar"
|
||||
app:tint="#455A64"
|
||||
android:background="@drawable/circle_edit_background"
|
||||
android:backgroundTint="#ECEFF1"
|
||||
android:padding="8dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginStart="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="ANO DE FUNDAÇÃO:"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#616161"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_detail_foundation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="1995"
|
||||
android:textSize="16sp"
|
||||
android:textColor="#263238"
|
||||
android:textStyle="bold"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Stadium Section (Hidden per screenshot but kept in model, or should I show it?)
|
||||
The screenshot doesn't explicitly show Stadium but the code had it.
|
||||
I will hide it for now to match screenshot strictly or add it if plenty space?
|
||||
The user said "appears like this", implies following the screenshot.
|
||||
But previously stadium was shown. I will add it as well for completeness if it fits,
|
||||
or just omit if the screenshot is strict.
|
||||
Screenshot: CLUBE, PRESIDENTE, MORADA, ANO DE FUNDACAO. No Stadium.
|
||||
I will omit Stadium from UI to match unique request "like this".
|
||||
-->
|
||||
|
||||
<!-- Players Button -->
|
||||
<Button
|
||||
android:id="@+id/btn_players"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:text="JOGADORES\n(Ver Lista)"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="12dp"
|
||||
android:backgroundTint="#1976D2"
|
||||
app:icon="@drawable/ic_soccer"
|
||||
app:iconGravity="textStart"
|
||||
app:iconSize="32dp"
|
||||
app:iconTint="@color/white"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="40dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_foundation"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
android:layout_marginBottom="20dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
41
app/src/main/res/layout/fragment_club_players.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5"
|
||||
tools:context=".ui.clubs.ClubPlayersFragment">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_players_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="8dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_no_players"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Sem jogadores inscritos"
|
||||
android:textSize="18sp"
|
||||
android:textColor="#757575"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBarPlayers"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
55
app/src/main/res/layout/fragment_clubs.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background_light">
|
||||
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/toggleGroupEscalao"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:checkedButton="@id/btnSeniores"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:singleSelection="true">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnSeniores"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Seniores" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnJuniores"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Juniores" />
|
||||
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_clubs"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toggleGroupEscalao" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#ECEFF1">
|
||||
android:background="@color/background_light">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -16,7 +16,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Definições"
|
||||
android:textColor="#263238"
|
||||
android:textColor="@color/primary_color"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="Personaliza a aplicação de acordo com o teu gosto."
|
||||
android:textColor="#546E7A"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
@@ -33,30 +33,34 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardUseCompatPadding="true"
|
||||
app:strokeColor="#CFD8DC"
|
||||
app:strokeWidth="1dp">
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="@color/divider"
|
||||
app:strokeWidth="1dp"
|
||||
app:cardBackgroundColor="@color/surface_card">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="18dp">
|
||||
android:padding="20dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:contentDescription="@string/menu_definicoes"
|
||||
android:padding="4dp"
|
||||
android:src="@android:drawable/ic_menu_manage" />
|
||||
android:src="@android:drawable/ic_menu_manage"
|
||||
app:tint="@color/black"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
@@ -64,7 +68,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Conta"
|
||||
android:textColor="#263238"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
@@ -72,7 +76,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Atualiza os teus dados pessoais"
|
||||
android:textColor="#607D8B"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -80,7 +84,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/menu_definicoes"
|
||||
android:src="@android:drawable/ic_media_next" />
|
||||
android:src="@android:drawable/ic_media_next"
|
||||
app:tint="@color/text_secondary"/>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
@@ -89,13 +94,16 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardUseCompatPadding="true">
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="@color/divider"
|
||||
app:strokeWidth="1dp"
|
||||
app:cardBackgroundColor="@color/surface_card">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="18dp">
|
||||
android:padding="20dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -113,7 +121,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Notificações"
|
||||
android:textColor="#263238"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
@@ -122,7 +130,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Ativadas"
|
||||
android:textColor="#607D8B"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -136,8 +144,8 @@
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
android:background="#ECEFF1" />
|
||||
android:layout_marginVertical="16dp"
|
||||
android:background="@color/divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -155,7 +163,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Modo escuro"
|
||||
android:textColor="#263238"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
@@ -164,7 +172,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Inativo"
|
||||
android:textColor="#607D8B"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -181,19 +189,22 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardUseCompatPadding="true">
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="@color/divider"
|
||||
app:strokeWidth="1dp"
|
||||
app:cardBackgroundColor="@color/surface_card">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="18dp">
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Ajuda e suporte"
|
||||
android:textColor="#263238"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
@@ -202,20 +213,19 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="Consulta a nossa base de conhecimento ou fala connosco."
|
||||
android:textColor="#607D8B"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOpenSystemSettings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:backgroundTint="#1E88E5"
|
||||
android:layout_marginTop="16dp"
|
||||
android:backgroundTint="@color/black"
|
||||
android:text="Abrir definições do sistema"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="#FFFFFF" />
|
||||
android:textColor="@color/white" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
<?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"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@color/background_light"
|
||||
tools:context=".ui.gallery.GalleryFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_gallery"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:text="Jornadas"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_color"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_matchdays"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="16dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,22 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout 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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@color/background_light"
|
||||
tools:context=".ui.home.HomeFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_home"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:text="Classificação"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_color"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Table Header (Clean) -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="12dp"
|
||||
android:paddingHorizontal="4dp"
|
||||
android:background="#00000000">
|
||||
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="#"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Clube"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="J"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"
|
||||
android:tooltipText="Jogos" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="Pts"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/divider"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_standings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="4dp" />
|
||||
</LinearLayout>
|
||||
201
app/src/main/res/layout/fragment_live_game_detail.xml
Normal file
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background_light">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- Header Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="@color/primary_color"
|
||||
app:cardCornerRadius="24dp"
|
||||
app:cardElevation="6dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_game_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="65'"
|
||||
android:textColor="@color/live_time"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_home_team"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:text="Home"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@+id/detail_score"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/detail_game_time" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_score"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:text="1 - 1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="36sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/detail_home_team"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/detail_home_team" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_away_team"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="Away"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/detail_home_team"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/detail_score"
|
||||
app:layout_constraintTop_toTopOf="@+id/detail_home_team" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Stats Section -->
|
||||
<TextView
|
||||
android:id="@+id/text_stats_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="Estatísticas ao Vivo"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="@color/surface_card">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- Possession -->
|
||||
<TextView
|
||||
android:id="@+id/label_possession"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="Posse de Bola"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_possession_home"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="50%"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginEnd="12dp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_possession"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_weight="1"
|
||||
android:max="100"
|
||||
android:progress="50"
|
||||
android:progressDrawable="@drawable/custom_progress_bg"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_possession_away"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="50%"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginStart="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/divider"
|
||||
android:layout_marginVertical="16dp"/>
|
||||
|
||||
<!-- Shots -->
|
||||
<TextView
|
||||
android:id="@+id/label_shots"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="Remates"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_shots_home"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="5"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/secondary_color"
|
||||
android:layout_marginEnd="32dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_shots_away"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="3"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/secondary_color"
|
||||
android:layout_marginStart="32dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
33
app/src/main/res/layout/fragment_live_games.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background_light">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_live_games"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="8dp"
|
||||
android:clipToPadding="false"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_no_games"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Não há jogos ao vivo no momento"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
66
app/src/main/res/layout/item_club.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="6dp"
|
||||
app:cardBackgroundColor="@color/surface_card"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_logo"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
app:cardCornerRadius="25dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardBackgroundColor="#F0F0F0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_club_logo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_menu_gallery"
|
||||
android:padding="8dp"/>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_club_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="Club Name"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="17sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/text_club_stadium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/card_logo"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_club_stadium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="Stadium Name"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/text_club_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_club_name" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
85
app/src/main/res/layout/item_live_game.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
app:cardBackgroundColor="@color/surface_card"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_game_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="45'"
|
||||
android:textColor="@color/live_time"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/live_indicator"
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:background="@drawable/shape_circle_live"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/text_game_time"
|
||||
app:layout_constraintEnd_toStartOf="@+id/text_game_time"
|
||||
app:layout_constraintTop_toTopOf="@+id/text_game_time" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_home_team"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:text="Home Team"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@+id/text_score"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text_game_time" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_score"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:background="@drawable/shape_score_bg"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="2 - 1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/text_home_team"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/text_home_team" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_away_team"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="Away Team"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/text_home_team"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/text_score"
|
||||
app:layout_constraintTop_toTopOf="@+id/text_home_team" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
58
app/src/main/res/layout/item_match.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<!-- Home Team -->
|
||||
<TextView
|
||||
android:id="@+id/text_home_team"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:text="Home"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
<!-- Score / Time -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:minWidth="60dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_score"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Vs"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/secondary_color"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="15:00"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_secondary" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Away Team -->
|
||||
<TextView
|
||||
android:id="@+id/text_away_team"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:text="Away"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary" />
|
||||
|
||||
</LinearLayout>
|
||||
39
app/src/main/res/layout/item_matchday.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="4dp"
|
||||
app:contentPadding="0dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header -->
|
||||
<TextView
|
||||
android:id="@+id/text_matchday_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/primary_light"
|
||||
android:textColor="@color/white"
|
||||
android:padding="12dp"
|
||||
android:text="Jornada 1"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<!-- Matches List -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_matches"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/item_match" xmlns:tools="http://schemas.android.com/tools"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
25
app/src/main/res/layout/item_player.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_player_icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_menu_camera"
|
||||
android:contentDescription="Player Icon"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_player_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Player Name"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
59
app/src/main/res/layout/item_standing.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="16dp"
|
||||
android:paddingHorizontal="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_position"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="1"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_team_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Team Name"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="normal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_played"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="P"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_points"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="Pts"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#F5F5F5"/>
|
||||
</LinearLayout>
|
||||
@@ -1,35 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
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:gravity="bottom"
|
||||
android:layout_height="200dp"
|
||||
android:background="@drawable/ic_header_login_bg"
|
||||
android:gravity="top"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark">
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Light">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/nav_header_desc"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
app:srcCompat="@mipmap/ic_launcher_round" />
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:cardCornerRadius="40dp"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="4dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/nav_header_desc"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@mipmap/ic_launcher_round" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
android:paddingTop="4dp"
|
||||
android:text="@string/nav_header_title"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/textViewSubtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/nav_header_subtitle" />
|
||||
android:text="@string/nav_header_subtitle"
|
||||
android:textColor="@color/background_light"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
@@ -12,6 +12,14 @@
|
||||
android:id="@+id/nav_gallery"
|
||||
android:icon="@drawable/ic_menu_gallery"
|
||||
android:title="@string/menu_gallery" />
|
||||
<item
|
||||
android:id="@+id/nav_live_games"
|
||||
android:icon="@android:drawable/ic_menu_view"
|
||||
android:title="@string/menu_live_games" />
|
||||
<item
|
||||
android:id="@+id/nav_clubs"
|
||||
android:icon="@android:drawable/ic_menu_my_calendar"
|
||||
android:title="@string/menu_clubs" />
|
||||
<item
|
||||
android:id="@+id/nav_definicoes"
|
||||
android:icon="@android:drawable/ic_menu_preferences"
|
||||
|
||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 982 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -22,4 +22,60 @@
|
||||
android:name="com.example.vdcscore.ui.definicoes.DefinicoesFragment"
|
||||
android:label="@string/menu_definicoes"
|
||||
tools:layout="@layout/fragment_definicoes" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_live_games"
|
||||
android:name="com.example.vdcscore.ui.livegames.LiveGamesFragment"
|
||||
android:label="@string/menu_live_games"
|
||||
tools:layout="@layout/fragment_live_games">
|
||||
<action
|
||||
android:id="@+id/action_nav_live_games_to_nav_live_game_detail"
|
||||
app:destination="@id/nav_live_game_detail" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_live_game_detail"
|
||||
android:name="com.example.vdcscore.ui.livegames.LiveGameDetailFragment"
|
||||
android:label="@string/title_live_game_detail"
|
||||
tools:layout="@layout/fragment_live_game_detail" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_clubs"
|
||||
android:name="com.example.vdcscore.ui.clubs.ClubsFragment"
|
||||
android:label="@string/menu_clubs"
|
||||
tools:layout="@layout/fragment_clubs">
|
||||
<action
|
||||
android:id="@+id/action_nav_clubs_to_nav_club_detail"
|
||||
app:destination="@id/nav_club_detail" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_club_detail"
|
||||
android:name="com.example.vdcscore.ui.clubs.ClubDetailFragment"
|
||||
android:label="Detalhes do Clube"
|
||||
tools:layout="@layout/fragment_club_detail">
|
||||
<argument
|
||||
android:name="clubId"
|
||||
app:argType="string" />
|
||||
<argument
|
||||
android:name="escalao"
|
||||
app:argType="string" />
|
||||
<action
|
||||
android:id="@+id/action_nav_club_detail_to_nav_club_players"
|
||||
app:destination="@id/nav_club_players" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_club_players"
|
||||
android:name="com.example.vdcscore.ui.clubs.ClubPlayersFragment"
|
||||
android:label="Jogadores"
|
||||
tools:layout="@layout/fragment_club_players">
|
||||
<argument
|
||||
android:name="clubId"
|
||||
app:argType="string" />
|
||||
<argument
|
||||
android:name="escalao"
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
|
||||
</navigation>
|
||||
@@ -1,7 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.VdcScore" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
<!-- Force White Status Bar even in Dark Mode -->
|
||||
<item name="android:statusBarColor">@color/white</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
|
||||
<item name="colorPrimary">@color/primary_color</item>
|
||||
<item name="colorPrimaryVariant">@color/primary_dark</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<item name="colorSecondary">@color/secondary_color</item>
|
||||
<item name="colorSecondaryVariant">@color/secondary_dark</item>
|
||||
<item name="colorOnSecondary">@color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.VdcScore" parent="Base.Theme.VdcScore" />
|
||||
|
||||
<style name="Theme.VdcScore.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<!-- Explicitly enforce status bar settings here too -->
|
||||
<item name="android:statusBarColor">@color/white</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -2,4 +2,27 @@
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
|
||||
<!-- Minimalist Palette -->
|
||||
<color name="primary_color">#000000</color> <!-- Black -->
|
||||
<color name="primary_light">#404040</color> <!-- Dark Grey -->
|
||||
<color name="primary_dark">#000000</color>
|
||||
|
||||
<color name="secondary_color">#212121</color> <!-- Dark Grey Accent -->
|
||||
<color name="secondary_light">#484848</color>
|
||||
<color name="secondary_dark">#000000</color>
|
||||
|
||||
<color name="live_indicator">#00E676</color> <!-- Bright Green (Keep for utility) -->
|
||||
<color name="live_time">#FF1744</color> <!-- Red for time (Keep for utility) -->
|
||||
|
||||
<color name="background_light">#FFFFFF</color> <!-- Pure White Background -->
|
||||
<color name="surface_light">#FFFFFF</color>
|
||||
<color name="surface_card">#FFFFFF</color> <!-- White Card -->
|
||||
|
||||
<color name="text_primary">#212121</color> <!-- Almost Black -->
|
||||
<color name="text_secondary">#757575</color> <!-- Grey -->
|
||||
<color name="text_on_primary">#FFFFFF</color>
|
||||
|
||||
<color name="divider">#EEEEEE</color> <!-- Very light grey divider -->
|
||||
<color name="input_background">#F5F5F5</color> <!-- Light grey for inputs/cards if needed -->
|
||||
</resources>
|
||||
@@ -1,14 +1,25 @@
|
||||
<resources>
|
||||
<string name="app_name">VdcScore</string>
|
||||
<string name="title_activity_main">MainActivity</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="nav_header_title">Android Studio</string>
|
||||
<string name="nav_header_subtitle">android.studio@android.com</string>
|
||||
<string name="nav_header_desc">Navigation header</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="title_activity_main">Classificação</string>
|
||||
<string name="navigation_drawer_open">Abrir menu</string>
|
||||
<string name="navigation_drawer_close">Fechar menu</string>
|
||||
<string name="nav_header_title">VdcScore</string>
|
||||
<string name="nav_header_subtitle">O teu clube</string>
|
||||
<string name="nav_header_desc">Cabeçalho de navegação</string>
|
||||
<string name="action_settings">Definições</string>
|
||||
|
||||
<string name="menu_home">Home</string>
|
||||
<string name="menu_gallery">Gallery</string>
|
||||
<string name="menu_home">Classificação</string>
|
||||
<string name="menu_gallery">Jornadas</string>
|
||||
<string name="menu_definicoes">Definições</string>
|
||||
<string name="menu_live_games">Jogos ao Vivo</string>
|
||||
<string name="title_live_game_detail">Detalhes do Jogo</string>
|
||||
<string name="menu_clubs">Clubes</string>
|
||||
|
||||
<!-- Profile Strings -->
|
||||
<string name="change_photo_title">Alterar Foto de Perfil</string>
|
||||
<string name="choose_gallery">Escolher da Galeria</string>
|
||||
<string name="enter_url">Inserir URL</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="url_hint">https://exemplo.com/foto.jpg</string>
|
||||
</resources>
|
||||
@@ -1,8 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.VdcScore" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your light theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
|
||||
<item name="colorPrimary">@color/primary_color</item>
|
||||
<item name="colorPrimaryVariant">@color/primary_dark</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<item name="colorSecondary">@color/secondary_color</item>
|
||||
<item name="colorSecondaryVariant">@color/secondary_dark</item>
|
||||
<item name="colorOnSecondary">@color/white</item>
|
||||
|
||||
<!-- Status Bar Settings -->
|
||||
<item name="android:statusBarColor">@color/white</item>
|
||||
<item name="android:windowLightStatusBar">true</item> <!-- Dark icons -->
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
|
||||
<item name="android:textColorPrimary">@color/text_primary</item>
|
||||
<item name="android:textColorSecondary">@color/text_secondary</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.VdcScore" parent="Base.Theme.VdcScore" />
|
||||
@@ -10,6 +24,10 @@
|
||||
<style name="Theme.VdcScore.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<!-- Explicitly enforce status bar settings here too to avoid inheritance issues -->
|
||||
<item name="android:statusBarColor">@color/white</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.VdcScore.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
BIN
build_log.txt
Normal file
@@ -1,5 +1,5 @@
|
||||
[versions]
|
||||
agp = "8.13.1"
|
||||
agp = "8.13.2"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.3.0"
|
||||
espressoCore = "3.7.0"
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,4 +1,4 @@
|
||||
#Wed Nov 19 10:03:29 WET 2025
|
||||
#Wed Feb 25 12:48:32 WET 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
|
||||