Skip to content

Commit

Permalink
Added comments to code.
Browse files Browse the repository at this point in the history
  • Loading branch information
Wood, Jacob G committed Jul 1, 2021
1 parent 27c842b commit 8926227
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 35 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencies {
implementation "org.greenrobot:eventbus:3.2.0"
implementation "androidx.core:core-ktx:1.5.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
def fragment_version = "1.3.4"
def fragment_version = "1.3.5"

// Kotlin
implementation "androidx.fragment:fragment-ktx:$fragment_version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,45 +26,61 @@
import org.greenrobot.eventbus.Subscribe;

public class MainActivity extends Fragment {
private Weapon mWeapon = new Weapon();
/* MainActivity extends Fragment, allowing it to be used more in a more modular way. MainActivity is not actually the default
* starting activity, but is the first activity/fragment that the user sees as it is the default view as defined in the navigation
graph "nav_graph.xml". */
private Weapon mWeapon = new Weapon(); // declares a Weapon model object whose variables will be passed to most other processes
// declares several text fields that will be bound to their corresponding views
EditText mEditTextDamage;
EditText mEditTextReloadTime;
EditText mEditTextFireRate;
EditText mEditTextMagazineSize;

// declares several text blocks that will be bound to their corresponding views
TextView mTextViewTimeToEmptyMagazine;
TextView mTextViewDamagePerSecond;
TextView mTextViewDamagePerMagazine;
TextView mTextViewTimeSpentShooting;
TextView mTextViewTimeSpentReloading;
TextView mTextViewDPSSustained;

// declares several buttons that will be bound to their corresponding views
Button mAutoScanButton;
Button mButtonSaveWeapon;


// constructor that calls "MainActivity" constructor and gives main_activity.xml as a layout. Layout is subsequently inflated.
public MainActivity() {
super(R.layout.main_activity);
}


// https://stackoverflow.com/questions/62671106/onactivityresult-method-is-deprecated-what-is-the-alternative
// defines actions to be executed upon completion of an activity (cameraActivity)
ActivityResultLauncher<Intent> cameraActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
public void onActivityResult(ActivityResult result) { // code that executes when Activity completes
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
Intent data = result.getData(); //gets data from result and saves it as an Intent
if (data != null) {
buildWeapon(data);
buildWeapon(data); //build weapon if data was returned from activity
}

}
}
});

// overrides onViewCreated(). Executes after view is created, and therefore, after onCreate() and onCreateView().
// getView() only works after onCreateView(), which is why the overridden method is onViewCreated()
// see https://stackoverflow.com/a/6496000/7136798 for more details
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
// method accepts a View, which is the View created by onCreateView(), and a Bundle, which is the bundle
// passed into onCreateView().
// the following statements bind View elements (from layout file) to their corresponding class variables
mEditTextDamage = getView().findViewById(R.id.editTextDamage);
mEditTextReloadTime = getView().findViewById(R.id.editTextReloadTime);
mEditTextFireRate = getView().findViewById(R.id.editTextFireRate);
Expand All @@ -80,12 +96,13 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mAutoScanButton = getView().findViewById(R.id.autoScanButton);
mButtonSaveWeapon = getView().findViewById(R.id.saveWeaponButton);

initListeners();
initListeners(); //calls method to initialize listeners for bound objects
}


// function to initialize listeners
protected void initListeners() {
TextWatcher textWatcher = new TextWatcher() {
TextWatcher textWatcher = new TextWatcher() { // TextWatcher objects are called when an "Editable" object (that it's attached to) is changed
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

Expand All @@ -97,104 +114,117 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {
}

@Override
public void afterTextChanged(Editable s) {
public void afterTextChanged(Editable s) { // I'm only concerned with the behavior that occurs *after* text is changed
updateWeapon();
updateTextViews();
}
};

// the following statements attach the previously instantiated textWatcher to several "Editable" objects through the use of a text-change listener
mEditTextDamage.addTextChangedListener(textWatcher);
mEditTextReloadTime.addTextChangedListener(textWatcher);
mEditTextFireRate.addTextChangedListener(textWatcher);
mEditTextMagazineSize.addTextChangedListener(textWatcher);

// when clicked, the autoscan will launch a CameraActivity
mAutoScanButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// creates intent to launch CameraActivity. getActivity() returns the FragmentActivity (or AppCompatActivity) that the current fragment is associated with (NavHostActivity in this case)
// getApplicationContext() returns the context of the global Application object of the current process (in this case returns context of NavHostActivity)
Intent intent = new Intent(getActivity().getApplicationContext(), CameraActivity.class);
cameraActivityResultLauncher.launch(intent);
cameraActivityResultLauncher.launch(intent); //activity is launched and program flow control is passed to cameraActivityResultLauncher, which handles post-activity logic
}
});

// when clicked, the button to save your weapon launches an event that switches the active fragment
mButtonSaveWeapon.setOnClickListener(view -> {
//((NavHostActivity) getActivity()).switchFragment(SaveWeapon.class);
//EventBus.getDefault().post(new NavHostActivity.SwitchFragEvent(SaveWeapon.class));
//Navigation.findNavController(view).navigate(R.id.action_mainActivityFrag_to_saveWeaponFrag);
//launches activity by posting an event using EventBus and passing control to the subscribing method
EventBus.getDefault().post(new NavHostActivity.SwitchFragEvent(R.id.action_mainActivityFrag_to_saveWeaponFrag, view));

/* EventBus is used because it contains a simple framework that can be used to pass data from the calling activity (or fragment) to the child fragment.
* It's also super re-usable and allows me to write a few less lines of code (theoretically) per fragment switch.
See https://stackoverflow.com/questions/13216916/how-to-replace-the-activitys-fragment-from-the-fragment-itself#comment56148125_13221546 for another reason why you should use EventBus. */
});
}

//onStart() registers the EventBus listener so that it picks up any posts that occur. This subscription is valid for the duration of the lifecycle of the calling class (MainActivity).
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

//onsStop() unregisters the EventBus listener when the class'/activity's lifecycle ends. Because MainActivity is the "start destination" (defined in nav_graph.xml), the lifecycle should extend to the lifetime of the application.
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}

//a "subscriber" method that handles behavior when a SwitchFragEvent is posted. Reads as unused because it is executed asynchronously, once an event is posted.
@Subscribe
public void switchFragment(NavHostActivity.SwitchFragEvent event) {
int resId = event.resId;
View view = event.view;
int resId = event.resId; //sets resID according to the event object's resId value
View view = event.view; // sets view object according to the event object's View
Log.d("SwitchFragEvent", "success!");
//creates bundle containing weapon info to pass to the newly displayed fragment
Bundle bundle = new Bundle();
bundle.putString("weapon", mWeapon.toString());
bundle.putInt("damage", mWeapon.getDamage());
bundle.putFloat("reload_time", mWeapon.getReloadTime());
bundle.putFloat("fire_rate", mWeapon.getFireRate());
bundle.putInt("magazine_size", mWeapon.getMagazineSize());


//bundle.putString("current_weapon", (getSupportFragmentManager().findFragmentByTag("main_activity")).getCurrentWeapon);
//navigates to the given resId (or with the action defined by resId). findNavController returns the NavController given by the view of the onClick listener (or other caller that posts a compatible event).
Navigation.findNavController(view).navigate(resId);
}


//sets displayed text according to data returned to it by an external activity/fragment
private void buildWeapon(Intent data) {
Weapon resultWeapon = (Weapon) data.getSerializableExtra("weapon");
if (resultWeapon != null) {
Weapon resultWeapon = (Weapon) data.getSerializableExtra("weapon"); //gets data from Intent and creates a Weapon object with it
//sets displayed values (in the editable text fields) according to the values of resultWeapon
if (resultWeapon != null) { //check to ensure that there was sufficient data passed to construct a Weapon (otherwise resultWeapon is null)
mEditTextDamage.setText(String.valueOf(resultWeapon.getDamage()));
mEditTextReloadTime.setText(String.valueOf(resultWeapon.getReloadTime()));
mEditTextFireRate.setText(String.valueOf(resultWeapon.getFireRate()));
mEditTextMagazineSize.setText(String.valueOf(resultWeapon.getMagazineSize()));
}
}

//updates mWeapon values according to user input in text fields
private void updateWeapon() {
//checks to ensure that none of the text fields were changed to be blank (e.g. user hits backspace) and assigns these values to mWeapon accordingly
if (!mEditTextDamage.getText().toString().equals("") && !mEditTextReloadTime.getText().toString().equals("")
&& !mEditTextFireRate.getText().toString().equals("") && !mEditTextMagazineSize.getText().toString().equals("")) {
int damage = Integer.parseInt(mEditTextDamage.getText().toString());
float reloadTime = Float.parseFloat(mEditTextReloadTime.getText().toString());
float fireRate = Float.parseFloat(mEditTextFireRate.getText().toString());
int magazineSize = Integer.parseInt(mEditTextMagazineSize.getText().toString());

// Get all values
//sets mWeapon variable values according to local variables, which are defined above
mWeapon.setDamage(damage);
mWeapon.setReloadTime(reloadTime);
mWeapon.setFireRate(fireRate);
mWeapon.setMagazineSize(magazineSize);
}
}

//updates text blocks according to the values of mWeapon
protected void updateTextViews() {
//I think I calculated the following two instead of getting them from the Weapon class because it didn't print them nice when I tried it the other way, but I can't be sure ¯\_(ツ)_/¯
double dpsSustained = Math.round(mWeapon.getDPSSustained() * 100.0) / 100.0;
double dps = Math.round(mWeapon.getDamagePerSecond() * 100.0) / 100.0;

//updates values of text blocks
mTextViewDPSSustained.setText(String.valueOf(dpsSustained));
mTextViewDamagePerSecond.setText(String.valueOf(dps));
mTextViewTimeToEmptyMagazine.setText(String.valueOf(mWeapon.getTimeToEmptyMagazine()));
mTextViewDamagePerMagazine.setText(String.valueOf(mWeapon.getDamagePerMagazine()));
mTextViewTimeSpentReloading.setText(String.valueOf(mWeapon.getTimeSpentReloading()));
mTextViewTimeSpentShooting.setText(String.valueOf(mWeapon.getTimeSpentShooting()));
}

}





Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@

import com.borderlandsdpscalculator.borderlands3dpscalculator.R;

//FragmentActivity is the base class for AppCompatActivity, so we can use AppCompatActivity to contain and display a fragment
public class NavHostActivity extends AppCompatActivity {

public NavHostActivity() {
public NavHostActivity() { //constructor instantiates and inflates layout with a Fragment Container View, which is used to hold and display different Fragments
super(R.layout.nav_host_container);
}

public static class SwitchFragEvent {
public static class SwitchFragEvent { //acts as an event that is accessible from anywhere (provided a NavHostActivity object has already been instantiated)
//following variables are final, as they are not changed after being set during instantiation, and public, because the subscriber needs to be able to retrieve their values to perform its function
public final int resId;
public final View view;

public SwitchFragEvent(@IdRes int resId, View view) {
public SwitchFragEvent(@IdRes int resId, View view) { //constructor that takes two parameters and sets instance variables with them. Necessary to pass data from caller to subscriber outside of caller scope.
this.resId = resId;
this.view = view;
}
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/activity_save_weapon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?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"
Expand Down
4 changes: 1 addition & 3 deletions app/src/main/res/layout/main_activity.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>

<!-- Main activity layout, which is the default landing that users see -->
<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"
Expand Down Expand Up @@ -144,8 +144,6 @@
android:layout_height="wrap_content"
android:text="@string/save_weapon" />



</LinearLayout>

<androidx.constraintlayout.widget.Guideline
Expand Down
8 changes: 3 additions & 5 deletions app/src/main/res/layout/nav_host_container.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<!-- res/layout/nav_host_container.xml -->
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
<!-- creates a Fragment Container View to hold fragments and specifies a navGraph that defines how most navigation among activities and fragments will be controlled -->
<androidx.fragment.app.FragmentContainerView 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/fragment_container_view"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
/>
app:navGraph="@navigation/nav_graph" />
2 changes: 2 additions & 0 deletions app/src/main/res/navigation/nav_graph.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- I used https://blog.usejournal.com/the-navigation-component-not-that-hard-ca705cf4326 as a guide to get me started with Navigation -->
<!-- Navigation graph that defines how navigation among fragments and activities operates. Starting view is MainView -->
<navigation 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"
Expand Down

0 comments on commit 8926227

Please sign in to comment.