So I have an interesting problem. I have a ListView that I want to maintain the exact row selection and yoffset on an orientation change. As such I call:
list.postDelayed(new Runnable() {
#Override
public void run() {
list.requestFocusFromTouch();
list.setSelectionFromTop(finalPosition, yoffset);
}
},100);
Seems pretty straightforward and it works well. The problem is that when I change the orientation twice (get back to the original orientation, ie landscape->portrait->landscape) than the list has exited TouchMode, ie list.isInTouchMode() returns false (On the first orientation change, list.isInTouchMode() returns true and everything is great, clicking works etc). As such when you scroll the listview programatically using setSelectionFromTop() and click on an item in the list without touching somewhere else in the app first, the list jumps and scrolls to where I clicked, highlighting the wrong item. It's very annoying and I can't seem to find a fix for it. Any ideas and suggestions are most welcome.
Calling list.requestFocusFromTouch() seems to have no effect on setting TouchMode.
More info:
Android:To set an item as selected when the ListView opens?
I found a post from Romain Guy "Whenever you touch the screen, anywhere in the phone, you enter touch
mode for all of the applications. This is the desired and expected
behavior. " http://groups.google.com/group/android-developers/browse_thread/thread/590b02939d14675b/077ad77e4217e56e?lnk=gst&q=[android]+scroll+listview+not+in+touchmode#077ad77e4217e56e
All i want to do is somehow get into TouchMode without forcing the user to actually touch the device on the second orientation change. I have tried list.dispatchTouchEvent() multiple times. Its possible I am sending the wrong motion events:
list.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN ,
list.getWidth(), list.getHeight(), 0));
list.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE ,
list.getWidth(), list.getHeight(), 0));
list.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP ,
list.getWidth(), list.getHeight(), 0));
Another option would be to figure out why we are no longer in TouchMode. I have not overriden onConfigurationChanged() so the layout is completely rebuilt on each orientation change.
Thanks in advance!
Jared
Try using setItemChecked(...) method of the Listview. I've seen that used a fair bit when the Listview is set to CHOICE_MODE_SINGLE, as that mode really makes each listview item a checkable object.
Also look at the following QA where someone was trying to do something similar. It appears that the easiest solution was to create a different background for 'checked' items.
Android listview array adapter selected
Related
I've got a GridView with a custom Adapter, displaying thumbnails of pictures to the user. I can select and deselect pictures (I use setAlpha(0.25) on the views to notify the user of the change), and that's all well and fine.
Now what I want to do next, is have a button on top of the gridview that clears the whole selection, i.e. call setAlpha(1.0) on all views that were changed. So far I can reset my elements in the adapter, and I can setAlpha to 1, but the view doesn't update unless I scroll it out of the display, and then get back to it, or notify the adapter of changes, which redraws all my views, which does not look too pretty if only one element was selected.
I already dynamically set and reset individual elements through the GridView's onClickListener, but can't do this for more. I even tried calling performClick on all selected items through my button, but again it only displays the changes after the views have been out of the screen and are shown again.
Here's how I simulate the clicks:
for (int i = 0; i < mAdapter.getCount(); i++) {
PictureForSelection tempPic = (PictureForSelection) mAdapter.getItem(i);
if (tempPic.isPicSelected()) {
//tempPic.setIfSelected(false);
gridview.performItemClick(mAdapter.getView(i, null, null), i, i);
}
}
EDIT:
Conclusion - don't simulate clicks like this :)
So now I skip click simulation and use this:
gridview.getChildAt(i).setAlpha((float) 1.0);
In general it does exactly what I wanted it to do, except for one case:
If I have for example 3 pictures selected, one is off screen, one is partly shown, and one is fully shown, the ones shown (even partially) don't update their views.
If all the selected pictures are displayed it works flawlessly, but if some are out of the display, the rest do not update until the adapter's getView() gets called by Android. Still, thanks #mmlooloo for getting me so far.
If anyone knows a way around this, please do share :)
After setting your alpha you can call imageview.invalidate(); this causes your imageview to redraw itself.
if notifyDataSetChanged() is not working you can try like this.
i'm not sure whether this works,
1.onclick of the button you set the gridView.setAdapter(null);
2. Then set a new CustomAdapter object to gridview with default values.
I have a tablet app with a Master / Detail layout, with a TableView in the Master panel that changes the content of the Detail pane. I'd like to have the master's row stay highlighted when clicked like it does in the android OS settings.
Right now the best I'm able to do is set the backgroundColor to a new color in response to a 'click' event. However, when I do a quick tap, the row highlights, then blinks back to normal before highlighting again. I'm guessing this is the delay between when I lift my finger off and when the backgroundColor gets changed.
tableview.addEventListener('click', function(e) {
...
else if (e.rowData.id == 3) { // scan history
e.row.backgroundColor = 'blue';
This appears to be the way others have done it: http://developer.appcelerator.com/question/124359/android---tableviews-deselectrow
And if I was just using android and not Titanium: How can I highlight the table row on click ?
Try this instead. The touch start is called immediately, while the click usually is not. Note that according to the docs a scroll event and a touch event cant happen concurrently for iOS and Android, so you probably want to handle the touchcancel event also if you have a `touchstart`` listener.
tableview.addEventListener('touchstart', function(e) {
...
// Get the source row, and then get its id
else if (e.source.id == 3) { // scan history
e.row.backgroundColor = 'blue';
});
EDIT:
Maybe a better way to do this would be to handle the touchend event. This would handle bothe the quick taps, the user sliding to a different row, and the scrolling edge cases.
When creating your row, use:
selectionStyle : "NONE"
This prevents it from changing color on click/touch
And roll your own event listeners to govern exactly when your row is highlighted.
The iOS blue row selection color is something like: "#006EF1"
Here's my problem:
In my android app I use AutoCompleteTextView and refresh items list for each 5 seconds. Refreshing is working, when I call notifyDataSetChanged(). But when I type here something and it'll give me the list of matching items and then I close it manually, when another thread is refreshing the list and calling notifyDataSetChanged() dropdown list is showing automatically (even if I closed it before). And it's really annoying, because if list is long it takes whole screen and after closing it'll appear in another 5 secounds.
I tried dismissDropDown() just after calling notifyDataSetChanged(), but it doesn't have any effect. It looks like dropdown is showing with a little delay. It's also not good way to fix it, because if user hasn't closed the list it'll close after a refresh. Also tried to take focus away - still no effect.
So I need a method to:
update my items list (via notifyDataSetChanged()) without automatically showing dropdown list, but if dropdown was already showed don't close it.
Hope you can help,
cheers
I did it, finally. I post here a solution, maybe someone will use this.
To check if dropdown is visible:
final boolean isVisible = autocomplete.isPopupShowing();
Next, call notifyDataSetChanged(),
Finally:
new Handler().post(new Runnable(){
#Override
public void run() {
if(!isVisible){
autocomplete.dismissDropDown();
}
}
});
This works perfectly.
I have also this problem, I think it seems to be a bug, i solved this by the following way
First of all set your AutoCompleteTextView focusable property to false.
Second change your AutoCompleteTextView focusable property to true in onTouch event of that view.For that you have to implement onTouchListener to the AutoCompleteTextview.
Whenever you touching on that AutoCompleteTextView, you should change focusable property to true otherwise keep it focusable to false. So that the dropdown list is never appear when the view is in unfocusable state.
It shows dropdown list automatically, only when the view is in focusable state which is annoying to user, otherwise it works good.
I need all of the other views in my arrayadapter to check their attributes and return to a default attribute at certain times
use case: listview items (a)(b)(c)(d) , when you touch (a) it's background turns black. This is done in the ontouchListener. But when you touch view (b) it's background turns black BUT (a)'s needs to turn back to the default which is not black
I dabbled around with recalling the arrayadapter at the end of the view.OnClickListener but the problem with this is that it also resets the scroll position of the view, so if this list was much longer - which it is - and user touched item (r) , then it would reset the list and put the user back at item (a) at the top
I was looking at notifydatasetchangedbut I am not sure how to use that and where it should work
insight appreciated
notifyDataSetChanged will do the job. You can call that at any time in your code and this will trigger the adapter to call getView for the visible list items again and so update their content. So basically the only thing you have to do is to update the list item states or information before calling that method.
I have an android-app with a listview in an activity. The listview has, if I call it so, three data states.
no data loaded from inet -> only one dummy item is visible, saying that data is loading;
data is loaded and shown in list;
one listitem is clicked and now shows more information for this listitem (so it is increased in its height).
On every state change (1 -> 2, 2 -> 3), I call notifyDataSetChanged() on this ListAdapater.
This causes the listview to scroll down to the last item. This is ugly in the first transition and even more ugly in the second because the clicked list item is now out of focus.
As I can see, this happens with a google g1 with android 1.6. An htc touch with the same sdk acts like desired (I will try to figure it out with some more devices).
To avoid this, I tried to read out getScrollY() and set this value back. but this returns 0. The reason for this return value I already found on stackoverflow in other questions.
Has anyone else seen this problem? Why does the listview scroll to the last item? It was mentioned that listview keeps track of the scroll position. but it seems that it does not in my case.
Or maybe I am calling the wrong refresh method? Is notifyDataSetChanged the correct one?
I believe you want:
listview.setTranscriptMode(ListView.TRANSCRIPT_MODE_DISABLED);