我遇到的问题是我的ListView的自定义ArrayAdapter,它有一个Gallery小部件和两个TextViews作为子级,不会更新Gallery小部件及其内容。
要设置应用程序的背景,我正在创建一个应用程序,允许两个或多个设备通过蓝牙相互连接,并将每个设备的照片流式传输到其连接的设备。现在,为了实现起见,每个设备都在一个可滚动的列表视图中表示,其中包含图库窗口小部件(所有设备的图像可以水平滚动)和下面的两个TextView窗口小部件,用于标识发件人。
ListView的布局如下:
<LinearLayout ...>
<Gallery .../>
<LinearLayout>
<TextView .../>
<TextView .../>
</LinearLayout>
</LinearLayout>
图像发送和接收不是问题,我已经反复测试过它们。
问题似乎是自定义ArrayAdapter的notifyDataSetChanged()
方法不按预期运行。当我在ListView中创建一个新的ImageHolderClass对象(在我的主Activity
中)时,我按如下方式创建:mImageHolderAdapter.add(new ImageHolderClass(this, "Me", mBtAdapter.getAddress(), mLocalImageList));
。知道适配器的add()
方法应该调用notifyDataSetChanged()
,它可以按照预期的方式为创建和添加的第一个对象工作。但是当我添加另一个对象或将任何新图像添加到对象的imageList
时,它们会创建存储在第一个对象中的图像的精确副本。
现在,有趣的是每个ImageHolderClass
中的两个TextView变量都会被更新,但是Gallery中的图像似乎保持完全相同。
我尝试绕过add()
(使用ImageHolderAdapter()
)方法中的addItem()
方法,然后仅在添加其他图片时强制notifyDataSetChanged()
,似乎显示其他图像(但不显示所有图像),但不是仅当设备和其他设备没有连接时。
我的自定义ArrayAdapter如下:
public class ImageHolderAdapter extends ArrayAdapter<ImageHolderClass>{
private ArrayList<ImageHolderClass> objects;
public ImageHolderAdapter(Context context, int layoutResourceId, ArrayList<ImageHolderClass> objects) {
super(context, layoutResourceId, objects);
this.objects = objects;
}
public static class ViewHolder {
public Gallery gallery;
public TextView deviceName;
public TextView deviceAddress;
public ArrayList imageList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Assign the view we are converting to a local variable
View v = convertView;
ViewHolder holder;
// first check to see if the view is null. If it is, then we have to inflate it.
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.imageholder, null);
holder = new ViewHolder();
holder.gallery = (Gallery)v.findViewById(R.id.gallery);
holder.gallery.setAdapter(new ImageAdapter(getContext(), objects.get(position).imageList));
holder.deviceName = (TextView)v.findViewById(R.id.deviceName);
holder.deviceAddress = (TextView)v.findViewById(R.id.deviceAddress);
v.setTag(holder);
} else {
holder = (ViewHolder)v.getTag();
}
final ImageHolderClass imageHolderClass = objects.get(position);
if (imageHolderClass != null) {
holder.gallery = imageHolderClass.getGallery();
holder.deviceName.setText(imageHolderClass.getDeviceName());
holder.deviceAddress.setText(imageHolderClass.getDeviceAddress());
}
return v;
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
ArrayList list;
public ImageAdapter(Context c, ArrayList list) {
mContext = c;
this.list = list;
TypedArray attr = mContext.obtainStyledAttributes(R.styleable.TestbedActivity);
mGalleryItemBackground = attr.getResourceId(R.styleable.TestbedActivity_android_galleryItemBackground, 0);
attr.recycle();
}
public int getCount() {
return list.size();
}
public Object getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap((Bitmap)list.get(position));
imageView.setLayoutParams(new Gallery.LayoutParams(180, 150));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setBackgroundResource(mGalleryItemBackground);
return imageView;
}
}
}
以及上面使用的ImageHolderClass如下:
public class ImageHolderClass {
public Gallery gallery;
public String deviceName;
public String deviceAddress;
public ArrayList imageList;
public ImageHolderClass() {
super();
}
public ImageHolderClass(Context c, String deviceName, String deviceAddress, ArrayList imageList) {
super();
this.gallery = new Gallery(c);
this.deviceName = deviceName;
this.deviceAddress = deviceAddress;
this.imageList = imageList;
}
public Gallery getGallery() {
return gallery;
}
public void setGallery(Gallery gallery) {
this.gallery = gallery;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getDeviceAddress() {
return deviceAddress;
}
public void setDeviceAddress(String deviceAddress) {
this.deviceAddress = deviceAddress;
}
public void setImageList(ArrayList list) {
this.imageList = list;
}
public ArrayList getImageList() {
return imageList;
}
}
结果图像(两个ListView对象具有相同的图像(但不应该))可以在下图中看到: http://i.stack.imgur.com/koL2Q.jpg
我尝试使用自定义Gallery
替换HorizontalListView
窗口小部件,但这给了我完全相同的结果,所以我知道这不是由于Gallery
窗口小部件实现。
更新
我修改了我的代码,将每个图片分别添加到ImageHolderAdapter
。之前,我会创建一个ArrayList
,将所有图像存储在其中,然后在ImageHolderAdapter
中创建一个新对象。下面的方法显示了我将如何“批量”添加图像
public void loadImages(String userName, String deviceAddress, ArrayList imageList) {
mImageHolderAdapterList.add(new ImageHolderClass(this, userName, deviceAddress, imageList));
mImageHolderAdapter.notifyDataSetChanged();
}
现在,我在填充ImageHolderClass
之前创建了imageList
对象。然后,我从ImageHolderAdapter
(使用mImageHolderAdapter.getItem(position)
)获取特定对象,从中获取imageList
,add()
获取ArrayList
。每当我做出任何修改时,我都会致电mImageHolderAdapter.notifyDataSetChanged()
。
但是,如果我单独填充图像,则现在不显示任何图像。我得到的只是一个黑屏,图像应该是。
答案 0 :(得分:1)
您应该在if语句之外设置图库的适配器。
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.imageholder, null);
holder = new ViewHolder();
holder.gallery = (Gallery)v.findViewById(R.id.gallery);
holder.deviceName = (TextView)v.findViewById(R.id.deviceName);
holder.deviceAddress = (TextView)v.findViewById(R.id.deviceAddress);
v.setTag(holder);
} else {
holder = (ViewHolder)v.getTag();
}
holder.gallery.setAdapter(new ImageAdapter(getContext(), objects.get(position).imageList));
答案 1 :(得分:0)
Updating the list view when the adapter data changes
尝试使视图或适配器无效(notifyDataSetChanged())...