简体   繁体   English

Xamarin 表单可折叠 StackLayout

[英]Xamarin Forms Collapsable StackLayout

I'm trying to implement a kind of collapsable StackLayout.我正在尝试实现一种可折叠的 StackLayout。 Every tine the user clicks the button, it expands or collapse the stacklayout to show/hide more details.用户点击按钮的每一刻,它都会展开或折叠堆栈布局以显示/隐藏更多细节。

在此处输入图片说明

I was able to achieve more/less this with the code below, but it doesn't look right and the effect isn't great, because it grows immediately and I'm applying the effect to other element.我可以使用下面的代码实现更多/更少的效果,但它看起来不正确并且效果也不是很好,因为它会立即增长并且我正在将效果应用于其他元素。

Do you have any suggestions to do this, I'm using xamarin Forms?你有什么建议可以做到这一点,我正在使用 xamarin Forms?

XAML 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>

Code代码

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;
}

You can create a Custom control that does this for you.您可以创建一个为您执行此操作的自定义控件。 If you create an 'ExpandableView' Content View with Xaml like:如果您使用 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>

And wire up the .cs class like so:并像这样连接 .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;
        }
    }

And define it in your xaml like so:并在您的 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>

Where CustomControls is the reference to namespace where the ExpandableView exists.其中 CustomControls 是对存在 ExpandableView 的命名空间的引用。

You can expand this further by adding things such as animations on expand, highlight the 'Summary Region' when expanded etc...您可以通过添加诸如展开时的动画、展开时突出显示“摘要区域”等内容来进一步扩展它...

In your APP class, add flag to enable experimental feature:在您的 APP 类中,添加标志以启用实验性功能:

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

Then, you can use it like this:然后,您可以像这样使用它:

<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>

For more information https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/expander有关更多信息https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/expander

Wrap your everything but MoreDetails to another stack layout and name it "TopLayout"将除 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 - here is your displacement value 100 - 这是你的位移值

As a bonus:作为奖励:

MoreLessImage.RotateXTo(180, Duration, TargetEasing); 

you can morph your button like this to animate ShowMore/ShowLess image你可以像这样改变你的按钮来动画 ShowMore/ShowLess 图像

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM