I need to set the firstVisibleItem. right now when I use smoothScrollToPositionFromTop there seems to be some visible scrolling (of course). I am drawing a blank on what the alternative method is. I have used it before, but I just can't seem to find it. Basically instead of smooth scrolling, it "instantaneously" sets the position that I select plus whatever offset I pass it. Does anyone remember which method does this? It's something like
listView.setAsTop(position, offset)
Use AbsListView#setSelection(int position):
new Handler().post(new Runnable() {
#Override
public void run() {
listView.setSelection(position);
}
});
Make sure listView and position are member variables or declared as final.
Related
I have a listview with 150+ items, I need to make one visible from code. I currently use smoothscrolltoposition but when the desired item is far away from the current visible item it takes several seconds to arrive.
Is there anyway to simply get rid of the smooth scrolling and simply make the item visible directly?
Thanks,
Ignacio
You can use postdelayed for smooth scroll
listview.postDelayed(new Runnable() {
#Override
public void run() {
// smoothscrolltoposition
}
}, 100);
After several testing and reading the thread suggested by audi , I got this solution:
Strangely, the trick is in reassign the adapter to the listview, not even it is needed to recreate it, just reassign.
listView.Adapter = adapter;
listView.FastScrollEnabled = true;
listView.SetSelection(index);
adapter.NotifyDataSetChanged();
I need to be able to programmatically dismiss an item inside a RecyclerView without the user actually swiping (instead I want to dismiss the item when they tap a button in the card). A lot of libraries I've seen only seem to support actual swipes.
I've tried using an existing library and just simulate a MotionEvent by creating a swipe on my own programmatically, but this interferes with another horizontal-swipe listener, so I'm wondering how else this could be done, ideally for a RecyclerView but if anyone knows how to for a ListView instead I can try to adapt that.
I've looked at this library as well as others for inspiration but I can't figure out how to trigger the swipes programmatically instead.
Use a ListView or RecyclerView with custom adapter, and call notifyDataSetChanged after removing an item from the datalist:
private void removeListItem(View rowView, final int position) {
Animation anim = AnimationUtils.loadAnimation(this,
android.R.anim.slide_out_right);
anim.setDuration(500);
rowView.startAnimation(anim);
new Handler().postDelayed(new Runnable() {
public void run() {
values.remove(position); //Remove the current content from the array
adapter.notifyDataSetChanged(); //Refresh list
}
}, anim.getDuration());
}
Use one of the libraries that offer the swipe to dissmis funcionality ad extract the animation part, if im not mistaken its at the action_up at the onTouch(). Then call it from your onClick of the button.
As mentioned here, Android's GridView.scrollTo() doesn't work. The method the solution mentioned, setSelectedPosition, doesn't seem to exist in GridView
smoothScrollToPosition does work, but I really don't want the animation.
For context, I have a CursorAdapter-backed GridView, and I want the view to "reset", i.e. scroll to the top, when I change the cursor.
I've been using setSelection(int position) for this, and it seems to be working just fine. To scroll to the top, just use 0 for position.
From the docs:
If in touch mode, the item will not be selected but it will still be positioned appropriately.
Edit:
Added code to post setSelection as a Runnable:
albumsView.post(new Runnable() {
#Override
public void run() {
albumsView.setSelection(0);
}
});
I have found that in order to reliably use gridView.setSelection(index), I have to first call gridView.setAdapter() (even if the adapter has already been set and has not changed). Like so:
gridView.setAdapter(gridAdapter);
gridView.setSelection(index);
I have an unusual issue with my ListView. I currently have a "deselectAll()" method which iterates through the items in my ListView and sets them to unchecked (the items implement the Checkable interface). The "checked" variable gets changed correctly (the view reports as not being checked), but the visual indicator (in this case, a background change) does not show the view as unchecked (the background stays the color of a checked item).
I am iterating and deselecting through my listview like so (I also added my declerations):
private ListView vw_entryList;
private void deselectAll() {
for (int i = 0; i < sAdapter.getCount(); i++) {
((Entry)vw_entryList.getItemAtPosition(i)).setChecked(false);
}
}
The code for my implemented setChecked() is as follows:
public void setChecked(boolean checked) {
_checked = checked;
if (checked) {
setBackgroundResource(R.drawable.listview_checked);
}
else {
setBackgroundResource(R.drawable.listview_unchecked);
}
invalidate();
}
It should be noted that when the items are clicked, they are toggled between checked and unchecked in the OnItemClickListener, and this works ok, with the background change and everything. The code for toggling is very similar:
public void toggle() {
_checked = !_checked;
setBackgroundResource(_checked ?
R.drawable.listview_checked : R.drawable.listview_unchecked);
invalidate();
}
The only difference I can see is where the methods are called from. toggle() is called from within the OnItemClickListener.onClick() method, while my deselectAll() is called from within a button's standard OnClickListener, both in the same class. Does anyone have any ideas as to why the background doesn't change when I call my deselectAll() function?
Do you have custom, non-standard color for the background? If so you might take a look at http://www.curious-creature.org/2008/12/22/why-is-my-list-black-an-android-optimization/ - it boils down to setting android:cacheColorHint attribute of your list to the background color. Maybe that will help.
Edited after further discussion:
I think you need to call getAdapter().notifyDataSetChanged() on the List rather than invalidate(). List is really build in the way that it is relying on adapter to provide the data. What you are doing in fact you have an implicit adapter - Entry is really kept in the adapter and by setting checked, you are changing the data model really, but if you do not call notifyDataSetChanged() the list does not really know that the model has changed and will not recreate the views (invalidate() will only redraw the existing ones).
After trying everything (thanks for your help Jarek), I found a solution that works for my purposes. Instead of implicitly calling the setChecked() within the view that was clicked, I leave it up to the setItemChecked() method within the ListView class.
My updated code:
private void deselectAll() {
for (int i = 0; i < sAdapter.getCount(); i++) {
vw_entryList.setItemChecked(i, false);
}
}
My best guess is that the ListView knows that its items implement the Checkable class, and thus requires itself to be the handler of all item operations. Something along those lines. If anyone can explain in more detail why this solution works while the others did not, I'll reward them with the answer and an upvote.
I have a view (custom drawn) added with getWindowManager().addView() and later I'm modifiying the LayoutParameters of it (changing x & width) and call getWindowManager().updateViewLayout(). This works but I am getting two screen refreshes, first one only moves the whole thing according to the new x and later one scales it according to the new width. Any ideas about why is this happening even though I only call updateViewLayout just one time with the new layout parameters?
FYI: onDraw method of the custom drawn view mentioned here is also called only one time by the system during this process.
Try:
runOnUiThread(new Runnable() {
public void run() {
view.updateViewLayout();
}
});
http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
If it doesn't work, check this:
How to move a view in Android?
Are you doing this?
try to do :
view.post(new Runnable() {
public void run() {
view.updateViewLayout();
}
});
updateViewLayout is an a method that can be overriden by your custom ViewGroup and in this overrided method you can implement all what your want to change.
Maybe you do something wrong in it?
Or also maybe you have to implement this code in UiThread like in other questions. - In this case when you change your parameters asynchronously with first call of drawing function by system you method maybe can change only one parameter and on second call the second parameter will be also changed.