Yes,I know there is position parametar in AdapterView.OnItemClickListener callback, but this parametar return position of filtered(shown) list.
For example I have _countriesEvisitor arraylist and I would like to get selected country object by looking into position like this:
public AdapterView.OnItemClickListener setOnCitizenshipAutocompleteItemClickListener(){
return (adapterView, view, position, id) -> {
CountryEvisitor citizenship=new CountryEvisitor();
citizenship=_countriesEvisitor.get(position);
_visit.setCitizenship(citizenship);
};
}
_countriesEvisitor has 250 items, and when I start typing for example Hrvatska I get only one item, and it has position 0 (because it is first and only one in shown list) although it is 247th in the _countriesEvisitor list from which list autocomplete adapter is made of.
How to get selected country?
Just use like below code.
public AdapterView.OnItemClickListener setOnCitizenshipAutocompleteItemClickListener(){
return (adapterView, view, position, id) -> {
CountryEvisitor citizenship= (CountryEvisitor ) view.getAdapter().getItem(position);
citizenship=_citizenship.getcitizenship();
_visit.setCitizenship(citizenship);
};}
Keep a second list with the original items, and search through the list matching your search result and get the index of that item
...
_countriesEvisitor.get(position);
int result = -1;
for(int x = 0; x < originalList.size; x++) {
if (/* some check here */) {
result = x;
break;
}
}
if (result != -1) {
// check if result is not -1 and use the index
}
Related
I am using default project for Android TV. Following is the code for creating cards in my BrowseFragment:
private void loadRows() {
List<Movie> list = MovieList.setupMovies();
ListRowPresenter mListRowPresenter = new ListRowPresenter();
mRowsAdapter = new ArrayObjectAdapter(mListRowPresenter);
mListRowPresenter.setRowViewSelected(/*HOW TO GET VIEWHOLDER HERE?*/, false);
CardPresenter cardPresenter = new CardPresenter();
int i;
for (i = 0; i < NUM_ROWS; i++) {
if (i != 0) {
Collections.shuffle(list);
}
ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
for (int j = 0; j < NUM_COLS; j++) {
listRowAdapter.add(list.get(j % 5));
}
HeaderItem header = new HeaderItem(i, MovieList.MOVIE_CATEGORY[i]);
mRowsAdapter.add(new ListRow(header, listRowAdapter));
}
setAdapter(mRowsAdapter);
}
I am doing this as I don't want to make first card of row get selected when I launch app. It should only get selected after user press down button on Dpad. If I can't do it this way, what should I do to get mentioned behavior?
You can setRowViewSelected by subclassing ListRowPresenter and overriding initializeRowViewHolder(RowPresenter.ViewHolder holder)
#Override
protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) {
super.initializeRowViewHolder(holder);
setRowViewSelected(holder, false);
}
But I don't think you can unselect all items in BrowseFragment using this approach.
Try setting your ItemViewSelectedListener after your data is loaded instead of setting in onActivityCreated to have all items unselected on initial launch.
Possible reason why top left item of row will always get selected by default and you cannot have all unselected items on initial launch:
BrowseFragment's onItemSelected method (line 1372-1382) on initial launch calls mMainFragmentRowsAdapter.getSelectedPosition()
#Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
RowPresenter.ViewHolder rowViewHolder, Row row) {
int position = mMainFragmentRowsAdapter.getSelectedPosition(); //<--
if (DEBUG) Log.v(TAG, "row selected position " + position);
onRowSelected(position);
if (mExternalOnItemViewSelectedListener != null) { //<--
mExternalOnItemViewSelectedListener.onItemSelected(itemViewHolder, item,
rowViewHolder, row);
}
}
where getSelectedPosition() always returns 0
(line 483-485)
public int getSelectedPosition() {
return 0;
}
It also calls mExternalOnItemViewSelectedListener.onItemSelected where mExternalOnItemViewSelectedListener is the ItemViewSelectedListener that you set in MainFragment of your app.
So on initial launch, 0th item in 0th row gets selected as a default selected item but if you delay setting mExternalOnItemViewSelectedListener this call will not reach your item selected listener the first time.
you can use this callback method .
void onRowViewSelected (RowPresenter.ViewHolder vh,
boolean selected)
Called when the given row view changes selection state. A subclass may override this to respond to selected state changes of a Row. A subclass may make visual changes to Row view but must not create animation on the Row view.
mListRowPresenter.setRowViewSelected(vh, false);
why you are deselecting initially ? i didn't get your Question Clearly can you please explain what you want to do Exactly ??
Say i have an Array list called listitem which updates every time a GridView is clicked.
It gets the item of the GridView that was clicked and adds it to the array list, which is also used as the backing array for an adapter of a ListView.
That works fine but instead of adding the same rows to the ListView, I want to display a message like item_clicked (2) when it was clicked twice,
and if its clicked again display item_clicked (3) and so on.
I tried to approach this with this code:
public void addItems(int position) {
if (listItems.contains(value.get(position))) {
int index = listItems.indexOf(value.get(position));
listItems.set(index,value.get(position)); <- here
} else {
listItems.add(value.get(position));
adapter.notifyDataSetChanged();
}
}
position is the index of the GridView and values is an array of the values of the GridView.
This is my GridView code:
int index = 0;
while (rs.next()) {
value.add("ID :" + rs.getString(1) + " Nombre:" + rs.getString(3));
list2.add(values.get(index));
index++;
Log.w("query result: ", rs.getString(1));
}
ArrayAdapter adapter = new ArrayAdapter(papeleta_act.this, R.layout.list_item, list2);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
addItems(position);
}
});
} catch (Exception e) {
Log.w("My error;", e);
}
}
I would appreciate any idea of how to approach this prob.
Thanks in advance!
For the sake of simplicity, let's assume all items in the GridView are of a single type, and let's call it A. In this case, the ArrayList holds items of type A.
A simple solution would be to have listitem contain objects of a type that wrap A and also have a counter, for the times clicked. Possible implementation is:
public class B {
public A mA;
public int times_clicked;
}
How to show the times clicked in the ListView depends on your implementation of the layout. The default behavior of an ArrayAdapter is to check if the root element of the layout it was given is a TextView, and then set its text to the result of the toString() function of the item it is showing, so you could add this method to class B:
public String toString(){
if(times_clicked == 1 && A != null)
return A.toString();
else
return "item_clicked ("+times_clicked+")";
}
I'm using a ListView with sections. I have a list of ArrayAdapters, one for each section.
I need to determine the right adapter on onItemClick to launch a method in the adapter.
How do I do get a reference to the the right adapter?
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id)
{
adapterList.get(x).toggleBought(position);
//need to determine x (the x'th adapter in the list
//or somehow get a reference to the adapter instead of adapterList.get(x)
}
and here's the code where the adapterlist is created:
adapterList = new ArrayList<CartRowAdapter>(); //list of ArrayAdapters
oListAdapter = new CartListAdapter(getActivity()); //BaseAdapter
for (int i = 0; i < cartLists.size(); i++)
{
adapterList.add(new CartRowAdapter(getActivity(), R.layout.cart_row,
cartLists.get(i)));
oListAdapter.addSection(cartLists.get(i).get(0).getAisle(),
adapterList.get(i));
}
listView.setAdapter(oListAdapter);
The parent AdapterView is passed in as a parameter to onItemClick() and it has getAdapter().
I ended up fixing this by writing an ugly hack.
I had another by having the item position off since each section header also counted.
Also for the adapters the first item on each adapter is position 0, so I'm calculating that as well.
Although it's an ugly hack, at least it works perfectly for what I'm doing. i is the number I was looking for.
int i = 0;
int sizes = 0;
while (true)
{
sizes += cartLists.get(i).size();
position -= 1;
if (position < sizes)
{
position -= sizes;
position += cartLists.get(i).size();
break;
}
else
{
i++;
}
}
I have a list view with a custom ArrayAdapter.
I have created a custom chackable linear layout and so far every thing works great with this code:
public ArrayList<FBFriend> getSelectedFriends()
{
ArrayList<FBFriend> checkedFriends = new ArrayList<FBFriend>();
SparseBooleanArray checkedItems = m_FriendsListView.getCheckedItemPositions();
int size = checkedItems != null ? checkedItems.size() : 0;
for (int i = 0; i < size; i++)
{
if (checkedItems.valueAt(i) == true)
{
FBFriend selectedFriend = m_FriendsList.get(checkedItems.keyAt(i));
checkedFriends.add(selectedFriend);
Log.i(TAG, "Selected Friend:" + checkedItems.keyAt(i) + " - " + selectedFriend.toString());
}
}
return checkedFriends;
}
when i filter my list of friends using this:
public void onInputFriendSearchTextChanged(CharSequence cs, int arg1, int arg2, int arg3)
{
m_FBFriendsListAdapter.getFilter().filter(cs);
m_FBFriendsListAdapter.notifyDataSetChanged();
}
the method above (getSelectedFriends) returns the wrong friends becuse it considers the selected positions and not the selected IDs.
I have defined in my adapter the following in hope that it will cause the getCheckedItemPositions method to use the IDs:
#Override
public long getItemId(int position)
{
FBFriend friend = getItem(position);
return Long.parseLong(friend.getID());
}
#Override
public boolean hasStableIds()
{
return true;
}
but it did not help ...
any way to get the correct selected items when the list adapter is filtered ?
Found the BUG !!!
the reason was in method extracting the selected item.
I have used this:
FBFriend selectedFriend = m_FriendsList.get(checkedItems.keyAt(i));
but actually i cannot call get on the list becuse it will not keep track on filtered items.
what sholud be done is:
FBFriend selectedFriend = m_FriendsListAdapter.getItem(checkedItems.keyAt(i));
so the ArrayAdapter actually keep track on the new position of each item according to the filter and will return the correct item.
I'm trying to implement my own StickyGridHeadersBaseAdapter, my current source code here - http://paste.org.ru/?11jrjh, and I use it like
ModeAdapter adapter = new ModeAdapter(this);
modeGridView.setAdapter(adapter);
Problems which I have is that
1) I have no idea how to call notifyDataSetChanged() for this adapter, so I can't change items
2) And implementation of AdapterView.OnItemClickListener (http://paste.org.ru/?mvgt7b) works strange
Mode mode = (Mode) adapter.getItem(position);
returns null for items with 1st and 2nd positions, item on 3rd position is actual 1st item in adapter.
Where is my fault here?
One more question is why I can't cast adapterView.getAdapter() in my OnItemClickListener to my ModeAdapter class. What if I want to call notifyDataSetChanged() here?
I didn't find any examples for custom implementation of StickyGridHeadersBaseAdapter here.
Thanks in advance.
I had the same issue as you 2):
after the first header i got the item of the previous row, after the second header got the item of two rows up, etc...
The reason is the following:
StickyHeadersGridView:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mOnItemClickListener.onItemClick(parent, view, mAdapter.translatePosition(position).mPosition, id);
}
The position is corrected. so in your onItemClick you get the corrected value of position.
If than you request the item with: Mode mode = (Mode) adapter.getItem(position);
you get StickyGridHeadersBaseAdapterWrapper.getItem(int pos)
#Override
public Object getItem(int position) throws ArrayIndexOutOfBoundsException {
Position adapterPosition = translatePosition(position);
if (adapterPosition.mPosition == POSITION_FILLER || adapterPosition.mPosition == POSITION_HEADER) {
// Fake entry in view.
return null;
}
return mDelegate.getItem(adapterPosition.mPosition);
}
In StickyGridHeadersBaseAdapterWrapper.getItem() position gets corrected for the second time which causes the wrong item to be returned...
I added a work-around:
In StickyHeadersBaseAdapterWrapper I added:
public Object getItemAtDelegatePosition(int pos) {
return mDelegate.getItem(pos);
}
And I use this in onItemClick:
Mode item = (Mode) ((StickyGridHeadersBaseAdapterWrapper)parent.getAdapter()).getItemAtDelegatePosition(position);
An easier way to get an item would be:
StickyGridHeadersBaseAdapterWrapper wrapper = (StickyGridHeadersBaseAdapterWrapper) parent.getAdapter();
Mode item = (Mode ) wrapper.getWrappedAdapter().getItem(position);