View cleanup.

Makes more numeric fields Steppers.
Sets titles for fragments.
Sets focus on the first EditText on most edit pages.
Makes Checkbox be a SwitchCompat
Fixes monster list item view.
This commit is contained in:
Tom Hicks
2021-06-26 02:37:37 -07:00
parent 36c26e4c42
commit 2427f69da9
28 changed files with 258 additions and 124 deletions

View File

@@ -29,11 +29,9 @@ public class EditAbilityScoresFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_edit_ability_scores, container, false); View root = inflater.inflate(R.layout.fragment_edit_ability_scores, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_ability_scores));
mViewModel.getStrength().observe(getViewLifecycleOwner(), value -> mHolder.strength.setValue(value)); mViewModel.getStrength().observe(getViewLifecycleOwner(), value -> mHolder.strength.setValue(value));
mHolder.strength.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setStrength(newValue)); mHolder.strength.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setStrength(newValue));

View File

@@ -21,6 +21,7 @@ import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R; import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.data.enums.ArmorType; import com.majinnaibu.monstercards.data.enums.ArmorType;
import com.majinnaibu.monstercards.helpers.ArrayHelper; import com.majinnaibu.monstercards.helpers.ArrayHelper;
import com.majinnaibu.monstercards.ui.components.Stepper;
import com.majinnaibu.monstercards.ui.shared.MCFragment; import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.TextChangedListener; import com.majinnaibu.monstercards.utils.TextChangedListener;
@@ -34,11 +35,9 @@ public class EditArmorFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_edit_armor, container, false); View root = inflater.inflate(R.layout.fragment_edit_armor, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_armor));
mHolder.armorType.setAdapter(new ArrayAdapter<ArmorType>(requireContext(), R.layout.dropdown_list_item, ArmorType.values()) { mHolder.armorType.setAdapter(new ArrayAdapter<ArmorType>(requireContext(), R.layout.dropdown_list_item, ArmorType.values()) {
@NonNull @NonNull
@@ -73,14 +72,14 @@ public class EditArmorFragment extends MCFragment {
}); });
mHolder.armorType.setSelection(ArrayHelper.indexOf(ArmorType.values(), mViewModel.getArmorType().getValue())); mHolder.armorType.setSelection(ArrayHelper.indexOf(ArmorType.values(), mViewModel.getArmorType().getValue()));
mHolder.naturalArmorBonus.setText(mViewModel.getNaturalArmorBonusValueAsString()); mHolder.naturalArmorBonus.setValue(mViewModel.getNaturalArmorBonusUnboxed());
mHolder.naturalArmorBonus.addTextChangedListener((new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setNaturalArmorBonus(s.toString())))); mHolder.naturalArmorBonus.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setNaturalArmorBonus(newValue));
mHolder.hasShield.setChecked(mViewModel.getHasShieldValueAsBoolean()); mHolder.hasShield.setChecked(mViewModel.getHasShieldValueAsBoolean());
mHolder.hasShield.setOnCheckedChangeListener((buttonView, isChecked) -> mViewModel.setHasShield(isChecked)); mHolder.hasShield.setOnCheckedChangeListener((buttonView, isChecked) -> mViewModel.setHasShield(isChecked));
mHolder.shieldBonus.setText(mViewModel.getShieldBonusValueAsString()); mHolder.shieldBonus.setValue(mViewModel.getShieldBonusUnboxed());
mHolder.shieldBonus.addTextChangedListener((new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setShieldBonus(s.toString())))); mHolder.shieldBonus.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setShieldBonus(newValue));
mHolder.customArmor.setText(mViewModel.getCustomArmor().getValue()); mHolder.customArmor.setText(mViewModel.getCustomArmor().getValue());
mHolder.customArmor.addTextChangedListener((new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setCustomArmor(s.toString())))); mHolder.customArmor.addTextChangedListener((new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setCustomArmor(s.toString()))));
@@ -90,9 +89,9 @@ public class EditArmorFragment extends MCFragment {
private static class ViewHolder { private static class ViewHolder {
private final Spinner armorType; private final Spinner armorType;
private final EditText naturalArmorBonus; private final Stepper naturalArmorBonus;
private final SwitchCompat hasShield; private final SwitchCompat hasShield;
private final EditText shieldBonus; private final Stepper shieldBonus;
private final EditText customArmor; private final EditText customArmor;
ViewHolder(View root) { ViewHolder(View root) {

View File

@@ -13,6 +13,7 @@ import androidx.navigation.Navigation;
import com.google.android.material.switchmaterial.SwitchMaterial; import com.google.android.material.switchmaterial.SwitchMaterial;
import com.majinnaibu.monstercards.R; import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.ui.components.Stepper;
import com.majinnaibu.monstercards.ui.shared.MCFragment; import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.TextChangedListener; import com.majinnaibu.monstercards.utils.TextChangedListener;
@@ -20,17 +21,22 @@ public class EditBasicInfoFragment extends MCFragment {
private EditMonsterViewModel mViewModel; private EditMonsterViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
@Override
public void onStart() {
super.onStart();
mHolder.name.requestFocus();
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_edit_basic_info, container, false); View root = inflater.inflate(R.layout.fragment_edit_basic_info, container, false);
setTitle(getString(R.string.title_edit_basic_info));
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
mHolder.name.setText(mViewModel.getName().getValue()); mHolder.name.setText(mViewModel.getName().getValue());
mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString()))); mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString())));
@@ -49,8 +55,8 @@ public class EditBasicInfoFragment extends MCFragment {
mHolder.customHitPoints.setText(mViewModel.getCustomHitPoints().getValue()); mHolder.customHitPoints.setText(mViewModel.getCustomHitPoints().getValue());
mHolder.customHitPoints.addTextChangedListener((new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setCustomHitPoints(s.toString())))); mHolder.customHitPoints.addTextChangedListener((new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setCustomHitPoints(s.toString()))));
mHolder.hitDice.setText(mViewModel.getHitDiceValueAsString()); mHolder.hitDice.setValue(mViewModel.getHitDiceUnboxed());
mHolder.hitDice.addTextChangedListener((new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setHitDice(s.toString())))); mHolder.hitDice.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setHitDice(newValue));
mHolder.hasCustomHitPoints.setChecked(mViewModel.getHasCustomHitPointsValueAsBoolean()); mHolder.hasCustomHitPoints.setChecked(mViewModel.getHasCustomHitPointsValueAsBoolean());
mHolder.hasCustomHitPoints.setOnCheckedChangeListener((button, isChecked) -> mViewModel.setHasCustomHitPoints(isChecked)); mHolder.hasCustomHitPoints.setOnCheckedChangeListener((button, isChecked) -> mViewModel.setHasCustomHitPoints(isChecked));
@@ -65,7 +71,7 @@ public class EditBasicInfoFragment extends MCFragment {
private final EditText subtype; private final EditText subtype;
private final EditText alignment; private final EditText alignment;
private final EditText customHitPoints; private final EditText customHitPoints;
private final EditText hitDice; private final Stepper hitDice;
private final SwitchMaterial hasCustomHitPoints; private final SwitchMaterial hasCustomHitPoints;
ViewHolder(View root) { ViewHolder(View root) {

View File

@@ -33,10 +33,9 @@ public class EditChallengeRatingFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_edit_challenge_rating, container, false); View root = inflater.inflate(R.layout.fragment_edit_challenge_rating, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_challenge_rating));
mHolder.challengeRating.setAdapter(new ArrayAdapter<ChallengeRating>(requireContext(), R.layout.dropdown_list_item, ChallengeRating.values()) { mHolder.challengeRating.setAdapter(new ArrayAdapter<ChallengeRating>(requireContext(), R.layout.dropdown_list_item, ChallengeRating.values()) {
@NonNull @NonNull

View File

@@ -4,12 +4,12 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry; import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@@ -48,11 +48,9 @@ public class EditLanguageFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_language, container, false); View root = inflater.inflate(R.layout.fragment_edit_language, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_language));
mHolder.name.setText(mViewModel.getName().getValue()); mHolder.name.setText(mViewModel.getName().getValue());
mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString()))); mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString())));
@@ -73,9 +71,15 @@ public class EditLanguageFragment extends MCFragment {
return root; return root;
} }
@Override
public void onStart() {
super.onStart();
mHolder.name.requestFocus();
}
private static class ViewHolder { private static class ViewHolder {
EditText name; EditText name;
CheckBox canSpeak; SwitchCompat canSpeak;
ViewHolder(View root) { ViewHolder(View root) {
name = root.findViewById(R.id.name); name = root.findViewById(R.id.name);

View File

@@ -41,10 +41,9 @@ public class EditLanguagesFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_languages_list, container, false); View root = inflater.inflate(R.layout.fragment_edit_languages_list, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_languages));
setupRecyclerView(mHolder.list); setupRecyclerView(mHolder.list);
setupAddLanguageButton(mHolder.addLanguage); setupAddLanguageButton(mHolder.addLanguage);

View File

@@ -332,6 +332,10 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
this.setHitDice(parsedHitDice != null ? parsedHitDice : 0); this.setHitDice(parsedHitDice != null ? parsedHitDice : 0);
} }
public int getHitDiceUnboxed() {
return Helpers.unboxInteger(mHitDice.getValue(), 1);
}
public String getHitDiceValueAsString() { public String getHitDiceValueAsString() {
return mHitDice.getValue().toString(); return mHitDice.getValue().toString();
} }
@@ -349,6 +353,10 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
this.setNaturalArmorBonus(parsedValue != null ? parsedValue : 0); this.setNaturalArmorBonus(parsedValue != null ? parsedValue : 0);
} }
public int getNaturalArmorBonusUnboxed() {
return Helpers.unboxInteger(mNaturalArmorBonus.getValue(), 0);
}
public String getNaturalArmorBonusValueAsString() { public String getNaturalArmorBonusValueAsString() {
return mNaturalArmorBonus.getValue().toString(); return mNaturalArmorBonus.getValue().toString();
} }
@@ -398,6 +406,10 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
this.setShieldBonus(parsedValue != null ? parsedValue : 0); this.setShieldBonus(parsedValue != null ? parsedValue : 0);
} }
public int getShieldBonusUnboxed() {
return Helpers.unboxInteger(mShieldBonus.getValue(), 0);
}
public LiveData<String> getCustomArmor() { public LiveData<String> getCustomArmor() {
return mCustomArmor; return mCustomArmor;
} }

View File

@@ -25,11 +25,10 @@ public class EditSavingThrowsFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_edit_saving_throws, container, false); View root = inflater.inflate(R.layout.fragment_edit_saving_throws, container, false);
mViewHolder = new ViewHolder(root); mViewHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_saving_throws));
mViewHolder.strengthProficiency.setValue(mViewModel.getStrengthProficiency().getValue()); mViewHolder.strengthProficiency.setValue(mViewModel.getStrengthProficiency().getValue());
mViewHolder.strengthProficiency.setOnValueChangedListener(value -> mViewModel.setStrengthProficiency(value)); mViewHolder.strengthProficiency.setOnValueChangedListener(value -> mViewModel.setStrengthProficiency(value));
mViewHolder.strengthAdvantage.setValue(mViewModel.getStrengthAdvantage().getValue()); mViewHolder.strengthAdvantage.setValue(mViewModel.getStrengthAdvantage().getValue());

View File

@@ -24,7 +24,6 @@ import com.majinnaibu.monstercards.utils.Logger;
import com.majinnaibu.monstercards.utils.TextChangedListener; import com.majinnaibu.monstercards.utils.TextChangedListener;
public class EditSkillFragment extends MCFragment { public class EditSkillFragment extends MCFragment {
// TODO: when this view is shown select focus on the name edit text and select it's contents
private EditMonsterViewModel mEditMonsterViewModel; private EditMonsterViewModel mEditMonsterViewModel;
private EditSkillViewModel mViewModel; private EditSkillViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
@@ -50,11 +49,9 @@ public class EditSkillFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_edit_skill, container, false); View root = inflater.inflate(R.layout.fragment_edit_skill, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_skill));
mHolder.abilityScore.setValue(mViewModel.getAbilityScore().getValue()); mHolder.abilityScore.setValue(mViewModel.getAbilityScore().getValue());
mHolder.abilityScore.setOnValueChangedListener(value -> mViewModel.setAbilityScore(value)); mHolder.abilityScore.setOnValueChangedListener(value -> mViewModel.setAbilityScore(value));
@@ -81,6 +78,12 @@ public class EditSkillFragment extends MCFragment {
return root; return root;
} }
@Override
public void onStart() {
super.onStart();
mHolder.name.requestFocus();
}
private static class ViewHolder { private static class ViewHolder {
AbilityScorePicker abilityScore; AbilityScorePicker abilityScore;
AdvantagePicker advantage; AdvantagePicker advantage;

View File

@@ -42,10 +42,9 @@ public class EditSkillsFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_skills_list, container, false); View root = inflater.inflate(R.layout.fragment_edit_skills_list, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_skills));
setupRecyclerView(mHolder.list); setupRecyclerView(mHolder.list);
setupAddSkillButton(mHolder.addSkill); setupAddSkillButton(mHolder.addSkill);

View File

@@ -27,11 +27,9 @@ public class EditSpeedFragment extends MCFragment {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_edit_speed, container, false); View root = inflater.inflate(R.layout.fragment_edit_speed, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_speed));
mHolder.baseSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWalkSpeed(newValue)); mHolder.baseSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWalkSpeed(newValue));
mHolder.baseSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value)); mHolder.baseSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value));

View File

@@ -21,7 +21,6 @@ import com.majinnaibu.monstercards.utils.Logger;
import com.majinnaibu.monstercards.utils.TextChangedListener; import com.majinnaibu.monstercards.utils.TextChangedListener;
public class EditStringFragment extends MCFragment { public class EditStringFragment extends MCFragment {
// TODO: when this fragment is shown focus on the edit text and select it's contents
private EditMonsterViewModel mEditMonsterViewModel; private EditMonsterViewModel mEditMonsterViewModel;
private EditStringViewModel mViewModel; private EditStringViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
@@ -52,6 +51,7 @@ public class EditStringFragment extends MCFragment {
mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_string, container, false); View root = inflater.inflate(R.layout.fragment_edit_string, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getTitleForStringType(mStringType));
mHolder.description.setText(mViewModel.getValueAsString()); mHolder.description.setText(mViewModel.getValueAsString());
mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setValue(s.toString()))); mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setValue(s.toString())));
@@ -69,14 +69,34 @@ public class EditStringFragment extends MCFragment {
return root; return root;
} }
private String getTitleForStringType(StringType type) {
switch (type) {
case CONDITION_IMMUNITY:
return getString(R.string.title_edit_condition_immunity);
case DAMAGE_IMMUNITY:
return getString(R.string.title_edit_damage_immunity);
case DAMAGE_RESISTANCE:
return getString(R.string.title_edit_damage_resistance);
case DAMAGE_VULNERABILITY:
return getString(R.string.title_edit_damage_vulnerability);
case SENSE:
return getString(R.string.title_edit_sense);
default:
return "";
}
}
@Override
public void onStart() {
super.onStart();
mHolder.description.requestFocus();
}
private static class ViewHolder { private static class ViewHolder {
EditText description; EditText description;
EditText name;
ViewHolder(View root) { ViewHolder(View root) {
description = root.findViewById(R.id.description); description = root.findViewById(R.id.description);
name = root.findViewById(R.id.name);
} }
} }
} }

View File

@@ -56,11 +56,29 @@ public class EditStringsFragment extends MCFragment {
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_strings_list, container, false); View root = inflater.inflate(R.layout.fragment_edit_strings_list, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getTitleForStringType(mStringType));
setupRecyclerView(mHolder.list); setupRecyclerView(mHolder.list);
setupAddButton(mHolder.addItem); setupAddButton(mHolder.addItem);
return root; return root;
} }
private String getTitleForStringType(StringType type) {
switch (type) {
case CONDITION_IMMUNITY:
return getString(R.string.title_edit_condition_immunities);
case DAMAGE_IMMUNITY:
return getString(R.string.title_edit_damage_immunities);
case DAMAGE_RESISTANCE:
return getString(R.string.title_edit_damage_resistances);
case DAMAGE_VULNERABILITY:
return getString(R.string.title_edit_damage_vulnerabilities);
case SENSE:
return getString(R.string.title_edit_senses);
default:
return "";
}
}
private void setupRecyclerView(@NonNull RecyclerView recyclerView) { private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
Context context = requireContext(); Context context = requireContext();
LinearLayoutManager layoutManager = new LinearLayoutManager(context); LinearLayoutManager layoutManager = new LinearLayoutManager(context);

View File

@@ -52,6 +52,7 @@ public class EditTraitFragment extends MCFragment {
mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_trait, container, false); View root = inflater.inflate(R.layout.fragment_edit_trait, container, false);
mHolder = new EditTraitFragment.ViewHolder(root); mHolder = new EditTraitFragment.ViewHolder(root);
setTitle(getTitleForTraitType(mTraitType));
mHolder.name.setText(mViewModel.getNameAsString()); mHolder.name.setText(mViewModel.getNameAsString());
mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString()))); mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString())));
@@ -72,6 +73,31 @@ public class EditTraitFragment extends MCFragment {
return root; return root;
} }
@Override
public void onStart() {
super.onStart();
mHolder.name.requestFocus();
}
private String getTitleForTraitType(TraitType type) {
switch (type) {
case ABILITY:
return getString(R.string.title_edit_ability);
case ACTION:
return getString(R.string.title_edit_action);
case LAIR_ACTION:
return getString(R.string.title_edit_lair_action);
case LEGENDARY_ACTION:
return getString(R.string.title_edit_legendary_action);
case REACTIONS:
return getString(R.string.title_edit_reaction);
case REGIONAL_ACTION:
return getString(R.string.title_edit_regional_action);
default:
return "";
}
}
private static class ViewHolder { private static class ViewHolder {
EditText description; EditText description;
EditText name; EditText name;

View File

@@ -57,11 +57,31 @@ public class EditTraitsFragment extends MCFragment {
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_traits_list, container, false); View root = inflater.inflate(R.layout.fragment_edit_traits_list, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getTitleForTraitType(mTraitType));
setupRecyclerView(mHolder.list); setupRecyclerView(mHolder.list);
setupAddButton(mHolder.addTrait); setupAddButton(mHolder.addTrait);
return root; return root;
} }
private String getTitleForTraitType(TraitType type) {
switch (type) {
case ABILITY:
return getString(R.string.title_edit_abilities);
case ACTION:
return getString(R.string.title_edit_actions);
case LAIR_ACTION:
return getString(R.string.title_edit_lair_actions);
case LEGENDARY_ACTION:
return getString(R.string.title_edit_legendary_actions);
case REACTIONS:
return getString(R.string.title_edit_reactions);
case REGIONAL_ACTION:
return getString(R.string.title_edit_regional_actions);
default:
return "";
}
}
private void setupRecyclerView(@NonNull RecyclerView recyclerView) { private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
Context context = requireContext(); Context context = requireContext();
LinearLayoutManager layoutManager = new LinearLayoutManager(context); LinearLayoutManager layoutManager = new LinearLayoutManager(context);

View File

@@ -60,7 +60,6 @@ public class MonsterListRecyclerViewAdapter extends RecyclerView.Adapter<Monster
@Override @Override
public void onBindViewHolder(final @NonNull ViewHolder holder, int position) { public void onBindViewHolder(final @NonNull ViewHolder holder, int position) {
Monster monster = mValues.get(position); Monster monster = mValues.get(position);
holder.mIdView.setText(monster.id.toString().substring(0, 6));
holder.mContentView.setText(monster.name); holder.mContentView.setText(monster.name);
holder.itemView.setTag(monster); holder.itemView.setTag(monster);
holder.itemView.setOnClickListener(mOnClickListener); holder.itemView.setOnClickListener(mOnClickListener);
@@ -106,12 +105,10 @@ public class MonsterListRecyclerViewAdapter extends RecyclerView.Adapter<Monster
} }
static class ViewHolder extends RecyclerView.ViewHolder { static class ViewHolder extends RecyclerView.ViewHolder {
final TextView mIdView;
final TextView mContentView; final TextView mContentView;
ViewHolder(View view) { ViewHolder(View view) {
super(view); super(view);
mIdView = view.findViewById(R.id.id_text);
mContentView = view.findViewById(R.id.content); mContentView = view.findViewById(R.id.content);
} }
} }

View File

@@ -63,7 +63,6 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<Searc
@Override @Override
public void onBindViewHolder(final ViewHolder holder, int position) { public void onBindViewHolder(final ViewHolder holder, int position) {
Monster monster = mValues.get(position); Monster monster = mValues.get(position);
holder.mIdView.setText(monster.id.toString().substring(0, 6));
holder.mContentView.setText(monster.name); holder.mContentView.setText(monster.name);
holder.itemView.setTag(monster); holder.itemView.setTag(monster);
holder.itemView.setOnClickListener(view -> { holder.itemView.setOnClickListener(view -> {
@@ -83,12 +82,10 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<Searc
} }
public static class ViewHolder extends RecyclerView.ViewHolder { public static class ViewHolder extends RecyclerView.ViewHolder {
final TextView mIdView;
final TextView mContentView; final TextView mContentView;
ViewHolder(View view) { ViewHolder(View view) {
super(view); super(view);
mIdView = view.findViewById(R.id.id_text);
mContentView = view.findViewById(R.id.content); mContentView = view.findViewById(R.id.content);
} }
} }

View File

@@ -5,6 +5,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal" android:orientation="horizontal"
tools:context=".ui.components.AbilityScorePicker"> tools:context=".ui.components.AbilityScorePicker">
<!-- // TODO: style this control to look less awful by default -->
<TextView <TextView
android:id="@+id/label" android:id="@+id/label"

View File

@@ -6,6 +6,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
tools:context=".ui.components.AdvantagePicker"> tools:context=".ui.components.AdvantagePicker">
<!-- // TODO: style this control to look less awful by default -->
<TextView <TextView
android:id="@+id/label" android:id="@+id/label"

View File

@@ -6,6 +6,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
tools:context=".ui.components.ProficiencyPicker"> tools:context=".ui.components.ProficiencyPicker">
<!-- // TODO: style this control to look less awful by default -->
<TextView <TextView
android:id="@+id/label" android:id="@+id/label"

View File

@@ -7,13 +7,19 @@
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
tools:context=".ui.components.Stepper"> tools:context=".ui.components.Stepper">
<!-- // TODO: Make these text views use the size and appearance of the material text input -->
<TextView <TextView
android:id="@+id/text" android:id="@+id/text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingHorizontal="4dp"
android:paddingTop="4dp"
android:paddingBottom="11dp"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@id/label"
tools:text="20 (+5)" /> tools:text="20 (+5)" />
<TextView <TextView
@@ -21,15 +27,39 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="" android:text=""
android:textAppearance="?attr/textAppearanceSubtitle1" android:textAppearance="@android:style/TextAppearance.Material.Caption"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="Strength" /> tools:text="Strength" />
<!--
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="20 (+5)" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@android:style/TextAppearance.Material.Caption"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Strength" />
android:layout_marginTop="8dp"
-->
<Button <Button
android:id="@+id/decrement" android:id="@+id/decrement"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:text="@string/label_decrement_field" android:text="@string/label_decrement_field"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/increment" app:layout_constraintEnd_toStartOf="@id/increment"
@@ -39,6 +69,7 @@
android:id="@+id/increment" android:id="@+id/increment"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:text="@string/label_increment_field" android:text="@string/label_increment_field"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView 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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@@ -15,21 +16,15 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<!-- // TODO: Make this a stepper instead of a text field --> <com.majinnaibu.monstercards.ui.components.Stepper
<com.google.android.material.textfield.TextInputLayout android:id="@+id/naturalArmorBonus"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"> android:layout_margin="@dimen/text_margin"
app:label="@string/label_natural_armor_bonus"
<com.google.android.material.textfield.TextInputEditText app:maxValue="99"
android:id="@+id/naturalArmorBonus" app:minValue="0"
android:layout_width="match_parent" app:stepAmount="1" />
android:layout_height="wrap_content"
android:hint="@string/label_natural_armor_bonus"
android:importantForAutofill="no"
android:inputType="numberSigned"
tools:text="+2" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.switchmaterial.SwitchMaterial <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/hasShield" android:id="@+id/hasShield"
@@ -37,23 +32,17 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
android:text="@string/label_has_a_shield" android:text="@string/label_has_a_shield"
android:textSize="20sp" /> android:textAppearance="@android:style/TextAppearance.Material.Medium" />
<!-- // TODO: Make this a stepper instead of a text field --> <com.majinnaibu.monstercards.ui.components.Stepper
<com.google.android.material.textfield.TextInputLayout android:id="@+id/shieldBonus"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"> android:layout_margin="@dimen/text_margin"
app:label="@string/label_shield_bonus"
<com.google.android.material.textfield.TextInputEditText app:maxValue="99"
android:id="@+id/shieldBonus" app:minValue="0"
android:layout_width="match_parent" app:stepAmount="1" />
android:layout_height="wrap_content"
android:hint="@string/label_shield_bonus"
android:importantForAutofill="no"
android:inputType="numberSigned"
tools:text="4" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView 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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@@ -19,6 +20,8 @@
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/label_name" android:hint="@string/label_name"
android:importantForAutofill="no" android:importantForAutofill="no"
android:inputType="textCapWords" android:inputType="textCapWords"
@@ -86,21 +89,15 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<!-- Hit Dice (int) --> <!-- Hit Dice (int) -->
<!-- // TODO: Make this a stepper instead of a text field --> <com.majinnaibu.monstercards.ui.components.Stepper
<com.google.android.material.textfield.TextInputLayout android:id="@+id/hitDice"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"> android:layout_margin="@dimen/text_margin"
app:label="@string/label_hit_dice"
<com.google.android.material.textfield.TextInputEditText app:maxValue="99"
android:id="@+id/hitDice" app:minValue="1"
android:layout_width="match_parent" app:stepAmount="1" />
android:layout_height="wrap_content"
android:digits="0123456789"
android:hint="@string/label_hit_dice"
android:importantForAutofill="no"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.switchmaterial.SwitchMaterial <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/hasCustomHitPoints" android:id="@+id/hasCustomHitPoints"
@@ -108,7 +105,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
android:text="@string/label_has_custom_hp" android:text="@string/label_has_custom_hp"
android:textSize="@dimen/text_h4_size" /> android:textAppearance="@android:style/TextAppearance.Material.Medium" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -25,11 +25,12 @@
tools:text="Medicine" /> tools:text="Medicine" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<CheckBox <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/canSpeak" android:id="@+id/canSpeak"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/label_can_speak_language" /> android:layout_margin="@dimen/text_margin"
android:text="@string/label_can_speak_language"
android:textAppearance="@android:style/TextAppearance.Material.Medium" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -67,7 +67,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
android:text="@string/label_can_hover" android:text="@string/label_can_hover"
android:textSize="@dimen/text_h4_size" /> android:textAppearance="@android:style/TextAppearance.Material.Medium" />
<com.google.android.material.switchmaterial.SwitchMaterial <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/hasCustomSpeed" android:id="@+id/hasCustomSpeed"
@@ -75,7 +75,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
android:text="@string/label_has_custom_speed" android:text="@string/label_has_custom_speed"
android:textSize="@dimen/text_h4_size" /> android:textAppearance="@android:style/TextAppearance.Material.Medium" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -1,20 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:layout_margin="@dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@+id/id_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem" />
</LinearLayout>

View File

@@ -86,7 +86,39 @@
<string name="strength_abbreviation">STR</string> <string name="strength_abbreviation">STR</string>
<string name="title_collections">Collections</string> <string name="title_collections">Collections</string>
<string name="title_dashboard">Dashboard</string> <string name="title_dashboard">Dashboard</string>
<string name="title_edit_abilities">Ability</string>
<string name="title_edit_ability">Abilities</string>
<string name="title_edit_ability_scores">Ability Scores</string>
<string name="title_edit_action">Action</string>
<string name="title_edit_actions">Actions</string>
<string name="title_edit_armor">Armor</string>
<string name="title_edit_basic_info">Basic Info</string>
<string name="title_edit_challenge_rating">Challenge Rating</string>
<string name="title_edit_condition_immunities">Condition Immunities</string>
<string name="title_edit_condition_immunity">Condition Immunity</string>
<string name="title_edit_damage_immunities">Damage Immunities</string>
<string name="title_edit_damage_immunity">Damage Immunity</string>
<string name="title_edit_damage_resistance">Damage Resistance</string>
<string name="title_edit_damage_resistances">Damage Resistances</string>
<string name="title_edit_damage_vulnerabilities">Damage Vulnerabilities</string>
<string name="title_edit_damage_vulnerability">Damage Vulnerability</string>
<string name="title_edit_lair_action">Lair Action</string>
<string name="title_edit_lair_actions">Lair Actions</string>
<string name="title_edit_language">Language</string>
<string name="title_edit_languages">Languages</string>
<string name="title_edit_legendary_action">Legendary Action</string>
<string name="title_edit_legendary_actions">Legendary Actions</string>
<string name="title_edit_monster">Edit %1$s</string> <string name="title_edit_monster">Edit %1$s</string>
<string name="title_edit_reaction">Reaction</string>
<string name="title_edit_reactions">Reactions</string>
<string name="title_edit_regional_action">Regional Action</string>
<string name="title_edit_regional_actions">Regional Actions</string>
<string name="title_edit_speed">Speed</string>
<string name="title_edit_saving_throws">Saving Throws</string>
<string name="title_edit_sense">Senses</string>
<string name="title_edit_senses">Senses</string>
<string name="title_edit_skill">Skill</string>
<string name="title_edit_skills">Skills</string>
<string name="title_library">Library</string> <string name="title_library">Library</string>
<string name="title_search">Search</string> <string name="title_search">Search</string>
<string name="wisdom_abbreviation">WIS</string> <string name="wisdom_abbreviation">WIS</string>