Xamarin Forms 可折叠 StackLayout

Posted

技术标签:

【中文标题】Xamarin Forms 可折叠 StackLayout【英文标题】:Xamarin Forms Collapsable StackLayout 【发布时间】:2016-09-21 15:29:21 【问题描述】:

我正在尝试实现一种可折叠的 StackLayout。 用户每点击一次按钮,就会展开或折叠 stacklayout 以显示/隐藏更多细节。

我能够使用下面的代码实现更多/更少的这一点,但它看起来不正确并且效果也不是很好,因为它会立即增长并且我正在将效果应用于其他元素。

您有什么建议吗,我正在使用 xamarin Forms?

XAML

<?xml version="1.0" encoding="utf-8" ?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Sample.MyStackLayout" >

  <StackLayout x:Name="TopLayout">
    <StackLayout Orientation="Horizontal">
      <Label Text="some text" VerticalOptions="Center" HorizontalOptions="StartAndExpand"  />
      <Label Text="123" VerticalOptions="Center" HorizontalOptions="End" FontSize="Large" />
    </StackLayout>

    <BoxView Color="Black" HeightRequest="1" />

    <StackLayout Orientation="Horizontal">
      <Label Text="some text" VerticalOptions="Center" HorizontalOptions="StartAndExpand"  />
      <Label Text="123" VerticalOptions="Center" HorizontalOptions="End" FontSize="Large" />
    </StackLayout>

    <StackLayout Orientation="Horizontal">
      <Label Text="some text" VerticalOptions="Center" HorizontalOptions="StartAndExpand"  />
      <Label Text="123" VerticalOptions="Center" HorizontalOptions="End" FontSize="Large" />
    </StackLayout>

    <Button x:Name="btn" Text="Button" Clicked="btnClicked" />
  </StackLayout>


  <StackLayout x:Name="MoreDetails" IsVisible="False">
    <Label Text="some text 1"></Label>
    <Label Text="some text 2"></Label>
    <Label Text="some text 3"></Label>
    <Label Text="some text 4"></Label>
    <Label Text="some text 5"></Label>
    <Label Text="some text 6"></Label>
    <Label Text="some text 7"></Label>
    <Label Text="some text 8"></Label>
  </StackLayout>
</StackLayout>

代码

public AccountInfo()

    InitializeComponent();


bool isExpanded = false;
protected async void btnClicked(object sender, EventArgs e)

    if (isExpanded)
    
        await MoreDetails.FadeTo(0);
        MoreDetails.IsVisible = !isExpanded;
    
    else
    
        MoreDetails.IsVisible = !isExpanded;
        await MoreDetails.FadeTo(1);
    

    isExpanded = !isExpanded;

【问题讨论】:

功能现已集成到 Xamarin 形式中,您可以尝试一下,它更加稳定docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/… 【参考方案1】:

您可以创建一个自定义控件来为您执行此操作。如果您使用 Xaml 创建一个“ExpandableView”内容视图,例如:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyProject.CustomControls.ExpandableView">
    <StackLayout  x:Name="Layout" Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
        <StackLayout x:Name="SummaryRegion"/>               
        <StackLayout x:Name="DetailsRegion" IsVisible="False"/>
    </StackLayout>
</ContentView>

然后像这样连接 .cs 类:

    public partial class ExpandableView: ContentView
    

        private TapGestureRecognizer _tapRecogniser;
        private StackLayout _summary;
        private StackLayout _details;

        public ExpandableView()
        
            InitializeComponent();
            InitializeGuestureRecognizer();
            SubscribeToGuestureHandler();    
        

        private void InitializeGuestureRecognizer()
        
            _tapRecogniser= new TapGestureRecognizer();
            SummaryRegion.GestureRecognizers.Add(_tapRecogniser);
        

        private void SubscribeToGuestureHandler()
        
            _tapRecogniser.Tapped += TapRecogniser_Tapped;
        

        public virtual StackLayout Summary
        
            get  return _summary; 
            set
            
                _summary = value;    
                SummaryRegion.Children.Add(_summary);
                OnPropertyChanged();
            
        

        public virtual StackLayout Details
        
           get  return _details; 
           set 
           
              _details = value;
              DetailsRegion.Children.Add(_details);
              OnPropertyChanged();
           
       

       private void TapRecogniser_Tapped(object sender, EventArgs e)
    
        if (DetailsRegion.IsVisible)
        
            DetailsRegion.IsVisible = false;
        
        else
        
             DetailsRegion.IsVisible = true;
        
    

并像这样在您的 xaml 中定义它:

                     <CustomControls:ExpandableView>
                            <CustomControls:ExpandableView.Summary>
                                   <StackLayout>
                                    YOUR STUFF HERE 
                                </StackLayout>
                            </CustomControls:ExpandableView.Summary>
                            <CustomControls:ExpandableView.Details>
                                <StackLayout>
                                    YOUR STUFF HERE 
                                </StackLayout>
                            </CustomControls:ExpandableView.Details>
                        </CustomControls:ExpandableView>

CustomControls 是对 ExpandableView 所在的命名空间的引用。

您可以通过添加一些东西来进一步扩展它,例如展开时的动画、展开时突出显示“摘要区域”等...

【讨论】:

您介意给我写一些详细信息吗?我应该如何实现您的代码?第一个 XAML 应该在一个文件中正确吗? C# 代码应该在那个 XAML 视图的 CS 文件中?那么您提供的第二个 XAML 代码应该在哪里? 是的,因此您将拥有一个名为 ExpandableView.xaml 之类的 XAML 文件,其中包含第一个 sn-p,现在此 XAML 文件不是 ContentPage,而是“ContentView”。接下来,您将让 ExpandableView.xaml.cs 包含第二个 sn-p。然后在您的实际页面中,您将获得来自第三个 sn-p 的代码。您需要确保您的页面可以看到自定义控制文件。【参考方案2】:

在您的 APP 类中,添加标志以启用实验功能:

Device.SetFlags(new string[]  "Expander_Experimental" );

然后,你可以这样使用它:

<Expander>
<Expander.Header>
    <StackLayout>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="AUTO"/>
                <RowDefinition Height="AUTO"/>
                <RowDefinition Height="AUTO"/>
                <RowDefinition Height="AUTO"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Label Grid.Row="0" Text="One label" />
            <Label Grid.Row="1" Text="One label" />
            <Label Grid.Row="2" Text="One label" />

            <Label Grid.Row="0" Grid.Column="1" Text="123" />
            <Label Grid.Row="1" Grid.Column="1" Text="123" />
            <Label Grid.Row="2" Grid.Column="1" Text="123" />

            <Image x:Name="Your_Image_DropDown" Grid.Row="3" 
             Grid.ColumnSpan="2" Source="YOUR IMAGE LINK/SOURCE HERE" 
             HorizontalOptions="Center"/>


        </Grid>
    </StackLayout>
</Expander.Header>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="AUTO"/>
        <RowDefinition Height="AUTO"/>
        <RowDefinition Height="AUTO"/>
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <Label Grid.Row="0" Text="One label" />
    <Label Grid.Row="1" Text="One label" />
    <Label Grid.Row="2" Text="One label" />

    <Label Grid.Row="0" Grid.Column="1" Text="123" />
    <Label Grid.Row="1" Grid.Column="1" Text="123" />
    <Label Grid.Row="2" Grid.Column="1" Text="123" />

  </Grid>
  </Expander>

更多信息 https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/expander

【讨论】:

【参考方案3】:

将除 MoreDetails 之外的所有内容包装到另一个堆栈布局并将其命名为“TopLayout”

  void ShowMore()
    TopLayout.TranslateTo(0, -TopLayout.Bounds.Height, 300,  Easing.Linear);
    MoreDetails.LayoutTo(new Rectangle(0, 0, MoreDetails.Bounds.Width, MoreDetails.Bounds.Height + TopLayout.Bounds.Height), 300, Easing.Linear);
    

    void ShowLess()
    TopLayout.TranslateTo(0, 0, 300,  Easing.Linear);
    MoreDetails.LayoutTo(new Rectangle(0, MoreDetails.Bounds.Height, MoreDetails.Bounds.Width, MoreDetails.Bounds.Height - MoreDetails.Bounds.Height), 300, Easing.Linear);
    

100 - 这是你的位移值

作为奖励:

MoreLessImage.RotateXTo(180, Duration, TargetEasing); 

你可以像这样变形你的按钮来动画 ShowMore/ShowLess 图像

【讨论】:

抱歉,我可能做错了什么,但我粘贴了您的代码,但没有按预期工作。我的想法是删除(隐藏)较低的堆栈布局。 Btw Easing.None 在我的 Xamarin 表单版本中不存在,所以我使用的是 Linear。我也将所有主要内容包装在 StackLayout 中,所以我有 [StackLayout > StackLayout TopLayout AND St​​ackLayout ModerDetails] 感谢您的帮助,但无法编译,TranslateTo 采用此参数:double x, double y, uint length = 250, Easing easing = null。顺便说一句,您在 ShowMore 和 ShowLess 之后缺少“()” 是的,抱歉,为此,我正在实现完全相同的布局,并从内存中写入。已编辑 不走运。当无显示时,MoreDetails 面板会消失,但父级不会调整大小。在 showMore 上,MoreDetails 出现,但在 TopLayout 顶部滚动。 :( 你确定你调用的是正确的函数吗?尝试从 showMore 开始

以上是关于Xamarin Forms 可折叠 StackLayout的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xamarin Forms 中滚动时折叠(隐藏或向上滑动)导航栏(标题栏)?

Xamarin.Forms 可绑定属性

如何在 xamarin ios 项目中制作可展开和可折叠的表格视图

Xamarin android 分组通知未被可折叠摘要取代

Xamarin.forms - 如何在 MapView 上创建可拖动元素(标记)?

Xamarin.Forms - 如何使用可点击图像制作自定义视图?