我一直在编写一个Android应用程序,它在从服务器接收数据时生成动态视图。
我发现当在另一个线程内部尝试创建视图时,不会显示按钮,但会显示线性布局。
例如,以下内容不起作用......
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Task thread = new Task(() =>
{
RunOnUiThread(() =>
{
ShowDynamicLayout();
});
});
thread.Start();
return;
}
但这确实......
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
ShowDynamicLayout();
return;
}
ShowDynamicView:
private void ShowDynamicLayout()
{
var scrollView = new ScrollView(this)
{
LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent)
};
var mainLayout = new LinearLayout(this)
{
Orientation = Orientation.Vertical,
LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent)
};
scrollView.AddView(mainLayout);
for (int n = 1; n < 10; n++)
{
var dv = new DynamicView(this, n)
{
LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, 100)
};
mainLayout.AddView(dv);
}
SetContentView(scrollView);
}
DynamicView:
public class DynamicView : LinearLayout
{
private List<LinearLayout> layouts;
public DynamicView(Context context, int count) :
base(context)
{
this.Initialize(count);
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
base.OnSizeChanged(w, h, oldw, oldh);
foreach (var l in this.layouts)
{
l.LayoutParameters = new LinearLayout.LayoutParams(w / this.layouts.Count, ViewGroup.LayoutParams.WrapContent);
}
}
private void Initialize(int count)
{
this.Orientation = Orientation.Horizontal;
this.SetBackgroundColor(new Color(0, 125, 0));
layouts = new List<LinearLayout>();
for (int n = 0; n < count; n++)
{
var layout = new LinearLayout(this.Context)
{
Orientation = Orientation.Vertical,
LayoutParameters =
new LinearLayout.LayoutParams(this.Width / count, ViewGroup.LayoutParams.WrapContent)
};
layouts.Add(layout);
var button = new Button(this.Context)
{
Text = "New button"
};
button.SetBackgroundColor(new Color(125, 0, 0));
layout.AddView(button);
this.AddView(layout);
}
}
}
答案 0 :(得分:1)
我发现当尝试在不同的线程内创建视图时,按钮不会显示,但会显示线性布局。
我不知道根深蒂固的原因,但似乎你的代码是由没有线程的android系统执行的。 Android重新渲染您的视图。(您可以在OnDraw
上设置断点时查看它,并检查线程和非线程的中断时间差异。)
无论如何,问题在于以下几行:
LayoutParameters =new LinearLayout.LayoutParams(this.Width / count, ViewGroup.LayoutParams.WrapContent)
。
在Initialize函数中,因为它在OnCreate
中调用,所以此时this.Width
始终为0,因为此视图尚未被测量。因此,你不会得到预期的观点。
<强>解决方案:强>
您应该将初始化和渲染逻辑分开并在OnDraw
中调用渲染逻辑,如下所示:
public class DynamicView : LinearLayout
{
private List<LinearLayout> layouts;
int count;
public DynamicView(Context context, int count) :
base(context)
{
this.count = count;
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
base.OnSizeChanged(w, h, oldw, oldh);
this.Initialize(count);
foreach (var l in this.layouts)
{
l.LayoutParameters = new LinearLayout.LayoutParams(w / this.layouts.Count, ViewGroup.LayoutParams.WrapContent);
}
}
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
//call the render logic in OnDraw
FillView();
}
private void Initialize(int count)
{
//initialize logic
this.Orientation = Orientation.Horizontal;
this.SetBackgroundColor(new Color(0, 125, 0));
layouts = new List<LinearLayout>();
}
//render logic
private void FillView()
{
for (int n = 0; n < count; n++)
{
var layout = new LinearLayout(this.Context)
{
Orientation = Orientation.Vertical,
Background = new ColorDrawable(new Color(0, 10, 0)),
LayoutParameters =
new LinearLayout.LayoutParams(this.Width / count, ViewGroup.LayoutParams.WrapContent)
};
layouts.Add(layout);
var button = new Button(this.Context)
{
Text = "New button"
};
button.SetBackgroundColor(new Color(125, 0, 0));
layout.AddView(button);
this.AddView(layout);
}
}
}