I have a ListView that gets its layout for each item from "rowlayout".
I want to do something to one of the buttons in the rowlayout in my main activity, how do i get a reference to it findviewbyid doesn't work.
I guess i'm essentially not understanding a general concept of how to get a reference to a view in a custom layout- unless getting a view from a ListView is different. Can anyone help? thanks.
ListView is a ViewGroup so you can just iterate over its children:
int n = getChildCount();
for (int i = 0; i < n; i++) {
doSomethingToView(getChildAt(i));
}
However, you must be careful. ListView is pretty special and only has a subset of children that you might expect. It only holds (roughly) references to children that are currently visible and reuses them as they disappear.
What you might consider is changing underlying adapter instead and than notifying the ListView that its adapter changed, so it needs to redraw children. Or alternatively, you can make the child of ListView directly listen for events that are supposed to change it and then adjust itself.
If you are inflating a custom layout in the getView method of your adapter, you can get a view like this
LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.your_custom_layout, parent, false);
TextView tv = (TextView) rowView.findViewById(R.id.your_tv_id);
You can use partial refresh principle if you implement ListView in the way of ViewHolder, just like this:
private void refreshPartially(int position){
int firstVisiblePosition = listview.getFirstVisiblePosition();
int lastVisiblePosition = listview.getLastVisiblePosition();
if(position>=firstVisiblePosition && position<=lastVisiblePosition){
View view = listview.getChildAt(position - firstVisiblePosition);
if(view.getTag() instanceof ViewHolder){
ViewHolder vh = (ViewHolder)view.getTag();
//holder.play.setBackgroundResource(resId);//Do something here.
...
}
}
}
Possibly you can use the answer from this android - listview get item view by position to get the child view at a position then call findViewById() on that child view.
Related
Is it possible to change layout of selected item in ListView?
I made simple app with ListView using Custom Adapter. It's working great, but I would like to change the layout of selected item to different layout.
In practice, the clicked item would expand it's height and some new buttons would appear. Once user deselects the items, it would go back to classic layout.
This is my Custom Adapter code
public class ListAdapter extends ArrayAdapter<Polozka> {
// context mem variable
private Context mContext;
// Konstruktory
public ListAdapter(Context context,int textViewResourceId){
super(context,textViewResourceId);
}
public ListAdapter(Context context, int resource, List<Polozka> items){
super(context,resource,items);
this.mContext=context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
if (v == null){
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.polozkanakupniseznam,null);
}
final Polozka p = getItem(position);
if (p != null){
final TextView tt1 = (TextView) v.findViewById(R.id.seznam_nazevPolozky);
TextView tt2 = (TextView) v.findViewById(R.id.seznam_pocetPolozky);
CheckBox cb1 = (CheckBox) v.findViewById(R.id.checkBox_koupeno);
Button btnPridat = (Button) v.findViewById(R.id.buttonPridat);
Button btnOdebrat = (Button) v.findViewById(R.id.buttonOdebrat);
if (tt1 != null){
tt1.setText(p.getNazev());
}
if (tt2 != null){
tt2.setText(Integer.toString(p.getPocet()));
}
return v;
}}
This is how I set adapter to my listview
lv = (ListView) findViewById(R.id.lv);
adapter = new ListAdapter(this,R.layout.polozkaseznam,list);
lv.setAdapter(adapter);
I figured out how to change layout of every item by creating new custom adapter and asigning it to the ListView, but that's sadly not what I need.
Thank you very much!
The getView() method of the adapter is used to create the original view. In there you can use the view's setOnTouchListener() method to add a View.OnTouchListener implementation. The onTouch() handler of that class receives the selected view.
A useful member to add to the OnTouchListener implementation is a GestureDetector; this is created with an OnGestureListener implementation to which you can pass the MotionEvent received in the OnTouchListener's onTouch() callback. This listener is then used to distinguish various events (single tap, double tap, etc); GestureDetector.SimpleOnGestureListener is good implementation to use with a number of callbacks handling such events you can override.
At some point (e.g., in the SimpleGestureListener's onDown() callback, which fires when an item is first touched), you can modify the layout of the view handed to the OnTouchListener. To change it back, you could either use a handler for the "on up" phase of a gesture, or, if you wish the item to remain as is until something else is selected, hold a reference to the last selected view and change it when another one is selected.
In case this last point is not clear, the idea is that the SimpleGestureListener is a member object of the view's OnTouchListener instance, therefore it can access the view belonging to the enclosing OnTouchListener.
I have custom listview and array adapter with ViewHolder. When click listview item, it expands new layout below. Problem is: unfortunately it is opened for every +9th item in listview.. For example: if item 0 is clicked; 0,9,18th elements opens their expand layouts. Any idea without looking code ?
I have no idea, but this sounds familair with an issue I had. I had a listview with TextView objects and multiple were selected and got typed in the same value.
I had a very, very dirty fix for that, in my custom adapter I'd always make a new View, no matter what:
#Override
public View getView (final int position, View convertView, final ViewGroup parent) {
//if (convertView == null) {
// Inflate the view from the converter
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
convertView = layoutInflater.inflate(converter.getLayout(), parent, false);
//}
// Populate the view from the converter
converter.populateInflatedView(convertView, getItem(position));
return convertView;
}
Source can be found here if you want to know what the converter is about.
On a side note, I have created a sort of interface type of thing for a TreeView, however this is in Activity form which uses a ScrollView. So this is not really a ListView type of deal, but might help you. The Tree part can be found on the Tree-link, with an implementation in the subject package.
As far as I understood the getView's purpose is to "give" the ListView (or other interface), the specific view, each time the adapter is "asked to".
I got the object by the position :
myItem = (myItem) getItem(position);
then I checked if the convertView is not null, and initialized a default layout:
itemLayout = (RelativeLayout) convertView;
if (itemLayout == null) {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
itemLayout= (RelativeLayout) inflater.inflate (R.layout.my_item,null);
}
And now I want to make the connection between my item/object and its layout- or in other words: fill this layout's views with the values of this item.
How can I make it? Or did I understand the whole concept completely wrong?
Please check the ViewHolder pattern for Android ListView or use RecyclerView instead.
I got a ListView with a custom Adapter.
In the Adapter a layout is inflated from xml.
All works fine, and I can see the items, until the Screen Orientation is changed.
I know that the Activity is recreated (or resumed) then, and the ListView is recreated too, as well as the Adapter.
But there are no items in the ListView now. The Adapter isn't empty, I use toasts to display the count of items in the Adapter.
I guess there is an inflating problem, because if I use the same Adapter (or an adapter with the same data) to a new ListView nothing is shown as well.
But the most crazy thing I don't understand is, that if I let my getView() method return a simple TextView, all works fine, even after orientation change.
I tried several things, like don't recycle a View so that it is inflated every time, or save the View to the matching Item (from getItem(position) from the Adapter).
I'm grateful for all hints :)
EDIT: so I was asked for some code.
Here is the getView() of my Adaptar
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
final Event event = getItem(position);
if (view == null) {
view = inflater.inflate(R.layout.new_event_item_layout, parent,
false);
view.setTag(R.id.eventDate, view.findViewById(R.id.eventDate));
view.setTag(R.id.eventTime, view.findViewById(R.id.eventTime));
view.setTag(R.id.eventName, view.findViewById(R.id.eventName));
view.setTag(R.id.eventBemerkungen,
view.findViewById(R.id.eventBemerkungen));
view.setTag(R.id.eventIcon, view.findViewById(R.id.eventIcon));
}
((TextView) view.getTag(R.id.eventDate)).setText(event.getDate());
((TextView) view.getTag(R.id.eventTime)).setText(event.getName());
((TextView) view.getTag(R.id.eventName)).setText(event.getTime());
((TextView) view.getTag(R.id.eventBemerkungen)).setText(event
.getDescription());
SquaredImageView icon = (SquaredImageView) view.getTag(R.id.eventIcon);
Picasso.with(context).load(event.getUri())
.placeholder(R.drawable.ic_reload).into(icon);
view.setBackgroundColor(event.getBackgroundColor());
view.setVisibility(View.VISIBLE);
return view;
//return getDummyTextView();
}
public TextView getDummyTextView()
{
TextView tv=new TextView(context);
tv.setText("YOLO BIATCHSES");
tv.setTextColor(Color.WHITE);
return tv;
}
I have had the same exact problem although it wasn't because of orientation change and I found the solution by just setting listView.setAdapter(adapter) again after the recreation of the activity or whatever case you have. I suspect the listview is basically losing the pointer to the adapter.
I have to inflate the group of items in a listview and i need to find inflated view anywhere in the program .
May I know how to find the view.
How to set id and get id of inflated listview.
Thanks in Advance
In the Adapter of your list view
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.newlistrow, null);
//Access your inflated layout using vi
TextView sometextview= (TextView) vi.findViewById(R.id.textview); // sometextview
Typically you don't find views in a list view. The adapter behind the list view will pass you the view plus the underlying position of your data that you need to render via the getView method.
To answer your question of how to get or set id of inflated view you should call getId or setId on the inflated view.
http://developer.android.com/reference/android/view/View.html#setId(int)
http://developer.android.com/reference/android/view/View.html#getId()
View myView = LayoutInflater.from(activity).inflate(R.layout.list_item_punch_log, null);
myView.setId(android.R.id.button1);
int id = myView.getId();
However doing this and finding views in a list view is a very dangerous act as it will cause some really funny behaviors on the listview. Maybe you can tell us what you are trying to do and we can guide you from there.