شاشة تقديمية (splash screen) أفضل لبرامج windows phone 7

من منا لم تواجهه مشكلة عند جعل الشاشة التقديمية تظهر في الصفحة الأولى!، المشكلة ليست في التجريب، ولكن المشكلة ستظهر حينما تجرب مايكروسوفت تطبيقاتك قبل نشرها، لذلك ساحاول هنا عرض كيف يمكنك أن استبدال الشاشة التقديمية الاعتيادية بواحدة أفضل بكثير.

وكما نعلم فإن فريق مايكروسوفت يقوم بفحص التطبيقات قبل قبولها في السوق ، وهناك بعض الشروط التي يجب أن تتحقق في التطبيقات لقبولها ، أهمها هي عند ضغط المستخدم في الشاشة الأولى للبرنامج لزر الرجوع يجب أن يخرج من البرنامج وهذا لن يحدث إن كنت ستستخدم الشاشة التقديمية الاعتيادية حيث ستظهر الشاشة التقديمية له

وأيضا سوف أعرض كيفية إضافة شريط تحميل ( progressbar) لإعطاء البرنامج شيئا من الحركة والتفاعل

,تحميل المشروع جاهز وبه مكتبة العمل

في البداية أنشئ مشروع جديد وبعد ذلك أنشئ صفحة جديدة بعنوان MySplash.xaml

الآن أضف مرجع reference لفضاء الأسماء System.Windows.Controls.Primitives وهو System.Windows.Controls

وبعد ذلك أضف شريط التحميل (progressbar) للصفحة ، وقد قمت بإنشاء مكتبة DLL لأوفر عليك كتابة الكود وهي باسم Libs_ProgressTempCSharp وموجودة في ملفات الكود المرفقة ويمكنك إضافتها من add reference

وبعدها قم بفتح صفحة التطبيق العامة (App.xaml) واستدعي المكتبة بالشكل التالي :

xmlns:unsupported="clr-namespace:Microsoft.Phone.Controls.Unsupported"    

وبعد ذلك أضف هذه الوسوم بداخل وسم Application.Resources

      <Application.Resources>            
<Style x:Key="PerformanceProgressBar" TargetType="ProgressBar">
<Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="Background" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="Maximum" Value="100"/>
 <Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="Padding" Value="{StaticResource PhoneHorizontalMargin}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<unsupported:RelativeAnimatingContentControl HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
 <unsupported:RelativeAnimatingContentControl.Resources>
<ExponentialEase EasingMode="EaseOut" Exponent="1" x:Key="ProgressBarEaseOut"/>
<ExponentialEase EasingMode="EaseOut" Exponent="1" x:Key="ProgressBarEaseIn"/> </unsupported:RelativeAnimatingContentControl.Resources>
 <VisualStateManager.VisualStateGroups>
 <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate"/>
 <VisualState x:Name="Indeterminate">
 <Storyboard RepeatBehavior="Forever" Duration="00:00:04.4">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="IndeterminateRoot">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
 </DiscreteObjectKeyFrame.Value>
 </DiscreteObjectKeyFrame>
 </ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DeterminateRoot">
<DiscreteObjectKeyFrame KeyTime="0">
 <DiscreteObjectKeyFrame.Value>
 <Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.0" Storyboard.TargetProperty="X" Storyboard.TargetName="R1TT">
 <LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2" Storyboard.TargetProperty="X" Storyboard.TargetName="R2TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
 <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetProperty="X" Storyboard.TargetName="R3TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
 <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
 <LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
 <EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
 </DoubleAnimationUsingKeyFrames>
 <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.6" Storyboard.TargetProperty="X" Storyboard.TargetName="R4TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
 <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
<LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
 <EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
 </DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.8" Storyboard.TargetProperty="X" Storyboard.TargetName="R5TT">
<LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
 <LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
 </DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R1">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
 </DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R2">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R3">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
 <DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
 </DoubleAnimationUsingKeyFrames>
 <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.6" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R4">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
 <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.8" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R5">
<DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
 </Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
 <Grid>
<Grid x:Name="DeterminateRoot" Margin="{TemplateBinding Padding}" Visibility="Visible">
<Rectangle x:Name="ProgressBarTrack" Fill="{TemplateBinding Background}" Height="4" Opacity="0.1"/>
<Rectangle x:Name="ProgressBarIndicator" Fill="{TemplateBinding Foreground}" HorizontalAlignment="Left" Height="4"/> </Grid>
<Border x:Name="IndeterminateRoot" Margin="{TemplateBinding Padding}" Visibility="Collapsed">
 <Grid HorizontalAlignment="Left">
<Rectangle Fill="{TemplateBinding Foreground}" Height="6" IsHitTestVisible="False" Width="6" x:Name="R1" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="R1TT"/>
 </Rectangle.RenderTransform> </Rectangle>
<Rectangle Fill="{TemplateBinding Foreground}" Height="6" IsHitTestVisible="False" Width="6" x:Name="R2" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="R2TT"/>
</Rectangle.RenderTransform> </Rectangle>
<Rectangle Fill="{TemplateBinding Foreground}" Height="6" IsHitTestVisible="False" Width="6" x:Name="R3" Opacity="0" CacheMode="BitmapCache"> <Rectangle.RenderTransform>
<TranslateTransform x:Name="R3TT"/>
 </Rectangle.RenderTransform> </Rectangle>
<Rectangle Fill="{TemplateBinding Foreground}" Height="6" IsHitTestVisible="False" Width="6" x:Name="R4" Opacity="0" CacheMode="BitmapCache">
<Rectangle.RenderTransform>
 <TranslateTransform x:Name="R4TT"/>
 </Rectangle.RenderTransform> </Rectangle>
 <Rectangle Fill="{TemplateBinding Foreground}" Height="6" IsHitTestVisible="False" Width="6" x:Name="R5" Opacity="0" CacheMode="BitmapCache"> <Rectangle.RenderTransform>
<TranslateTransform x:Name="R5TT"/>
 </Rectangle.RenderTransform> </Rectangle>
 </Grid> </Border> </Grid>
</unsupported:RelativeAnimatingContentControl>
</ControlTemplate>
 </Setter.Value>
</Setter>
 </Style>
</Application.Resources>

حاول ترتيب وتزيين شاشتك التقديمية بالطريقة التي تحبها ( أنا قمت باستخدام أبسط طريقة ) ، أضف أداة شريط التحميل ( progressbar) ، واختر لون لها ولا تنسى استخدام التنسيق الخاص بها :

<ProgressBar x:Name="DownloadProgress" IsIndeterminate="False"    Style="{StaticResource PerformanceProgressBar}" Margin="0,347,7,173" />    

أيضا لا تنسى إسناد القيمة true للخاصية IsIndeterminate الخاصة بالأداة progressbar في حدث تحميل الصفحة بالشكل التالي:

this.DownloadProgress.IsIndeterminate = true;    

إلى الآن لم نقم بعمل أي شيء جديد ، اجعل الصفحة الأخرى ( ليست صفحة MySplash.xaml) هي الصفحة الافتراضية ( DefaultTask) ، بالتأكيد ستقوم بتغييرها من ملف WMAppManifest.xml وهنا قمت باستدعاء صفحة [ MainPage.xaml ]

قم بفتح الصفحة  MainPage واستدعاء فضاء الأسماء التالية :

  using System.Threading; using System.Windows.Controls.Primitives;    

وفضاء الأسماء الأول يحتوي على فئة BackgroundWorker  التي تستخدم لل multithreading وهي تستخدم لإراحة ال thread في الوقت الذي تريده

والثاني يحتوي على أداة popup وهي مسؤولة عن إظهار الصفحة أو ال usercontrol أو أي قطعة في الصفحة الحالية

الآن لنكتب الكود:

ضع هذا الكود بداخل الفئة

    Popup Mypopup = new Popup() { IsOpen = true, Child = new MySplash() };
BackgroundWorker MybackroungWorker=new BackgroundWorker();

أنا استخدمت object initializer لل popup ثم أسندت قيمة true للمتغير IsOpen وهناك شيء آخر مهم وهو إسناد اسم لعنصر child ( وهي هنا الشاشة التقديمية MySplash ) ، ولاحظ أنه يجب استدعاء اسم فئة الصفحة وليس اسم الصفحة نفسها

             private void PopupView()
 {
 MybackroungWorker.DoWork += ((s, args) =>< {
 Thread.Sleep(4000); // time here });
 MybackroungWorker.RunWorkerCompleted += ((s, args) =>
 { this.Dispatcher.BeginInvoke(() =>
 {
 this.Mypopup.IsOpen = false;
 }
 ); }); MybackroungWorker.RunWorkerAsync(); }

هذه الدالة تدعى popup ، اجعل وقت ال backgroundworker أن يوقف ال thread بواسطة دالة Thread.Sleep() ، فهي تأخذ قيمة الوسيط بأجزاء الألف من الثانية وهنا 4 ثواني ( 4000 جزء من الألف من الثانية )

الان تحتاج لإستدعاء الدالة وأنا أفضل أن تستدعيها من خلال مشيد

     PopupView();    

بقي أمر واحد وهو عند الضفط على زر الرجوع ، سيتم ظهور هذه ال popup ، لذلك قمت بعمل متغير عام من خلاله يتم فحص هل تم ظهور الشاشة التقديمية أم لا ، ويمكن وضع هذا المتغير في فئة بالشكل التالي:

                public class General              {             public static bool IsOpen = false;             
}

فحص العملية قبل استدعاء الدالة

  if (General.IsOpen==false)

الشي المذهل يكمن في شيفرة فئة Popup انه يمكنك استخدامها في مواضع عدة ، حيث ستعطي برنامجك تأثيرا جميلا، على سبيل المثال يمكن ان تستخدمها لإظهار معلومات حول برنامجك ويمكن أن تخفيها عند ضغط المستخدم عليها... وغيرها الكثير فهذا الأمر سيعتمد على احتياجات البرنامج لديك ، وأنا سأترك لك حرية التفكير والابداع

About the author

خليل سليم

Leave a Comment

هذا الموقع يستخدم Akismet للحدّ من التعليقات المزعجة والغير مرغوبة. تعرّف على كيفية معالجة بيانات تعليقك.