file360

Log | Files | Refs

DrawerLayout.cs (20856B)


      1 using System;
      2 using System.Linq;
      3 using System.Windows;
      4 using Windows.Foundation;
      5 using Windows.UI;
      6 using Windows.UI.Xaml;
      7 using Windows.UI.Xaml.Controls;
      8 using Windows.UI.Xaml.Input;
      9 using Windows.UI.Xaml.Media;
     10 using Windows.UI.Xaml.Media.Animation;
     11 
     12 namespace File360
     13 {
     14     public class DrawerLayout : Grid
     15     {
     16         #region Globals and events
     17         private readonly PropertyPath _translatePath = new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)");
     18         private readonly PropertyPath _colorPath = new PropertyPath("(Grid.Background).(SolidColorBrush.Color)");
     19 
     20         private readonly TranslateTransform _listFragmentTransform = new TranslateTransform();
     21         private readonly TranslateTransform _deltaTransform = new TranslateTransform();
     22         private const int MaxAlpha = 190;
     23 
     24         public delegate void DrawerEventHandler(object sender);
     25         public event DrawerEventHandler DrawerOpened;
     26         public event DrawerEventHandler DrawerClosed;
     27 
     28         private Storyboard _fadeInStoryboard;
     29         private Storyboard _fadeOutStoryboard;
     30         private Grid _listFragment;
     31         private Grid _mainFragment;
     32         private Grid _shadowFragment;
     33         private double grabCornerLeft = 40;
     34         #endregion
     35 
     36         #region Properties
     37 
     38         public bool IsDrawerOpen { get; set; }
     39         private PropertyPath TranslatePath
     40         {
     41             get { return _translatePath; }
     42         }
     43         private PropertyPath ColorPath
     44         {
     45             get { return _colorPath; }
     46         }
     47 
     48         #endregion
     49 
     50         #region Methods
     51 
     52         public DrawerLayout()
     53         {
     54             IsDrawerOpen = false;
     55         }
     56 
     57         public void InitializeDrawerLayout()
     58         {
     59             if (Children == null) return;
     60             if (Children.Count < 2) return;
     61 
     62             try
     63             {
     64                 _mainFragment = Children.OfType<Grid>().ElementAt(1);
     65                 _listFragment = Children.OfType<Grid>().ElementAt(2);
     66             }
     67             catch (Exception)
     68             {
     69                 //ShowStatus(ex.Message);
     70                 return;
     71             }
     72 
     73             if (_mainFragment == null || _listFragment == null) return;
     74 
     75             _mainFragment.Name = "_mainFragment";
     76             _listFragment.Name = "_listFragment";
     77 
     78             // _mainFragment
     79             _mainFragment.HorizontalAlignment = HorizontalAlignment.Left;
     80             _mainFragment.VerticalAlignment = VerticalAlignment.Stretch;
     81 
     82             // Render transform _listFragment
     83             _listFragment.HorizontalAlignment = HorizontalAlignment.Left;
     84             _listFragment.VerticalAlignment = VerticalAlignment.Stretch;
     85             _listFragment.Width = Window.Current.Bounds.Width > Window.Current.Bounds.Height ? (Window.Current.Bounds.Height * 2) / 3 : (Window.Current.Bounds.Width * 2) / 3;
     86             if (_listFragment.Background == null) _listFragment.Background = new SolidColorBrush(Color.FromArgb(40, 46, 46, 46));
     87 
     88             var animatedTranslateTransform = new TranslateTransform { X = -_listFragment.Width - 200, Y = 0 };
     89 
     90             _listFragment.RenderTransform = animatedTranslateTransform;
     91             _listFragment.RenderTransformOrigin = new Point(0.5, 0.5);
     92 
     93             _listFragment.UpdateLayout();
     94 
     95 
     96             // Create a shadow element
     97             _shadowFragment = new Grid
     98             {
     99                 Name = "_shadowFragment",
    100                 Background = new SolidColorBrush(Color.FromArgb(0, 255, 255, 255)),
    101                 HorizontalAlignment = HorizontalAlignment.Stretch,
    102                 VerticalAlignment = VerticalAlignment.Stretch,
    103                 Visibility = Visibility.Collapsed
    104             };
    105 
    106             // Set ZIndexes
    107             Canvas.SetZIndex(_shadowFragment, 49);
    108             Canvas.SetZIndex(_listFragment, 51);
    109             Children.Add(_shadowFragment);
    110 
    111             // Create a new fadeIn animation storyboard
    112             _fadeInStoryboard = new Storyboard();
    113 
    114             // New double animation
    115             var doubleAnimation1 = new DoubleAnimation
    116             {
    117                 Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
    118                 To = 0
    119             };
    120 
    121             Storyboard.SetTarget(doubleAnimation1, _listFragment);
    122             Storyboard.SetTargetProperty(doubleAnimation1, TranslatePath.Path);
    123             _fadeInStoryboard.Children.Add(doubleAnimation1);
    124 
    125             // New color animation for _shadowFragment
    126             var colorAnimation1 = new ColorAnimation
    127             {
    128                 Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
    129                 To = Color.FromArgb(190, 0, 0, 0)
    130             };
    131 
    132             Storyboard.SetTarget(colorAnimation1, _shadowFragment);
    133             Storyboard.SetTargetProperty(colorAnimation1, ColorPath.Path);
    134             _fadeInStoryboard.Children.Add(colorAnimation1);
    135 
    136             // Create a new fadeOut animation storyboard
    137             _fadeOutStoryboard = new Storyboard();
    138 
    139             // New double animation
    140             var doubleAnimation2 = new DoubleAnimation
    141             {
    142                 Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
    143                 To = -_listFragment.Width - 200
    144             };
    145 
    146             Storyboard.SetTarget(doubleAnimation2, _listFragment);
    147             Storyboard.SetTargetProperty(doubleAnimation2, TranslatePath.Path);
    148             _fadeOutStoryboard.Children.Add(doubleAnimation2);
    149 
    150             // New color animation for _shadowFragment
    151             var colorAnimation2 = new ColorAnimation
    152             {
    153                 Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
    154                 To = Color.FromArgb(0, 0, 0, 0)
    155             };
    156 
    157             Storyboard.SetTarget(colorAnimation2, _shadowFragment);
    158             Storyboard.SetTargetProperty(colorAnimation2, ColorPath.Path);
    159             _fadeOutStoryboard.Children.Add(colorAnimation2);
    160 
    161 
    162             _mainFragment.ManipulationMode = ManipulationModes.TranslateX;
    163             _mainFragment.ManipulationStarted += mainFragment_ManipulationStarted;
    164 
    165             _listFragment.ManipulationMode = ManipulationModes.TranslateX;
    166             _listFragment.ManipulationStarted += listFragment_ManipulationStarted;
    167 
    168             _shadowFragment.ManipulationMode = ManipulationModes.TranslateX;
    169             _shadowFragment.ManipulationStarted += shadowFragment_ManipulationStarted;
    170 
    171             _shadowFragment.Tapped += shadowFragment_Tapped;
    172 
    173         }
    174 
    175 
    176         public void OpenDrawer()
    177         {
    178             if (_fadeInStoryboard == null || _mainFragment == null || _listFragment == null) return;
    179             _shadowFragment.Visibility = Visibility.Visible;
    180             _shadowFragment.IsHitTestVisible = true;
    181             _fadeInStoryboard.Begin();
    182             IsDrawerOpen = true;
    183 
    184             if (DrawerOpened != null)
    185                 DrawerOpened(this);
    186         }
    187         public void CloseDrawer()
    188         {
    189             if (_fadeOutStoryboard == null || _mainFragment == null || _listFragment == null) return;
    190             _fadeOutStoryboard.Begin();
    191             _fadeOutStoryboard.Completed += fadeOutStoryboard_Completed;
    192             IsDrawerOpen = false;
    193 
    194             if (DrawerClosed != null)
    195                 DrawerClosed(this);
    196         }
    197         private void shadow_Completed(object sender, object e)
    198         {
    199             _shadowFragment.IsHitTestVisible = false;
    200             _shadowFragment.Visibility = Visibility.Collapsed;
    201             IsDrawerOpen = false;
    202 
    203             // raise close event
    204             if (DrawerClosed != null) DrawerClosed(this);
    205         }
    206         private void fadeOutStoryboard_Completed(object sender, object e)
    207         {
    208             _shadowFragment.Visibility = Visibility.Collapsed;
    209             IsDrawerOpen = false;
    210             if (DrawerClosed != null) DrawerClosed(this);
    211         }
    212         private void MoveListFragment(double left, Color color)
    213         {
    214             var s = new Storyboard();
    215 
    216             var doubleAnimation = new DoubleAnimation
    217             {
    218                 Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
    219                 To = left
    220             };
    221 
    222             Storyboard.SetTarget(doubleAnimation, _listFragment);
    223             Storyboard.SetTargetProperty(doubleAnimation, TranslatePath.Path);
    224             s.Children.Add(doubleAnimation);
    225 
    226             var colorAnimation = new ColorAnimation { Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)), To = color };
    227 
    228             Storyboard.SetTarget(colorAnimation, _shadowFragment);
    229             Storyboard.SetTargetProperty(colorAnimation, ColorPath.Path);
    230             s.Children.Add(colorAnimation);
    231 
    232             s.Begin();
    233         }
    234         private void FadeShadowFragment(double left)
    235         {
    236             // Show shadow fragment
    237             _shadowFragment.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
    238             _shadowFragment.Visibility = Visibility.Visible;
    239 
    240             // Set bg color based on current _listFragment position.
    241             var maxLeft = _listFragment.ActualWidth;
    242             var currentLeft = maxLeft - left;
    243 
    244             var temp = Convert.ToInt32((currentLeft / maxLeft) * MaxAlpha);
    245 
    246             // Limit temp variable to 190 to avoid OverflowException
    247             if (temp > MaxAlpha) temp = MaxAlpha;
    248 
    249             byte alphaColorIndex;
    250             try
    251             {
    252                 alphaColorIndex = Convert.ToByte(MaxAlpha - temp);
    253             }
    254             catch
    255             {
    256                 alphaColorIndex = 0;
    257             }
    258 
    259             _shadowFragment.Background = new SolidColorBrush(Color.FromArgb(alphaColorIndex, 0, 0, 0));
    260         }
    261 
    262         #endregion
    263 
    264 
    265         #region Main fragment manipulation events
    266 
    267         private void mainFragment_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
    268         {
    269             // If the user has the first touch on the left side of canvas, that means he's trying to swipe the drawer
    270             if (e.Position.X <= grabCornerLeft)
    271             {
    272                 //Manipulation can be allowed
    273                 _mainFragment.ManipulationDelta += mainFragment_ManipulationDelta;
    274                 _mainFragment.ManipulationCompleted += mainFragment_ManipulationCompleted;
    275             }
    276         }
    277         private void mainFragment_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
    278         {
    279             if (Math.Abs(e.Cumulative.Translation.X) > 0 && e.Cumulative.Translation.X <= _listFragment.Width)
    280             {
    281                 _deltaTransform.X = -_listFragment.Width + e.Cumulative.Translation.X;
    282                 _listFragment.RenderTransform = _deltaTransform;
    283                 FadeShadowFragment(e.Cumulative.Translation.X);
    284                 //ShowStatus(e.Cumulative.Translation.X.ToString());
    285             }
    286             //if ()
    287             //{
    288             //    //mainFragment_ManipulationCompleted(this, null);
    289             //    return;
    290             //}
    291 
    292         }
    293         private void mainFragment_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
    294         {
    295             // Get left of _listFragment
    296             var transform = (TranslateTransform)_listFragment.RenderTransform;
    297             if (transform == null) return;
    298             var left = transform.X;
    299 
    300             // Set snap divider to 1/20 of _mainFragment width
    301             var snapLimit = _mainFragment.ActualWidth / 20;
    302 
    303             // Get init position of _listFragment
    304             var initialPosition = -_listFragment.Width;
    305 
    306             // If current left coordinate is smaller than snap limit, close drawer
    307             if (Math.Abs(initialPosition - left) < snapLimit + 50)
    308             {
    309                 MoveListFragment(initialPosition, Color.FromArgb(0, 0, 0, 0));
    310                 _shadowFragment.Visibility = Visibility.Collapsed;
    311                 _shadowFragment.IsHitTestVisible = false;
    312 
    313                 _mainFragment.ManipulationDelta -= mainFragment_ManipulationDelta;
    314                 _mainFragment.ManipulationCompleted -= mainFragment_ManipulationCompleted;
    315                 IsDrawerOpen = false;
    316 
    317                 // raise DrawerClosed event
    318                 if (DrawerClosed != null) DrawerClosed(this);
    319             }
    320             // else open drawer
    321             else if (Math.Abs(initialPosition - left) > snapLimit)
    322             {
    323                 // move drawer to zero
    324                 MoveListFragment(0, Color.FromArgb(190, 0, 0, 0));
    325                 _shadowFragment.Visibility = Visibility.Visible;
    326                 _shadowFragment.IsHitTestVisible = true;
    327                 _mainFragment.ManipulationDelta -= mainFragment_ManipulationDelta;
    328                 _mainFragment.ManipulationCompleted -= mainFragment_ManipulationCompleted;
    329                 IsDrawerOpen = true;
    330 
    331                 // raise DrawerClosed event
    332                 if (DrawerOpened != null) DrawerOpened(this);
    333             }
    334         }
    335 
    336         #endregion
    337 
    338         #region List Fragment manipulation events
    339 
    340         private void listFragment_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
    341         {
    342             var listWidth = _listFragment.Width;
    343             if (e.Position.X >= listWidth) return;
    344             _listFragment.ManipulationDelta += listFragment_ManipulationDelta;
    345             _listFragment.ManipulationCompleted += listFragment_ManipulationCompleted;
    346         }
    347         private void listFragment_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
    348         {
    349             if (e.Cumulative.Translation.X <= -_listFragment.Width)
    350             {
    351                 listFragment_ManipulationCompleted(this, null);
    352                 return;
    353             }
    354             else if (_listFragmentTransform.X >= 0 && e.Delta.Translation.X > 0)
    355             {
    356                 listFragment_ManipulationCompleted(this, null);
    357                 return;
    358             }
    359             _listFragmentTransform.X = e.Cumulative.Translation.X;
    360             _listFragment.RenderTransform = _listFragmentTransform;
    361             FadeShadowFragment(e.Cumulative.Translation.X + _listFragment.Width);
    362         }
    363         private void listFragment_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
    364         {
    365             // Get left of _listFragment
    366             var transform = (TranslateTransform)_listFragment.RenderTransform;
    367             if (transform == null) return;
    368             var left = transform.X;
    369 
    370             // Set snap divider to 1/4 of _mainFragment height
    371             var snapLimit = _mainFragment.ActualHeight / 4;
    372 
    373             // Get init position of _listFragment
    374             const int initialPosition = 0;
    375 
    376             // If current left coordinate is smaller than snap limit, close drawer
    377             if (Math.Abs(initialPosition - left) > snapLimit)
    378             {
    379                 MoveListFragment(-_listFragment.Width, Color.FromArgb(0, 0, 0, 0));
    380                 _shadowFragment.Visibility = Visibility.Collapsed;
    381                 _shadowFragment.IsHitTestVisible = false;
    382                 _shadowFragment.ManipulationDelta -= listFragment_ManipulationDelta;
    383 
    384                 _listFragment.ManipulationDelta -= listFragment_ManipulationDelta;
    385                 _listFragment.ManipulationCompleted -= listFragment_ManipulationCompleted;
    386                 IsDrawerOpen = false;
    387 
    388                 // raise DrawerClosed event
    389                 if (DrawerClosed != null) DrawerClosed(this);
    390             }
    391             // else open drawer
    392             else if (Math.Abs(initialPosition - left) < snapLimit)
    393             {
    394                 // move drawer to zero
    395                 MoveListFragment(0, Color.FromArgb(190, 0, 0, 0));
    396                 _shadowFragment.Visibility = Visibility.Visible;
    397                 _shadowFragment.IsHitTestVisible = true;
    398                 _shadowFragment.ManipulationDelta += listFragment_ManipulationDelta;
    399 
    400                 _listFragment.ManipulationDelta -= listFragment_ManipulationDelta;
    401                 _listFragment.ManipulationCompleted -= listFragment_ManipulationCompleted;
    402                 IsDrawerOpen = true;
    403 
    404                 // raise Drawer_Open event
    405                 if (DrawerOpened != null) DrawerOpened(this);
    406             }
    407         }
    408 
    409         #endregion
    410         #region Shadow fragment manipulation events
    411         private void shadowFragment_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
    412         {
    413             if (e.Cumulative.Translation.X > 0) return;
    414             _shadowFragment.ManipulationDelta += _shadowFragment_ManipulationDelta;
    415             _shadowFragment.ManipulationCompleted += _shadowFragment_ManipulationCompleted;
    416         }
    417 
    418         private void _shadowFragment_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
    419         {
    420             if (e.Cumulative.Translation.X <= -_listFragment.Width)
    421             {
    422                 _shadowFragment_ManipulationCompleted(this, null);
    423                 return;
    424             }
    425             else if (_listFragmentTransform.X >= 0 && e.Delta.Translation.X > 0)
    426             {
    427                 _shadowFragment_ManipulationCompleted(this, null);
    428                 return;
    429             }
    430             _listFragmentTransform.X = e.Cumulative.Translation.X;
    431             _listFragment.RenderTransform = _listFragmentTransform;
    432             FadeShadowFragment(e.Cumulative.Translation.X + _listFragment.Width);
    433 
    434         }
    435         private void _shadowFragment_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
    436         {
    437             // Get left of _listFragment
    438             var transform = (TranslateTransform)_listFragment.RenderTransform;
    439             if (transform == null) return;
    440             var left = transform.X;
    441 
    442             // Set snap divider to 1/4 of _mainFragment height
    443             var snapLimit = _mainFragment.ActualHeight / 4;
    444 
    445             // Get init position of _listFragment
    446             const int initialPosition = 0;
    447 
    448             // If current left coordinate is smaller than snap limit, close drawer
    449             if (Math.Abs(initialPosition - left) > snapLimit)
    450             {
    451                 MoveListFragment(-_listFragment.Width, Color.FromArgb(0, 0, 0, 0));
    452 
    453                 _shadowFragment.Visibility = Visibility.Collapsed;
    454                 _shadowFragment.IsHitTestVisible = false;
    455                 _shadowFragment.ManipulationDelta -= _shadowFragment_ManipulationDelta;
    456                 _shadowFragment.ManipulationCompleted -= _shadowFragment_ManipulationCompleted;
    457 
    458                 _listFragment.ManipulationDelta -= listFragment_ManipulationDelta;
    459                 _listFragment.ManipulationCompleted -= listFragment_ManipulationCompleted;
    460 
    461                 IsDrawerOpen = false;
    462 
    463                 // raise DrawerClosed event
    464                 if (DrawerClosed != null) DrawerClosed(this);
    465             }
    466             // else open drawer
    467             else if (Math.Abs(initialPosition - left) < snapLimit)
    468             {
    469                 // move drawer to zero
    470                 MoveListFragment(0, Color.FromArgb(190, 0, 0, 0));
    471 
    472                 _shadowFragment.Visibility = Visibility.Visible;
    473                 _shadowFragment.IsHitTestVisible = true;
    474                 _shadowFragment.ManipulationDelta -= _shadowFragment_ManipulationDelta;
    475                 _shadowFragment.ManipulationCompleted -= _shadowFragment_ManipulationCompleted;
    476 
    477                 _listFragment.ManipulationDelta -= listFragment_ManipulationDelta;
    478                 _listFragment.ManipulationCompleted -= listFragment_ManipulationCompleted;
    479 
    480                 IsDrawerOpen = true;
    481 
    482                 // raise Drawer_Open event
    483                 if (DrawerOpened != null) DrawerOpened(this);
    484             }
    485         }
    486 
    487         private void shadowFragment_Tapped(object sender, TappedRoutedEventArgs e)
    488         {
    489             var shadow = new Storyboard();
    490 
    491             var doubleAnimation = new DoubleAnimation
    492             {
    493                 Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
    494                 To = -_listFragment.Width - 200
    495             };
    496 
    497             Storyboard.SetTarget(doubleAnimation, _listFragment);
    498             Storyboard.SetTargetProperty(doubleAnimation, TranslatePath.Path);
    499             shadow.Children.Add(doubleAnimation);
    500 
    501             var colorAnimation = new ColorAnimation
    502             {
    503                 Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200)),
    504                 To = Color.FromArgb(0, 0, 0, 0)
    505             };
    506 
    507             Storyboard.SetTarget(colorAnimation, _shadowFragment);
    508             Storyboard.SetTargetProperty(colorAnimation, ColorPath.Path);
    509             shadow.Children.Add(colorAnimation);
    510 
    511             shadow.Completed += shadow_Completed;
    512             shadow.Begin();
    513             _shadowFragment.IsHitTestVisible = false;
    514         }
    515         #endregion
    516         //#region ShowStatus
    517         //public void ShowStatus(string info)
    518         //{
    519         //    rootPage.NotifyUser(info);
    520         //}
    521         //#endregion
    522 
    523     }
    524 }