我正在尝试为Xamarin Native C#中的windows phone 8.1创build电子书阅读器。
我已经成功地阅读了电子书对象,现在正在按照章节的介绍,在多个Web视图中呈现这些数据。 Web视图将根据章节长度垂直滚动。 不过,我也希望网页视图改变左右滑动的章节,最重要的是书页翻转animation。
像这个示例项目 ,但不是在Silverlight中。
PS自从我开始开发窗口只有一个星期,所以请忍受我。 我在这里尽力而为 非常感谢 :)
Pageturn.cs(PageTurner7 Silverlight的实现
using System; //using System.Windows.Ink; using System.Collections.Generic; using Windows.UI.Xaml.Documents; using System.Windows; using Windows.UI.Xaml.Input; using Windows.UI.Xaml; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Shapes; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Animation; using Windows.UI.Xaml.Markup; using Windows.Foundation; namespace epub_reader.WinPhone { public class PageTurn { public PageTurn() { } private int _index = 0; // Current spread index private double _width; // Width of each page private double _height; // Height of each page private int _count = 0; // Number of even/odd page pairs private bool _turning = false; // True if page turn in progress private bool _animating = false; // True if animated turn completion in progress private double _percent = 0.0; // Percent turned (0 = 0%,1 = 100%) private double _startPos = -1; // X coordinate of initial mouse click private int _direction = 0; // -1 = Turning left,1 = Turning right private double _step = 0.025; // Step size for animations private double _shadowWidth = 16; // Maximum shadow width private double _shadowBreak = 5; // Number of degrees required for shadow to attain maximum width private double _sensitivity = 1.0; // Higher number -> More mouse movement required for full turn private FrameworkElement _owner = null; // Owner of mouse capture private List<Canvas> _evens = new List<Canvas>(); // Even pages private List<Canvas> _odds = new List<Canvas>(); // Odd pages private polygon _shadow = null; // polygon object used to draw shadow private Storyboard _timer = null; // Storyboard timer for animations private Canvas _canvas = null; // Canvas containing pages private Canvas _workingOdd = null; // Working right page private Canvas _workingEven = null; // Working left page private PathGeometry _oddClipRegion = null; private Linesegment _oddClipRegionLinesegment1 = null; private Linesegment _oddClipRegionLinesegment2 = null; private PathGeometry _evenClipRegion = null; private Linesegment _evenClipRegionLinesegment1 = null; private Linesegment _evenClipRegionLinesegment2 = null; private Linesegment _evenClipRegionLinesegment3 = null; private TransformGroup _transformGroup = null; private RotateTransform _rotateTransform = null; private TranslateTransform _translateTransform = null; // XAML deFinition for clip region used on right-hand pages private const string _opg = "<PathGeometry xmlns="http://schemas.microsoft.com/client/2007">" + "<Pathfigure StartPoint="0,0">" + "<Linesegment />" + "<Linesegment />" + "</Pathfigure>" + "</PathGeometry>"; // XAML deFinition for clip region used on left-hand pages private const string _epg = "<PathGeometry xmlns="http://schemas.microsoft.com/client/2007">" + "<Pathfigure StartPoint="0,0">" + "<Linesegment Point="0,0" />" + "<Linesegment Point="0,0" />" + "</Pathfigure>" + "</PathGeometry>"; // XAML deFinition for transforms used on left-hand pages private const string _tg = "<TransformGroup xmlns="http://schemas.microsoft.com/client/2007">" + "<RotateTransform />" + "<TranslateTransform />" + "</TransformGroup>"; // XAML deFinition for Storyboard timer private const string _sb = "<Storyboard xmlns="http://schemas.microsoft.com/client/2007" Duration="0:0:0.01" />"; // XAML deFinition for shadow polygon private const string _poly = "<polygon xmlns="http://schemas.microsoft.com/client/2007" Canvas.ZIndex="4" Fill="Black" Opacity="0.2" Points="0,0 0,0" Visibility="Collapsed">" + "<polygon.Clip>" + "<RectangleGeometry Rect="0,{0},{1}" />" + "</polygon.Clip>" + "</polygon>"; //////////////////////////////////////////////////////////////////////// // Events public event EventHandler PageTurned; //////////////////////////////////////////////////////////////////////// // Properties public int CurrentSpreadindex { get { return _index; } } public int SpreadCount { get { return _count; } } public double Sensitivity { get { return _sensitivity; } set { _sensitivity = value; } } //////////////////////////////////////////////////////////////////////// // Public methods public void Initialize(Canvas canvas) { _canvas = canvas; // Create a Storyboard for timing animations _timer = (Storyboard)XamlReader.Load(_sb); //_timer.Completed += new EventHandler(OnTimerTick); _timer.Completed += OnTimerTick; // Create a PathGeometry for clipping right-hand pages _oddClipRegion = (PathGeometry)XamlReader.Load(_opg); _oddClipRegionLinesegment1 = (Linesegment)_oddClipRegion.figures[0].Segments[0]; _oddClipRegionLinesegment2 = (Linesegment)_oddClipRegion.figures[0].Segments[1]; // Create a PathGeometry for clipping left-hand pages string xaml = String.Format(_epg,_evens[0].Height); _evenClipRegion = (PathGeometry)XamlReader.Load(xaml); _evenClipRegionLinesegment1 = (Linesegment)_evenClipRegion.figures[0].Segments[0]; _evenClipRegionLinesegment2 = (Linesegment)_evenClipRegion.figures[0].Segments[1]; _evenClipRegionLinesegment3 = (Linesegment)_evenClipRegion.figures[0].Segments[2]; // Create a TransformGroup for transforming left-hand pages _transformGroup = (TransformGroup)XamlReader.Load(_tg); _rotateTransform = (RotateTransform)_transformGroup.Children[0]; _translateTransform = (TranslateTransform)_transformGroup.Children[1]; // Initialize internal variables _count = _evens.Count; _width = _evens[0].Width; _height = _evens[0].Height; // Create a polygon to provide shadow during page turns _shadow = (polygon)XamlReader.Load(String.Format(_poly,_width * 2,_height)); _canvas.Children.Add(_shadow); // Initialize z-order InitializeZOrder(); } private void OnTimerTick(object sender,object e) { _percent += _step; if (_percent < 0.0) _percent = 0.0; else if (_percent > 1.0) _percent = 1.0; TurnTo(_percent); if (_percent == 0.0) { if (_direction == 1) { _index--; if (PageTurned != null) PageTurned(this,EventArgs.Empty); } Reset(); } else if (_percent == 1.0) { if (_direction == -1) { _index++; if (PageTurned != null) PageTurned(this,EventArgs.Empty); } Reset(); } else _timer.Begin(); } public void AddSpread(Canvas left,Canvas right) { left.Pointerpressed += Left_Pointerpressed; ; ; //left.MouseLeftButtonDown += new MouseButtonEventHandler(OnBeginRightTurn); left.PointerMoved += Left_PointerMoved; //left.MouseMove += new MouseEventHandler(OnContinueRightTurn); left.PointerReleased += Left_PointerReleased; ; //left.MouseLeftButtonUp += new MouseButtonEventHandler(OnEndRightTurn); _evens.Add(left); right.Pointerpressed += Right_Pointerpressed; right.PointerMoved += Right_PointerMoved; right.PointerReleased += Right_PointerReleased; _odds.Add(right); } private void Right_Pointerpressed(object sender,PointerRoutedEventArgs e) { if (_animating) return; // Do nothing if animation in progress // Do nothing if trying to turn left but last // page is displayed if (_index == _count - 1) return; // Start a left turn _turning = true; _direction = -1; _percent = 0.0; _startPos = e.GetCurrentPoint((FrameworkElement)sender).Position.X; _owner = (FrameworkElement)sender; ((FrameworkElement)sender).CapturePointer(e.Pointer); // Turn page to specified angle TurnTo(_percent); // Cache references to "working" pages _workingOdd = _odds[_index]; _workingEven = _evens[_index + 1]; // Assign clipping regions and transforms to relevant canvases RectangleGeometry rect = new RectangleGeometry(); rect.Transform = _oddClipRegion.Transform; rect.Rect = _oddClipRegion.Bounds; _workingOdd.Clip = rect; //_workingOdd.Clip = _oddClipRegion; //_workingEven.Clip = _evenClipRegion; RectangleGeometry rect2 = new RectangleGeometry(); rect2.Rect = _evenClipRegion.Bounds; rect2.Transform = _evenClipRegion.Transform; _workingEven.Clip = rect2; _workingEven.RenderTransform = _transformGroup; // Set z-indexes for a left turn _evens[_index + 1].SetValue(Canvas.ZIndexProperty,2); _odds[_index + 1].SetValue(Canvas.ZIndexProperty,0); } private void Right_PointerMoved(object sender,PointerRoutedEventArgs e) { if (_animating) return; // Do nothing if animation in progress if (_turning) { // Compute change in X double dx = _startPos - e.GetCurrentPoint((FrameworkElement)sender).Position.X; // If mouse moved right,update _startPos so page // begins turning with first move left if (dx < 0) { _startPos = e.GetCurrentPoint((FrameworkElement)sender).Position.X; return; } // Compute turn percentage based on change in X double percent = dx / (_width * _sensitivity); if (percent > 1.0) percent = 1.0; else if (percent < 0.0) percent = 0.0; // Exit Now if no change if (percent == _percent) return; // Update percent turned _percent = percent; // Turn page to specified angle TurnTo(_percent); } } private void Right_PointerReleased(object sender,PointerRoutedEventArgs e) { if (_animating) return; // Do nothing if animation in progress if (_turning) CompleteTurn(); } private void Left_Pointerpressed(object sender,PointerRoutedEventArgs e) { if (_animating) return; // Do nothing if animation in progress // Do nothing if trying to turn right but first // page is displayed if (_index == 0) return; // Start a right turn _turning = true; _direction = 1; _percent = 1.0; _startPos = e.GetCurrentPoint((FrameworkElement)sender).Position.X; _owner = (FrameworkElement)sender; ((FrameworkElement)sender).CapturePointer(e.Pointer); // Turn page to specified angle TurnTo(_percent); // Cache references to "working" pages _workingOdd = _odds[_index - 1]; _workingEven = _evens[_index]; // Assign clipping regions and transforms to relevant canvases RectangleGeometry rect = new RectangleGeometry(); rect.Transform = _oddClipRegion.Transform; rect.Rect = _oddClipRegion.Bounds; _workingOdd.Clip = rect; //_workingOdd.Clip = _oddClipRegion; //_workingEven.Clip = _evenClipRegion; RectangleGeometry rect2 = new RectangleGeometry(); rect2.Rect = _evenClipRegion.Bounds; rect2.Transform = _evenClipRegion.Transform; _workingEven.Clip = rect2; _workingEven.RenderTransform = _transformGroup; // Set z-indexes for a right turn _evens[_index].SetValue(Canvas.ZIndexProperty,3); _evens[_index - 1].SetValue(Canvas.ZIndexProperty,0); _odds[_index - 1].SetValue(Canvas.ZIndexProperty,2); } private void Left_PointerMoved(object sender,PointerRoutedEventArgs e) { if (_animating) return; // Do nothing if animation in progress if (_turning) { // Compute change in X double dx = e.GetCurrentPoint((FrameworkElement)(((FrameworkElement)sender).Parent)).Position.X - _startPos; // If mouse moved left,update _startPos so page // begins turning with first move right if (dx < 0) { _startPos = e.GetCurrentPoint((FrameworkElement)(((FrameworkElement)sender).Parent)).Position.X; return; } // Compute turn percentage based on change in X double percent = 1.0 - (dx / (_width * _sensitivity)); if (percent > 1.0) percent = 1.0; else if (percent < 0.0) percent = 0.0; // Exit Now if no change if (percent == _percent) return; // Update percent turned _percent = percent; // Turn page to specified angle TurnTo(this._percent); } } private void Left_PointerReleased(object sender,PointerRoutedEventArgs e) { if (_animating) return; // Do nothing if animation in progress if (_turning) CompleteTurn(); } public void GoToSpread(int index) { if (index != _index && index > 0 && index < _count) { _index = index; InitializeZOrder(); if (PageTurned != null) PageTurned(this,EventArgs.Empty); } } //////////////////////////////////////////////////////////////////////// // Helper methods private void TurnTo(double percent) { // Compute angle of rotation double degrees = 45 - (percent * 45); double radians = degrees * Math.PI / 180; // Compute x coordinates along bottom of canvas double dx1 = _width - (percent * _width); double dx2 = _width - dx1; // Compute tangent of rotation angle double tan = Math.Tan(radians); // Configure clipping region for right-hand page double p2y; if (tan == 0) p2y = _height; else p2y = _height + (dx1 / tan); double p3x = p2y * tan; _oddClipRegionLinesegment1.Point = new Point(0,p2y); _oddClipRegionLinesegment2.Point = new Point(p3x,0); // Configure clipping region for left-hand page double p7x = dx2 - (_height * tan); if (p7x >= 0.0) // 4-corner clipping region { _evenClipRegion.figures[0].StartPoint = new Point(0,0); _evenClipRegionLinesegment1.Point = new Point(0,_height); _evenClipRegionLinesegment2.Point = new Point(dx2,_height); _evenClipRegionLinesegment3.Point = new Point(p7x,0); } else // 3-corner clipping region { double y = _height - (dx2 / tan); _evenClipRegion.figures[0].StartPoint = _evenClipRegionLinesegment3.Point = new Point(0,y); _evenClipRegionLinesegment1.Point = new Point(0,_height); } // Apply clipping regions and transforms _rotateTransform.CenterX = dx2; _rotateTransform.CenterY = _height; _rotateTransform.Angle = 2 * degrees; _translateTransform.X = 2 * (_width - dx2); // Configure shadow if (percent == 0.0 || percent == 1.0) { _shadow.Visibility = Visibility.Collapsed; return; } _shadow.Visibility = Visibility.Visible; double min = this._shadowBreak; double max = 45 - this._shadowBreak; double width; if (degrees > min && degrees < max) width = _shadowWidth; else { if (degrees <= min) width = (degrees / _shadowBreak) * _shadowWidth; else // degrees >= max width = ((45 - degrees) / _shadowBreak) * _shadowWidth; } double x1 = _width + dx1 + (_height * tan); double x2 = _width + dx1; double y2 = _height; double x3 = x2 + width; double y3 = _height; double x4 = x1 + width; _shadow.Points[0] = new Point(x1,0); _shadow.Points[1] = new Point(x2,y2); _shadow.Points[2] = new Point(x3,y3); _shadow.Points[3] = new Point(x4,0); } private void CompleteTurn() { if (_percent == 0.0) { if (_direction == 1) { _index--; if (PageTurned != null) PageTurned(this,EventArgs.Empty); } Reset(); return; } if (_percent == 1.0) { if (_direction == -1) { _index++; if (PageTurned != null) PageTurned(this,EventArgs.Empty); } Reset(); return; } if (_percent < 0.5) _step = -Math.Abs(_step); else _step = Math.Abs(_step); _animating = true; _timer.Begin(); } private void Reset() { _turning = false; _animating = false; _direction = 0; if (_owner != null) _owner.ReleasePointerCaptures(); _owner = null; if (_workingOdd != null && _workingOdd.Clip != null) _workingOdd.Clip = null; if (_workingEven != null && _workingEven.Clip != null) _workingEven.Clip = null; if (_workingEven != null && _workingEven.RenderTransform != null) _workingEven.RenderTransform = null; _workingOdd = null; _workingEven = null; _shadow.Visibility = Visibility.Collapsed; InitializeZOrder(); } private void InitializeZOrder() { for (int i = 0; i < _count; i++) { _evens[i].SetValue(Canvas.ZIndexProperty,(i == _index) ? 1 : -1); _odds[i].SetValue(Canvas.ZIndexProperty,(i == _index) ? 1 : -1); } } } }
你可以试一下CarouselView来实现xamarin形式的触发器功能,这里是示例 – https://blog.xamarin.com/flip-through-items-with-xamarin-forms-carouselview/
如果你想在Xamarin Native中实现,请检查下面的IOS和Android链接。
IOS- https://github.com/jzeferino/Xamarin.iOS.iCarousel
Android- https://github.com/MobMaxime/xamarin-android-samples/tree/master/CarouselViewProject-master
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。