2009-12-09 53 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(); 
}