2009-12-09 78 views
2

是否可以在没有ScatterView的情况下翻转/旋转/缩放物品?我想要操作可以位于其他元素之上的项目,例如按钮,列表或应该是静态的自定义控件。当我将它们添加到ScatterView时,它们都变成ScatterViewItems,这不是所需的效果。表面开发:翻译/旋转/缩放没有ScatterView的物品

回答

0

是的,你可以使用ManipulationProcessor的附带API

4

扩大对马克的回答有点...

是的,你可以使用操作和惯性的API来实现这一点,看到这个overview page

前阵子我创建的本质做了什么scatterview做,但有以下限制我自己很基本的scatterview控制:

  • 只有一个孩子,所以它的工作原理更像是一个边境
  • 没有默认像SV子项目的外观或特殊行为确实

的一个问题是打我,同时发展这是你必须让你的容器控件占据比实际的孩子面积较大。否则,当手指位于操作对象之外时,您将无法可靠地捕捉到接触事件。我所做的是使我的容器全屏(1024x768),并且是透明的,并且对我的情况来说它工作正常。

对于操作本身,您使用Affine2DManipulationProcessor class的实例。该课程要求您开始操作,然后它会不断地向您提供delta事件(Affine2DManipulationDelta)。

如果您希望操作在用户释放手指后具有更真实的行为,您将使用与操作处理器类似的方式工作的Affine2DInertiaProcessor class。基本设置是,只要操作处理器完成(用户释放手指),就告诉惯性处理器启动。

让我们看看一些代码:)这是我的设置方法在我的容器类:

private void InitializeManipulationInertiaProcessors() 
{ 
    manipulationProcessor = new Affine2DManipulationProcessor(
     Affine2DManipulations.TranslateY | Affine2DManipulations.TranslateX | 
     Affine2DManipulations.Rotate | Affine2DManipulations.Scale, 
     this); 
    manipulationProcessor.Affine2DManipulationCompleted += new EventHandler<Affine2DOperationCompletedEventArgs>(processor_Affine2DManipulationCompleted); 
    manipulationProcessor.Affine2DManipulationDelta += new EventHandler<Affine2DOperationDeltaEventArgs>(processor_Affine2DManipulationDelta); 
    inertiaProcessor = new Affine2DInertiaProcessor(); 
    inertiaProcessor.Affine2DInertiaDelta += new EventHandler<Affine2DOperationDeltaEventArgs>(processor_Affine2DManipulationDelta); 
} 

要开始这一切,我的陷阱ContactDown在我的容器类:

protected override void OnContactDown(ContactEventArgs e) 
{ 
    base.OnContactDown(e); 
    e.Contact.Capture(this); 
    // Tell the manipulation processor what contact to track and it will 
    // start sending manipulation delta events based on user motion. 
    manipulationProcessor.BeginTrack(e.Contact); 
    e.Handled = true; 
} 

这一切,现在坐下来让操作处理器完成它的工作。每当它有新的数据时,它将引起delta事件(用户移动手指时发生几次/秒)。请注意,作为处理器的消费者,您需要根据这些值进行操作。它只会告诉你诸如“用户已经应用X度旋转”或“用户移动手指X,Y像素”等事情。你通常做的是将这些值转发给rendertransforms,以实际向用户显示发生了什么。

在我的情况下,我的子对象有三个硬编码的rendertransform:“translate”,“rotate”和“scale”,我用处理器的值更新。我也做了一些边界检查,以确保对象不会发生移动的表面之外或缩放过大或过小:

/// <summary> 
/// This is called whenever the manipulator or the inertia processor has calculated a new position 
/// </summary> 
/// <param name="sender">The processor who caused the change</param> 
/// <param name="e">Event arguments containing the calculations</param> 
void processor_Affine2DManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e) 
{    
    var x = translate.X + e.Delta.X; 
    var y = translate.Y + e.Delta.Y; 
    if (sender is Affine2DManipulationProcessor) 
    { 
     // Make sure we don't move outside the screen 
     // Inertia processor does this automatically so only adjust if sender is manipulation processor 
     y = Math.Max(0, Math.Min(y, this.ActualHeight - box.RenderSize.Height)); 
     x = Math.Max(0, Math.Min(x, this.ActualWidth - box.RenderSize.Width)); 
    } 
    translate.X = x; 
    translate.Y = y; 
    rotate.Angle += e.RotationDelta; 
    var newScale = scale.ScaleX * e.ScaleDelta; 
    Console.WriteLine("Scale delta: " + e.ScaleDelta + " Rotate delta: " + e.RotationDelta); 
    newScale = Math.Max(0.3, Math.Min(newScale, 3)); 
    scale.ScaleY = scale.ScaleX = newScale; 
} 

这里有一点要注意的是,无论是操控和惯性处理器使用delta事件的相同回调

的最后一块拼图是当用户释放手指和我要开始惯性处理器:

/// <summary> 
/// This is called when the manipulator has completed (i.e. user released contacts) and we let inertia take over movement to make a natural slow down 
/// </summary> 
void processor_Affine2DManipulationCompleted(object sender, Affine2DOperationCompletedEventArgs e) 
{ 
    inertiaProcessor.InitialOrigin = e.ManipulationOrigin; 

    // Set the deceleration rates. Smaller number means less friction (i.e. longer time before it stops) 
    inertiaProcessor.DesiredAngularDeceleration = .0010; 
    inertiaProcessor.DesiredDeceleration = .0010; 
    inertiaProcessor.DesiredExpansionDeceleration = .0010; 
    inertiaProcessor.Bounds = new Thickness(0, 0, this.ActualWidth, this.ActualHeight); 
    inertiaProcessor.ElasticMargin = new Thickness(20); 

    // Set the initial values. 
    inertiaProcessor.InitialVelocity = e.Velocity; 
    inertiaProcessor.InitialExpansionVelocity = e.ExpansionVelocity; 
    inertiaProcessor.InitialAngularVelocity = e.AngularVelocity; 

    // Start the inertia. 
    inertiaProcessor.Begin(); 
}