在 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);
}