如何避免在 MvxGridView 上不正确地重用自定义单元格?
How to avoid incorrect reusing of custom cells on MvxGridView?
我有 Android 应用程序页面(在片段上),MvxGridView 的布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<MvxGridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:numColumns="1"
android:horizontalSpacing="0dp"
android:verticalSpacing="0dp"
local:MvxBind="ItemsSource DayGraphsItems"
local:MvxItemTemplate="@layout/day_graph_item" />
</LinearLayout>
我有一个用于绘制图表的自定义视图:
public class GraphView : View
{
Paint mPaint;
Bitmap mBitmap;
Canvas mCanvas;
Path mPath;
Paint mBitmapPaint;
public List<string> Data { get; set; }
public GraphView(Context context, Android.Util.IAttributeSet attributeSet) : base(context)
{
mPaint = new Paint();
mPaint.AntiAlias = true;
mPaint.Dither = true;
mPaint.SetARGB(0xFF, 0xFF, 0xFF, 0xFF);
mPaint.SetStyle(Paint.Style.FillAndStroke);
mPaint.StrokeJoin = Paint.Join.Round;
mPaint.StrokeCap = Paint.Cap.Round;
mPaint.StrokeWidth = 1;
mPaint.TextSize = 24;
mPath = new Path();
mBitmapPaint = new Paint();
mBitmapPaint.SetARGB(0xFF, 0xFF, 0xff, 0xff);
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
if (w > 0 && h > 0)
{
mBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888);
mCanvas = new Canvas(mBitmap);
_canvasHeight = h;
_canvasWidth = w;
DrawTheGraph(Data);
}
}
public override void Draw(Canvas canvas)
{
canvas.DrawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.DrawPath(mPath, mPaint);
canvas.Restore();
}
private void DrawTheGraph(List<string> data)
{
// here is drawing of the graph which works well
}
}
我有自定义绑定
public class GraphCustomBinding : MvxConvertingTargetBinding
{
public static string Name = "GraphCustom";
public GraphCustomBinding(GraphView target) : base(target)
{
}
protected override void SetValueImpl(object target, object value)
{
var data = new List<string>();
data = (List<string>)value;
var targetGraphView = (GraphView)target;
targetGraphView.Data = data;
}
public override Type TargetType
{
get { return typeof(GraphView); }
}
}
绑定已在设置中正确注册。
我有 DayGraphsItems 列表元素的项目布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="15dp"
android:paddingBottom="15dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
style="@style/TextViewCurrentConditionsHeader"
local:MvxBind="Text Title" />
<Pogoda.Droid.GraphView
android:layout_width="match_parent"
android:layout_height="300dp"
android:padding="5dp"
local:MvxBind="GraphCustom Data, Mode=TwoWay" />
</LinearLayout>
编辑:
DayGraphsItems 是 DayGraphItem 的列表,给出如下:
public class DayGraphItem
{
public int Id { get; set; }
public string Title { get; set; }
public List<string> Data { get; set; }
}
视图在片段上:
[Register("pogoda.droid.DayGraphsFragment")]
public class DayGraphsFragment : BaseFragment<DayGraphsViewModel>
{
public const string TAG = "DayGraphsFragmentTag";
public override string UniqueImmutableCacheTag
{
get
{
return TAG;
}
}
public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
return this.BindingInflate(Resource.Layout.day_graphs_layout, null);
}
}
问题: 图表绘制正确,但如果单元格多于屏幕上一次显示的单元格,向下滚动后我会看到单元格这是以前绘制的而不是新绘制的(似乎被重复使用)。
问题:如何避免这种情况并显示新图表而不是这些 "scrolled out from the top"?
对我有用的解决方案是
创建 EnhancedMvxListView
并在第 1 点中使用它替换 MvxGridView
。
public class EnhancedMvxListView : MvxListView
{
public EnhancedMvxListView(Context context, IAttributeSet attrs) : base(context, attrs, new EnhancedMvxAdapter(context))
{
}
public EnhancedMvxListView(Context context, IAttributeSet attrs, IMvxAdapter adapter) : base(context, attrs, new EnhancedMvxAdapter(context))
{
}
}
其中EnhancedMvxAdapter
是下面的
public class EnhancedMvxAdapter : MvxAdapterWithChangedEvent
{
public EnhancedMvxAdapter(Context context) : base(context)
{
}
protected override View GetBindableView(View convertView, object dataContext, ViewGroup parent, int templateId)
{
templateId = GetTemplateId(dataContext);
var view = base.GetBindableView(convertView, dataContext, parent, templateId);
var context = dataContext as DayGraphItem;
view.FindViewById<TextView>(Resource.Id.graphTitle).Text = context.Title;
view.FindViewById<GraphView>(Resource.Id.graphDrawing).Data = context.Data;
return view;
}
private int GetTemplateId(object data)
{
return Resource.Layout.day_graph_item;
}
}
最后在第 2 点的文件中。我已经替换了
public List<string> Data { get; set; }
和
List<string> _data;
public List<string> Data
{
get
{
return _data;
}
set
{
if (value != null && value != _data)
{
_data = value;
if ((int)_canvasWidth == 0 || (int)_canvasHeight == 0)
return;
mBitmap = Bitmap.CreateBitmap((int)_canvasWidth, (int)_canvasHeight, Bitmap.Config.Argb8888);
mCanvas = new Canvas(mBitmap);
DrawTheGraph(Data);
}
}
}
我有 Android 应用程序页面(在片段上),MvxGridView 的布局如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <MvxGridView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:numColumns="1" android:horizontalSpacing="0dp" android:verticalSpacing="0dp" local:MvxBind="ItemsSource DayGraphsItems" local:MvxItemTemplate="@layout/day_graph_item" /> </LinearLayout>
我有一个用于绘制图表的自定义视图:
public class GraphView : View { Paint mPaint; Bitmap mBitmap; Canvas mCanvas; Path mPath; Paint mBitmapPaint; public List<string> Data { get; set; } public GraphView(Context context, Android.Util.IAttributeSet attributeSet) : base(context) { mPaint = new Paint(); mPaint.AntiAlias = true; mPaint.Dither = true; mPaint.SetARGB(0xFF, 0xFF, 0xFF, 0xFF); mPaint.SetStyle(Paint.Style.FillAndStroke); mPaint.StrokeJoin = Paint.Join.Round; mPaint.StrokeCap = Paint.Cap.Round; mPaint.StrokeWidth = 1; mPaint.TextSize = 24; mPath = new Path(); mBitmapPaint = new Paint(); mBitmapPaint.SetARGB(0xFF, 0xFF, 0xff, 0xff); } protected override void OnSizeChanged(int w, int h, int oldw, int oldh) { if (w > 0 && h > 0) { mBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888); mCanvas = new Canvas(mBitmap); _canvasHeight = h; _canvasWidth = w; DrawTheGraph(Data); } } public override void Draw(Canvas canvas) { canvas.DrawBitmap(mBitmap, 0, 0, mBitmapPaint); canvas.DrawPath(mPath, mPaint); canvas.Restore(); } private void DrawTheGraph(List<string> data) { // here is drawing of the graph which works well } }
我有自定义绑定
public class GraphCustomBinding : MvxConvertingTargetBinding { public static string Name = "GraphCustom"; public GraphCustomBinding(GraphView target) : base(target) { } protected override void SetValueImpl(object target, object value) { var data = new List<string>(); data = (List<string>)value; var targetGraphView = (GraphView)target; targetGraphView.Data = data; } public override Type TargetType { get { return typeof(GraphView); } } }
绑定已在设置中正确注册。
我有 DayGraphsItems 列表元素的项目布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="15dp" android:paddingRight="15dp" android:paddingTop="15dp" android:paddingBottom="15dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical|center_horizontal" style="@style/TextViewCurrentConditionsHeader" local:MvxBind="Text Title" /> <Pogoda.Droid.GraphView android:layout_width="match_parent" android:layout_height="300dp" android:padding="5dp" local:MvxBind="GraphCustom Data, Mode=TwoWay" /> </LinearLayout>
编辑:
DayGraphsItems 是 DayGraphItem 的列表,给出如下:
public class DayGraphItem { public int Id { get; set; } public string Title { get; set; } public List<string> Data { get; set; } }
视图在片段上:
[Register("pogoda.droid.DayGraphsFragment")] public class DayGraphsFragment : BaseFragment<DayGraphsViewModel> { public const string TAG = "DayGraphsFragmentTag"; public override string UniqueImmutableCacheTag { get { return TAG; } } public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState) { base.OnCreateView(inflater, container, savedInstanceState); return this.BindingInflate(Resource.Layout.day_graphs_layout, null); } }
问题: 图表绘制正确,但如果单元格多于屏幕上一次显示的单元格,向下滚动后我会看到单元格这是以前绘制的而不是新绘制的(似乎被重复使用)。
问题:如何避免这种情况并显示新图表而不是这些 "scrolled out from the top"?
对我有用的解决方案是
创建 EnhancedMvxListView
并在第 1 点中使用它替换 MvxGridView
。
public class EnhancedMvxListView : MvxListView
{
public EnhancedMvxListView(Context context, IAttributeSet attrs) : base(context, attrs, new EnhancedMvxAdapter(context))
{
}
public EnhancedMvxListView(Context context, IAttributeSet attrs, IMvxAdapter adapter) : base(context, attrs, new EnhancedMvxAdapter(context))
{
}
}
其中EnhancedMvxAdapter
是下面的
public class EnhancedMvxAdapter : MvxAdapterWithChangedEvent
{
public EnhancedMvxAdapter(Context context) : base(context)
{
}
protected override View GetBindableView(View convertView, object dataContext, ViewGroup parent, int templateId)
{
templateId = GetTemplateId(dataContext);
var view = base.GetBindableView(convertView, dataContext, parent, templateId);
var context = dataContext as DayGraphItem;
view.FindViewById<TextView>(Resource.Id.graphTitle).Text = context.Title;
view.FindViewById<GraphView>(Resource.Id.graphDrawing).Data = context.Data;
return view;
}
private int GetTemplateId(object data)
{
return Resource.Layout.day_graph_item;
}
}
最后在第 2 点的文件中。我已经替换了
public List<string> Data { get; set; }
和
List<string> _data;
public List<string> Data
{
get
{
return _data;
}
set
{
if (value != null && value != _data)
{
_data = value;
if ((int)_canvasWidth == 0 || (int)_canvasHeight == 0)
return;
mBitmap = Bitmap.CreateBitmap((int)_canvasWidth, (int)_canvasHeight, Bitmap.Config.Argb8888);
mCanvas = new Canvas(mBitmap);
DrawTheGraph(Data);
}
}
}