aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMenny Even Danan <menny@evendanan.net>2015-05-27 13:15:47 +0000
committerMenny Even Danan <menny@evendanan.net>2015-05-27 13:15:47 +0000
commit48a3d1f2ba1a574db68e801323846e10d3219bf6 (patch)
tree77fbc18f1f82bbd5f3ecbfa037995ad0783a2b24
parent717809cf50e7b2729872a6251a9a50af6c4d99dd (diff)
downloadAnySoftKeyboard-48a3d1f2ba1a574db68e801323846e10d3219bf6.tar.gz
AnySoftKeyboard-48a3d1f2ba1a574db68e801323846e10d3219bf6.tar.bz2
initial pass. Does not interact with the actual Dictionary yet. Issue #466
-rw-r--r--src/main/AndroidManifest.xml15
-rw-r--r--src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific.java13
-rw-r--r--src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V3.java6
-rw-r--r--src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V8.java6
-rw-r--r--src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/AbbreviationDictionaryEditorFragment.java68
-rw-r--r--src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWord.java26
-rw-r--r--src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWordsAdapter.java199
-rw-r--r--src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserDictionaryEditorFragment.java89
-rw-r--r--src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserWordsListAdapter.java311
-rw-r--r--src/main/res/drawable-hdpi/ic_cancel.pngbin0 -> 688 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_cancel.pngbin0 -> 546 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_cancel.pngbin0 -> 790 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_cancel.pngbin0 -> 1032 bytes
-rw-r--r--src/main/res/layout/abbreviation_dictionary_word_row_edit.xml9
-rw-r--r--src/main/res/layout/user_dictionary_editor.xml23
-rw-r--r--src/main/res/layout/user_dictionary_word_row_edit.xml10
-rw-r--r--src/main/res/layout/word_editor_empty_view.xml18
-rw-r--r--src/main/res/values/ids.xml6
18 files changed, 346 insertions, 453 deletions
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index a1829b179..77ac7212a 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.menny.android.anysoftkeyboard">
+ package="com.menny.android.anysoftkeyboard">
<supports-screens
android:anyDensity="true"
@@ -55,7 +55,8 @@
<!-- settings ui activities -->
<!-- this is just a proxy activity, it does nothing but direct to the actual setting ativity
I use this, so I can 'disable' this activity at runtime, and so remove ASK from the launcher's icons -->
- <activity android:theme="@style/Theme.AskApp"
+ <activity
+ android:theme="@style/Theme.AskApp"
android:name="com.menny.android.anysoftkeyboard.LauncherSettingsActivity"
android:icon="@drawable/ic_launcher_settings"
android:launchMode="singleTop"
@@ -66,10 +67,12 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
- <activity android:theme="@style/Theme.AskApp"
+ <activity
+ android:theme="@style/Theme.AskApp"
android:name="com.anysoftkeyboard.ui.settings.MainSettingsActivity"
android:icon="@drawable/ic_launcher_settings"
android:launchMode="singleTask"
+ android:windowSoftInputMode="adjustPan"
android:label="@string/ime_name">
</activity>
@@ -81,13 +84,15 @@
android:theme="@style/Theme.AskApp.Popup">
</activity>
<!-- ui when a crash happens -->
- <activity android:theme="@style/Theme.AskApp.NoTitle"
+ <activity
+ android:theme="@style/Theme.AskApp.NoTitle"
android:name="com.anysoftkeyboard.ui.SendBugReportUiActivity"
android:icon="@drawable/ic_launcher"
android:label="@string/ime_name">
</activity>
<!-- for voice -->
- <service android:name="com.google.android.voiceime.ServiceHelper" />
+ <service android:name="com.google.android.voiceime.ServiceHelper"/>
+
<activity
android:name="com.google.android.voiceime.ActivityHelper"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
diff --git a/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific.java b/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific.java
index 89cdf9c77..2fe7a4a0d 100644
--- a/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific.java
+++ b/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.graphics.Canvas;
import android.view.GestureDetector;
import android.view.inputmethod.InputConnection;
-import android.widget.AbsListView;
import com.anysoftkeyboard.IndirectlyInstantiated;
import com.anysoftkeyboard.WordComposer;
@@ -28,15 +27,13 @@ import com.anysoftkeyboard.WordComposer;
@IndirectlyInstantiated
public interface DeviceSpecific {
- public String getApiLevel();
+ String getApiLevel();
- public MultiTouchSupportLevel getMultiTouchSupportLevel(Context appContext);
+ MultiTouchSupportLevel getMultiTouchSupportLevel(Context appContext);
- public GestureDetector createGestureDetector(Context appContext, AskOnGestureListener listener);
+ GestureDetector createGestureDetector(Context appContext, AskOnGestureListener listener);
- public void commitCorrectionToInputConnection(InputConnection ic, WordComposer word);
+ void commitCorrectionToInputConnection(InputConnection ic, WordComposer word);
- public void performListScrollToPosition(AbsListView listView, int position);
-
- public boolean isHardwareAcceleratedCanvas(Canvas canvas);
+ boolean isHardwareAcceleratedCanvas(Canvas canvas);
}
diff --git a/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V3.java b/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V3.java
index d1c84e45d..d6d46037f 100644
--- a/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V3.java
+++ b/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V3.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.graphics.Canvas;
import android.view.GestureDetector;
import android.view.inputmethod.InputConnection;
-import android.widget.AbsListView;
import com.anysoftkeyboard.IndirectlyInstantiated;
import com.anysoftkeyboard.WordComposer;
@@ -51,11 +50,6 @@ public class DeviceSpecific_V3 implements DeviceSpecific {
}
@Override
- public void performListScrollToPosition(AbsListView listView, int position) {
- listView.setSelection(position);
- }
-
- @Override
public boolean isHardwareAcceleratedCanvas(Canvas canvas) {
return false;
}
diff --git a/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V8.java b/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V8.java
index 7bde76d58..c1e581f4c 100644
--- a/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V8.java
+++ b/src/main/java/com/anysoftkeyboard/devicespecific/DeviceSpecific_V8.java
@@ -20,7 +20,6 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.view.GestureDetector;
-import android.widget.AbsListView;
import com.anysoftkeyboard.IndirectlyInstantiated;
@@ -52,9 +51,4 @@ public class DeviceSpecific_V8 extends DeviceSpecific_V7 {
AskOnGestureListener listener) {
return new AskV8GestureDetector(appContext, listener);
}
-
- @Override
- public void performListScrollToPosition(AbsListView listView, int position) {
- listView.smoothScrollToPosition(position);
- }
} \ No newline at end of file
diff --git a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/AbbreviationDictionaryEditorFragment.java b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/AbbreviationDictionaryEditorFragment.java
index 863aa450d..cfce9fd0a 100644
--- a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/AbbreviationDictionaryEditorFragment.java
+++ b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/AbbreviationDictionaryEditorFragment.java
@@ -7,7 +7,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
-import android.widget.ListAdapter;
import android.widget.TextView;
import com.anysoftkeyboard.dictionaries.EditableDictionary;
@@ -32,60 +31,61 @@ public class AbbreviationDictionaryEditorFragment extends UserDictionaryEditorFr
}
@Override
- protected ListAdapter getWordsListAdapter(List<UserWordsListAdapter.Word> wordsList) {
- return new AbbreviationWordsListAdapter(
- getActivity(),
- wordsList,
- this);
+ protected EditorWordsAdapter createAdapterForWords(List<EditorWord> wordsList) {
+ return new AbbreviationEditorWordsAdapter(wordsList, getActivity());
}
- private static class AbbreviationWordsListAdapter extends UserWordsListAdapter {
+ private static class AbbreviationEditorWordsAdapter extends EditorWordsAdapter {
- public AbbreviationWordsListAdapter(Context context, List<Word> words, AdapterCallbacks callbacks) {
- super(context, words, callbacks);
- }
+ private final Context mContext;
- private static String getAbbreviation(@Nullable Word word) {
- if (word == null) return "";
- return AbbreviationsDictionary.getAbbreviation(word.word, word.frequency);
+ public AbbreviationEditorWordsAdapter(List<EditorWord> editorWords, Context context) {
+ super(editorWords, LayoutInflater.from(context));
+ mContext = context;
}
- private static String getExplodedSentence(@Nullable Word word) {
- if (word == null) return "";
- return AbbreviationsDictionary.getExplodedSentence(word.word, word.frequency);
+ @Override
+ protected EditorWord.Editing createEmptyNewEditing() {
+ return new EditorWord.Editing("", 0);
}
- @Override
- protected void updateEditedWordRow(View rootView, TextView wordView, Word word) {
- wordView.setText(getAbbreviation(word));
- EditText explodedSentence = (EditText)rootView.findViewById(R.id.word_target_view);
- explodedSentence.setText(getExplodedSentence(word));
+ protected void bindNormalWordViewText(TextView wordView, EditorWord editorWord) {
+ wordView.setText(mContext.getString(R.string.abbreviation_dict_word_template,
+ getAbbreviation(editorWord), getExplodedSentence(editorWord)));
}
@Override
- protected void updateNormalWordRow(View rootView, TextView wordView, Word word) {
- wordView.setText(getContext().getString(R.string.abbreviation_dict_word_template,
- getAbbreviation(word), getExplodedSentence(word)));
+ protected View inflateEditingRowView(LayoutInflater layoutInflater, ViewGroup parent) {
+ return layoutInflater.inflate(R.layout.abbreviation_dictionary_word_row_edit, parent, false);
}
@Override
- protected View inflateEditedWordRow(LayoutInflater inflater, ViewGroup parent) {
- return inflater.inflate(R.layout.abbreviation_dictionary_word_row_edit, parent, false);
+ protected void bindEditingWordViewText(EditText wordView, EditorWord editorWord) {
+ wordView.setText(getAbbreviation(editorWord));
+ EditText explodedSentence = (EditText) ((View)wordView.getParent()).findViewById(R.id.word_target_view);
+ explodedSentence.setText(getExplodedSentence(editorWord));
}
@Override
- protected Word onWordEditApproved(View approveButton, @Nullable Word oldWord) {
- View parent = ((View) approveButton.getParent());
- EditText abbreviationView = (EditText) parent.findViewById(R.id.word_view);
- EditText explodedSentenceView = (EditText) parent.findViewById(R.id.word_target_view);
- final String newAbbreviation = abbreviationView.getText().toString();
+ protected EditorWord createNewEditorWord(EditText wordView, EditorWord oldEditorWord) {
+ EditText explodedSentenceView = (EditText) ((View)wordView.getParent()).findViewById(R.id.word_target_view);
+ final String newAbbreviation = wordView.getText().toString();
final String newExplodedSentence = explodedSentenceView.getText().toString();
if (TextUtils.isEmpty(newAbbreviation) || TextUtils.isEmpty(newExplodedSentence)) {
- return null;
+ return oldEditorWord;
} else {
- return new Word(newAbbreviation+newExplodedSentence, newAbbreviation.length());
+ return new EditorWord(newAbbreviation + newExplodedSentence, newAbbreviation.length());
}
}
- }
+ private static String getAbbreviation(@Nullable EditorWord word) {
+ if (word == null) return "";
+ return AbbreviationsDictionary.getAbbreviation(word.word, word.frequency);
+ }
+
+ private static String getExplodedSentence(@Nullable EditorWord word) {
+ if (word == null) return "";
+ return AbbreviationsDictionary.getExplodedSentence(word.word, word.frequency);
+ }
+ }
}
diff --git a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWord.java b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWord.java
new file mode 100644
index 000000000..227d383f0
--- /dev/null
+++ b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWord.java
@@ -0,0 +1,26 @@
+package com.anysoftkeyboard.ui.settings.wordseditor;
+
+import android.support.annotation.NonNull;
+
+/*package*/ class EditorWord {
+ @NonNull
+ public final String word;
+ public final int frequency;
+
+ public EditorWord(@NonNull String word, int frequency) {
+ this.word = word;
+ this.frequency = frequency;
+ }
+
+ public static class Editing extends EditorWord {
+ public Editing(@NonNull String word, int frequency) {
+ super(word, frequency);
+ }
+ }
+
+ public static class AddNew extends EditorWord {
+ public AddNew() {
+ super("", -1);
+ }
+ }
+}
diff --git a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWordsAdapter.java b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWordsAdapter.java
new file mode 100644
index 000000000..db49a8216
--- /dev/null
+++ b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/EditorWordsAdapter.java
@@ -0,0 +1,199 @@
+package com.anysoftkeyboard.ui.settings.wordseditor;
+
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.menny.android.anysoftkeyboard.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EditorWordsAdapter extends RecyclerView.Adapter<EditorWordsAdapter.EditorWordViewHolder> {
+
+ protected final List<EditorWord> mEditorWords;
+ private final LayoutInflater mLayoutInflater;
+
+ public EditorWordsAdapter(List<EditorWord> editorWords, LayoutInflater layoutInflater) {
+ mEditorWords = new ArrayList<>(editorWords);
+ mEditorWords.add(new EditorWord.AddNew());
+ mLayoutInflater = layoutInflater;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ EditorWord editorWord = mEditorWords.get(position);
+ if (editorWord instanceof EditorWord.Editing) {
+ return R.id.word_editor_view_type_editing_row;
+ } else if (editorWord instanceof EditorWord.AddNew) {
+ if (position == 0) {
+ return R.id.word_editor_view_type_empty_view_row;
+ } else {
+ return R.id.word_editor_view_type_add_new_row;
+ }
+ } else {
+ return R.id.word_editor_view_type_row;
+ }
+ }
+
+ @Override
+ public EditorWordViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ switch (viewType) {
+ case R.id.word_editor_view_type_editing_row:
+ return new EditorWordViewHolderEditing(inflateEditingRowView(mLayoutInflater, parent));
+ case R.id.word_editor_view_type_empty_view_row:
+ return new EditorWordViewHolderAddNew(mLayoutInflater.inflate(R.layout.word_editor_empty_view, parent, false));
+ case R.id.word_editor_view_type_add_new_row:
+ return new EditorWordViewHolderAddNew(mLayoutInflater.inflate(R.layout.user_dictionary_word_row_add, parent, false));
+ default:
+ return new EditorWordViewHolderNormal(mLayoutInflater.inflate(R.layout.user_dictionary_word_row, parent, false));
+ }
+ }
+
+ protected View inflateEditingRowView(LayoutInflater layoutInflater, ViewGroup parent) {
+ return layoutInflater.inflate(R.layout.user_dictionary_word_row_edit, parent, false);
+ }
+
+ @Override
+ public void onBindViewHolder(EditorWordViewHolder holder, int position) {
+ holder.bind(mEditorWords.get(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return mEditorWords.size();
+ }
+
+ public void addNewWordAtEnd(RecyclerView wordsRecyclerView) {
+ final int lastLocation = mEditorWords.size() - 1;
+ EditorWord editorWord = mEditorWords.get(lastLocation);
+ if (editorWord instanceof EditorWord.AddNew) {
+ mEditorWords.remove(lastLocation);
+ }
+ final int newLastLocation = mEditorWords.size() - 1;
+ mEditorWords.add(createEmptyNewEditing());
+ notifyItemChanged(newLastLocation);
+ wordsRecyclerView.smoothScrollToPosition(newLastLocation);
+ }
+
+ protected EditorWord.Editing createEmptyNewEditing() {
+ return new EditorWord.Editing("", 128);
+ }
+
+ protected void bindNormalWordViewText(TextView wordView, EditorWord editorWord) {
+ wordView.setText(editorWord.word);
+ }
+
+ protected void bindEditingWordViewText(EditText wordView, EditorWord editorWord) {
+ wordView.setText(editorWord.word);
+ }
+
+ protected EditorWord createNewEditorWord(EditText wordView, EditorWord oldEditorWord) {
+ return new EditorWord(wordView.getText().toString(), oldEditorWord.frequency);
+ }
+
+ /*package*/ abstract class EditorWordViewHolder extends RecyclerView.ViewHolder {
+ private EditorWord mWord;
+
+ public EditorWordViewHolder(View itemView) {
+ super(itemView);
+ }
+
+ protected int getItemPosition() {
+ return mEditorWords.indexOf(mWord);
+ }
+
+ public void bind(EditorWord editorWord) {
+ mWord = editorWord;
+ }
+ }
+
+ private class EditorWordViewHolderAddNew extends EditorWordViewHolder implements View.OnClickListener {
+
+ public EditorWordViewHolderAddNew(View itemView) {
+ super(itemView);
+ itemView.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ final int itemPosition = getItemPosition();
+ mEditorWords.remove(itemPosition);
+ mEditorWords.add(itemPosition, createEmptyNewEditing());
+ notifyItemChanged(itemPosition);
+ }
+ }
+
+ private class EditorWordViewHolderNormal extends EditorWordViewHolder implements View.OnClickListener {
+ private final TextView mWordView;
+
+ public EditorWordViewHolderNormal(View itemView) {
+ super(itemView);
+ mWordView = (TextView) itemView.findViewById(R.id.word_view);
+ mWordView.setOnClickListener(this);
+ itemView.findViewById(R.id.delete_user_word).setOnClickListener(this);
+ }
+
+ @Override
+ public void bind(EditorWord editorWord) {
+ super.bind(editorWord);
+ bindNormalWordViewText(mWordView, editorWord);
+ }
+
+ @Override
+ public void onClick(View v) {
+ final int itemPosition = getItemPosition();
+ if (v == mWordView) {
+ EditorWord editorWord = mEditorWords.remove(itemPosition);
+ mEditorWords.add(itemPosition, new EditorWord.Editing(editorWord.word, editorWord.frequency));
+ notifyItemChanged(itemPosition);
+ } else if (v.getId() == R.id.delete_user_word) {
+ mEditorWords.remove(itemPosition);
+ notifyItemRemoved(itemPosition);
+ }
+ }
+ }
+
+ private class EditorWordViewHolderEditing extends EditorWordViewHolder implements View.OnClickListener {
+ private final EditText mWordView;
+
+ public EditorWordViewHolderEditing(View itemView) {
+ super(itemView);
+ mWordView = (EditText) itemView.findViewById(R.id.word_view);
+ itemView.findViewById(R.id.approve_user_word).setOnClickListener(this);
+ itemView.findViewById(R.id.cancel_user_word).setOnClickListener(this);
+ }
+
+ @Override
+ public void bind(EditorWord editorWord) {
+ super.bind(editorWord);
+ bindEditingWordViewText(mWordView, editorWord);
+ }
+
+ @Override
+ public void onClick(View v) {
+ final int itemPosition = getItemPosition();
+ final boolean addNewRow = (itemPosition == mEditorWords.size()-1);
+ if (v.getId() == R.id.cancel_user_word || TextUtils.isEmpty(mWordView.getText())) {
+ EditorWord editorWord = mEditorWords.remove(itemPosition);
+ if (addNewRow) {
+ mEditorWords.add(itemPosition, new EditorWord.AddNew());
+ } else {
+ mEditorWords.add(itemPosition, new EditorWord(editorWord.word, editorWord.frequency));
+ }
+ } else if (v.getId() == R.id.approve_user_word) {
+ EditorWord editorWord = mEditorWords.remove(itemPosition);
+ mEditorWords.add(itemPosition, createNewEditorWord(mWordView, editorWord));
+ if (addNewRow) {
+ mEditorWords.add(new EditorWord.AddNew());
+ notifyItemInserted(mEditorWords.size() - 1);
+ }
+ }
+ notifyItemChanged(itemPosition);
+ }
+ }
+}
diff --git a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserDictionaryEditorFragment.java b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserDictionaryEditorFragment.java
index c645823d8..e36915e04 100644
--- a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserDictionaryEditorFragment.java
+++ b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserDictionaryEditorFragment.java
@@ -23,21 +23,18 @@ import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
-import android.widget.GridView;
-import android.widget.ListAdapter;
-import android.widget.ListView;
import android.widget.Spinner;
import com.anysoftkeyboard.dictionaries.EditableDictionary;
@@ -46,7 +43,6 @@ import com.anysoftkeyboard.dictionaries.WordsCursor;
import com.anysoftkeyboard.keyboards.KeyboardAddOnAndBuilder;
import com.anysoftkeyboard.keyboards.KeyboardFactory;
import com.anysoftkeyboard.utils.Log;
-import com.menny.android.anysoftkeyboard.AnyApplication;
import com.menny.android.anysoftkeyboard.R;
import net.evendanan.pushingpixels.AsyncTaskWithProgressWindow;
@@ -59,7 +55,7 @@ import java.util.Comparator;
import java.util.List;
public class UserDictionaryEditorFragment extends Fragment
- implements AsyncTaskWithProgressWindow.AsyncTaskOwner, AdapterView.OnItemClickListener, UserWordsListAdapter.AdapterCallbacks {
+ implements AsyncTaskWithProgressWindow.AsyncTaskOwner {
private Dialog mDialog;
@@ -79,10 +75,11 @@ public class UserDictionaryEditorFragment extends Fragment
private String mSelectedLocale = null;
EditableDictionary mCurrentDictionary;
- AbsListView mWordsListView;//this may be either ListView or GridView (in tablets)
- private static final Comparator<UserWordsListAdapter.Word> msWordsComparator = new Comparator<UserWordsListAdapter.Word>() {
+ RecyclerView mWordsRecyclerView;
+
+ private static final Comparator<EditorWord> msWordsComparator = new Comparator<EditorWord>() {
@Override
- public int compare(UserWordsListAdapter.Word lhs, UserWordsListAdapter.Word rhs) {
+ public int compare(EditorWord lhs, EditorWord rhs) {
return lhs.word.compareTo(rhs.word);
}
};
@@ -117,19 +114,9 @@ public class UserDictionaryEditorFragment extends Fragment
}
});
- View emptyView = view.findViewById(R.id.empty_user_dictionary);
- emptyView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- createEmptyItemForAdd();
- }
- });
-
- mWordsListView = (AbsListView) view.findViewById(android.R.id.list);
- mWordsListView.setFastScrollEnabled(true);
- //this is for the "empty state" - it will allow the user to quickly add the first word.
- mWordsListView.setEmptyView(emptyView);
- mWordsListView.setOnItemClickListener(this);
+ mWordsRecyclerView = (RecyclerView) view.findViewById(R.id.words_recycler_view);
+ mWordsRecyclerView.setHasFixedSize(false);
+ mWordsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
@Override
@@ -157,12 +144,9 @@ public class UserDictionaryEditorFragment extends Fragment
}
private void createEmptyItemForAdd() {
- UserWordsListAdapter adapter = (UserWordsListAdapter) mWordsListView.getAdapter();
+ EditorWordsAdapter adapter = (EditorWordsAdapter) mWordsRecyclerView.getAdapter();
if (adapter == null || !isResumed()) return;
- final int addWordItemIndex = adapter.getCount() == 0 ? 0 : adapter.getCount() - 1;
- //will use smooth scrolling on API8+
- AnyApplication.getDeviceSpecific().performListScrollToPosition(mWordsListView, addWordItemIndex);
- onItemClick(mWordsListView, null, addWordItemIndex, 0l);
+ adapter.addNewWordAtEnd(mWordsRecyclerView);
}
@Override
@@ -275,15 +259,11 @@ public class UserDictionaryEditorFragment extends Fragment
}).create();
}
- private void deleteWord(String word) {
- mCurrentDictionary.deleteWord(word);
- }
-
private void fillWordsList() {
Log.d(TAG, "Selected locale is " + mSelectedLocale);
new UserWordsEditorAsyncTask(this) {
private EditableDictionary mNewDictionary;
- private List<UserWordsListAdapter.Word> mWordsList;
+ private List<EditorWord> mWordsList;
@Override
protected void onPreExecute() {
@@ -306,7 +286,7 @@ public class UserDictionaryEditorFragment extends Fragment
mWordsList = new ArrayList<>(mCursor.getCursor().getCount());
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
- UserWordsListAdapter.Word word = new UserWordsListAdapter.Word(
+ EditorWord word = new EditorWord(
mCursor.getCurrentWord(),
mCursor.getCurrentWordFrequency());
mWordsList.add(word);
@@ -318,39 +298,21 @@ public class UserDictionaryEditorFragment extends Fragment
}
protected void applyResults(Void result, Exception backgroundException) {
- ListAdapter adapter = getWordsListAdapter(mWordsList);
- //AbsListView introduced the setAdapter method in API11, so I'm required to check the instance type
- if (mWordsListView instanceof ListView) {
- //this is NOT a redundant cast!
- ((ListView)mWordsListView).setAdapter(adapter);
- } else if (mWordsListView instanceof GridView) {
- //this is NOT a redundant cast!
- ((GridView)mWordsListView).setAdapter(adapter);
- } else {
- throw new ClassCastException("Unknown mWordsListView type "+mWordsListView.getClass());
- }
+ mWordsRecyclerView.setAdapter(createAdapterForWords(mWordsList));
}
}.execute();
}
- protected ListAdapter getWordsListAdapter(List<UserWordsListAdapter.Word> wordsList) {
- return new UserWordsListAdapter(
- getActivity(),
- wordsList,
- this);
+ protected EditorWordsAdapter createAdapterForWords(List<EditorWord> wordsList) {
+ return new EditorWordsAdapter(wordsList, LayoutInflater.from(getActivity()));
}
protected EditableDictionary getEditableDictionary(String locale) {
return new UserDictionary(getActivity().getApplicationContext(), locale);
}
-
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- ((UserWordsListAdapter) mWordsListView.getAdapter()).onItemClicked(parent, position);
- }
-
+/*
@Override
- public void onWordDeleted(final UserWordsListAdapter.Word word) {
+ public void onWordDeleted(final EditorWord word) {
new UserWordsEditorAsyncTask(this) {
@Override
protected Void doAsyncTask(Void[] params) throws Exception {
@@ -365,8 +327,12 @@ public class UserDictionaryEditorFragment extends Fragment
}.execute();
}
+ private void deleteWord(String word) {
+ mCurrentDictionary.deleteWord(word);
+ }
+
@Override
- public void onWordUpdated(final String oldWord, final UserWordsListAdapter.Word newWord) {
+ public void onWordUpdated(final String oldWord, final EditorWord newWord) {
new UserWordsEditorAsyncTask(this) {
@Override
@@ -383,10 +349,5 @@ public class UserDictionaryEditorFragment extends Fragment
fillWordsList();
}
}.execute();
- }
-
- @Override
- public void performDiscardEdit() {
- ((UserWordsListAdapter) mWordsListView.getAdapter()).onItemClicked(mWordsListView, -1/*doesn't really matter what position it is*/);
- }
+ }*/
}
diff --git a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserWordsListAdapter.java b/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserWordsListAdapter.java
deleted file mode 100644
index c09f77e5c..000000000
--- a/src/main/java/com/anysoftkeyboard/ui/settings/wordseditor/UserWordsListAdapter.java
+++ /dev/null
@@ -1,311 +0,0 @@
-package com.anysoftkeyboard.ui.settings.wordseditor;
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import com.menny.android.anysoftkeyboard.R;
-
-import java.util.List;
-
-/**
- * List adapter to be used with the words editor fragment.
- */
-class UserWordsListAdapter extends ArrayAdapter<UserWordsListAdapter.Word> implements View.OnClickListener {
-
- public static class Word {
- @NonNull
- public final String word;
- public final int frequency;
-
- public Word(@NonNull String word, int frequency) {
- this.word = word;
- this.frequency = frequency;
- }
-
- @Override
- public int hashCode() {
- return word.hashCode() + frequency;
- }
-
- @Override
- public String toString() {
- return word;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Word) {
- Word otherWord = (Word) o;
- return otherWord.frequency == frequency && otherWord.word.equals(word);
- } else {
- return false;
- }
- }
- }
-
- public static interface AdapterCallbacks {
- void onWordDeleted(Word word);
-
- void onWordUpdated(String oldWord, Word newWord);
-
- void performDiscardEdit();
- }
-
- private final LayoutInflater mInflater;
- private AdapterCallbacks mCallbacksListener;
-
- private final int NONE_POSITION = -1;
- private int mCurrentlyEditPosition = NONE_POSITION;
-
- private final int TYPE_NORMAL = 0;
- private final int TYPE_EDIT = 1;
- private final int TYPE_ADD = 2;
-
- public UserWordsListAdapter(Context context, List<Word> words, AdapterCallbacks callbacks) {
- super(context, R.id.word_view, words);
- mCallbacksListener = callbacks;
- mInflater = LayoutInflater.from(context);
- }
-
- @Override
- public int getViewTypeCount() {
- //one for normal, and the second type is "editing"
- //it will inflate the same layout on both occasions, but will allow use to stop re-creation and re-use of the EDIT view.
- //the third one is for the "add new word"
- return 3;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public long getItemId(int position) {
- switch (getItemViewType(position)) {
- case TYPE_EDIT:
- return 1;
- case TYPE_ADD:
- return 2;
- default:
- final Word word = getItem(position);
- return word.hashCode();
- }
- }
-
- @Override
- public int getCount() {
- final int baseCount = super.getCount();
- if (baseCount == 0 && mCurrentlyEditPosition == NONE_POSITION)
- return 0;//in the case that there are no words (and not editing the first word), I have a special "empty state"
-
- return super.getCount() + 1;//the plus one is for the "Add new";
- }
-
- @Override
- public int getItemViewType(int position) {
- if (mCurrentlyEditPosition == position)
- return TYPE_EDIT;
- else if (position == super.getCount())//this is the last item, which is an "Add word" item.
- return TYPE_ADD;
- else
- return TYPE_NORMAL;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final int viewType = getItemViewType(position);
- TextView wordView;
- if (convertView == null) {
- switch (viewType) {
- case TYPE_NORMAL:
- convertView = inflateNormalWordRow(mInflater, parent);
- assert convertView != null;
- final View deleteButton = convertView.findViewById(R.id.delete_user_word);
- deleteButton.setOnClickListener(this);
- break;
- case TYPE_EDIT:
- convertView = inflateEditedWordRow(mInflater, parent);
- assert convertView != null;
- final View approveButton = convertView.findViewById(R.id.approve_user_word);
- approveButton.setOnClickListener(this);
- wordView = ((TextView) convertView.findViewById(R.id.word_view));
- wordView.setOnKeyListener(mOnEditBoxKeyPressedListener);
- wordView.addTextChangedListener(mOnEditBoxTextChangedListener);
- wordView.setOnEditorActionListener(mEditBoxActionListener);
- break;
- case TYPE_ADD:
- convertView = inflateAddWordRow(mInflater, parent);
- assert convertView != null;
- break;
- default:
- throw new IllegalArgumentException("Unknown view type!");
- }
- }
-
- wordView = ((TextView) convertView.findViewById(R.id.word_view));
- final Word word;
- //why to check the position against the super.getCount, and not the view type?
- //good question! In the state where we adding a new word, the underling array is still one short,
- //so the view type will be "EDIT", but the count will still be one less.
- if (position == super.getCount()) {
- word = null;/*empty word at the "add new word" row*/
- } else {
- word = getItem(position);
- }
- convertView.setTag(word);
-
- switch (viewType) {
- case TYPE_NORMAL:
- updateNormalWordRow(convertView, wordView, word);
- break;
- case TYPE_EDIT:
- updateEditedWordRow(convertView, wordView, word);
- //I want the text-box to take the focus now.
- wordView.requestFocus();
- break;
- }
- return convertView;
- }
-
- protected void updateEditedWordRow(View rootView, TextView wordView, Word word) {
- wordView.setText(word == null? "" : word.word);
- }
-
- protected void updateNormalWordRow(View rootView, TextView wordView, Word word) {
- wordView.setText(word.word);
- }
-
- protected View inflateAddWordRow(LayoutInflater inflater, ViewGroup parent) {
- return inflater.inflate(R.layout.user_dictionary_word_row_add, parent, false);
- }
-
- protected View inflateEditedWordRow(LayoutInflater inflater, ViewGroup parent) {
- return inflater.inflate(R.layout.user_dictionary_word_row_edit, parent, false);
- }
-
- protected View inflateNormalWordRow(LayoutInflater inflater, ViewGroup parent) {
- return inflater.inflate(R.layout.user_dictionary_word_row, parent, false);
- }
-
- public void onItemClicked(AdapterView<?> listView, int position) {
- if (mCurrentlyEditPosition == NONE_POSITION && position >= 0) {
- //nothing was in edit mode, so we start a new one
- mCurrentlyEditPosition = position;
- //see http://stackoverflow.com/a/2680077/1324235
- listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
- } else {
- //there was an edit in progress. Clicking out side will cause DISCARD.
- mCurrentlyEditPosition = NONE_POSITION;
- //see http://stackoverflow.com/a/2680077/1324235
- listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
- listView.requestFocus();
- }
- notifyDataSetChanged();
- }
-
-
- @Override
- public final void onClick(View v) {
- final Word word = (Word) ((View) v.getParent()).getTag();
- switch (v.getId()) {
- case R.id.delete_user_word:
- onWordDeleted(word);
- break;
- case R.id.approve_user_word:
- Word newWord = onWordEditApproved(v, word);
- mCurrentlyEditPosition = NONE_POSITION;
- if (newWord == null || TextUtils.isEmpty(newWord.word) || newWord.frequency == 0) {
- //this is weird.. The user wanted the word to be deleted?
- //why not clicking on the delete icon?!
- //I'm ignoring.
- notifyDataSetChanged();//reloading the list.
- } else {
- mCallbacksListener.onWordUpdated(word == null? "" : word.word, newWord);
- }
- break;
- }
- }
-
- protected void onWordDeleted(Word word) {
- mCallbacksListener.onWordDeleted(word);
- }
-
- protected Word onWordEditApproved(View approveButton, @Nullable Word oldWord) {
- View parent = ((View) approveButton.getParent());
- EditText editBox = (EditText) parent.findViewById(R.id.word_view);
- final String newWord = editBox.getText().toString();
- if (TextUtils.isEmpty(newWord)) {
- return null;
- } else {
- return new Word(newWord, oldWord == null? 128 : oldWord.frequency);
- }
- }
-
- protected final View.OnKeyListener mOnEditBoxKeyPressedListener = new View.OnKeyListener() {
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_BACK:
- //discarded!
- mCallbacksListener.performDiscardEdit();
- return true;
- case KeyEvent.KEYCODE_ENTER:
- EditText edit = (EditText)v;
- if ((edit.getImeOptions() & EditorInfo.IME_ACTION_DONE) == EditorInfo.IME_ACTION_DONE) {
- View parent = (View) v.getParent();
- View approveButton = parent.findViewById(R.id.approve_user_word);
- onClick(approveButton);
- } else if ((edit.getImeOptions() & EditorInfo.IME_ACTION_NEXT) == EditorInfo.IME_ACTION_NEXT) {
- View nextField = edit.focusSearch(View.FOCUS_RIGHT);
- if (nextField != null)
- nextField.requestFocus();
- }
- return true;
- default:
- return false;
- }
- }
- };
-
- protected final TextView.OnEditorActionListener mEditBoxActionListener = new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- View parent = (View) v.getParent();
- View approveButton = parent.findViewById(R.id.approve_user_word);
- onClick(approveButton);
- return true;
- }
- };
-
- private final TextWatcher mOnEditBoxTextChangedListener = 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) {
-
- }
- };
-
-}
diff --git a/src/main/res/drawable-hdpi/ic_cancel.png b/src/main/res/drawable-hdpi/ic_cancel.png
new file mode 100644
index 000000000..c83434042
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_cancel.png
Binary files differ
diff --git a/src/main/res/drawable-mdpi/ic_cancel.png b/src/main/res/drawable-mdpi/ic_cancel.png
new file mode 100644
index 000000000..a674ad738
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_cancel.png
Binary files differ
diff --git a/src/main/res/drawable-xhdpi/ic_cancel.png b/src/main/res/drawable-xhdpi/ic_cancel.png
new file mode 100644
index 000000000..a7260559a
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_cancel.png
Binary files differ
diff --git a/src/main/res/drawable-xxhdpi/ic_cancel.png b/src/main/res/drawable-xxhdpi/ic_cancel.png
new file mode 100644
index 000000000..4258c1678
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_cancel.png
Binary files differ
diff --git a/src/main/res/layout/abbreviation_dictionary_word_row_edit.xml b/src/main/res/layout/abbreviation_dictionary_word_row_edit.xml
index 866bc7a2b..56db7e15e 100644
--- a/src/main/res/layout/abbreviation_dictionary_word_row_edit.xml
+++ b/src/main/res/layout/abbreviation_dictionary_word_row_edit.xml
@@ -54,4 +54,13 @@
android:scaleType="centerInside"
android:src="@drawable/ic_accept"
android:background="@drawable/transparent_click_feedback_background"/>
+ <ImageView
+ android:id="@+id/cancel_user_word"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ android:adjustViewBounds="true"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_cancel"
+ android:background="@drawable/transparent_click_feedback_background"/>
</LinearLayout> \ No newline at end of file
diff --git a/src/main/res/layout/user_dictionary_editor.xml b/src/main/res/layout/user_dictionary_editor.xml
index e1e94b5dd..5337eb947 100644
--- a/src/main/res/layout/user_dictionary_editor.xml
+++ b/src/main/res/layout/user_dictionary_editor.xml
@@ -19,23 +19,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <include layout="@layout/user_dictionary_editor_abslistview" />
-
- <LinearLayout
- android:id="@+id/empty_user_dictionary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="16dp"
- android:visibility="gone"
- android:background="@drawable/transparent_click_feedback_background">
- <TextView
- style="@style/Ask.Text.SubTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center"
- android:text="@string/user_dict_settings_empty_text"
- android:drawablePadding="12dp"
- android:drawableTop="@drawable/ic_large_new" />
- </LinearLayout>
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/words_recycler_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
</FrameLayout> \ No newline at end of file
diff --git a/src/main/res/layout/user_dictionary_word_row_edit.xml b/src/main/res/layout/user_dictionary_word_row_edit.xml
index 91c7eb626..e1c853522 100644
--- a/src/main/res/layout/user_dictionary_word_row_edit.xml
+++ b/src/main/res/layout/user_dictionary_word_row_edit.xml
@@ -31,4 +31,14 @@
android:scaleType="centerInside"
android:src="@drawable/ic_accept"
android:background="@drawable/transparent_click_feedback_background"/>
+
+ <ImageView
+ android:id="@+id/cancel_user_word"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ android:adjustViewBounds="true"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_cancel"
+ android:background="@drawable/transparent_click_feedback_background"/>
</LinearLayout> \ No newline at end of file
diff --git a/src/main/res/layout/word_editor_empty_view.xml b/src/main/res/layout/word_editor_empty_view.xml
new file mode 100644
index 000000000..36e6f6cd6
--- /dev/null
+++ b/src/main/res/layout/word_editor_empty_view.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ android:background="@drawable/transparent_click_feedback_background">
+
+ <TextView
+ style="@style/Ask.Text.SubTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:text="@string/user_dict_settings_empty_text"
+ android:drawablePadding="12dp"
+ android:drawableTop="@drawable/ic_large_new"/>
+</LinearLayout> \ No newline at end of file
diff --git a/src/main/res/values/ids.xml b/src/main/res/values/ids.xml
index 2110702c0..1b874415d 100644
--- a/src/main/res/values/ids.xml
+++ b/src/main/res/values/ids.xml
@@ -9,4 +9,10 @@
<item name="keyboard_ui_handler_MSG_REMOVE_CLOSE_SUGGESTIONS_HINT" type="id" />
<item name="popup_manager_dismiss_preview_message_id" type="id" />
+
+ <!-- words editor view types -->
+ <item name="word_editor_view_type_row" type="id" />
+ <item name="word_editor_view_type_editing_row" type="id" />
+ <item name="word_editor_view_type_add_new_row" type="id" />
+ <item name="word_editor_view_type_empty_view_row" type="id" />
</resources> \ No newline at end of file