windows phone開發學習–自己實現一個Gallery control

來源:互聯網
上載者:User

開發過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控制項進行改進,這樣就可以直接用而不用那麼費事了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.