我有以下情况。
我有一个ListView,ListView的每个项目都包含不同的小部件(TextViews,ImageViews等等),这些小部件在自定义适配器的getView()
方法中从一个布局中充气。
现在,我想实现以下目标:
当触发某个事件时,我想要更改项目内的视图的背景。
请问我该怎么做?
这是项目布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/cardlayout"
android:layout_width="320dp"
android:layout_height="130dp"
android:background="@android:color/transparent"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp" >
<FrameLayout
android:layout_width="320dp"
android:layout_height="117dp" >
<View
android:id="@+id/card"
android:layout_width="320dp"
android:layout_height="117dp"
android:background="@drawable/card_selector" />
</FrameLayout>
</LinearLayout>
我需要更改card
我试过这样做:
View v=lv.getAdapter().getView(index, null, lv);
View card =(View)v.findViewById(R.id.card);
card.setBackgroundResource(R.drawable.pressed_background_card);
但没有成功: - ((
答案 0 :(得分:7)
当你的事件被触发时,你应该只在你的适配器上调用notifyDataSetChanged,这样它就会再次调用所有可见元素的getView。
你的getView方法应该考虑到一些元素可能有不同的背景颜色(如果元素不需要改变背景,不要忘记将它设置为正常颜色,否则回收你会有很多元素和背景改变当你滚动)
编辑:
我会尝试这样的事情:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null)
{
convertView = LayoutInflater.from(getContext()).inflate(R.layout.card, parent, false);
}
//This part should also be optimised with a ViewHolder
//because findViewById is a costly operation, but that's not the point of this example
CardView cardView =(CardView)convertView .findViewById(R.id.card);
//I suppose your card should be determined by your adapter, not a new one each time
Card card = getItem(position);
//here you should check sthg like the position presence in a map or a special state of your card object
if(mapCardWithSpecialBackground.contains(position))
{
card.setBackgroundResource(specialBackground);
}
else
{
card.setBackgroundResource(normalBackground);
}
cardView.setCard(card);
return convertView;
}
在特殊事件中,我会将项目的位置添加到地图中并调用notifyDataSetChanged。
答案 1 :(得分:2)
使用onitemclicklistener,它有方法onclicksomething..that需要四个或五个参数。 (查看父级,视图视图,int位置,int id)。使用view参数自定义背景。
<强>更新强> 这是我的一些代码,如果你不明白我建议阅读有关回收和ViewHolder模式的内容。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
{
ViewHolder viewHolder;
// If convertView isn't a recycled view, create a new.
if(convertView == null){
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_gallery_frame, parent, false);
viewHolder = new ViewHolder();
// Here you must be able to find your Widget inside convertView and set a listener to it I guess?
viewHolder.nameHolder = (TextView) convertView.findViewById(R.id.nameTv);
// Set a reference to newly inflated view
convertView.setTag(viewHolder);
}
// If it is, then get the ViewHolder by tag
else{
viewHolder = (ViewHolder)convertView.getTag();
}
// Set the data
GalleryFrame galleryFrame = galleryFrameArrayList.get(position);
viewHolder.nameHolder.setText(galleryFrame.getName());
return convertView;
}
}
// Viewholder pattern which holds all widgets used
public static class ViewHolder{
public TextView nameHolder;
}
答案 2 :(得分:2)
我假设你有一个模型对象用于&#34;绘制&#34;列表项,例如背景颜色是基于boolean
或其他东西确定的。
您需要做的就是更改您决定的值TextView
应该具有哪种背景颜色。
您的getView()
方法应该包含类似
if (myModelObj.isBrown()) {
myTextView.setBackgroundResource(R.drawable.brown_bg);
else
myTextView.setBackgroundResource(R.drawable.not_brown_bg);
触发ur事件时应该执行的操作,在模型中设置brown
boolean的值
并在适配器上调用notifyDataSetChanged()
修改强>
如果由于某种原因你不想打电话给nofitfyDataSetChanged(),虽然它不会移动你的列表的滚动位置,并且正确的回收它不会导致糟糕的性能
您可以找到代表您要编辑的列表项的View对象(如果它是可见的),只需更改其中的背景,而无需刷新列表。
int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount();
int wantedChild = wantedPosition - firstPosition
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
// Wanted item isn't displayed
return;
}
View wantedView = listView.getChildAt(wantedChild);
然后使用wantedView编辑背景
可以找到此答案here
答案 3 :(得分:1)
试试这个:
View v=lv.getAdapter().getView(index, null, lv);
View card =(View)v.findViewById(R.id.card);
card.setBackgroundResource(R.drawable.pressed_background_card);
card.invalidate();
v.invalidate();
这些函数强制您的视图重绘自己,然后它们将再次渲染。 看看invalidate()
答案 4 :(得分:1)
我通常做的是:
public static class EventDetailsRenderer {
private TextView title;
private TextView description;
private Event item;
public EventDetailsRenderer(View view) {
extractFromView(view);
}
private final void extractFromView(View view) {
title = (TextView) view.findViewById(R.id.EventTitle);
description = (TextView) view.findViewById(R.id.Description);
}
public final void render() {
render(item);
}
public final void render(Event item) {
this.item= item;
title.setText(item.getTitle());
description.setText(item.getDescription());
}
}
private class EventsAdapter
extends ArrayAdapter<Event> {
public EventsAdapter(Context context) {
super(context, R.layout.list_node__event_details, 0);
}
public void addAllItems(Event... services) {
for (int i = 0; i < services.length; i++) {
add(services[i]);
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Event event = getItem(position);
EventDetailsRenderer eventRenderer;
if (convertView != null && convertView.getTag() != null) {
eventRenderer = (EventDetailsRenderer) convertView.getTag();
} else {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_node__event_details, null);
eventRenderer = new EventDetailsRenderer(convertView);
convertView.setTag(eventRenderer);
}
eventRenderer.render(event);
return convertView;
}
}
注意:这个例子可能无法编译我从我的一些代码粘贴它并删除了一些行来显示一个例子,但逻辑是相同的。
然后当你想渲染它时,只需从列表中获取子项,迭代它们,检查渲染器是否包含要翻转的卡并调用其渲染方法...然后渲染特定项目列表不影响其余项目。
让我知道这是否有效......
亚当。
答案 5 :(得分:1)
用户 EasyListViewAdapters 库https://github.com/birajpatel/EasyListViewAdapters
功能