如何在Absolutelayout中实现拖动框架

时间:2017-11-29 00:23:12

标签: xamarin.forms

我在absolutelayout中有一个框架,如下所示。我希望该用户能够在屏幕上拖动和重新定位此框架。我试图实现一个平移手势但不幸的是它没有按预期工作。我可以向我展示正确的方法吗?是否可以不使用任何第三方库?

<AbsoluteLayout>

        <Frame x:Name="frm"  Padding="1" AbsoluteLayout.LayoutFlags="All"  AbsoluteLayout.LayoutBounds="0.5,0,0.3,0.3"  IsVisible="{Binding IsSmallTimerVisible}" >
            <Frame.GestureRecognizers>
                <PanGestureRecognizer PanUpdated="OnPanUpdated" />
            </Frame.GestureRecognizers>
            <shared:_customControl/>
        </Frame>

Grid  VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" AbsoluteLayout.LayoutFlags="All"  AbsoluteLayout.LayoutBounds="0,0,1,1">
            <Grid.RowDefinitions>
                <RowDefinition Height="0.1*" />
                <RowDefinition Height="0.3*" />
                <RowDefinition Height="2.5*" />
            </Grid.RowDefinitions>

背后的代码中
 double x, y;
        private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
        {
            switch (e.StatusType)
            {
                case GestureStatus.Running:
                    // Translate and ensure we don't pan beyond the wrapped user interface element bounds.
                    Content.TranslationX =
                      Math.Max(Math.Min(0, x + e.TotalX), -Math.Abs(Content.Width - App.ScreenWidth));
                    Content.TranslationY =
                      Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs(Content.Height - App.ScreenHeight));
                    break;

                case GestureStatus.Completed:
                    {
                        // Store the translation applied during the pan
                        x = Content.TranslationX;
                        y = Content.TranslationY;
                        AbsoluteLayout.SetLayoutBounds(frm, new Rectangle(x, y, .3, .3));
                        break;
                    }

            }


        }

1 个答案:

答案 0 :(得分:1)

看起来像你需要的是触摸跟踪效果

This示例与您的要求非常相似。

void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
    BoxView boxView = sender as BoxView;

    switch (args.Type)
    {
        case TouchActionType.Pressed:
            // Don't allow a second touch on an already touched BoxView
            if (!dragDictionary.ContainsKey(boxView))
            {
                dragDictionary.Add(boxView, new DragInfo(args.Id, args.Location));

                // Set Capture property to true
                TouchEffect touchEffect = (TouchEffect)boxView.Effects.FirstOrDefault(e => e is TouchEffect);
                touchEffect.Capture = true;
            }
            break;

        case TouchActionType.Moved:
            if (dragDictionary.ContainsKey(boxView) && dragDictionary[boxView].Id == args.Id)
            {
                Rectangle rect = AbsoluteLayout.GetLayoutBounds(boxView);
                Point initialLocation = dragDictionary[boxView].PressPoint;
                rect.X += args.Location.X - initialLocation.X;
                rect.Y += args.Location.Y - initialLocation.Y;
                AbsoluteLayout.SetLayoutBounds(boxView, rect);
            }
            break;

        case TouchActionType.Released:
            if (dragDictionary.ContainsKey(boxView) && dragDictionary[boxView].Id == args.Id)
            {
                dragDictionary.Remove(boxView);
            }
            break;
    }
}
  

Pressed逻辑设置TouchEffect对象的Capture属性   为真。这具有为所有后续事件提供的效果   那个手指指向同一个事件处理程序。

     

Moved逻辑通过更改LayoutBounds来移动BoxView   附属财产。事件参数的Location属性是   总是相对于被拖动的BoxView,如果BoxView是   以恒定速率拖动,位置属性   连续的事件将大致相同。例如,如果是   手指在其中心按下BoxView,Pressed动作存储了一个   PressPoint属性(50,50),后续保持不变   事件。如果BoxView以恒定速率对角拖动,则   Moved操作期间的后续位置属性可能是值   (55,55),在这种情况下,Moved逻辑将水平加5   和BoxView的垂直位置。这会移动BoxView   它的中心再次直接在手指下。

     

您可以使用不同的方式同时移动多个BoxView元素   手指。