Android get dictionary suggestions (equivalent to UiTextChecker) - android

I'm trying to implement some code in Android similar to code my colleague has written for iOS.
In his code he takes some input text and asks the system for autocomplete suggestions. The purpose is to guess what the next letter might be, so if the user has typed "pri" the possibilities might most likely be "c" (for "price"), "d" (for "pride"), "g" (for "prig") etc
Now my colleague uses an API in iOS called "UiTextChecker().completions" to get possible completions for the text typed so far. I'm looking for something similar in Android.
I saw this answer from 5 years ago which seems to imply that you have to write your own code, and include your own dictionary. Is this still true? Does anyone know of project (and a dictionary) which can be freely used (or at least have some code to parse and organize the dictionaries referred to), or do I have to write my own dictionary and all the code too?
Seems unlikely so much work would be needed to duplicate a simple call in iOS, but I have not found any examples except many many examples of AutoCompleteTextView with a tiny dictionary of 5 fruit or 10 countries.

Well, I really can't find a way to do this - so I simply imported a list of the most commonly used couple of thousand words in English into my app (comma separated), then have some code like this:
// let's create a list of 1000 words
String thousandWords = resources.getString(R.string.words1000list);
String[] list = thousandWords.split(",");
words = Arrays.asList(list);
and I wrote some code like this (uses Java 8):
public class WordPredicates {
public static Predicate<String> startsWith(final String prefix) {
return p -> p.startsWith(prefix);
}
public static List<String> getCandidates (List<String> wordsList, Predicate<String> predicate) {
return wordsList.stream().filter(predicate).collect(Collectors.<String>toList());
}
}
Then whenever I have some text I want possible completions I simply call:
List<String> completions = WordPredicates.getCandidates(words, WordPredicates.startsWith(word));
Works a treat

Related

Android: Is there an object in Kotlin that contains all characters like colon, semicolon etc

Right now I am starting a new project and I usually had a constant class for symbols like:
object Symbols{
const val CHAR_COLON = ":"
const val CHAR_COMMA = ","
const val CHAR_SEMICOLON = ";"
etc.
}
Would be great if a class like this was already added in Java or Kotlin but I don't seem to find anything like this. Does anyone know of such a thing? Thanks.
I'm not sure why you want to define constants for individual characters (just use the char, it's a constant!) but the Unicode standard defines a bunch of categories for characters, and you can access those through the Java Character class, which also has some methods for getting a character's type.
Kotlin gives you a CharCategory enum class which contains all these categories, and some functions that make it a little easier - for example you can do this:
println(CharCategory.OTHER_PUNCTUATION.contains(','))
>> true
But for example, '-' is not in the OTHER_PUNCTUATION category, aka category Po. That comes under DASH_PUNCTUATION, Pd. If you notice, all the punctuation category codes start with P, so you could do this kind of thing:
val punctuationCategories
= CharCategory.values().filter { it.code.first() == 'P' }
val Char.isPunctuation: Boolean get() = punctuationCategories.any { it.contains(this) }
println('-'.isPunctuation)
>> true
That's just a basic overview and pointing out this stuff is baked into the Unicode standard - I don't really know a lot about it (I can't see a more convenient way to do this but I could be wrong) and I'm not sure if it's helpful, but there it is!
Kotlin does have an object full of constants for "Unicode symbols used in proper Typography" for some reason though! Also a couple with typos in the name so they had to deprecate them, now that's what I call typography
edit: I should point out that Unicode aims to represent every writing system that ever existed, so its scope of what counts as "punctuation" might be a bit broader than what you're looking for! It depends if you're just trying to check a character, or if you want to create a collection of punctuation characters. If you just want to limit things to a particular Charset, like US_ASCII or whatever, I'm not sure how you can get access to all the characters that covers

Ionic2-Calendar now failing on the device

I am developing an Ionic 4 based app with Angular 8 and have a strange situation that has developed. I am using this calendar.
It seems to be similar to this issue... and you will see I have commented there asking how they solved it to no avail.
It works fine on the browser using ionic -serve and WAS working fine on my android device (I haven't gotten to iOS yet).
There was an andoid update to my phone last week and since then, the calendar page doesnt work any longer.
I have stripped out most of the code and simplified it to the extent that it (almost) works now but I have to remove the datasource object.
This leads me to believe there is something wrong with the data in the datasource which I had found before when incorrectly formatted. However, I am uncertain if this is the issue.
The startTime and endTimes come from the server and are converted from ISO strings like this:
fixAppointmentTimesFromServer(appointment: Appointment) {
appointment.startTime = new Date(appointment.StartTimeServer);
appointment.endTime = new Date(appointment.EndTimeServer);
}
If I log out the type of object in the appoinmtents array like this:
this.userService.appointments.forEach( appt => {
console.log(appt.startTime);
console.log(typeof (appt.startTime));
console.log(appt.endTime);
console.log(typeof (appt.endTime));
});
it shows the start/endTimes as strings so I was wondering if this could be the issue, or if thats just more of the mystery that is JS Date objects..?
Or if anyone can tell me how to actually find and get into the Calendar module to debug it, then that might help?
I've added an additional:
this.platform.ready().then( res => {
...
at the start of the ngOninit().
The whole start/end time thing could just be a red herring...
Any thoughts at all? Thanks
I am answering my own question here since I don't want others to have the same issues I had tracking this down.
The way I was fixing up the date for the ionic2 calendar wasn't adequate (apparently) as it needs a millisecond based Date Object to work properly. Different browser versions seem to operate differently.
So, the way I fix up the dates from the server now is as follows:
fixAppointmentTimesFromServer(appointment: Appointment) {
const start = new Date(appointment.StartTimeServer);
const end = new Date(appointment.EndTimeServer);
appointment.startTime = new Date(Date.UTC(start.getFullYear(), start.getMonth(),
start.getDate(), start.getHours(), start.getMinutes()));
appointment.endTime = new Date(Date.UTC(end.getFullYear(), end.getMonth(), end.getDate(), end.getHours(), end.getMinutes()));
}
This converts first to a string and then converts again to get a UTC (millisecond) based Date object. Which does work.
A word of caution however:
I found that when I wasn't getting the data from the server, but using the already converted data from out of Ionic Storage, it broke again. This needing me to reconvert the data when getting it out of storage. So, this wasn't some 'funny date on the server' to JS thing, moreover a perfect example of how completely ******* up Javascript actually is!

How to parameterise all strings in android application

I am building an application and I am thinking of how to "parametrise" all the strings in the application (is it even possible) in order to allow me to change them easily without "redeploying" it again ...
meaning it will be somewhere in a file with strings (something like you have PO files in PHP when using templates and different languages) where I can manage it ..
it might be useful when I would like to use different languages :)
I am kinda struggling on this one, so I was thinking if you can give me a clue or show me where to "go" to study how this should be implemented ..
Thanks
If you want different langage in your app, create as many strings.xml files as you need. However, when you add new strings file, you have to redeploy.
To avoid that, you should call a specific API in backend which send you all the texts according to the langage of the device. For that you must manage back and front.
So if I understand your question correcly go to res - >value folder -> strings.xml - > open it and you will see something like this:
<string name="app_name">this is your app name</string>
And now every time that you want text to be "this is your app name" all you need to do is to add this line:
android:text="#string/app_name"
And when you will change the actual string in strings.xml it will also change in every place he is being used (android:text="#string/app_name")
Android has a built-in mechanism for localising assets (Strings included)
https://developer.android.com/guide/topics/resources/localization#creating-alternatives
What you are trying to do is known as 'Localisation', this can be helpful if you want to give users different language support and similar kind of stuff.
In android, this is done by putting all the strings in the Strings.xml file located in the res folder.
If you're using android studio, just press Alt + Enter on any hardcoded string and then select 'Extract string resource' from the popup, give the name of the string and Voila! you're done.
It is also a part of good coding practice, in fact you've might have noticed 'Lint warnings' in your layout files if you type any hardcoded string, and it asks you to add this string in the strings.xml file
You can create a separate String file for each language that you wanna include.
Option 1
Using the Default Built-In Mechanism
You already have answers about this or you can read the official documentation about it.
Essentially, you maintain an xml file called strings.xml which is a key-value of Strings. Each file (one per language) will be located in a values folder. E.g.: for french, you'd want values-fr/strings.xml. Each file will include all the translated strings. If a value is not found in French, then the english file will be searched instead as a fallback. If the key is not there, the app will crash (if I am not mistaken).
Pros
Included with the system
Supports many languages
Packed at compile time, always available.
Cons
Resources are "read-only" once they are compiled; you cannot change a string and save the change this way.
Option 2
Roll your own Thing.
If you need to be able to dynamically alter these strings, you'll need a few key pieces:
A way to obtain/download said strings.
A default in case step 1 fails (what if the user cannot download them?) You need defaults.
To ensure every widget that needs to display text, calls your own creation of a class that can manage said dynamic strings (i'll elaborate down below)
You need to know what to do if a String is somehow magically missing; because this is dynamic, there has to be a fallback in case the string is not found (see 2)
This has to be relatively fast (you don't want expensive lookups when constructing strings and UI elements).
Pros
You can model this the way it works best for you
You will be able to load strings as you see fit and even change them at runtime.
Cons
You have to build all this.
It's error prone, and most likely slower than the native solution.
You must ensure you don't miss strings and that you have dafults.
You must modify normal widgets (say TextView) to understand how to fetch the strings (or you must always provide them), and this is not going to be automatic, you'll either have to delegate or subclass into a YourCustomTextViewThatUnderstandsYourStringThing extends TextView (name... is just a draft ;) )
You must ensure you don't leak memory by keeping strings in memory you don't care anymore.
If you want to "persist" these downloaded languages (and you should), you have to write/use your own persisting mechanism (either by writing the files or by using some database, shared preferences is not the place for these).
You need to cache them (see above) and manage the validity of the strings (what if they become old, can they become old? when should you re-fetch them?)
etc.
As you can see it's not trivial and each app has its own world of problems to solve, but that's roughly what it means.
As for "code"... the simplest way I can think of (or rather, the bare basics) are:
Find a way to "store" the strings: e.g.:
Map<String, String> oneLanguage
So in this Map, you store the KEY (to find the value) and the VALUE:
oneLanguage.put("app_name", "My Super App")
Keep all the strings in one place in memory:
Map<String, Map<String, String>> allLanguages
so then you do:
allLanguages.put("English", oneLanguage);
Now you can add other languages:
anotherLanguage.put("app_name", "Mi Super App"); //my Spanish is top-notch
allLanguages.put("Spanish", anotherLanguage);
Now you have a place where to store (in memory) all your keys/values for each language.
When you want to retrieve Spanish, you'd have a method like:
String getString(#NonNull String locale, #NonNull String key) {
return allLanguages.get(locale).get(key);
}
And then you'd need to (either manually or via subclassing or whatever approach you find more convenient) to set these strings like:
// I mean, don't hardcode the locale... but you get the idea.
appNameTextView.setText(yourLanguageManager.getString("Spanish", "app_name"));
What approach you take for this last step, is entirely up to you.
As usual, all the above is pseudo-code, and not a complete solution to this approach. Things you want to do: ask the device what locale is using, keep track of which locale is in use (so you don't have to pass it every time), fetch these locales from your server (not pictured) :), persist these to disk, as well as save in shared preferences, the "locale" key that the user has selected, add methods to your yourLanguageManager so it can have things like:
boolean updateLocale(String locale, Map<String, String newStrings)
boolean deleteLocale(String locale)
Map<String, String> getLocale(String locale)
etc.. you get the idea.
All in all, it's just a simple data structure that can contain keys and values.
Good luck!

Android Spinner - System view VS User view

I have been creating Spinner controls (Combo boxes/Drop downs) in one of my apps, and was surprised to find out how difficult it was to achieve all of the following features:
User facing Strings are externalized, taking advantage of strings.xml internationalisation (I18N) feature of Android.
Spinner selections operate using a System view, which facilitates not having to work with or map Strings to meaningful values (yuck).
User view to System view mapping should be easy, automated and minimal (i.e not hand rolled for every component).
Others have attempted solutions to this, but universally as far as I could see they suffer from one or many of the following problems:
UI code is creeping into their enum class which doesn’t belong there (messy), nearly all existing solutions suffered from this.
Hardcoded User facing Strings in their enum classes. Because these are not externalized you cannot do I18N using the stock Android features.
Authors typically make the Fragment or Activity an OnItemSelectedListener which perpetuates a common problem of inheritance for convenience, where composition is more appropriate.
I have developed my own solution which does this: http://www.androidanalyse.com/android-spinner-externalize-user-strings-mapped-to-system-enum/
My question is, have I missed something? This seems like something that should not have been this hard (which makes me feel like I'm possibly reinventing the wheel).
Below is some example code showing my solution in-use (which is available Apache 2 license from the link above).
String none = getString(R.string.none);
String light = getString(R.string.light);
String medium = getString(R.string.medium);
String strong = getString(R.string.strong);
SpinnerUtil.createNewSpinner(view, R.id.wind, Arrays.asList(none, light, medium, strong), WindLevel.values(),
new SpinnerItemSelectedListener<WindLevel>() {
public void onItemSelected(Spinner item, WindLevel value) {
// Take whatever action you wish to here.
}});
I would just use ArrayAdapter<WindLevel>. Yes, you created a custom typed listener, but the regular event listener gets the position and can call getItem() on the ArrayAdapter<WindLevel> to get a WindLevel properly typed.
IMHO, the vast majority of Spinner widgets will be populated with material read in from a database, the Internet, or some other dynamic data source, rather than populated by some sort of enum with display values coming from static strings that can be internationalized ahead of time.
This is not to say that your code is useless: if you find it useful, then it was worth writing. And I am sure that there are apps out there that contain your targeted pattern (i.e., a Spinner backed by an enum or equivalent where the display values are known in advance and can be internationalized) who might find your solution useful as well. Every developer who writes enough code cooks up these sorts of helper classes and the like that help map an OS or framework model into something that better fits the developer's own mental model. So long as you are not perceiving any performance issues, it's all good.
Also, note that OnItemSelectedListener is an interface; implementing that interface on an existing class is not inheritance.
I believe the reason nobody answered you is :
What problem are you trying to solve ? Spinners existed prior to your well designed attempt.
Why reinvent them in exactly the same way they exist in Android ?
http://developer.android.com/guide/topics/ui/controls/spinner.html
It is a beautiful wheel indeed you designed, but still, it is just a wheel :)
UPDATE :
I think I begin to understand what you did. This is interesting. I'm not sure why you did not go to the pattern implemented by the ListPreference with its entries and entryvalues.
In fact, I'm not sure I understand why the Android team did not go that route either.
In any case, it is worth proposing your idea to the Android framework. It is after all open source.

How to perform Redo Undo operation in EditText

I want to know is there any method or any link or tutorial to perform redo undo operation in Android edittext. If any one knows than please let me know.
Quick note on the Antti-Brax/Divers(Kidinov) solution. It works great, except if you try to use it with a TextView post-API 23, you'll run into problems, because guess-what, Google actually added a hidden UndoManager (android.content.UndoManager) and didn't document it or make it obvious it was there. But if you have a hard/bluetooth keyboard in Marshmallow or Nougat and hit ^Z or SHIFT-^Z, you'll get undo/redo.
The problem comes if you're already using Antti-Brax's class with an EditText, and you also hook it to ^Z and shift-^Z, you'll run into problems with anyone using a hard keyboard. Namely the ^Z will trigger BOTH the native and Antti-Brax's undo, leading to two undos simultaneously, which isn't good. And after a few of them, you'll probably get a Spannable out of bounds crash.
A possible solution I found is to subclass the TextView/TextEdit/whatever and intercept the undo/redo calls from the TextView so they don't run as follows:
#Override
public boolean onTextContextMenuItem(int id) {
int ID_UNDO, ID_REDO;
try {
ID_UNDO = android.R.id.undo;
ID_REDO = android.R.id.redo;
} catch (Resources.NotFoundException e) {
ID_UNDO = 16908338; // 0x1020032
ID_REDO = 16908339; // 0x1020033
}
return !((id == ID_UNDO) || (id == ID_REDO)) && super.onTextContextMenuItem(id);
}
Those magic id numbers were found here, and are used only as a backup if the android.R.id.undo values aren't found. (it also might be reasonable to assume that if the values aren't there the feature isn't there, but anyway...)
This is not the best solution because both undo trackers are still there and both are running in the background. But at least you won't trigger both of them simultaneously with ^Z. It's the best I could think to do until this gets officially documented and the getUndoManager() methods of TextView is no longer hidden...
Why they made a feature you can't turn off (or even know if it was there or not) "live" in released Android I can't say.
I just opened an issue on Android's issue tracker if anyone wants to follow this.
There is an implementation of undo/redo for Android EditText in
http://credentiality-android-scripting.googlecode.com/hg/android/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/activity/ScriptEditor.java
The code works but does not handle configuration changes properly. I am working on a fix and will post here when it is complete.
My Google search was :-
android edittext onTextChanged undo
I know this is an old question, but as there is no accepted answer, and this is an issue I've tackled myself from many angles, I'd like to add my solution in case it helps anyone. My answer is probably most relevant to large (1,000words+) volumes of text editing apps that require this feature.
The simplest way to resolve this problem is to make periodic copies of all text on screen, save it to an array and call setText() every time the Undo method is called. This makes for a reliable system, but it isn't ideal for large (i.e. 1,000words+) text editing apps. This is because it:
Is wasteful. It could be that only one word changes in a two thousand word document, so that's one thousand, nine hundred and ninety nine words needlessly committed to memory.
Can lead to performance issues, as some low-tier hardware struggles with rendering large amounts of text. On some of my test devices, this method can lead to freezes of a few seconds whenever Undo is called.
The solution I currently use is comparatively complex, but I've published the results in a library here.
Essentially, this library saves a copy of text as soon as a user begins typing, and then another copy of text once they've stopped typing for a set amount of time (in my case, two seconds). The two text strings are then compared, and the altered section of text returned, the indexes where the alterations occured, and details on whether or not the change was an addition of new text, a deletion, or a replacement of old text with new text.
The net result is that only the necessary text is saved, and when Undo is called, there is only a local delete(), replace() or insert() call, which makes for much faster operations on large text fields.
Here is the undo/redo implementation that was linked to from Gary Phillips' answer extracted into a reusable and universal undo/redo plugin for any widget that descends from a TextView. I added some code for persisting the undo history.
http://code.google.com/p/android/issues/detail?id=6458#c123
Hope this helps.
To preserve EditText Styling with regards to undo:
You can create an ArrayList<EditText> or ArrayList<String> (String containing html text) to store your last 10 (for example) actions. So ArrayList [0] would contain html text from your first action and ArrayList [9] would contain html text from your very last action. Each time the user taps "undo" in your app, you would apply ArrayList [size()-1] to your EditText and then remove ArrayList [size()-1] from your Array.

Categories

Resources