【问题标题】:Xamarin Forms ScrollView is not scrolling correctlyXamarin Forms ScrollView 未正确滚动
【发布时间】:2017-12-14 17:48:49
【问题描述】:

我们有一个即时消息应用程序。我们希望在收到消息时自动滚动,以便看到新消息。目前,当接收到需要滚动的第一条消息时,页面不会滚动。也就是说,新消息隐藏在我们的输入控件后面。它需要另一条消息或用户调整滚动视图,然后才能正常工作。

我们的 xaml 是这样的:

<ContentPage>
  <StackLayout x:Name="mainStackLayout">
    <customControls:NavBar />
    <ScrollView x:Name="mainScrollView">
      <StackLayout x:Name="mainScrollViewStackLayout">
        <ScrollView x:Name="messagesScrollView">
          <StackLayout x:Name="messagesScrollViewContentStackLayout">
            <!-- Messages are programmatically inserted here -->
          </StackLayout>
        </ScrollView>
      </StackLayout>
    </ScrollView>
    <StackLayout>
      <!-- a couple buttons/inputs for sending messages -->
    </StackLayout>
  </StackLayout>
</ContentPage>

我们调用滚动的代码如下所示:

public void ScrollMessagesToEnd()
{

    StackLayout messagesContent = (messagesScrollView.Content as StackLayout);
    var frame = messagesContent.Children.LastOrDefault();

    if (frame != null)
    {
            messagesScrollView.ScrollToAsync(frame, ScrollToPosition.MakeVisible, true);
    }
}

【问题讨论】:

  • 你的消息去哪儿了?某处有listView吗?
  • @YuriS 他们将以编程方式进入 StackLayout 消息ScrollViewContentStackLayout。我会添加评论以便清楚。
  • 作为什么插入?每条消息都是单独的布局?为什么不使用 ListView?如果你确实使用它,那么你就不需要 ScrollView。顺便说一句,Xamarin 强烈建议不要在滚动视图中使用 ListView,并且您正在主滚动视图中执行消息滚动视图。这是一种糟糕的设计。你能以某种方式简化它吗?我会做一个包含 3 个项目的堆栈布局:导航栏、列表视图和发送堆栈布局。列表视图将是唯一可滚动的。让我知道你的想法。我已经为您提供了一个解决方案,但我想把它改正:-)
  • 每条插入的消息都是一个扩展 Frame 的自定义视图。我不是这个页面的主要开发者,所以我不能说为什么我们不使用列表视图(如果我理解正确的话)列表视图中的自定义视图很痛苦。同样,如果我记得原始开发人员所说的正确,我们需要双滚动视图,因为 iOS 没有正确调整键盘,但 mainScrollView 允许页面移动并为其腾出空间。
  • 你能提供代码(这样我就不用写了)用测试数据填充消息吗?不确定我们是否可以使其与嵌套的 ScrollViews 一起使用。我宁愿找到iOS键盘的解决方案

标签: c# xamarin xamarin.forms


【解决方案1】:

不管解决方案如何,ScrollMessagesToEnd 都应该是异步的,你需要 await ScrollToAsync()。由于您现在正在等待ScrollToAsync(),因此我建议您在 UI 线程上明确运行它。

完成后,您可以尝试将await Task.Delay(300) 添加到您的方法的顶部,我之前必须这样做。

您可能还想尝试启用和禁用我发现可以影响滚动但在每个平台上测试的动画,因为每个平台的效果可能不同。

public async Task ScrollMessagesToEndAsync() //Adding Async to method name, also try to return Task and await this method in the calling code as well
{
    await Task.Delay(300); //Sometimes code runs too fast and a delay is needed, you may test whether only a specific platform needs the delay

    StackLayout messagesContent = (messagesScrollView.Content as StackLayout);
    var frame = messagesContent.Children.LastOrDefault();

    if (frame != null)
    {
        Device.BeginInvokeOnMainThread(async () => await messagesScrollView.ScrollToAsync(frame, ScrollToPosition.MakeVisible, true)); //You could try passing in false to disable animation and see if that helps
    }
}

【讨论】:

  • 不幸的是,这些都没有帮助。它似乎与我们的输入 StackLayout 高度相关,好像 Xamarin 无法告诉我们是否需要滚动“隐藏”消息。但是,当它最终滚动时(发送另一条消息或用户以触发它的方式进行交互),它的位置是正确的。
  • @GarrettDanielDeMeyer 哦该死的我没注意到你在ScrollView 中使用ScrollView。这可能是问题所在,就像Xamarin Forms does not support that,但我不能肯定地说。这是发生在 Android 还是 iOS 上?根据您在布局中的目标,您也许可以使用分组的ListView,甚至可能是popup type of control,这将允许您滚动。
  • 我对刚才的问题发表了评论,向另一位评论者解释了为什么我们有嵌套的 ScrollViews。看看它是否有助于您的理解以及我们在添加 mainScrollView 时是否误解了某些内容
  • @GarrettDanielDeMeyer 有道理。问题是当您的输入低于内部ScrollView(并且您的输入不在另一个外部ScrollView 内)时,键盘会覆盖所有内容。尝试移除外部ScrollView 以查看滚动是否已修复。如果是这样,并且您的问题仅限于 iOS,您可以尝试this 来解决键盘重叠问题。如果这不起作用,还有其他一些建议here
  • @GarrettDanielDeMeyer 是的,删除顶级滚动可以解决问题。见我上面的评论
【解决方案2】:

我强烈建议不要使用嵌套滚动视图,但如果你保留它们,那么这里就是解决方案。

相反

messagesScrollView.ScrollToAsync(frame, ScrollToPosition.MakeVisible, true);

使用

mainScrollView.ScrollToAsync(frame, ScrollToPosition.End, true);

mainScrollView.ScrollToAsync(frame, ScrollToPosition.MakeVisible, true);

【讨论】:

  • 我从我的 xaml 页面中删除了 mainScrollView,它解决了我的滚动问题!它引入了几个小的 UI 间距问题,但我相信我可以解决这个问题。顺便说一句,您在此答案中的第一行和最后一行代码看起来与我相同。虽然我不需要尝试它们,但我看不出有什么区别,您可能需要澄清一下,以防它在以后对其他人有所帮助。
  • @GarrettDanielDeMeyer 当用户点击位于ListView下方的Entry时,您是如何处理覆盖UI的键盘的?
  • @GarrettDanielDeMeyer 错字。我确定了答案。如果您使用 ScrollToPosition.End,您可能不需要寻找框架,但我没有测试过
  • @hvaughan3 在这种情况下,我注册键盘事件并在显示时将条目移到键盘上方
猜你喜欢
  • 2016-09-03
  • 1970-01-01
  • 2017-12-25
  • 1970-01-01
  • 2020-01-11
  • 2018-12-01
  • 1970-01-01
  • 2021-01-15
  • 1970-01-01
相关资源
最近更新 更多