MvvmCross:MvxAdapter GetBindableView 方法在第一个无限循环 child
MvvmCross: MvxAdapter GetBindableView method loops indefinitely on first child
我的适配器的 GetBindableView
方法通常为我的 MvxGridView 的所有 child 调用,但是它在第一个 child.
上无限循环
在 MvxFragment 中,我在 OnCreateView
方法中将适配器设置为 MvxGridView:
public class MetronomeFragment : MvxFragment<MetronomeViewModel>, View.IOnTouchListener
{
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignored = base.OnCreateView (inflater, container, savedInstanceState);
var view = this.BindingInflate (Resource.Layout.fragment_metronome, null);
// GridView
var gridView = view.FindViewById<MvxGridView>(Resource.Id.grid_view);
gridView.Adapter = new CustomAdapter (Activity, (MvxAndroidBindingContext)BindingContext);
return view;
}
}
我的部分观点:
<Mvx.MvxGridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:stretchMode="columnWidth"
android:numColumns="5"
android:verticalSpacing="@dimen/metronome_grid_view_vertical_spacing"
local:MvxBind="ItemsSource MeasureViewModel.Measure.BeatList"
local:MvxItemTemplate="@layout/template_item_metronome_beat" />
我的模板:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/item_metronome_beat_layout_width"
android:layout_height="@dimen/item_metronome_beat_layout_height"
android:layout_gravity="center"
local:cardBackgroundColor="@color/card_view"
local:cardCornerRadius="@dimen/card_view_corner_radius"
local:MvxBind="CardElevation BoolToElevation(IsPlaying, 2); Alpha BoolToAlpha(IsPlaying, 0.5)">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/item_metronome_beat_margin">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
local:MvxBind="DrawableId BeatToImageResource(.)" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="@dimen/text_small"
local:MvxBind="Text Number" />
</RelativeLayout>
</android.support.v7.widget.CardView>
这是我的自定义适配器:
public class CustomAdapter : MvxAdapter
{
public CustomAdapter(Context context, IMvxAndroidBindingContext bindingContext)
: base(context, bindingContext)
{
}
protected override View GetBindableView(View convertView, object source, int templateId)
{
var beat = (Beat)source;
Mvx.Trace (beat.Number.ToString ());
return base.GetBindableView(convertView, source, templateId);
}
}
为了这个测试目的,我只记录节拍数 (DataContext object)。该列表包含 4 个节拍,输出为:1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... 它总是在第一个循环 child!!!
我正在使用 MvvmCross 4.0.0-beta5。
有人有想法吗?
干杯
终于找到解释了!
由于 ViewTreeObserver.GlobalLayout
事件和 RelativeLayout
.
的组合,这是意外的屏幕刷新
我的主要 activity OnCreate
方法中有这段代码可以显示(作为临时屏幕调试信息)屏幕尺寸和密度:
var contentView = FindViewById<View> (Window.IdAndroidContent);
var sizeText = FindViewById<Android.Widget.TextView> (Resource.Id.size_text);
contentView.ViewTreeObserver.GlobalLayout += (sender, e) => {
var height = (int) ((contentView.Height)/Resources.DisplayMetrics.Density);
var width = (int) ((contentView.Width)/Resources.DisplayMetrics.Density);
sizeText.Text = height + " x " + width + " " + Resources.DisplayMetrics.DensityDpi.ToString();
};
我不知道的是,这个方法被重复调用了。这意味着 TextView
中的文本每秒更改几次(即使大小没有更改)。
我的主要观点是:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/size_text" />
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:layout_above="@+id/ad_view" />
<com.google.android.gms.ads.AdView
android:id="@id/ad_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
local:adSize="BANNER"
local:adUnitId="@string/ad_unit_id" />
</RelativeLayout>
我的 FrameLayout
包含我的 GridView
包含在 RelativeLayout 以及我的 TextView
中。由于 TextView
的内容总是变化的,因此重新计算每个视图的大小。 GridView
也是这种情况,这意味着调用 GetBindable
方法。
要避免在获取大小时出现此调用循环,请让您的 activity 实现 Android.Views.ViewTreeObserver.IOnGlobalLayoutListener
并将其添加到 OnCreate
方法中:
var contentView = FindViewById<View> (Window.IdAndroidContent);
contentView.ViewTreeObserver.AddOnGlobalLayoutListener(this);
并添加此方法:
public void OnGlobalLayout ()
{
var metrics = Resources.DisplayMetrics;
var contentView = FindViewById<View> (Window.IdAndroidContent);
var sizeText = FindViewById<Android.Widget.TextView> (Resource.Id.size_text);
var height = (int) ((contentView.Height)/metrics.Density);
var width = (int) ((contentView.Width)/metrics.Density);
sizeText.Text = height + " x " + width + " " + metrics.DensityDpi.ToString();
contentView.ViewTreeObserver.RemoveOnGlobalLayoutListener(this);
}
大家周末愉快!!!
我的适配器的 GetBindableView
方法通常为我的 MvxGridView 的所有 child 调用,但是它在第一个 child.
在 MvxFragment 中,我在 OnCreateView
方法中将适配器设置为 MvxGridView:
public class MetronomeFragment : MvxFragment<MetronomeViewModel>, View.IOnTouchListener
{
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignored = base.OnCreateView (inflater, container, savedInstanceState);
var view = this.BindingInflate (Resource.Layout.fragment_metronome, null);
// GridView
var gridView = view.FindViewById<MvxGridView>(Resource.Id.grid_view);
gridView.Adapter = new CustomAdapter (Activity, (MvxAndroidBindingContext)BindingContext);
return view;
}
}
我的部分观点:
<Mvx.MvxGridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:stretchMode="columnWidth"
android:numColumns="5"
android:verticalSpacing="@dimen/metronome_grid_view_vertical_spacing"
local:MvxBind="ItemsSource MeasureViewModel.Measure.BeatList"
local:MvxItemTemplate="@layout/template_item_metronome_beat" />
我的模板:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/item_metronome_beat_layout_width"
android:layout_height="@dimen/item_metronome_beat_layout_height"
android:layout_gravity="center"
local:cardBackgroundColor="@color/card_view"
local:cardCornerRadius="@dimen/card_view_corner_radius"
local:MvxBind="CardElevation BoolToElevation(IsPlaying, 2); Alpha BoolToAlpha(IsPlaying, 0.5)">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/item_metronome_beat_margin">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
local:MvxBind="DrawableId BeatToImageResource(.)" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="@dimen/text_small"
local:MvxBind="Text Number" />
</RelativeLayout>
</android.support.v7.widget.CardView>
这是我的自定义适配器:
public class CustomAdapter : MvxAdapter
{
public CustomAdapter(Context context, IMvxAndroidBindingContext bindingContext)
: base(context, bindingContext)
{
}
protected override View GetBindableView(View convertView, object source, int templateId)
{
var beat = (Beat)source;
Mvx.Trace (beat.Number.ToString ());
return base.GetBindableView(convertView, source, templateId);
}
}
为了这个测试目的,我只记录节拍数 (DataContext object)。该列表包含 4 个节拍,输出为:1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... 它总是在第一个循环 child!!!
我正在使用 MvvmCross 4.0.0-beta5。
有人有想法吗?
干杯
终于找到解释了!
由于 ViewTreeObserver.GlobalLayout
事件和 RelativeLayout
.
我的主要 activity OnCreate
方法中有这段代码可以显示(作为临时屏幕调试信息)屏幕尺寸和密度:
var contentView = FindViewById<View> (Window.IdAndroidContent);
var sizeText = FindViewById<Android.Widget.TextView> (Resource.Id.size_text);
contentView.ViewTreeObserver.GlobalLayout += (sender, e) => {
var height = (int) ((contentView.Height)/Resources.DisplayMetrics.Density);
var width = (int) ((contentView.Width)/Resources.DisplayMetrics.Density);
sizeText.Text = height + " x " + width + " " + Resources.DisplayMetrics.DensityDpi.ToString();
};
我不知道的是,这个方法被重复调用了。这意味着 TextView
中的文本每秒更改几次(即使大小没有更改)。
我的主要观点是:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/size_text" />
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:layout_above="@+id/ad_view" />
<com.google.android.gms.ads.AdView
android:id="@id/ad_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
local:adSize="BANNER"
local:adUnitId="@string/ad_unit_id" />
</RelativeLayout>
我的 FrameLayout
包含我的 GridView
包含在 RelativeLayout 以及我的 TextView
中。由于 TextView
的内容总是变化的,因此重新计算每个视图的大小。 GridView
也是这种情况,这意味着调用 GetBindable
方法。
要避免在获取大小时出现此调用循环,请让您的 activity 实现 Android.Views.ViewTreeObserver.IOnGlobalLayoutListener
并将其添加到 OnCreate
方法中:
var contentView = FindViewById<View> (Window.IdAndroidContent);
contentView.ViewTreeObserver.AddOnGlobalLayoutListener(this);
并添加此方法:
public void OnGlobalLayout ()
{
var metrics = Resources.DisplayMetrics;
var contentView = FindViewById<View> (Window.IdAndroidContent);
var sizeText = FindViewById<Android.Widget.TextView> (Resource.Id.size_text);
var height = (int) ((contentView.Height)/metrics.Density);
var width = (int) ((contentView.Width)/metrics.Density);
sizeText.Text = height + " x " + width + " " + metrics.DensityDpi.ToString();
contentView.ViewTreeObserver.RemoveOnGlobalLayoutListener(this);
}
大家周末愉快!!!