get a subView inside a ListView's row layout - android

I need to change the drawable resource used in a ImageView inside a ListView's row.
I'm using this:
int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
return;
}
View wantedView = listView.getChildAt(wantedChild);
if I search with findViewById inside wantedView, I don't find the ImageView that I'm looking for.
How can I refer this ImageView to set another drawable resource?

fast way: use setTag(position) (or getItem or whatever you want to set as a tag) for your View in your adapter (getView method or relative) and further use listView.findViewByTag

Related

How to get the actual index of a child in a ListView?

I am currently using the getChildAt method for getting the child rows inside a ListView. The problem with this is that it only gets the child correctly if the ListView is scrolled all the way to the top.
If I were to scroll down a bit so that the first row is hidden and call the getChildAt method for position 1 it would get the view that is third in the ListView.
Is there a way to get the child view with an actual position rather than the position visible on the screen? So that in the case above the getChildAt would still return a view (2nd child) even if it isn't visible on the screen.
public View getViewByPosition(int pos, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (pos < firstListItemPosition || pos > lastListItemPosition ) {
return listView.getAdapter().getView(pos, null, listView);
} else {
final int childIndex = pos - firstListItemPosition;
return listView.getChildAt(childIndex);
}}
reference: android - listview get item view by position

get imageview from row listview (android)

how can I access a single imageview which is located inside a row of a listview?
I have a listview that contains many rows custom xml. each row contains a imageview and a TextView. Once inserted these lines in listview how can I change the bitmap of an imageview to a specific row?
Assuming you know which position you want to update and you're on the UI thread, you can use
public View getViewForPosition(int position){
int relativePos = position - listview.getFirstVisiblePosition();
if( relativePos < 0 || relativePos > listview.getChildCount()){
return null;
}
return listview.getChildAt(relativePos);
}
A return of null from this function means that position is offscreen. A non null will return the view from getView, and you can then do a findViewById on it to find the child you want.
If calling from a non-UI thread, you can be off by 1 due to calculating as the view mapping is changing. There is a hack to fix this I came up with once, but I'd suggest just not doing it.
Edit: here's the thread safe hack.
public View getViewForPosition(int position){
int relativePos = position - listview.getFirstVisiblePosition();
//Hack for allowing us to get a view for a position that is currently being created
if( (relativePos == listview.getChildCount() || relativePos == -1) && currentProcessingView != null){
return currentProcessingView;
}
if( relativePos < 0 || relativePos >= listview.getChildCount()){
return null;
}
return listview.getChildAt(relativePos);
}
currentProcessingView should be set in getView to the current position's view at the very beginning, and to null at the end of getView. If the position is not currently on screen it will return null, you need to be able to handle that.
You could uniquely tag each of the listview items and then use findViewWithTag on it.

how to get data from different items in a listview in android

I am working on list view in android where i have placed edit text on each item of a list view now I want to select some items of that list view and want to get data of the selected ones only ,I means items where I have filled edit text.
I am using list adapter to get data into the list view, now suggest me something if you got what I mean.
From Android: Access child views from a ListView:
int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
return;
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
View wantedView = listView.getChildAt(wantedChild);
And then:
EditText yourEditText = (EditText)wantedView.findViewById(R.id.yourEditTextId);

A ListView where a specific row can always be scrolled to the top?

I want to be able to take a ListView and have a specific row be scrollable to the top of that Listview's bounds, even if the row is near the end and normally wouldn't be able to scroll that high in a normal android ListView (similar to how twitter works when you drill into a specific tweet and that tweet is always scrollable to the top even when there's nothing underneath it.)
Is there any way I can accomplish this task easily? I've tried measuring the row i want to scroll to the top and applying bottom padding to account for the extra space it would need, but that yields odd results (i presume because changing padding and such during the measure pass of a view is ill advised). Doing so before the measure pass doesn't work since the measured height of the cell in question (and any cells after it) hasn't happened yet.
Looks like you the setSelectionFromTop method of listview.
mListView.setSelectionFromTop(listItemIndex, 0);
I figured it out; its a bit complex but it seems to work mostly:
public int usedHeightForAndAfterDesiredRow() {
int totalHeight = 0;
for (int index = 0; index < rowHeights.size(); index++) {
int height = rowHeights.get(rowHeights.keyAt(index));
totalHeight += height;
}
return totalHeight;
}
#Override
public View getView(int position, View convertView, final ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if (measuringLayout.getLayoutParams() == null) {
measuringLayout.setLayoutParams(new AbsListView.LayoutParams(parent.getWidth(), parent.getHeight()));
}
// measure the row ahead of time so that we know how much space will need to be added at the end
if (position >= mainRowPosition && position < getCount()-1 && rowHeights.indexOfKey(position) < 0) {
measuringLayout.addView(view, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
measuringLayout.measure(MeasureSpec.makeMeasureSpec(parent.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.UNSPECIFIED);
rowHeights.put(position, view.getMeasuredHeight());
measuringLayout.removeAllViews();
view.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
if (position == getCount()-1 && view.getLayoutParams().height == 0) {
// we know how much height the prior rows take, so calculate the last row with that.
int height = usedHeightForAndAfterDesiredRow();
height = Math.max(0, parent.getHeight() - height);
view.getLayoutParams().height = height;
}
return view;
}
This is in my adapter. It's a subclass of a merge adapter, but you can just put it in your code and substitute the super call with however you generate your rows.
the first if statement in getView() sets the layout params of a frame layout member var that is only intended for measuring, it has no parent view.
the second if statement calculates all the row heights for rows including and after the position of the row that I care about scrolling to the top. rowHeights is a SparseIntArray.
the last if statement assumes that there is one extra view with layout params already set at the bottom of the list of views whose sole intention is to be transparent and expand at will. the usedHeightForAndAfterDesiredRow call adds up all the precalculated heights which is subtracted from the parent view's height (with a min of 0 so we don't get negative heights). this ends up creating a view on the bottom that expands at will based on the heights of the other items, so a specific row can always scroll to the top of the list regardless of where it is in the list.

getChildAt return a View that is null

I try to animate a single item in my ListView, I've figured out that this is kinda hard. But, after some googling I came up with some codesnippets that I combined, but when I try to call my ListView's getChildAt in order to return the View, this returns null.
public void animateSingleItemInListView() {
final Animation animBounce = AnimationUtils.loadAnimation(context, R.anim.bounce);
int totalItemsInListView = lastCases.getCount();
int wantedPosition = 1; // Whatever position you're looking for
int firstPosition = lastCases.getFirstVisiblePosition() - lastCases.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
int childs = lastCases.getChildCount();
if (wantedChild < 0) {
Log.w("UPDATEUI", "Unable to get view for desired position, because it's not being displayed on screen.");
return;
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
View wantedView = lastCases.getChildAt(firstPosition);
wantedView.setAnimation(animBounce);
}
From the code:
The totalItemsInListView returns 10, which is correct number of rows in my ListView. The integer firstPosition is of course 0, but the getChildAt() method only returns null. How come? How can I get the first View from my ListView?
try to use
lastCases.getItemAtPosition(firstPosition)

Categories

Resources