windows phone开发学习--自己实现一个Gallery control

开发过android手机应用的人肯定对gallery control这个控件很熟悉,这个控件实现了几个屏幕之间的动态切换,也就是Andriod手机主页上那几页滑来滑去的效果。当然,windows phone上也有相应的东东,譬如panorama控件和pivot控件,但无奈这两个控件都不是gallery control控件的对应版,例如panorama永远会在右端显示那20像素,告诉人们右边还有内容,而pivot控件在滑动的时候页面会变成背景色而看不到一点东西,如果没有背景将会是黑乎乎的一片。这两者可能在别的场合用的很好,但却没有实现gallery control那种连续和渐进式的效果。既然不能生搬硬套,那只能自己实现windows phone版的gallery control了。

在stackoverflow上提问,无奈没有解答,用google搜,如大海捞针,好在功夫不负有心人,最终还是找到了一个国外大牛给出的解决方法。下面就详细说说如何自己实现gallery control。

首先给出效果,这里只有三个页面,无奈不能动态截图,这里只好看看静态的了:














从上面三个页面可以看到页面可以分为两个部分,上面是一个panoramatitle控件,底部就是类似于item的控件,不过这些控件都是需要自己实现,整个工程结构如下:



其中,panoramicTile控件布局如下:

<UserControl x:Class="PhoneApp1.PanoramicTitle"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="140" d:DesignWidth="1200">

    <Grid x:Name="LayoutRoot" Background="#FF1F1F1F">
        <TextBlock Style="{StaticResource PhoneTextPageTitle2Style}" Text="Panoramic title" />
    </Grid>
</UserControl>

windowsphoneControl1控件布局如下:

<UserControl x:Class="PhoneApp1.WindowsPhoneControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitleGrid is the name of the application and page title-->
        <Grid x:Name="TitleGrid" Grid.Row="0">
            <TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"/>
            <TextBlock Text="First page" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Style}"/>
        </Grid>

        <!--ContentGrid contains ListBox. Place additional content here-->
        <Grid x:Name="ContentGrid" Grid.Row="1">
                 <TextBlock Height="135" HorizontalAlignment="Left" Margin="6,6,0,0" Name="textBlock1" Text="This is the first page!" VerticalAlignment="Top" Width="468" />
        </Grid>
    </Grid>
</UserControl>

其他两个控件就是改了其中的textblock内容而已,这里不再赘述。


下面来说说最重要的mainpage, 其xaml页面如下:

<phone:PhoneApplicationPage 
    x:Class="PhoneApp1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    Loaded="PhoneApplicationPage_Loaded" xmlns:my="clr-namespace:PhoneApp1"
   >

    <UserControl.Resources>
        <Storyboard x:Name="PageChangeAnimation">
            <DoubleAnimation To="-480.0" SpeedRatio="4" Storyboard.TargetName="PanoramaContentTranslate" Storyboard.TargetProperty="X" />
            <DoubleAnimation x:Name="SlideTitleDoubleAnimation" SpeedRatio="4" Storyboard.TargetName="TitleTranslate" Storyboard.TargetProperty="X" />
        </Storyboard>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140" />
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Grid.Column="0" x:Name="TitlePanel">
            <StackPanel.RenderTransform>
                <TranslateTransform x:Name="TitleTranslate" />
            </StackPanel.RenderTransform>
        </StackPanel>

        <Grid x:Name="PanoramicGrid" Grid.Row="1" Grid.Column="0"
                        ManipulationDelta="PhoneApplicationPage_ManipulationDelta"
          ManipulationCompleted="PhoneApplicationPage_ManipulationCompleted" >
            <Grid.RenderTransform>
                <TranslateTransform x:Name="PanoramaContentTranslate" X="-480" Y="0" />
            </Grid.RenderTransform>
            <Grid.RowDefinitions>
                <RowDefinition />
            </Grid.RowDefinitions>

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

        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

可以看到其中定义了动画效果,滑动的依据是X轴方向上的偏移量,主页面是一个两行三列的grid,上面一行就是放panoramictitle控件的地方,下面三列分别对应三个windowsphonecontrol控件。

mainpage.xaml.cs代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

namespace PhoneApp1
{
    public partial class MainPage : PhoneApplicationPage
    {
        /// <summary>
        /// Size of the pages
        /// </summary>
        public const int PageWidth = 480;

        public MainPage()
        {

            //创建三个页面列表
            this.PageList = new List<UserControl>() 
                { 
                    new WindowsPhoneControl1() { IsEnabled = false }, 
                    new WindowsPhoneControl2() { IsEnabled = false }, 
                    new WindowsPhoneControl3() { IsEnabled = false } 
                };
            
            this.CurrentPageIndex = 0;

            InitializeComponent();

            SupportedOrientations = SupportedPageOrientation.Portrait;
        }

        /// <summary>
        /// Ordered list of the panorama pages
        /// </summary>
        protected List<UserControl> PageList { get; set; }

        /// <summary>
        /// Index of the page currently displayed
        /// </summary>
        protected int CurrentPageIndex { get; set; }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            var frame = (PhoneApplicationFrame)Application.Current.RootVisual;
            frame.Width = PageWidth * 3;

            //载入panoramictitle控件
            var title = new PanoramicTitle();

            this.TitlePanel.Children.Add(title);

            this.LoadPages();
        }

        private void LoadPages()
        {
            this.PanoramicGrid.Children.Clear();

            //滑倒第一页再向左滑动
            if (CurrentPageIndex == -1)
            {
                CurrentPageIndex = 2;
            }

            //滑倒第三页再向右滑动
            if (CurrentPageIndex == 3)
            {
                CurrentPageIndex = 0;
            }

            var currentPage = this.PageList[this.CurrentPageIndex];
            currentPage.IsEnabled = true;

            this.PanoramicGrid.Children.Add(currentPage);

            Grid.SetColumn(currentPage, 1);
            Grid.SetRow(currentPage, 1);

            if (this.PageList.Count > this.CurrentPageIndex + 1)
            {
                var nextPage = this.PageList[this.CurrentPageIndex + 1];
                nextPage.IsEnabled = false;

                this.PanoramicGrid.Children.Add(nextPage);

                Grid.SetColumn(nextPage, 2);
                Grid.SetRow(nextPage, 1);
            }

            if (this.CurrentPageIndex > 0)
            {
                var previousPage = this.PageList[this.CurrentPageIndex - 1];
                previousPage.IsEnabled = false;

                this.PanoramicGrid.Children.Add(previousPage);

                Grid.SetColumn(previousPage, 0);
                Grid.SetRow(previousPage, 1);
            }
        }

        private void PhoneApplicationPage_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            if (e.OriginalSource is Panel)
            {
                if (e.TotalManipulation.Translation.X < 0)
                {
                    if (e.TotalManipulation.Translation.X > -100 /*|| this.CurrentPageIndex >= this.PageList.Count - 1*/)
                    {
                        this.SlideTitleDoubleAnimation.To = this.CurrentPageIndex * PageWidth / 2 * -1;
                        this.PageChangeAnimation.Begin();
                    }
                    else
                    {
                        this.ChangePage(1);
                    }
                }
                else if (e.TotalManipulation.Translation.X > 0)
                {
                    if (e.TotalManipulation.Translation.X < 100 )
                    {
                        this.SlideTitleDoubleAnimation.To = this.CurrentPageIndex * PageWidth / 2 * -1;
                        this.PageChangeAnimation.Begin();
                    }
                    else
                    {
                        this.ChangePage(-1);
                    }
                }
            }
        }

        private void ChangePage(int step)
        {
            this.CurrentPageIndex += step;

            this.LoadPages();

            this.PanoramaContentTranslate.X += PageWidth * step;

            this.SlideTitleDoubleAnimation.To = this.CurrentPageIndex * PageWidth / 2 * -1;

            this.PageChangeAnimation.Begin();
        }

        private void PhoneApplicationPage_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            if (e.OriginalSource is Panel)
            {
                this.PanoramaContentTranslate.X = e.CumulativeManipulation.Translation.X - PageWidth;

                this.TitleTranslate.X = e.CumulativeManipulation.Translation.X / 2 - (this.CurrentPageIndex * PageWidth / 2);
            }
        }
    }
}

这里首先把三个控件加载到页面列表中,通过判断当前页面索引来选择当前页面,下一个页面,前一个页面分别是什么,并且将它们放到grid的三列中去。至于动画效果,可以从最后两个函数看出,确实是使用X轴的偏移量来调整的,用户自己也可以进一步调整效果。



以上就是在windows phone上实现Android gallery control的实现过程,不知道微软以后会不会对pivot控件进行改进,这样就可以直接用而不用那么费事了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值