如何检测控件在屏幕上是否可见

本文关键字:屏幕 是否 控件 何检测 检测 | 更新日期: 2023-09-27 17:50:21

我有一个Panorama控件,它有三个项目:

<phone:Panorama>
    <phone:PanoramaItem>
    </phone:PanoramaItem>
    <phone:PanoramaItem>
    </phone:PanoramaItem>
    <phone:PanoramaItem Header="third item" Orientation="Horizontal">
        <Grid>
            <StackPanel Margin="0,4,16,0" Orientation="Vertical" VerticalAlignment="Top">
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                </StackPanel>
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Margin="0,12,0,0">
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="Black" Height="173" Width="173" Margin="12,0,0,0"/>
                </StackPanel>
            </StackPanel>
        </Grid>
    </phone:PanoramaItem>
</phone:Panorama>

我怎么知道最后的Border与黑色背景是在屏幕上,并为用户可见?因为它是一个水平的PanoramaItem,我不能依靠全景的SelectedIndex。任何建议吗?

如何检测控件在屏幕上是否可见

如果你只是想检查一个元素是否在屏幕边界内,你可以使用VisualTreeHelper,像这样:

Rect screenBounds = new Rect(0, 0, Application.Current.Host.Content.ActualWidth, Application.Current.Host.Content.ActualHeight);
if (VisualTreeHelper.FindElementsInHostCoordinates(screenBounds, myPanorama).Contains(elementToCheck))
    Debug.WriteLine("Element is now visible");
else
    Debug.WriteLine("Element is no longer visible");
我对XAML做了两个更改(只是为了简化示例),首先我将Panorama: 命名为
<phone:Panorama x:Name="myPanorama">

其次,我还命名了Border元素,你要检查的可见性:

<Border x:Name="elementToCheck" Background="Black" Height="173" Width="173" Margin="12,0,0,0"/>

如果你还想在一个事件中检查它,当全景滚动正在改变它似乎变得有点困难,因为ManipulationDelta事件不工作,如果一个控件在其他控件之下。一种解决方案是在每次镜框报告触摸时进行检查。这是通过以下方式完成的:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    Touch.FrameReported += Touch_FrameReported;
}
private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
    // This is the same code as above
    Rect screenBounds = new Rect(0, 0, Application.Current.Host.Content.ActualWidth, Application.Current.Host.Content.ActualHeight);
    if (VisualTreeHelper.FindElementsInHostCoordinates(screenBounds, myPanorama).Contains(elementToCheck))
        Debug.WriteLine("Element is now visible");
    else
        Debug.WriteLine("Element is no longer visible");
}

您还需要VisualTreeHelperTouch的这两个using指令:

using System.Windows.Media;
using System.Windows.Input;

不幸的是,我现在想不出一个更简单的解决方案。

编辑:

对于事件来说,这还远远不够完美,例如,如果全景被程序化地"平移",或者当它抓拍时,它不会给出预期的结果。问题是全景是建立在PanningLayer, PanningTitleLayer, PanningBackgroundLayer之上的,而不是ScrollViewer,所以没有ScrollBar,这意味着没有Scroll事件:(

一种解决方案是使用计时器定期检查它是否可见,但这也是一种难看的解决方案。