I am using MVVMCross's wrapper around the Xamarin Android AutoCompleteTextView.
I use the PartialTextChanged changed event to signal that I need to call the ViewModel, from the View, to get some more suggestions.
This works fine up to the point the user selects an item from the list. After that point no changes to the text will cause the PartialTextChanged event to fire. It is as if filtering is turned off once a selection has been made.
There is a SetText method on the AutoCompleteTextView that seems to turn filtering on\off but I am unsure of the best way to use that.
The TextChangedEvent still fires on the control as does AfterTextChanged just not PartialTextChanged and it is that which drives the updates.
I have debugged through the MVVMCross source and cannot see a solution. Any have any ideas?
Where can I browse them mondroid\xamarin android code?
Thanks
After attaching the MVVMCross Source Code and debugging all the events I found that under certain circumstances I was not updating the ItemsSource after the PartialText property was being changed
The FilteringAdapter uses a ManualResetEvent around the change to PartialText and that is only signalled\set by the NotifyDataSetChanged method.
After finding this I also found that #slodge also mentions this in this answer, AutoComplete MVVM and Java Castings without using Java.Lang.Object on ViewModel. A constraint that until now had passed me by.
Note that because of the Android threading model it is essential that
every change in PartialText is met by an eventual signalled change in
ItemsSource - and this should be a single change in object collection
rather than lots of small changes.
Thanks
Related
I am building an app that displays a bunch of information that the user can edit, and I am having trouble keeping the UI updating the data displaid so it is consistent with the new edits done at runtime.
I have implemented updateUI methods that basically look like:
void updateUI(){
((TextView) fieldDisplay).setText(fieldCurrentValue);
...
}
I know I can run this method in things like an AsyncTask or similar stuff that makes it execute continuously. But Im concerned about efficency since its not really necesary to update the UI all the time, but only when the user inputs a value wich is not that often.
What would be the best approach to this?
EDIT:
The question is how to make sure the an UI element shows the current value of a field, regardless of how or why that field is updated.
My case specifically is the with this. Im trying to make an RPG character sheet, and I have like a bazillion Skills, wich are affected by another lot of fields, such as Characteristics, Modifiers, Categories...
The application should behave so, whenever any of the many fields affects it changes, it should display the new value.
Now, since keeping track of what field affects what is part of the problem, if could update whenever any field whatsoever changes, but I dont know how to do that.
I need to update several visual components in my app during a timeconsuming function, instead my app seems to hang during this function call, rather than update the visual components on the screen. When the function exit, I see only the last changes to the components.
Is there a simple way to do the updates, or do I need to create a parallel process and have a 'timer' to read the data simultaniously (using semaphores) and present them in the timer call ?
Any suggestions ?
I asked the same question yesterday here. Like mh taqia said you can use Application->ProcessMessages() but you have to be careful with it. For my application, it worked but look at some posts about the function first.
I tried following:
MainForm->Invalidate();
MyControlRoot->Repaint();
MyControlRoot is a control containing somewhat 50-60 different other controls
But MyControlRoot wouldn't repaint with this method. ..
Despite the warnings from you Remy, I tried Application->ProcessMessages();
...works for now...
By the way... I cannot see any warnings in Docwiki on using ProcessMessages... what could I expect?
RG
I have elements in a listview that change the way they look based on a network response
by the time the network responds the listview item (or item in the arraylist) could be at a different index
What I can do:
Make an alternate api call back to the server which returns all the items in the list (in their most updated form), and then call notifyDataSetChanged() on the adapter
but this seems like a waste of processes, and so does some alternative of searching an arraylist for the equivalent object, updating it and then calling notifyDataSetChanged()
Is there a way instead to have something like a BroadcastReceiver within the adapter that can keep track of the adapter item which started the network call or service? any maybe only respond to the receiver if the view is not currently recycled
It's hard to give an exact answer as your best approach since what you described is a really high level overview. I'll have to give an equal high level answer. Hopefully it help.
There's not many ways around searching an ArrayList in the adapter for a given item. One good idea:
You could create a custom adapter which is backed by an ArrayList but also maintains a Set of the data as well. The benefit is finding an item is O(1) however any adds or removes require you to modify two collections instead of one...which will cause a slight slow down. I've personally had to use this solution once for a highly complex adapter/listview. It could get updated quite often (to the point throttling notifyDataSetChanged() was once discussed) Surprisingly the slow down in maintaining a List and Set was hardly noticeable and overall worked well.
You could use a similar approach if your data has some sort of unique id associated with it. In which case you could build a Map of the data and use the maps values() method to obtain the List to use for the adapter. While using the keys to quickly find and update the required data. This may or may not be more difficult then the Set idea. Further if you can get your data into a SparseArray (having a unique int for each item), then you could use a SparseArrayAdapter which can get you O(log n) search times. Of course you loose the ability to sort your data in any meaningful way.
I'm not sure how viable the BroadcastReceiver idea is. I would see it more like each item's object instance would control the network request/response for itself, but that would seem tricky and odd. There's always the option of using a CursorAdapter. Just store all your data to DB. Have the network calls update the DB which can then be reflected within the CursorAdapter.
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.
I have a ListView bound to a SimpleCursorAdapter, and I want it to refresh when I modify the database (by inserting, updating or deleting rows). cursor.notifyDataSetChanged() has no effect (it's called on the UI thread) and ListView.removeViewAt(int) throws an UnsupportedOperationException.
What am I supposed to do on Android to get such a basic behavior?
Note that the database is correctly affected and the modification is shown when I restart the activity. But restarting the activity is not an option here, and changing the ListView adapter is the last resource here, since it's a hack and can't guarantee a smooth transition
DISCLAIMER
Quite basic question, asked millions of times and answered zero.
Please, do not answer if you have never done this in your code, don't ask for mine, and don't bother with try this or try that. Only answer if you know how it's done
From API >= 11 the way to do this is using a CursorLoader, this is also included in the Android Compatibility Library, so you can also use this if you are targeting a previous Android version. CursorLoader will make the query in a background thread and return you the cursor. You will need to implement a ContentProvider. You can read the documentation to get an idea of how to use it. Basically you init a loader and then you restart it when you know data has changed. In the callback you just swap the cursor of your adapter.
Or you can just use requery() on the Cursor. The adapter will get automatically notified of the changes. This method is deprecated now and, of course, it's not the recommended way.