带有自定义 ArrayAdapter 滚动问题的 ListFragment
ListFragment With Custom ArrayAdapter Scroll issue
嗨,我是 Android/Xamarin Dev 的新手,我有一个问题。我按照 here . I have a ListFragment with Custom ArrayAdapter . I make it Like this (ViewHolder) 中的示例进行操作,当我向下滚动时,我的项目感到困惑。我的意思是,如果我有一个包含 5 个项目的列表,并且当我向下滚动到其他项目时,一个项目的 textview 值为 10,一些项目随机获得值 10,我逐步调试并且我的 List/Array 有不包含值 10,我找不到问题的根源。
当我停止使用它时:
if (view != null)
{
holder = view.Tag as MenuItemHolder;
}
我没有问题,但我缺乏表现。
P.S对不起我的英语我是希腊人对不起我的坏话Post我是新来的:(
编辑这是我的代码:
这里的问题是当我 holder.NumberTextView.Text +1 是好的但是当我滚动 +1 随机到其他项目时
public override View GetView(int position, View convertView, ViewGroup parent)
{
MenuItemHolder holder = null;
var view = convertView;
if (view != null)
{
holder = view.Tag as MenuItemHolder;
}
if (holder == null)
{
holder = new MenuItemHolder();
view =LayoutInflater.From(Context).Inflate(Resource.Layout.rowWithButtons, null);
holder.RemoveButton = view.FindViewById<Button>(Resource.Id.DecreaseButton);
holder.AddButton = view.FindViewById<Button>(Resource.Id.IncreaseButton);
holder.NumberTextView = view.FindViewById<TextView>(Resource.Id.NumberTextView);
holder.AddButton.Click += delegate
{
holder.NumberTextView.Text = (Convert.ToInt32(holder.NumberTextView.Text) + 1).ToString();
};
holder.RemoveButton.Click += delegate
{
if ((Convert.ToInt32(holder.NumberTextView.Text) > 1))
{
holder.NumberTextView.Text = (Convert.ToInt32(holder.NumberTextView.Text) - 1).ToString();
}
};
view.Tag = holder;
}
holder.Title.Text = GetItem(position).Name;
return view;
}
public class MenuItemHolder : Java.Lang.Object
{
public TextView Title { get; set; }
public Button OptionsButton{ get; set; }
public TextView NumberTextView{ get; set; }
public Button AddButton{ get; set; }
public Button RemoveButton{ get; set; }
public Button DoneButton { get; set; }
}
问题是您将值存储在 NumberTextView 中,它是 holder 中的视图。
当 holder 为 null 时,ViewHolder 模式以您初始化视图一次的方式提高性能。这意味着 TextView(NumberTextView) 的一个实例绘制了 ListView 中的所有项目。这就是为什么当您增加值并将其存储在 NumberTextView 中时,您将值设置为所有列表项。您不会立即看到,因为列表不会重绘。当您滚动并且新列表项被绘制到屏幕时,它们具有相同的增加值。
解决方案是将每个列表项的值存储在其他地方。将字段添加到您从 GetItem 方法获得的对象。
例如:
public override View GetView(int position, View convertView, ViewGroup parent)
{
MenuItemHolder holder = null;
var view = convertView;
YourItemClass item = GetItem(position);
if (view != null)
{
holder = view.Tag as MenuItemHolder;
}
if (holder == null)
{
holder = new MenuItemHolder();
view = LayoutInflater.From(Context).Inflate(Resource.Layout.rowWithButtons, null);
holder.RemoveButton = view.FindViewById<Button>(Resource.Id.DecreaseButton);
holder.AddButton = view.FindViewById<Button>(Resource.Id.IncreaseButton);
holder.NumberTextView = view.FindViewById<TextView>(Resource.Id.NumberTextView);
holder.AddButton.Click += delegate
{
item.increaseValue();
holder.NumberTextView.Text = (item.Value).ToString();
};
holder.RemoveButton.Click += delegate
{
if (item.Value > 1))
{
item.decreaseValue();
holder.NumberTextView.Text = (item.Value).ToString();
}
};
view.Tag = holder;
}
holder.Title.Text = GetItem(position).Name;
holder.NumberTextView.Text = (item.Value).ToString();
return view;
}
public override YourItemClass GetItem(int position)
{
if(listOfItems != null)
return listOfItems.ElementAt(position);
return null;
}
class YourItemClass
{
public string Name { get; set; }
public string Value { get;set; }
public void increaseValue()
{
Value++;
}
public void decreaseValue()
{
Value--;
}
}
嗨,我是 Android/Xamarin Dev 的新手,我有一个问题。我按照 here . I have a ListFragment with Custom ArrayAdapter . I make it Like this (ViewHolder) 中的示例进行操作,当我向下滚动时,我的项目感到困惑。我的意思是,如果我有一个包含 5 个项目的列表,并且当我向下滚动到其他项目时,一个项目的 textview 值为 10,一些项目随机获得值 10,我逐步调试并且我的 List/Array 有不包含值 10,我找不到问题的根源。
当我停止使用它时:
if (view != null)
{
holder = view.Tag as MenuItemHolder;
}
我没有问题,但我缺乏表现。
P.S对不起我的英语我是希腊人对不起我的坏话Post我是新来的:(
编辑这是我的代码: 这里的问题是当我 holder.NumberTextView.Text +1 是好的但是当我滚动 +1 随机到其他项目时
public override View GetView(int position, View convertView, ViewGroup parent)
{
MenuItemHolder holder = null;
var view = convertView;
if (view != null)
{
holder = view.Tag as MenuItemHolder;
}
if (holder == null)
{
holder = new MenuItemHolder();
view =LayoutInflater.From(Context).Inflate(Resource.Layout.rowWithButtons, null);
holder.RemoveButton = view.FindViewById<Button>(Resource.Id.DecreaseButton);
holder.AddButton = view.FindViewById<Button>(Resource.Id.IncreaseButton);
holder.NumberTextView = view.FindViewById<TextView>(Resource.Id.NumberTextView);
holder.AddButton.Click += delegate
{
holder.NumberTextView.Text = (Convert.ToInt32(holder.NumberTextView.Text) + 1).ToString();
};
holder.RemoveButton.Click += delegate
{
if ((Convert.ToInt32(holder.NumberTextView.Text) > 1))
{
holder.NumberTextView.Text = (Convert.ToInt32(holder.NumberTextView.Text) - 1).ToString();
}
};
view.Tag = holder;
}
holder.Title.Text = GetItem(position).Name;
return view;
}
public class MenuItemHolder : Java.Lang.Object
{
public TextView Title { get; set; }
public Button OptionsButton{ get; set; }
public TextView NumberTextView{ get; set; }
public Button AddButton{ get; set; }
public Button RemoveButton{ get; set; }
public Button DoneButton { get; set; }
}
问题是您将值存储在 NumberTextView 中,它是 holder 中的视图。 当 holder 为 null 时,ViewHolder 模式以您初始化视图一次的方式提高性能。这意味着 TextView(NumberTextView) 的一个实例绘制了 ListView 中的所有项目。这就是为什么当您增加值并将其存储在 NumberTextView 中时,您将值设置为所有列表项。您不会立即看到,因为列表不会重绘。当您滚动并且新列表项被绘制到屏幕时,它们具有相同的增加值。
解决方案是将每个列表项的值存储在其他地方。将字段添加到您从 GetItem 方法获得的对象。
例如:
public override View GetView(int position, View convertView, ViewGroup parent)
{
MenuItemHolder holder = null;
var view = convertView;
YourItemClass item = GetItem(position);
if (view != null)
{
holder = view.Tag as MenuItemHolder;
}
if (holder == null)
{
holder = new MenuItemHolder();
view = LayoutInflater.From(Context).Inflate(Resource.Layout.rowWithButtons, null);
holder.RemoveButton = view.FindViewById<Button>(Resource.Id.DecreaseButton);
holder.AddButton = view.FindViewById<Button>(Resource.Id.IncreaseButton);
holder.NumberTextView = view.FindViewById<TextView>(Resource.Id.NumberTextView);
holder.AddButton.Click += delegate
{
item.increaseValue();
holder.NumberTextView.Text = (item.Value).ToString();
};
holder.RemoveButton.Click += delegate
{
if (item.Value > 1))
{
item.decreaseValue();
holder.NumberTextView.Text = (item.Value).ToString();
}
};
view.Tag = holder;
}
holder.Title.Text = GetItem(position).Name;
holder.NumberTextView.Text = (item.Value).ToString();
return view;
}
public override YourItemClass GetItem(int position)
{
if(listOfItems != null)
return listOfItems.ElementAt(position);
return null;
}
class YourItemClass
{
public string Name { get; set; }
public string Value { get;set; }
public void increaseValue()
{
Value++;
}
public void decreaseValue()
{
Value--;
}
}