在 GridView 中使用 ArrayAdapter 和 ViewFlipper 在位置 0 多次调用 getView,导致图像显示在任何位置
getView is called multiple times with position 0 with ArrayAdapter and ViewFlipper in GridView resulting in the image showing in any position
我正在尝试为我的 android 创建一个可滚动图像的 gridView app.Each 网格由作为标题的 textView 和 viewFlipper 组成,每个 viewflipper 都使用 imageView 自动更改图像。我正在使用 ArrayAdapter with holder pattern 来设置视图。
问题陈述:
我能够让设置工作,但有一个主要问题。问题是每个网格的 ViewFlipper 都显示其他所有其他网格的图像,但文本视图(即标题)显示正确。理想情况下,每个网格的 ViewFlipper 应该显示在其自己的集合中翻转的图像。但它也显示其他网格的取景器图像。
当我查看日志时,我可以看到 getView 大部分时间都在零位置被调用。我无法理解它的行为。根据我的理解,我已经正确地完成了所有操作,并且每个网格都应该在自己的图像集之间进行图像翻转。但它没有按预期工作。
适配器代码:-
public class GalleryImageAdapter extends ArrayAdapter<GalleryImage> {
public GalleryImageAdapter(Context context, int resource) {
super(context, resource);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if( convertView == null ) {
holder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate( R.layout.view_gallery_thumbnail, parent, false );
holder.vp = (ViewFlipper) convertView.findViewById( R.id.viewFlipper );
holder.caption=(TextView) convertView.findViewById(R.id.textView);
convertView.setTag( holder );
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.caption.setText(getItem(position).getCaption());
Log.e("GalleryAdapter", "Caption-out" + getItem(position).getCaption());
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
for (int i = 1; i <= 4; i++) {
String slideUrl = null;
holder.image1 = new ImageView(getContext());
holder.image1.setScaleType(ImageView.ScaleType.FIT_XY);
holder.image1.setAdjustViewBounds(true);
holder.image1.setLayoutParams(layoutParams);
if (getItem(position).getCaption().equals("AD")){
slideUrl = "http://www.example.com/projects/musicvideos/img/"+ getItem(position).getSlideBg(i) ;
}else {
slideUrl = "http://www.example.com/vi/" + getItem(position).getSlideBg(i) + "/xyz.jpg";
}
Log.e("GalleryAdapter", "slideUrl" + slideUrl);
Picasso.with(getContext()).load(slideUrl)
.placeholder(getContext().getResources().getDrawable(R.drawable.place))
.error(getContext().getResources().getDrawable(R.drawable.place))
.into(holder.image1);
holder.vp.addView(holder.image1);
}
holder.vp.setInAnimation(getContext(), android.R.anim.fade_in);
holder.vp.setOutAnimation(getContext(), android.R.anim.fade_out);
holder.vp.setAutoStart(true);
holder.vp.setFlipInterval(4000);
return convertView;
}
private class ViewHolder {
ImageView image1;
ViewFlipper vp;
TextView caption;
}
}
view_gallery_thumbnail.xml:-
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/textView"
android:textColor="#304f9f"
android:textColorHighlight="#304f9f"
android:textStyle="bold"
android:textSize="15sp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<ViewFlipper
android:id="@+id/viewFlipper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/textView"
/>
</RelativeLayout>
我正在动态获取数据,日志确认数据被正确获取,但适配器以某种方式未按正确顺序显示数据。我用picasso做图片展示。
过去 15 天以来,我一直陷入这个问题,但没有任何成功。我已经阅读并尝试了所有关于 Whosebug 上提到的类似问题的建议,但没有成功。
请帮忙。
我认为您的问题是在回收网格项时您永远不会从任何 ViewFlipper
中删除任何视图。这意味着 ViewFlipper
已经有来自先前 getView()
调用的子视图,现在您在回收时向其添加更多子视图。一个简单的单行修复是在 for 循环之前删除它之前的所有子项:
holder.vp.removeAllViews();
for (int i = 0; i < 4; i++) { ... }
或者,您可以在 ViewFlipper
标签内的布局 XML 中放置四个 ImageView
,然后将新图像绑定到它们,而不是实际删除、构建和添加新图像每次回收时都会查看(而且效率也会更高)。在那种情况下,您的 ViewHolder 应该包含所有四个,并且您不应该使用任何 addView()
和 removeAllViews()
调用。您还必须调用 imageView.setImageBitmap(null)
以在加载正确图像时清除当前图像,这样用户就不会看到之前绑定的错误图像。
编辑
将 ImageView 放入您的布局中:
<RelativeLayout ... >
<TextView ... />
<ViewFlipper ... >
<!-- HERE -->
<ImageView android:id="@+id/image1" ... />
<ImageView android:id="@+id/image2" ... />
<ImageView android:id="@+id/image3" ... />
<ImageView android:id="@+id/image4" ... />
</ViewFlipper>
</RelativeLayout>
更新 ViewHolder 以同时容纳 ImageView。当 convertView
为空时,您必须找到它们并分配它们。
class ViewHolder {
ViewFlipper viewFlipper;
TextView textView;
ImageView[] images;
}
然后您的绑定逻辑不需要删除或添加任何视图到 ViewFlipper,只需更新图像。
for (int i = 0; i < 4; i++) {
ImageView imageView = holder.images[i];
// This is a recycled view, so clear the previous image, otherwise there
// might be flickering in the UI
imageView.setImageBitmap(null);
// load proper image for this item
String url = ...
Picasso.with(getContext()).load(url)
...
.into(imageView);
}
我正在尝试为我的 android 创建一个可滚动图像的 gridView app.Each 网格由作为标题的 textView 和 viewFlipper 组成,每个 viewflipper 都使用 imageView 自动更改图像。我正在使用 ArrayAdapter with holder pattern 来设置视图。
问题陈述:
我能够让设置工作,但有一个主要问题。问题是每个网格的 ViewFlipper 都显示其他所有其他网格的图像,但文本视图(即标题)显示正确。理想情况下,每个网格的 ViewFlipper 应该显示在其自己的集合中翻转的图像。但它也显示其他网格的取景器图像。
当我查看日志时,我可以看到 getView 大部分时间都在零位置被调用。我无法理解它的行为。根据我的理解,我已经正确地完成了所有操作,并且每个网格都应该在自己的图像集之间进行图像翻转。但它没有按预期工作。
适配器代码:-
public class GalleryImageAdapter extends ArrayAdapter<GalleryImage> {
public GalleryImageAdapter(Context context, int resource) {
super(context, resource);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if( convertView == null ) {
holder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate( R.layout.view_gallery_thumbnail, parent, false );
holder.vp = (ViewFlipper) convertView.findViewById( R.id.viewFlipper );
holder.caption=(TextView) convertView.findViewById(R.id.textView);
convertView.setTag( holder );
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.caption.setText(getItem(position).getCaption());
Log.e("GalleryAdapter", "Caption-out" + getItem(position).getCaption());
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
for (int i = 1; i <= 4; i++) {
String slideUrl = null;
holder.image1 = new ImageView(getContext());
holder.image1.setScaleType(ImageView.ScaleType.FIT_XY);
holder.image1.setAdjustViewBounds(true);
holder.image1.setLayoutParams(layoutParams);
if (getItem(position).getCaption().equals("AD")){
slideUrl = "http://www.example.com/projects/musicvideos/img/"+ getItem(position).getSlideBg(i) ;
}else {
slideUrl = "http://www.example.com/vi/" + getItem(position).getSlideBg(i) + "/xyz.jpg";
}
Log.e("GalleryAdapter", "slideUrl" + slideUrl);
Picasso.with(getContext()).load(slideUrl)
.placeholder(getContext().getResources().getDrawable(R.drawable.place))
.error(getContext().getResources().getDrawable(R.drawable.place))
.into(holder.image1);
holder.vp.addView(holder.image1);
}
holder.vp.setInAnimation(getContext(), android.R.anim.fade_in);
holder.vp.setOutAnimation(getContext(), android.R.anim.fade_out);
holder.vp.setAutoStart(true);
holder.vp.setFlipInterval(4000);
return convertView;
}
private class ViewHolder {
ImageView image1;
ViewFlipper vp;
TextView caption;
}
}
view_gallery_thumbnail.xml:-
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/textView"
android:textColor="#304f9f"
android:textColorHighlight="#304f9f"
android:textStyle="bold"
android:textSize="15sp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<ViewFlipper
android:id="@+id/viewFlipper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/textView"
/>
</RelativeLayout>
我正在动态获取数据,日志确认数据被正确获取,但适配器以某种方式未按正确顺序显示数据。我用picasso做图片展示。
过去 15 天以来,我一直陷入这个问题,但没有任何成功。我已经阅读并尝试了所有关于 Whosebug 上提到的类似问题的建议,但没有成功。
请帮忙。
我认为您的问题是在回收网格项时您永远不会从任何 ViewFlipper
中删除任何视图。这意味着 ViewFlipper
已经有来自先前 getView()
调用的子视图,现在您在回收时向其添加更多子视图。一个简单的单行修复是在 for 循环之前删除它之前的所有子项:
holder.vp.removeAllViews();
for (int i = 0; i < 4; i++) { ... }
或者,您可以在 ViewFlipper
标签内的布局 XML 中放置四个 ImageView
,然后将新图像绑定到它们,而不是实际删除、构建和添加新图像每次回收时都会查看(而且效率也会更高)。在那种情况下,您的 ViewHolder 应该包含所有四个,并且您不应该使用任何 addView()
和 removeAllViews()
调用。您还必须调用 imageView.setImageBitmap(null)
以在加载正确图像时清除当前图像,这样用户就不会看到之前绑定的错误图像。
编辑
将 ImageView 放入您的布局中:
<RelativeLayout ... >
<TextView ... />
<ViewFlipper ... >
<!-- HERE -->
<ImageView android:id="@+id/image1" ... />
<ImageView android:id="@+id/image2" ... />
<ImageView android:id="@+id/image3" ... />
<ImageView android:id="@+id/image4" ... />
</ViewFlipper>
</RelativeLayout>
更新 ViewHolder 以同时容纳 ImageView。当 convertView
为空时,您必须找到它们并分配它们。
class ViewHolder {
ViewFlipper viewFlipper;
TextView textView;
ImageView[] images;
}
然后您的绑定逻辑不需要删除或添加任何视图到 ViewFlipper,只需更新图像。
for (int i = 0; i < 4; i++) {
ImageView imageView = holder.images[i];
// This is a recycled view, so clear the previous image, otherwise there
// might be flickering in the UI
imageView.setImageBitmap(null);
// load proper image for this item
String url = ...
Picasso.with(getContext()).load(url)
...
.into(imageView);
}