Skip to content

Commit

Permalink
Add drop down with special chars for Characters
Browse files Browse the repository at this point in the history
Custom DialogPreference with special character presets for character
preference settings in custom format.

Closes #37

Signed-off-by: Aron Heinecke <[email protected]>
  • Loading branch information
0xpr03 committed Oct 9, 2018
1 parent de59c88 commit 3f665f2
Show file tree
Hide file tree
Showing 12 changed files with 279 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ private void initView(@Nullable Bundle savedInstanceState) {
Button btnFileDialog = view.findViewById(R.id.bExportSelFile);
btnFileDialog.setOnClickListener(v -> selectFile());

spAdapterFormat = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item);
spAdapterFormat = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item);
spAdapterFormat.setDropDownViewResource(android.R.layout.select_dialog_singlechoice);

SharedPreferences settings = getActivity().getSharedPreferences(PREFS_NAME, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.preference.EditTextPreference;
import android.support.v7.preference.EditTextPreferenceDialogFragmentCompat;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.text.InputFilter;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.Constants;
Expand All @@ -28,8 +25,9 @@
import vocabletrainer.heinecke.aron.vocabletrainer.R;
import vocabletrainer.heinecke.aron.vocabletrainer.activity.FragmentActivity;
import vocabletrainer.heinecke.aron.vocabletrainer.lib.CSV.CSVCustomFormat;
import vocabletrainer.heinecke.aron.vocabletrainer.lib.Widget.CustomEditTextPreference;
import vocabletrainer.heinecke.aron.vocabletrainer.lib.ViewModel.FormatViewModel;
import vocabletrainer.heinecke.aron.vocabletrainer.lib.Widget.CharacterPreference;
import vocabletrainer.heinecke.aron.vocabletrainer.lib.Widget.CharacterPreferenceDialog;

/**
* Fragment for custom cFormat preferences<br>
Expand Down Expand Up @@ -288,13 +286,15 @@ public void onDisplayPreferenceDialog(Preference preference) {
// hack for custom dialog to allow for edittext filters

// dialog shown
//noinspection ConstantConditions
if (getFragmentManager().findFragmentByTag(C_DIALOG_TAG) != null) {
return;
}

DialogFragment f = null;
if (preference instanceof CustomEditTextPreference) {
f = EditTextPreferenceDialog.newInstance(preference.getKey(),lengthFilter);
if (preference instanceof CharacterPreference) {
//f = EditTextPreferenceDialog.newInstance(preference.getKey(),lengthFilter);
f = CharacterPreferenceDialog.newInstance(preference);
} else {
super.onDisplayPreferenceDialog(preference);
}
Expand Down Expand Up @@ -326,28 +326,4 @@ public boolean onBackPressed() {
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
verifyFormat();
}

/**
* Custom EditText preference dialog to allow for Filters
* Because correct Android is hard.
*/
public static class EditTextPreferenceDialog extends EditTextPreferenceDialogFragmentCompat {
private InputFilter[] filters;

public static EditTextPreferenceDialog newInstance(String key, InputFilter[] filters) {
final EditTextPreferenceDialog
fragment = new EditTextPreferenceDialog();
final Bundle b = new Bundle(1);
b.putString(ARG_KEY, key);
fragment.setArguments(b);
fragment.filters = filters;
return fragment;
}

@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
((EditText)view.findViewById(android.R.id.edit)).setFilters(filters);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package vocabletrainer.heinecke.aron.vocabletrainer.lib.Widget;

import android.content.Context;
import android.support.v7.preference.EditTextPreference;
import android.util.AttributeSet;

import vocabletrainer.heinecke.aron.vocabletrainer.R;

/**
* Custom EditTextPreference for single character settings
* Created by Aron Heinecke
*/
public class CharacterPreference extends EditTextPreference {
public CharacterPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public CharacterPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public CharacterPreference(Context context) {
super(context);
}

public CharacterPreference(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.dialogPreferenceStyle);
}

@Override
public int getDialogLayoutResource() {
return R.layout.dialog_character_preference;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package vocabletrainer.heinecke.aron.vocabletrainer.lib.Widget;

import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.support.v7.preference.DialogPreference;
import android.support.v7.preference.EditTextPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceDialogFragmentCompat;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

import vocabletrainer.heinecke.aron.vocabletrainer.R;
import vocabletrainer.heinecke.aron.vocabletrainer.lib.Storage.GenericSpinnerEntry;

/**
* Character Preference Dialog
*/
public class CharacterPreferenceDialog extends PreferenceDialogFragmentCompat {
private static final int MAX_LENGTH = 1;
private static final String ARG_TITLE = "title";
private static String PLACEHOLDER;
TextInputEditText charInput;
TextInputLayout charInputLayout;
Spinner spPreset;
ArrayAdapter<GenericSpinnerEntry<Character>> adapter;
private CustomItemSelectedListener listener;
private Button okButton;

public static CharacterPreferenceDialog newInstance(Preference preference) {
final CharacterPreferenceDialog
fragment = new CharacterPreferenceDialog();
final Bundle b = new Bundle(1);
b.putString(ARG_KEY, preference.getKey());
b.putString(ARG_TITLE, preference.getTitle().toString());
fragment.setArguments(b);
return fragment;
}

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
okButton = dialog.findViewById(AlertDialog.BUTTON_POSITIVE);
return dialog;
}

@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
PLACEHOLDER = getString(R.string.Placeholder);
DialogPreference preference = getPreference();

charInput = view.findViewById(R.id.tCharInput);
charInputLayout = view.findViewById(R.id.tCharInputLayout);
charInputLayout.setCounterEnabled(true);
charInputLayout.setCounterMaxLength(MAX_LENGTH);
String hint = getArguments().getString(ARG_TITLE,PLACEHOLDER);
charInputLayout.setHint(hint);
charInput.setSingleLine();
charInput.setHint(hint);
charInput.setText(((EditTextPreference) preference).getText());
spPreset = view.findViewById(R.id.spPreset);

adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapter.add(new GenericSpinnerEntry<>(null,getString(R.string.Character_Custom)));
adapter.add(new GenericSpinnerEntry<>('\t',getString(R.string.Character_Tab)));
adapter.add(new GenericSpinnerEntry<>('\r',getString(R.string.Character_Line_Feed)));
adapter.add(new GenericSpinnerEntry<>(',',getString(R.string.Character_Comma)));
adapter.add(new GenericSpinnerEntry<>(';',getString(R.string.Character_Semicolon)));
adapter.add(new GenericSpinnerEntry<>('"',getString(R.string.Character_Quotations_Mark)));
adapter.add(new GenericSpinnerEntry<>('\\',getString(R.string.Character_Backslash)));
spPreset.setAdapter(adapter);

listener = new CustomItemSelectedListener() {
@Override
public void itemSelected(AdapterView<?> parent, View view, int position, long id) {
Character selected = adapter.getItem(position).getObject();
if(selected != null){
charInput.setText(String.valueOf(selected));
}
}
};

spPreset.setOnItemSelectedListener(listener);

charInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {

}

@Override
public void afterTextChanged(Editable s) {
//listener.disableNextEvent();
updateSpinner();
int length = s.toString().toCharArray().length;
if(length == MAX_LENGTH){
charInputLayout.setError(null);
}else{
charInputLayout.setError(getString(R.string.Character_Incorrect_Amount));
}
}
});
}

private void updateSpinner(){
String input = charInput.getText().toString();
switch(input){
case "\t":
spPreset.setSelection(1);
break;
case "\r":
spPreset.setSelection(2);
break;
case ",":
spPreset.setSelection(3);
break;
case ";":
spPreset.setSelection(4);
break;
case "\"":
spPreset.setSelection(5);
break;
case "\\":
spPreset.setSelection(6);
break;
default:
spPreset.setSelection(0);
if(input.length() == MAX_LENGTH) {
adapter.getItem(0).updateObject(input.charAt(0));
}
}
}

@Override
public void onDialogClosed(boolean positiveResult) {
if(positiveResult && charInputLayout.getError() == null){
DialogPreference preference = getPreference();
if (preference instanceof EditTextPreference) {
EditTextPreference textPreference =
((EditTextPreference) preference);
// This allows the client to ignore the user value.
if(textPreference.callChangeListener(charInput.getText().toString())){
textPreference.setText(charInput.getText().toString());
}
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public final void onItemSelected(AdapterView<?> parent, View view, int position,
/**
* Set firstSelect as undone, disabling the next itemSelect call from triggering itemSelected
*/
public void setFirstUnselected() {
public void disableNextEvent() {
this.firstSelect = true;
}

Expand Down
36 changes: 36 additions & 0 deletions app/src/main/res/layout/dialog_character_preference.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
tools:context="vocabletrainer.heinecke.aron.vocabletrainer.lib.Widget.CharacterPreference">

<android.support.design.widget.TextInputLayout
android:id="@+id/tCharInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<android.support.design.widget.TextInputEditText
android:id="@+id/tCharInput"
android:hint="@string/Placeholder"
android:layout_width="match_parent"
android:maxLength="1"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>

<TextView
style="@style/InputLabel"
android:paddingTop="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/Character_Preference_Preset_Label" />

<Spinner
android:id="@+id/spPreset"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</LinearLayout>
2 changes: 2 additions & 0 deletions app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
<dimen name="ic_delete">30dp</dimen>
<dimen name="padd_10">10dp</dimen>
<dimen name="high_density">48dp</dimen>
<dimen name="input_label_vertical_spacing">8dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen>
</resources>
10 changes: 10 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
<string name="File_Diag_btn_OK">Overwrite</string>
<string name="File_Diag_btn_CANCEL">Cancel</string>
<!-- Messages -->
<string name="Character_Incorrect_Amount">Incorrect character amount!</string>
<string name="Perm_CSV">Permission is required to load/write your CSV files for import/export.</string>
<string name="File_Error_Mediastate">No storage found / is writable! Unable to continue.</string>
<string name="File_Error_Nullpointer">Unable to show files. Nullpointer</string>
Expand All @@ -136,6 +137,14 @@
<string name="Import_Warn_MAX_RECORD_SIZE">Entry has too many values: </string>
<string name="Import_Info_Import">Imported %d vocables</string>
<!-- Spinner -->
<string name="Character_Tab">Tab (\\t)</string>
<string name="Character_Comma">Comma (,)</string>
<string name="Character_Backslash">Backslash (\\)</string>
<string name="Character_Line_Feed">Line Feed (\\r)</string>
<string name="Character_Semicolon">Semicolon (;)</string>
<string name="Character_Quotations_Mark">Quotation Mark (\")</string>
<string name="Character_Custom">Custom Character</string>

<string name="Import_Multilist_REPLACE">Replace existing lists</string>
<string name="Import_Multilist_IGNORE">Ignore existing lists</string>
<string name="Import_Multilist_ADD">Append if list exists</string>
Expand All @@ -158,6 +167,7 @@
<string name="title_activity_format">FormatActivity</string>

<!--format preferences -->
<string name="Character_Preference_Preset_Label">Presets</string>
<string name="Pref_Multi_Transl">Multi-Translations</string>
<string name="Pref_Multi_Transl_Desc">Handle multiple translations</string>
<string name="Pref_Multi_Transl_Char">Multi-Translation Delimiter Char</string>
Expand Down
Loading

0 comments on commit 3f665f2

Please sign in to comment.