How would one find the position of a specific item within a ListView? (Populated by SimpleCursorAdapter).
The reason I ask: The listview is set to singleChoice mode. When the user closes and reopens the app, I'd like the user's selection to be remembered.
The way I've done it so far is when the user clicks on an item, the ID of the chosen item is saved to preferences. What I need to learn is how to reselect the item in the activity's onCreate method once it's been repopulated.
My code for saving the selected item's ID:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Cursor c = (Cursor) l.getItemAtPosition(position);
selectedItem = c.getLong(c.getColumnIndex("_id"));
}
(I've tried googling, but only seem to find how to get the position of the selected item)
Thanks!
You should try
//SimpleCursorAdapter adapter;
final int position = adapter.getCursor().getPosition();
API Docs:
public abstract int getPosition ()
Since: API Level 1
Returns the current position of the
cursor in the row set. The value is
zero-based. When the row set is first
returned the cursor will be at positon
-1, which is before the first row. After the last row is returned another
call to next() will leave the cursor
past the last entry, at a position of
count().
Returns
the current cursor position.
Update
To get an item's position based on the id used by the adapter:
private int getItemPositionByAdapterId(final long id)
{
for (int i = 0; i < adapter.getCount(); i++)
{
if (adapter.getItemId(i) == id)
return i;
}
return -1;
}
To get an item's position based on the underlying object's properties (member values)
//here i use `id`, which i assume is a member of a `MyObject` class,
//and this class is used to represent the data of the items inside your list:
private int getItemPositionByObjectId(final long id)
{
for (int i = 0; i < adapter.getCount(); i++)
{
if (((MyObject)adapter.getItem(i)).getId() == id)
return i;
}
return -1;
}
I do this straightforward in my own app:
long lastItem = prefs.getLong(getPreferenceName(), -1);
if (lastItem >= 0) {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
if (lastItem == cursor.getLong(0)) {
spinner.setSelection(cursor.getPosition());
break;
}
cursor.moveToNext();
}
}
Spinner is populated with the cursor's contents, so I just look through them and compare with the selected item id. In your case that would be a ListView.
When you say, "...reselecting the item in the activity's onCreate method...", do you mean that when the user returns to the ListView activity, whatever item was previously chosen, is now currently at the top of the screen (assuming enough items appear in the list below it)?
If so, then from onListItemClick, you should also make an effort to save the value of position, since it tells you the position in the list of the selected item. This would allow you to not need to reverse-lookup the position from the _id.
Or is that for some reason not an option for your purposes? Do you really need to instead figure out the position from the _id?
Related
I want to know if a certain position in a list view is currently shown. Let us say I have a list of 20 Items, how do i check if postion 9 i among the shown items as there may be multiple items on the screen.
In my App, i automatically scroll a List view for the user so i need to know if this postion is already somewhere on the screen
You can use the below code snippet for checking a specific list position is currently visible in list view.
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//Specify the list index that you want to check visibility
int listItemIndex = 9;
View listItem = getListView().getChildAt(listItemIndex);
if (listItem != null && listItem .getVisibility() == View.VISIBLE) {
//The list item is visible
}
}
Get all list items visible on the scroll
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//Loop to get tids of all completely visible List View's item scrolled on screen
for (int listItemIndex = 0; listItemIndex<=getListView().getLastVisiblePosition()- getListView().getFirstVisiblePosition(); listItemIndex++) {
//Specify the list index that you want to check visibility
View listItem = getListView().getChildAt(listItemIndex);
if (listItem != null && listItem .getVisibility() == View.VISIBLE) {
//The list item is visible
}
}
}
I want to create searching for items from recycler view.
I have MainActivity where I have the main recycler view and I have SearchActivity where I have the seconds recycler view for appearing of searching items. When user inputs a letter in the input I ask my SQLite for the same query as my input text. If my SQLite gives me data I insert these data in the second recycler view and appear their to user.
Here is it my code:
// onCreate() method
initRecyclerView(); // init empty recycler view
EditText et_input = getActivity().findViewById(R.id.et_search_for_task_input);
et_input.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged (CharSequence s, int start, int count, int after) {
// nothing...
}
#Override
public void onTextChanged (CharSequence s, int start, int before, int count) {
if (count == 0) { // if empty I show to user nothing
adapter.clearAll();
adapter.notifyDataSetChanged();
} else {
Cursor cursor = database.rawQuery("SELECT * FROM todo WHERE task LIKE '%" + String.valueOf(s) + "%'", null); // ask for data from database
if (cursor.moveToFirst()) { // if the response wasn't empty
do {
// add filter data in adapter and save adapter(notifyDataSetChanged();)
adapter.addTask(cursor.getString(cursor.getColumnIndex("task")));
adapter.notifyDataSetChanged();
} while (cursor.moveToNext());
}
cursor.close();
}
}
#Override
public void afterTextChanged (Editable s) {
// adapter.clearAll();
}
});
All works good. But I have the issue. When user inputs a letter he gets a list of searching items and if he want to add or remove the text in input he gets a list of new searching items with OLD SEARCHING ITEMS. So, I need to delete old searching items from adapter. How can I do it????
I've been trying to do the next: called in afterTextChanged the method adapter.clearAll();. I hoped that when user finishs to input his data, these data adds in adapter and adapter clears without update recycler view(notifyDataSet...();) and when he will search another he gets new list of searching items without old searching items. But I have nothing!!! Help me pls!
I hope I was able to tell you my problem and you can understand me :)
It's not very clear what exactly is your problem, but from what I think it is:
Every time user types a character a new character another onTextChanged event is fired and as you don't clear adapter in-between obviously your addTask entries accumulate.
afterTextChanged gets called after onTextChanged, so if you clear your adapter right after you populate it it ends up empty. I'm not sure if notifyDataSetChanged redraws RecyclerView immediately or queues it, but it's quite likely another notifyDataSetChanged might sneak in during adapter.clearAll or somewhere else leaving you with empty View. You should clear adapter immediately before repopulating it, not right after.
You don't need to call notifyDataSetChanged after every addTask. Add all the task for current iteration, then call notify... once.
If you read up on ontextChanged you'll see, that count in parameters only show how many characters changed (or rather how many characters are in currently typed word or smth), it's not the best choice to use it to detect if the CharSequence s is empty. Rather check the length of CharSequence s.
So what you need to do is:
#Override
public void onTextChanged (CharSequence s, int start, int before, int count) {
if (s.length() == 0) { // if empty I show to user nothing
adapter.clearAll();
adapter.notifyDataSetChanged();
} else {
Cursor cursor = database.rawQuery("SELECT * FROM todo WHERE task LIKE '%" + String.valueOf(s) + "%'", null); // ask for data from database
adapter.clearAll();
if (cursor.moveToFirst()) { // if the response wasn't empty
do {
// add filter data in adapter and save adapter(notifyDataSetChanged();)
adapter.addTask(cursor.getString(cursor.getColumnIndex("task")));
} while (cursor.moveToNext());
}
cursor.close();
adapter.notifyDataSetChanged();
}
}
That should do it provided your adapter is working as I expect it to. You never showed your RecyclerView adapter, so I don't know what addTask and clearAll do.
So I have a button, and this button switches the cell of a listview with the cell above, and vise versa for ANOTHER button which is for down (this one is for up... It doesn't matter which, I just decided to talk about this one). The whole button and list view thing is working, but my problem is when I press the up button, and then decide to press it again, it just acts as a down button. The reason for this is because it's still stuck on the same item/position of the list view, and I need to figure out a way to Override the position of the onItemClick in the code??
```
upButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//upButton onClick
Integer myTeam = position; //7 -159
Integer otherTeam = position - 1; //6 - 1678
Map<Integer, String> onClickMap = sortByValue(Constants.picklistMap);
String extraValue;
Log.e("myposition", myTeam.toString());
Log.e("otherposition", otherTeam.toString());
extraValue = onClickMap.get(myTeam); //159
String team = onClickMap.get(otherTeam);
Constants.picklistMap.put(myTeam, onClickMap.get(otherTeam));
Constants.picklistMap.put(otherTeam, extraValue); //6
Log.e("Position: ",Constants.picklistMap.get(position));
Log.e("Position - 1: ",Constants.picklistMap.get(position - 1));
if(myTeam != 0) {
dref.child("picklist").child(myTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(myTeam)));
dref.child("picklist").child(otherTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(otherTeam)));
} else {
Toast.makeText(getActivity(), "Nice try.
If you try it again, the app is going to crash as punishment ... (:",
Toast.LENGTH_LONG).show();
}
}
});
```
By overriding the position, I just mean how
position =+ 1
would make position = position + 1 in python, and I want to do the same thing in Java. The problem is I know that can't be done using the snippet of code I just used to increment the value of position!
Please help!
The reason I can't use position = position + 1 is because on the onItemClick, int position is defined, and then the onClick is created for the buttons, so I need position to be final for me to use it in the onClick, and if I got rid of final, i wouldn't be able to use it in the onClick as it can't be accessed from within an inner class when it's not final
Define which position you want to change, and use this method to update position. You can use this method in onClickListener. This should work.
private int position = 0;
private void up(ArrayList<Integer> arr){
if (position < 1 || position >= arr.size()) return;
int temp = arr.get(position - 1);
arr.set(position - 1, arr.get(position));
arr.set(position, temp);
position --;
}
I am trying to get the selected item from grid view in Android development. Here is the list of drawable I used to populate the grid view:
private static Integer[] iconlist = {
R.drawable.food_icon, R.drawable.transport_icon, R.drawable.entertainment_icon,
R.drawable.bill_icon, R.drawable.others_icon, R.drawable.salary_icon,
R.drawable.investment_icon, R.drawable.bonus_icon, R.drawable.medication_icon,
R.drawable.drinks_icon, R.drawable.car_icon, R.drawable.mask_icon,
R.drawable.shopping_icon, R.drawable.lottery_icon, R.drawable.pet_icon,
R.drawable.movie_icon, R.drawable.plant_icon, R.drawable.paint_icon,
};
And gridview on click listener:
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View v, int position, long id) {
Toast.makeText(getActivity(), "Grid Item " + (position + 1) + " Selected", Toast.LENGTH_LONG).show();
int selected = position + 1;
for(int i = 0; i < iconlist.length; i++){
if(iconlist[i] == selected){
}
}
}
});
I managed to get the correct integer position based on the clicks. What I am trying to do is based on the selected drawable, I am trying to extract out the string.
For example, when transport icon is clicked, I am trying to get the "transport_icon" string from "R.drawable.transport_icon" and store it as string. However, I not sure how to do it.
Any ideas?
first define a drawable from integer array (the ids)
Drawable drawable = context.getResources().getDrawable(iconlist[n]);
and you can get name of resources like this
String name = context.getResources().getResourceEntryName(ID);
this method should return what you need.
You can try in below way:
Context.getResources().getResourceEntryName(R.drawable.transport_icon)
or
Context.getResources().getResourceName(R.drawable.transport_icon)
Reference: https://developer.android.com/reference/android/content/res/Resources.html#getResourceEntryName(int)
Apparently the notifyDataSetChanged() only updates the visible items in the listview, I have a system that changes the background color of an item when its clicked (to dkgray), and I set everything else to transparent(the default), however other items that aren't visible remain selected(dkgray) (I only want the currently selected item to be dkgray). Is there a way to force notifyDataSetChanged() to update all items.
Here's example:
//makes all item backgrounds transparent
public void resetListViewBackground(){
for (int i = 0; i < listView.getChildCount(); i++){ //parent.getChildCount()
listView.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
}
}
//reloads the listview
private void reloadListView() {
listItems.clear();
adapter.notifyDataSetChanged();
listView.invalidateViews();
ArrayList<HashMap<String, String>> notesArrayList = dbTools.getAllNotes();
for (int i = 0; i < notesArrayList.size(); i++){
String temp = "";
if (notesArrayList.get(i).get("note").length() > 51){
temp = notesArrayList.get(i).get("note").substring(0,50).toString() + "...";
} else {
temp = notesArrayList.get(i).get("note").toString();
}
listItems.add(temp);
adapter.notifyDataSetChanged();
}
}
Everywhere I call resetListViewBackground(), I call reloadListView() after.
And this is what I use to highlight the selected item.
view.setBackgroundColor(Color.DKGRAY);
Also, the most common occurrence of this problem is that every 6th item is highlighted. The listview only shows about 4 items at a time.
The getChildCount() method won't work for all list items as view recycling is done.
Astral is right as he writes in the comments.
1) Create a custom adapter.(See http://windrealm.org/tutorials/android/listview-with-checkboxes-without-listactivity.php)
2)Inside the onListItemClick listener's onItemClick() method, call your adapter's notifyDataSetChanged() method(whenever the user clicks a list item).
I modified the project that I mentioned and posted it on my Dropbox.(Just import it in Eclipse and run).
Check it out at https://www.dropbox.com/s/gchccjzpkxk8n2z/Planets_modified.zip