Refactored main, added comments and bottom nav animations

This commit is contained in:
Pau 2025-05-13 21:10:23 +02:00
parent d0c5cf1f44
commit 5ab3288350
5 changed files with 269 additions and 88 deletions

View File

@ -19,7 +19,7 @@ import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import com.example.acloc.activities.ManageRolesActivity; import com.example.acloc.activity.ManageRolesActivity;
import com.example.acloc.api.ApiClient; import com.example.acloc.api.ApiClient;
import com.example.acloc.dialog.AlertChangePasswordDialog; import com.example.acloc.dialog.AlertChangePasswordDialog;
import com.example.acloc.dialog.AlertViewOrUpdateProfileDialog; import com.example.acloc.dialog.AlertViewOrUpdateProfileDialog;
@ -34,6 +34,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.ieslamar.acloc.R;
import java.util.Locale; import java.util.Locale;
@ -43,43 +44,74 @@ import retrofit2.Response;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName(); private static final String TAG = MainActivity.class.getSimpleName();
// UI Components
private RelativeLayout rlMainActivity; private RelativeLayout rlMainActivity;
private BottomNavigationView bottomNavigationView; private BottomNavigationView bottomNavigationView;
private Toolbar toolbar; private Toolbar toolbar;
// Variables
private Dialog dialog; private Dialog dialog;
private Context context; private Context context;
private Fragment currentFragment;
// Animation constants
private static final int ANIM_ENTER_RIGHT = R.anim.slide_in_right;
private static final int ANIM_EXIT_LEFT = R.anim.slide_out_left;
private static final int ANIM_ENTER_LEFT = R.anim.slide_in_left;
private static final int ANIM_EXIT_RIGHT = R.anim.slide_out_right;
private static final int ANIM_FADE_IN = android.R.anim.fade_in;
private static final int ANIM_FADE_OUT = android.R.anim.fade_out;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
// Get saved language from SharedPreferences applyLanguageSettings();
String savedLanguage = SharedPref.getLanguage(this);
// Check if current language matches saved
if (!Locale.getDefault().getLanguage().equals(savedLanguage)) {
setLocale(savedLanguage); // Apply only if needed
}
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
initToolbar(); initToolbar();
initUI(); initUI();
initObj(); initObj();
initListeners(); initListeners();
// Load default fragment // Load default fragment
loadDefaultFragment(savedInstanceState); loadDefaultFragment(savedInstanceState);
getRoleUuids(); fetchRoleUuids();
} }
/**
* Apply language settings from SharedPreferences
*/
private void applyLanguageSettings() {
String savedLanguage = SharedPref.getLanguage(this);
if (!Locale.getDefault().getLanguage().equals(savedLanguage)) {
setLocale(savedLanguage);
}
}
/**
* Initialize toolbar
*/
private void initToolbar() { private void initToolbar() {
toolbar = findViewById(R.id.toolbar); toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
} }
/**
* Initialize UI components
*/
private void initUI() { private void initUI() {
rlMainActivity = findViewById(R.id.rlMainActivity); rlMainActivity = findViewById(R.id.rlMainActivity);
bottomNavigationView = findViewById(R.id.bottomNavView); bottomNavigationView = findViewById(R.id.bottomNavView);
} }
/**
* Initialize objects
*/
private void initObj() {
context = this;
}
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
@ -89,11 +121,10 @@ public class MainActivity extends AppCompatActivity {
m.setOptionalIconsVisible(true); m.setOptionalIconsVisible(true);
} }
// show/hide the "Manage Roles" menu item // Show/hide the "Manage Roles" menu item based on user role
MenuItem manageNotesItem = menu.findItem(R.id.menu_manageRoles); MenuItem manageRolesItem = menu.findItem(R.id.menu_manageRoles);
if (!"admin".equalsIgnoreCase(SharedPref.getRole(context))) { boolean isAdmin = "admin".equalsIgnoreCase(SharedPref.getRole(context));
manageNotesItem.setVisible(false); // hide for non-admins manageRolesItem.setVisible(isAdmin);
}
return true; return true;
} }
@ -103,24 +134,29 @@ public class MainActivity extends AppCompatActivity {
int id = item.getItemId(); int id = item.getItemId();
if (id == R.id.menu_profile) { if (id == R.id.menu_profile) {
dialog = new AlertViewOrUpdateProfileDialog(context) dialog = new AlertViewOrUpdateProfileDialog(context).openProfileDialog();
.openProfileDialog();
return true; return true;
} else if (id == R.id.menu_changePassword) { } else if (id == R.id.menu_changePassword) {
dialog = new AlertChangePasswordDialog(context) dialog = new AlertChangePasswordDialog(context).openChangePasswordDialog();
.openChangePasswordDialog(); return true;
} else if (id == R.id.menu_changeLanguage) { } else if (id == R.id.menu_changeLanguage) {
changeLanguage(); showLanguageChangeDialog();
return true;
} else if (id == R.id.menu_manageRoles) { } else if (id == R.id.menu_manageRoles) {
Helper.goTo(MainActivity.this, ManageRolesActivity.class); Helper.goTo(MainActivity.this, ManageRolesActivity.class);
return true;
} else if (id == R.id.menu_logout) { } else if (id == R.id.menu_logout) {
AlertDialog dialog = DialogUtils.logoutDialog(context); DialogUtils.logoutDialog(context).show();
dialog.show(); return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private void changeLanguage() { /**
* Show dialog to confirm language change
*/
private void showLanguageChangeDialog() {
String currentLanguage = Locale.getDefault().getLanguage(); String currentLanguage = Locale.getDefault().getLanguage();
String newLanguage = currentLanguage.equals("es") ? "en" : "es"; String newLanguage = currentLanguage.equals("es") ? "en" : "es";
@ -128,20 +164,28 @@ public class MainActivity extends AppCompatActivity {
this, this,
getString(R.string.change_language_confirmation), getString(R.string.change_language_confirmation),
(dialogInterface, i) -> { (dialogInterface, i) -> {
SharedPref.setLanguage(this, newLanguage); // Save to SharedPref SharedPref.setLanguage(this, newLanguage);
setLocale(newLanguage); // Apply language setLocale(newLanguage);
restartApp();
// Restart app to apply change
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} }
); );
dialog.show(); dialog.show();
} }
// Method to update the language dynamically /**
* Restart app to apply language changes
*/
private void restartApp() {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
/**
* Set app locale
* @param lang Language code (e.g., "en", "es")
*/
private void setLocale(String lang) { private void setLocale(String lang) {
Locale locale = new Locale(lang); Locale locale = new Locale(lang);
Locale.setDefault(locale); Locale.setDefault(locale);
@ -149,22 +193,21 @@ public class MainActivity extends AppCompatActivity {
Configuration config = new Configuration(); Configuration config = new Configuration();
config.setLocale(locale); config.setLocale(locale);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); getBaseContext().getResources().updateConfiguration(
} config,
getBaseContext().getResources().getDisplayMetrics()
private void initObj() { );
context = this;
} }
/**
* Initialize listeners for UI components
*/
private void initListeners() { private void initListeners() {
// Set item selected listener for bottom navigation bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment selectedFragment = null; Fragment selectedFragment = null;
String title = ""; String title = "";
int id = item.getItemId(); int id = item.getItemId();
if (id == R.id.menu_myReports) { if (id == R.id.menu_myReports) {
selectedFragment = new MyReportsFragment(); selectedFragment = new MyReportsFragment();
title = getString(R.string.My_Report); title = getString(R.string.My_Report);
@ -177,23 +220,100 @@ public class MainActivity extends AppCompatActivity {
} }
if (selectedFragment != null) { if (selectedFragment != null) {
loadFragment(selectedFragment, title); loadFragmentWithAnimation(selectedFragment, title, getAnimationDirection(selectedFragment));
} }
return true; return true;
}
}); });
} }
/**
* Determine animation direction based on fragment navigation
* @param newFragment The fragment being navigated to
* @return Array of animation resource IDs [enter, exit]
*/
private int[] getAnimationDirection(Fragment newFragment) {
if (currentFragment == null) {
return new int[]{ANIM_FADE_IN, ANIM_FADE_OUT};
}
// Determine navigation direction based on fragment types
boolean goingRight = isNavigatingRight(currentFragment, newFragment);
if (goingRight) {
return new int[]{ANIM_ENTER_RIGHT, ANIM_EXIT_LEFT};
} else {
return new int[]{ANIM_ENTER_LEFT, ANIM_EXIT_RIGHT};
}
}
/**
* Determine if navigation is going right in the bottom nav
* @param current Current fragment
* @param next Fragment being navigated to
* @return true if navigating right, false if navigating left
*/
private boolean isNavigatingRight(Fragment current, Fragment next) {
// Get position in navigation order
int currentPos = getFragmentPosition(current);
int nextPos = getFragmentPosition(next);
return nextPos > currentPos;
}
/**
* Get fragment position in navigation order
* @param fragment Fragment to check
* @return Position index (0 for MyReports, 1 for Map, 2 for Favorites)
*/
private int getFragmentPosition(Fragment fragment) {
if (fragment instanceof MyReportsFragment) return 0;
if (fragment instanceof MapFragment) return 1;
if (fragment instanceof FavoriteFragment) return 2;
return 1; // Default to middle position
}
/**
* Load fragment with animation
* @param fragment Fragment to load
* @param title Title to display in toolbar
* @param animations Array of animation resource IDs [enter, exit]
*/
private void loadFragmentWithAnimation(Fragment fragment, String title, int[] animations) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(
animations[0], animations[1]
);
transaction.replace(R.id.flMainContainer, fragment);
transaction.commit();
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title);
}
currentFragment = fragment;
}
/**
* Load fragment without animation
* @param fragment Fragment to load
* @param title Title to display in toolbar
*/
private void loadFragment(Fragment fragment, String title) { private void loadFragment(Fragment fragment, String title) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.flMainContainer, fragment); transaction.replace(R.id.flMainContainer, fragment);
transaction.commit(); transaction.commit();
if (getSupportActionBar() != null) { if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title); // Correct way to set title with support action bar getSupportActionBar().setTitle(title);
}
} }
currentFragment = fragment;
}
/**
* Load default fragment if no saved instance state
* @param savedInstanceState Saved instance state
*/
private void loadDefaultFragment(Bundle savedInstanceState) { private void loadDefaultFragment(Bundle savedInstanceState) {
if (savedInstanceState == null) { if (savedInstanceState == null) {
Fragment defaultFragment = new MapFragment(); Fragment defaultFragment = new MapFragment();
@ -201,18 +321,26 @@ public class MainActivity extends AppCompatActivity {
loadFragment(defaultFragment, defaultTitle); loadFragment(defaultFragment, defaultTitle);
bottomNavigationView.setSelectedItemId(R.id.menu_map); bottomNavigationView.setSelectedItemId(R.id.menu_map);
currentFragment = defaultFragment;
} }
} }
// to change the fragment /**
* Open fragment from child component
* @param fragment Fragment to open
* @param title Title to display
* @param navItemId Navigation item ID to select
*/
public void openFragmentFromChild(Fragment fragment, String title, int navItemId) { public void openFragmentFromChild(Fragment fragment, String title, int navItemId) {
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.flMainContainer); Fragment currentFrag = getSupportFragmentManager().findFragmentById(R.id.flMainContainer);
if (currentFragment != null && currentFragment.getClass().equals(fragment.getClass())) { if (currentFrag != null && currentFrag.getClass().equals(fragment.getClass())) {
return; return;
} }
int[] animations = getAnimationDirection(fragment);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); transaction.setCustomAnimations(animations[0], animations[1]);
transaction.replace(R.id.flMainContainer, fragment); transaction.replace(R.id.flMainContainer, fragment);
transaction.commit(); transaction.commit();
@ -221,9 +349,13 @@ public class MainActivity extends AppCompatActivity {
} }
bottomNavigationView.setSelectedItemId(navItemId); bottomNavigationView.setSelectedItemId(navItemId);
currentFragment = fragment;
} }
private void getRoleUuids() { /**
* Fetch role UUIDs from API
*/
private void fetchRoleUuids() {
DialogUtils.showLoadingDialog(context, ""); DialogUtils.showLoadingDialog(context, "");
String token = "Bearer " + SharedPref.getAccessToken(context); String token = "Bearer " + SharedPref.getAccessToken(context);
@ -235,7 +367,26 @@ public class MainActivity extends AppCompatActivity {
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) { public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
DialogUtils.dismissDialog(); DialogUtils.dismissDialog();
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
JsonObject responseBody = response.body(); processRolesResponse(response.body());
} else {
Log.d(TAG, "Failed to load roles. Try again.");
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
DialogUtils.dismissDialog();
Log.e(TAG, "Get Roles Failure: ", t);
// Helper.makeSnackBar(rlMainActivity, context.getString(R.string.Network_error_Try_again));
}
});
}
/**
* Process roles response from API
* @param responseBody JSON response body
*/
private void processRolesResponse(JsonObject responseBody) {
JsonObject data = responseBody.getAsJsonObject("_data"); JsonObject data = responseBody.getAsJsonObject("_data");
if (data != null && data.has("role")) { if (data != null && data.has("role")) {
@ -257,19 +408,5 @@ public class MainActivity extends AppCompatActivity {
} else { } else {
Log.d(TAG, "No roles found."); Log.d(TAG, "No roles found.");
} }
} else {
Log.d(TAG, "Failed to load roles. Try again.");
} }
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
DialogUtils.dismissDialog();
Log.e(TAG, "Get Roles Failure: ", t);
// Helper.makeSnackBar(rlMainActivity, context.getString(R.string.Network_error_Try_again));
}
});
}
} }

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="-100%"
android:toXDelta="0%" />
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="100%"
android:toXDelta="0%" />
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0%"
android:toXDelta="-100%" />
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0%"
android:toXDelta="100%" />
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>