C# StackLayout内部的Xamarin.Forms列表视图
在我的Xamarin项目中,我有一个相当简单的XAML表单,它应该显示两个视图,一个垂直的C# StackLayout内部的Xamarin.Forms列表视图,c#,xamarin,xamarin.forms,C#,Xamarin,Xamarin.forms,在我的Xamarin项目中,我有一个相当简单的XAML表单,它应该显示两个视图,一个垂直的StackLayout,一个CameraView,一个ListView。CameraView将占用大部分空间。列表视图不得超过4-5项,但在运行期间会发生变化。以下是我目前掌握的XAML: <?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
StackLayout
,一个CameraView
,一个ListView
。CameraView
将占用大部分空间。列表视图
不得超过4-5项,但在运行期间会发生变化。以下是我目前掌握的XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Foo.CamPage"
xmlns:ctrl="clr-namespace:Foo.Controls">
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<ctrl:CameraView HeightRequest="2000"/>
<StackLayout VerticalOptions="FillAndExpand">
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Entry 1</x:String>
<x:String>Entry 2</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</StackLayout>
</StackLayout>
</ContentPage.Content>
这是关联的iOS渲染器:
[assembly: ExportRenderer(typeof(CameraView), typeof(CamPreviewRenderer))]
namespace Foo.iOS.Renderers
{
public class CamPreviewRenderer : ViewRenderer<CameraView, UICamPreview>
{
UICamPreview uiCameraPreview;
protected override void OnElementChanged(ElementChangedEventArgs<CameraView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
uiCameraPreview = new UICamPreview(e.NewElement.Camera);
SetNativeControl(uiCameraPreview);
}
if (e.OldElement != null)
{
// Unsubscribe
uiCameraPreview.Tapped -= OnCameraPreviewTapped;
}
if (e.NewElement != null)
{
// Subscribe
uiCameraPreview.Tapped += OnCameraPreviewTapped;
}
}
void OnCameraPreviewTapped(object sender, EventArgs e)
{
if (uiCameraPreview.IsPreviewing)
{
uiCameraPreview.CaptureSession.StopRunning();
uiCameraPreview.IsPreviewing = false;
}
else
{
uiCameraPreview.CaptureSession.StartRunning();
uiCameraPreview.IsPreviewing = true;
}
}
}
}
任何提示都值得欣赏。将这些视图放入两行网格中。一个视图希望使用与所需空间相同的空间,将“高度”设置为“自动”,另一个视图假设占用剩余空间,将“高度”设置为*。像这样的
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ctrl:CameraView Grid.Row="0"/>
<StackLayout VerticalOptions="FillAndExpand" Grid.Row="1">
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Entry 1</x:String>
<x:String>Entry 2</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</Grid>
</StackLayout>
</StackLayout>
</ContentPage.Content>
条目1
条目2
请记住,在布局方面,ListView是一个非常麻烦的工具。不管怎样,您可能不得不尝试设置高度的硬编码值。您是否尝试过覆盖OnLayout,通常代码是这样的
protected override void only布局(bool changed,int l,int t,int r,int b)
{
尝试
{
仅基础布局(已更改,l、t、r、b);
如果(!已更改)
返回;
int msw=50;
int-msh=50;
int layoutWidth=r-l;
int-layouthweight=b-t;
msw=MeasureSpec.MakeMasureSpec(layoutWidth,MeasureSpecMode.Justice);
msh=MeasureSpec.MakeMeasureSpec(layouthweight,MeasureSpecMode.justice);
查看、测量(msw、msh);
视图.布局(0,0,layoutWidth,layoutHeight);
}
catch(System.Exception-ex)
{
Logger.WriteException(ex);
}
}
CameraView控件是否正确刷新视图?。当Xamarin绘制cameraview时,stacklayout的FillAndExpand会侵入所有视图。如果你只使用相机控制,看起来还可以吗?是的,CameraView本身工作得很好。对不起,伙计,网格方法看起来很有希望,但它不起作用。ListView占用了所有空间。外部堆栈布局是多余的,对吗?TableView会让事情变得更好吗?是的,请尝试删除它并将网格移动到实际的ListView中,看看这是否有帮助。FillAndExpand选项可能已导致占用整个空间。还可以尝试使用Fill和Expand选项将该摄影机视图包装到stacklayout中。父stacklayout是否有可能未展开?如果我在布局上遇到困难,我通常会给所有控件添加背景色,以查看边框的结束位置。试试看,看看每个控件的结束位置。这将更容易为您找出哪个视图没有扩展。哦,等等!那么你是说外部堆栈布局很重要?我删除了它,因为我认为这也是多余的。如果我将两个高度都设置为*
,则两个视图共享相同的高度。这是一个开始。我发现你也可以说5*
,这样一个视图就可以大五倍。然而,ListView从未消失,尽管我还没有消失!看起来很有希望,我现在就试试这个。这是查看的方法,对吗?
namespace Foo.iOS.Renderers
{
public class UICamPreview : UIView
{
AVCaptureVideoPreviewLayer previewLayer;
CameraOptions cameraOptions;
public event EventHandler<EventArgs> Tapped;
public AVCaptureSession CaptureSession { get; private set; }
public bool IsPreviewing { get; set; }
public UICamPreview(CameraOptions options)
{
cameraOptions = options;
IsPreviewing = false;
Initialize();
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
previewLayer.Frame = rect;
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
OnTapped();
}
protected virtual void OnTapped()
{
var eventHandler = Tapped;
if (eventHandler != null)
{
eventHandler(this, new EventArgs());
}
}
void Initialize()
{
CaptureSession = new AVCaptureSession();
previewLayer = new AVCaptureVideoPreviewLayer(CaptureSession)
{
Frame = Bounds,
VideoGravity = AVLayerVideoGravity.ResizeAspectFill
};
var videoDevices = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video);
var cameraPosition = (cameraOptions == CameraOptions.Front) ? AVCaptureDevicePosition.Front : AVCaptureDevicePosition.Back;
var device = videoDevices.FirstOrDefault(d => d.Position == cameraPosition);
if (device == null)
{
return;
}
NSError error;
var input = new AVCaptureDeviceInput(device, out error);
CaptureSession.AddInput(input);
Layer.AddSublayer(previewLayer);
CaptureSession.StartRunning();
IsPreviewing = true;
}
}
}
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ctrl:CameraView Grid.Row="0"/>
<StackLayout VerticalOptions="FillAndExpand" Grid.Row="1">
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Entry 1</x:String>
<x:String>Entry 2</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</Grid>
</StackLayout>
</StackLayout>
</ContentPage.Content>