我在C#编码我的应用程序(使用monodroid),但我认为这个问题可以适用于常规的android java。
我有一个gridview,如果用户触摸了一个瓷砖或项目,我想要一个复选标记出现,如果他们触摸一个选中的瓷砖,我希望复选标记消失。我遇到的问题是如果用户触摸一个磁贴然后向下滚动复选标记将出现在随机磁贴上。我知道这与android回收视图的事实有关,但我无法弄清楚如何修复它。
这是我的gridview getview()
方法
public override View GetView(int position, View convertView, ViewGroup parent)
{
File f = files[position];
ViewHolder holder;
if (convertView == null)
{
LayoutInflater li = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
convertView = li.Inflate(Resource.Layout.gallery_item, parent, false) as LinearLayout;
holder = new ViewHolder();
holder.iv = convertView.FindViewById(Resource.Id.ivGalleryItem) as ImageView;
holder.iv.SetScaleType(ImageView.ScaleType.CenterCrop);
holder.ivCheck = convertView.FindViewById<ImageView>(Resource.Id.ivCheck);
convertView.SetTag(Resource.Layout.gallery_item, holder);
// * 我在这里说的是,如果用户触摸图块显示复选标记并将此图块设置为true以进行检查 < / p>
holder.iv.Click += delegate
{
if (isChecked[position])
{
holder.ivCheck.Visibility = ViewStates.Invisible;
isChecked[position] = false;
}
else
{
holder.ivCheck.Visibility = ViewStates.Visible;
isChecked[position] = true;
}
};
}
else
{
holder = (ViewHolder)convertView.GetTag(Resource.Layout.gallery_item);
}
// **************************here is wherere I say if the tile is true than show the checkmark if it is false dont show it
if (isChecked[position])
{
holder.ivCheck.Visibility = ViewStates.Visible;
}
else
{
holder.ivCheck.Visibility = ViewStates.Invisible;
}
if (f.Exists() && f.IsFile)
{
getPhotoTask.getphoto(holder.iv, f);
}
else
{
holder.iv.SetImageResource(Resource.Drawable.boostitred);
}
return convertView;
}
答案 0 :(得分:1)
看起来问题是你只是为屏幕上可见的第一个项目设置点击监听器;当您滚动显示其他项目时convertView != null
。
这意味着单击某些网格项(那些从屏幕上开始,后来出现在屏幕上的网格项)将错误地修改isChecked
数组。
例如,假设您首先在屏幕右侧显示12个网格项。当GridView
第一次调用getView
convertView == null
时,您的代码会创建一个新的View
(在这种情况下为LinearLayout
),一个新{ {1}},并为位置为0 - 11的视图分配一个点击监听器。当您滚动时,ViewHolder
开始回收现在不在屏幕上的视图,以便创建屏幕上显示的新视图。在这些情况下,GridView
,因此您的代码未设置点击侦听器。
我认为简单的解决方案如下:
convertView != null
正如您所看到的,我只是将public override View GetView(int position, View convertView, ViewGroup parent)
{
File f = files[position];
ViewHolder holder;
if (convertView == null)
{
LayoutInflater li = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
convertView = li.Inflate(Resource.Layout.gallery_item, parent, false) as LinearLayout;
holder = new ViewHolder();
holder.iv = convertView.FindViewById(Resource.Id.ivGalleryItem) as ImageView;
holder.iv.SetScaleType(ImageView.ScaleType.CenterCrop);
// *Here is where i say if the user touches a tile show a checkmark and set this tile to true for checked
holder.ivCheck = convertView.FindViewById<ImageView>(Resource.Id.ivCheck);
convertView.SetTag(Resource.Layout.gallery_item, holder);
}
else
{
holder = (ViewHolder)convertView.GetTag(Resource.Layout.gallery_item);
}
holder.iv.Click += delegate
{
if (isChecked[position])
{
holder.ivCheck.Visibility = ViewStates.Invisible;
isChecked[position] = false;
}
else
{
holder.ivCheck.Visibility = ViewStates.Visible;
isChecked[position] = true;
}
};
// **************************here is wherere I say if the tile is true than show the checkmark if it is false dont show it
if (isChecked[position])
{
holder.ivCheck.Visibility = ViewStates.Visible;
}
else
{
holder.ivCheck.Visibility = ViewStates.Invisible;
}
if (f.Exists() && f.IsFile)
{
getPhotoTask.getphoto(holder.iv, f);
}
else
{
holder.iv.SetImageResource(Resource.Drawable.boostitred);
}
return convertView;
}
代表的设置移到了最初的if / else之外。
然而,在Android世界中,我们通常不会在适配器中设置点击侦听器。相反,Click
和任何GridView
都有一个名为AdapterView
的方法。只要单击网格项,就会调用该方法。此时,您将能够更新setOnItemClickListener(AdapterView.OnItemClickListener listener)
数组,例如,该数组可能是isChecked
的成员,而不是适配器。