diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/components/Stepper.java b/app/src/main/java/com/majinnaibu/monstercards/ui/components/Stepper.java
new file mode 100644
index 0000000..1ae029a
--- /dev/null
+++ b/app/src/main/java/com/majinnaibu/monstercards/ui/components/Stepper.java
@@ -0,0 +1,144 @@
+package com.majinnaibu.monstercards.ui.components;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.utils.Logger;
+
+import java.util.Objects;
+
+
+public class Stepper extends ConstraintLayout {
+ private final ViewHolder mHolder;
+ private int mCurrentValue;
+ private int mStep;
+ private int mMinValue;
+ private int mMaxValue;
+ private String mLabel;
+ private OnValueChangeListener mOnValueChangeListener;
+ private OnFormatValueCallback mOnFormatValueCallback;
+
+ public Stepper(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+
+ mCurrentValue = 0;
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Stepper, 0, 0);
+ mStep = a.getInt(R.styleable.Stepper_stepAmount, 1);
+ mMinValue = a.getInt(R.styleable.Stepper_minValue, Integer.MIN_VALUE);
+ mMaxValue = a.getInt(R.styleable.Stepper_maxValue, Integer.MAX_VALUE);
+ mLabel = a.getString(R.styleable.Stepper_label);
+ a.recycle();
+
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View root = inflater.inflate(R.layout.component_stepper, this, true);
+
+ mHolder = new ViewHolder(root);
+
+ setValue(mCurrentValue);
+ mHolder.increment.setOnClickListener(v -> setValue(mCurrentValue + mStep));
+ mHolder.decrement.setOnClickListener(v -> setValue(mCurrentValue - mStep));
+
+ mHolder.label.setText(mLabel);
+ }
+
+ public Stepper(Context context) {
+ this(context, null);
+ }
+
+ public String getLabel() {
+ return mLabel;
+ }
+
+ public void setLabel(String newLabel) {
+ if (!Objects.equals(mLabel, newLabel)) {
+ mLabel = newLabel;
+ mHolder.label.setText(mLabel);
+ }
+ }
+
+ public int getValue() {
+ return mCurrentValue;
+ }
+
+ public void setValue(int value) {
+ int oldValue = this.mCurrentValue;
+ int newValue = Math.min(mMaxValue, Math.max(mMinValue, value));
+ Logger.logDebug(String.format("Setting stepper value value: %d, oldValue: %d, newValue: %d", value, oldValue, newValue));
+ if (newValue != oldValue) {
+ this.mCurrentValue = newValue;
+ if (mOnValueChangeListener != null) {
+ mOnValueChangeListener.onChange(newValue, oldValue);
+ }
+ if (mOnFormatValueCallback != null) {
+ mHolder.text.setText(mOnFormatValueCallback.onFormatValue(this.mCurrentValue));
+ } else {
+ mHolder.text.setText(String.valueOf(this.mCurrentValue));
+ }
+ }
+ }
+
+ public void setOnValueChangeListener(OnValueChangeListener listener) {
+ mOnValueChangeListener = listener;
+ }
+
+ public void setOnFormatValueCallback(OnFormatValueCallback callback) {
+ mOnFormatValueCallback = callback;
+ }
+
+ public int getStep() {
+ return mStep;
+ }
+
+ public void setStep(int step) {
+ this.mStep = step;
+ }
+
+ public int getMinValue() {
+ return mMinValue;
+ }
+
+ public void setMinValue(int minValue) {
+ this.mMinValue = minValue;
+ }
+
+ public int getMaxValue() {
+ return mMaxValue;
+ }
+
+ public void setMaxValue(int maxValue) {
+ this.mMaxValue = maxValue;
+ }
+
+ public interface OnValueChangeListener {
+ void onChange(int value, int previousValue);
+ }
+
+ public interface OnFormatValueCallback {
+ String onFormatValue(int value);
+ }
+
+ private static class ViewHolder {
+ final TextView text;
+ final TextView label;
+ final Button increment;
+ final Button decrement;
+
+ ViewHolder(View root) {
+ text = root.findViewById(R.id.text);
+ label = root.findViewById(R.id.label);
+ increment = root.findViewById(R.id.increment);
+ decrement = root.findViewById(R.id.decrement);
+ }
+ }
+}
diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java b/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java
index 0b36fd4..697a287 100644
--- a/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java
+++ b/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java
@@ -4,8 +4,6 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
@@ -14,11 +12,17 @@ import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.ui.components.Stepper;
public class EditAbilityScoresFragment extends Fragment {
+ private final String ABILITY_SCORE_FORMAT = "%d (%+d)";
private EditMonsterViewModel mViewModel;
private ViewHolder mHolder;
+ private int getModifier(int value) {
+ return value / 2 - 5;
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -31,72 +35,48 @@ public class EditAbilityScoresFragment extends Fragment {
mHolder = new ViewHolder(root);
- mViewModel.getStrength().observe(getViewLifecycleOwner(), value -> mHolder.strength.setText(String.valueOf(value)));
- mHolder.increaseStrength.setOnClickListener(v -> mViewModel.incrementStrength());
- mHolder.decreaseStrength.setOnClickListener(v -> mViewModel.decrementStrength());
+ mViewModel.getStrength().observe(getViewLifecycleOwner(), value -> mHolder.strength.setValue(value));
+ mHolder.strength.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setStrength(newValue));
+ mHolder.strength.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
- mViewModel.getDexterity().observe(getViewLifecycleOwner(), value -> mHolder.dexterity.setText(String.valueOf(value)));
- mHolder.increaseDexterity.setOnClickListener(v -> mViewModel.incrementDexterity());
- mHolder.decreaseDexterity.setOnClickListener(v -> mViewModel.decrementDexterity());
+ mViewModel.getDexterity().observe(getViewLifecycleOwner(), value -> mHolder.dexterity.setValue(value));
+ mHolder.dexterity.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setDexterity(newValue));
+ mHolder.dexterity.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
- mViewModel.getConstitution().observe(getViewLifecycleOwner(), value -> mHolder.constitution.setText(String.valueOf(value)));
- mHolder.increaseConstitution.setOnClickListener(v -> mViewModel.incrementConstitution());
- mHolder.decreaseConstitution.setOnClickListener(v -> mViewModel.decrementConstitution());
+ mViewModel.getConstitution().observe(getViewLifecycleOwner(), value -> mHolder.constitution.setValue(value));
+ mHolder.constitution.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setConstitution(newValue));
+ mHolder.constitution.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
- mViewModel.getIntelligence().observe(getViewLifecycleOwner(), value -> mHolder.intelligence.setText(String.valueOf(value)));
- mHolder.increaseIntelligence.setOnClickListener(v -> mViewModel.incrementIntelligence());
- mHolder.decreaseIntelligence.setOnClickListener(v -> mViewModel.decrementIntelligence());
+ mViewModel.getIntelligence().observe(getViewLifecycleOwner(), value -> mHolder.intelligence.setValue(value));
+ mHolder.intelligence.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setIntelligence(newValue));
+ mHolder.intelligence.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
- mViewModel.getWisdom().observe(getViewLifecycleOwner(), value -> mHolder.wisdom.setText(String.valueOf(value)));
- mHolder.increaseWisdom.setOnClickListener(v -> mViewModel.incrementWisdom());
- mHolder.decreaseWisdom.setOnClickListener(v -> mViewModel.decrementWisdom());
+ mViewModel.getWisdom().observe(getViewLifecycleOwner(), value -> mHolder.wisdom.setValue(value));
+ mHolder.wisdom.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWisdom(newValue));
+ mHolder.wisdom.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
- mViewModel.getCharisma().observe(getViewLifecycleOwner(), value -> mHolder.charisma.setText(String.valueOf(value)));
- mHolder.increaseCharisma.setOnClickListener(v -> mViewModel.incrementCharisma());
- mHolder.decreaseCharisma.setOnClickListener(v -> mViewModel.decrementCharisma());
+ mViewModel.getCharisma().observe(getViewLifecycleOwner(), value -> mHolder.charisma.setValue(value));
+ mHolder.charisma.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setCharisma(newValue));
+ mHolder.charisma.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
return root;
}
private static class ViewHolder {
- TextView strength;
- Button decreaseStrength;
- Button increaseStrength;
- TextView dexterity;
- Button increaseDexterity;
- Button decreaseDexterity;
- TextView constitution;
- Button increaseConstitution;
- Button decreaseConstitution;
- TextView intelligence;
- Button increaseIntelligence;
- Button decreaseIntelligence;
- TextView wisdom;
- Button increaseWisdom;
- Button decreaseWisdom;
- TextView charisma;
- Button increaseCharisma;
- Button decreaseCharisma;
+ final Stepper strength;
+ final Stepper dexterity;
+ final Stepper constitution;
+ final Stepper intelligence;
+ final Stepper wisdom;
+ final Stepper charisma;
ViewHolder(View root) {
strength = root.findViewById(R.id.strength);
- increaseStrength = root.findViewById(R.id.strength_increment);
- decreaseStrength = root.findViewById(R.id.strength_decrement);
dexterity = root.findViewById(R.id.dexterity);
- increaseDexterity = root.findViewById(R.id.dexterity_increment);
- decreaseDexterity = root.findViewById(R.id.dexterity_decrement);
constitution = root.findViewById(R.id.constitution);
- increaseConstitution = root.findViewById(R.id.constitution_increment);
- decreaseConstitution = root.findViewById(R.id.constitution_decrement);
intelligence = root.findViewById(R.id.intelligence);
- increaseIntelligence = root.findViewById(R.id.intelligence_increment);
- decreaseIntelligence = root.findViewById(R.id.intelligence_decrement);
wisdom = root.findViewById(R.id.wisdom);
- increaseWisdom = root.findViewById(R.id.wisdom_increment);
- decreaseWisdom = root.findViewById(R.id.wisdom_decrement);
charisma = root.findViewById(R.id.charisma);
- increaseCharisma = root.findViewById(R.id.charisma_increment);
- decreaseCharisma = root.findViewById(R.id.charisma_decrement);
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java b/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java
index 7ffb29f..0cf820e 100644
--- a/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java
+++ b/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java
@@ -4,9 +4,7 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.EditText;
-import android.widget.TextView;
import androidx.appcompat.widget.SwitchCompat;
import androidx.fragment.app.Fragment;
@@ -16,6 +14,7 @@ import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.ui.components.Stepper;
import com.majinnaibu.monstercards.utils.TextChangedListener;
public class EditSpeedFragment extends Fragment {
@@ -34,29 +33,25 @@ public class EditSpeedFragment extends Fragment {
mHolder = new ViewHolder(root);
- mViewModel.getWalkSpeed().observe(getViewLifecycleOwner(), value -> {
- mHolder.baseSpeed.setText(String.format(getString(R.string.format_distance_in_feet), value));
- });
- mHolder.incrementBaseSpeed.setOnClickListener(v -> mViewModel.incrementWalkSpeed());
- mHolder.decrementBaseSpeed.setOnClickListener(v -> mViewModel.decrementWalkSpeed());
+ mHolder.baseSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWalkSpeed(newValue));
+ mHolder.baseSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value));
+ mViewModel.getWalkSpeed().observe(getViewLifecycleOwner(), value -> mHolder.baseSpeed.setValue(value));
- mViewModel.getBurrowSpeed().observe(getViewLifecycleOwner(), value -> {
- mHolder.burrowSpeed.setText(String.format(getString(R.string.format_distance_in_feet), value));
- });
- mHolder.incrementBurrowSpeed.setOnClickListener(v -> mViewModel.incrementBurrowSpeed());
- mHolder.decrementBurrowSpeed.setOnClickListener(v -> mViewModel.decrementBurrowSpeed());
+ mHolder.burrowSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setBurrowSpeed(newValue));
+ mHolder.burrowSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value));
+ mViewModel.getBurrowSpeed().observe(getViewLifecycleOwner(), value -> mHolder.burrowSpeed.setValue(value));
- mViewModel.getClimbSpeed().observe(getViewLifecycleOwner(), value -> mHolder.climbSpeed.setText(String.format(getString(R.string.format_distance_in_feet), value)));
- mHolder.incrementClimbSpeed.setOnClickListener(v -> mViewModel.incrementClimbSpeed());
- mHolder.decrementBurrowSpeed.setOnClickListener(v -> mViewModel.decrementClimbSpeed());
+ mHolder.climbSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setClimbSpeed(newValue));
+ mHolder.climbSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value));
+ mViewModel.getClimbSpeed().observe(getViewLifecycleOwner(), value -> mHolder.climbSpeed.setValue(value));
- mViewModel.getFlySpeed().observe(getViewLifecycleOwner(), value -> mHolder.flySpeed.setText(String.format(getString(R.string.format_distance_in_feet), value)));
- mHolder.incrementFlySpeed.setOnClickListener(v -> mViewModel.incrementFlySpeed());
- mHolder.decrementBurrowSpeed.setOnClickListener(v -> mViewModel.decrementFlySpeed());
+ mHolder.flySpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setFlySpeed(newValue));
+ mHolder.flySpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value));
+ mViewModel.getFlySpeed().observe(getViewLifecycleOwner(), value -> mHolder.flySpeed.setValue(value));
- mViewModel.getSwimSpeed().observe(getViewLifecycleOwner(), value -> mHolder.swimSpeed.setText(String.format(getString(R.string.format_distance_in_feet), value)));
- mHolder.incrementSwimSpeed.setOnClickListener(v -> mViewModel.incrementSwimSpeed());
- mHolder.decrementBurrowSpeed.setOnClickListener(v -> mViewModel.decrementSwimSpeed());
+ mHolder.swimSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setSwimSpeed(newValue));
+ mHolder.swimSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value));
+ mViewModel.getSwimSpeed().observe(getViewLifecycleOwner(), value -> mHolder.swimSpeed.setValue(value));
mViewModel.getCanHover().observe(getViewLifecycleOwner(), value -> mHolder.canHover.setChecked(value));
mHolder.canHover.setOnCheckedChangeListener((buttonView, isChecked) -> mViewModel.setCanHover(isChecked));
@@ -73,41 +68,21 @@ public class EditSpeedFragment extends Fragment {
private static class ViewHolder {
- final TextView baseSpeed;
- final Button incrementBaseSpeed;
- final Button decrementBaseSpeed;
- final TextView burrowSpeed;
- final Button incrementBurrowSpeed;
- final Button decrementBurrowSpeed;
- final TextView climbSpeed;
- final Button incrementClimbSpeed;
- final Button decrementClimbSpeed;
- final TextView flySpeed;
- final Button incrementFlySpeed;
- final Button decrementFlySpeed;
- final TextView swimSpeed;
- final Button incrementSwimSpeed;
- final Button decrementSwimSpeed;
+ final Stepper baseSpeed;
+ final Stepper burrowSpeed;
+ final Stepper climbSpeed;
+ final Stepper flySpeed;
+ final Stepper swimSpeed;
final SwitchCompat canHover;
final SwitchCompat hasCustomSpeed;
final EditText customSpeed;
ViewHolder(View root) {
baseSpeed = root.findViewById(R.id.baseSpeed);
- incrementBaseSpeed = root.findViewById(R.id.baseSpeed_increment);
- decrementBaseSpeed = root.findViewById(R.id.baseSpeed_decrement);
burrowSpeed = root.findViewById(R.id.burrowSpeed);
- incrementBurrowSpeed = root.findViewById(R.id.burrowSpeed_increment);
- decrementBurrowSpeed = root.findViewById(R.id.burrowSpeed_decrement);
climbSpeed = root.findViewById(R.id.climbSpeed);
- incrementClimbSpeed = root.findViewById(R.id.climbSpeed_increment);
- decrementClimbSpeed = root.findViewById(R.id.climbSpeed_decrement);
flySpeed = root.findViewById(R.id.flySpeed);
- incrementFlySpeed = root.findViewById(R.id.flySpeed_increment);
- decrementFlySpeed = root.findViewById(R.id.flySpeed_decrement);
swimSpeed = root.findViewById(R.id.swimSpeed);
- incrementSwimSpeed = root.findViewById(R.id.swimSpeed_increment);
- decrementSwimSpeed = root.findViewById(R.id.swimSpeed_decrement);
canHover = root.findViewById(R.id.canHover);
hasCustomSpeed = root.findViewById(R.id.hasCustomSpeed);
customSpeed = root.findViewById(R.id.customSpeed);
diff --git a/app/src/main/res/layout/component_stepper.xml b/app/src/main/res/layout/component_stepper.xml
new file mode 100644
index 0000000..a330941
--- /dev/null
+++ b/app/src/main/res/layout/component_stepper.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_edit_ability_scores.xml b/app/src/main/res/layout/fragment_edit_ability_scores.xml
index ecd5b40..f709537 100644
--- a/app/src/main/res/layout/fragment_edit_ability_scores.xml
+++ b/app/src/main/res/layout/fragment_edit_ability_scores.xml
@@ -11,259 +11,64 @@
android:layout_height="wrap_content"
android:orientation="vertical">
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_strength"
+ app:maxValue="99"
+ app:minValue="1"
+ app:stepAmount="1" />
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_dexterity"
+ app:maxValue="99"
+ app:minValue="1"
+ app:stepAmount="1" />
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_constitution"
+ app:maxValue="99"
+ app:minValue="1"
+ app:stepAmount="1" />
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_intelligence"
+ app:maxValue="99"
+ app:minValue="1"
+ app:stepAmount="1" />
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_wisdom"
+ app:maxValue="99"
+ app:minValue="1"
+ app:stepAmount="1" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_charisma"
+ app:maxValue="99"
+ app:minValue="1"
+ app:stepAmount="1" />
diff --git a/app/src/main/res/layout/fragment_edit_speed.xml b/app/src/main/res/layout/fragment_edit_speed.xml
index 5de66a1..6e73ed5 100644
--- a/app/src/main/res/layout/fragment_edit_speed.xml
+++ b/app/src/main/res/layout/fragment_edit_speed.xml
@@ -11,215 +11,55 @@
android:layout_height="wrap_content"
android:orientation="vertical">
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_base_speed"
+ app:maxValue="1000"
+ app:minValue="0"
+ app:stepAmount="5" />
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_burrow_speed"
+ app:maxValue="1000"
+ app:minValue="0"
+ app:stepAmount="5" />
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_climb_speed"
+ app:maxValue="1000"
+ app:minValue="0"
+ app:stepAmount="5" />
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_fly_speed"
+ app:maxValue="1000"
+ app:minValue="0"
+ app:stepAmount="5" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_margin="@dimen/text_margin"
+ app:label="@string/label_swim_speed"
+ app:maxValue="1000"
+ app:minValue="0"
+ app:stepAmount="5" />
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fcb7c37..7932fdb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -65,5 +65,7 @@
Library
Search
WIS
+ Fly Speed
+ Swim Speed
\ No newline at end of file