Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >DraggableView C# Xamarin的恢复位置命令

DraggableView C# Xamarin的恢复位置命令
EN

Stack Overflow用户
提问于 2017-11-22 06:32:54
回答 1查看 87关注 0票数 0

问题是,当touchevent结束时,应该调用restore position命令,并将其还原回原来的位置。我认为问题在于我的财产变更事件。

第二个问题是,它应该能够锁在最近的数字标签上,并且能够正确地在它们上居中,但是我不知道如何做到这一点。我只是想要一些关于如何做这件事的建议,因为我是相当无知的。

网格

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Grid BackgroundColor="White" ColumnSpacing="10" RowSpacing="10">
            <Label Text="Red" FontSize="Medium" HorizontalOptions="Center" />
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <BoxView Color="Black" Grid.Column="1" Grid.RowSpan="1"/>
            <BoxView Color="Gray" Grid.Column="2" Grid.RowSpan="1"/>
            <Label Text="9" Font ="60" Grid.Row="1" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="8" Font ="60" Grid.Row="2" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="7" Font ="60" Grid.Row="3" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="6" Font ="60" Grid.Row="4" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="5" Font ="60" Grid.Row="5" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="4" Font ="60" Grid.Row="6" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="3" Font ="60" Grid.Row="7" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="2" Font ="60" Grid.Row="8" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="1" Font ="60" Grid.Row="9" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
            <Label Text="0" Font ="60" Grid.Row="10" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />

            <local:DraggableView x:Name="dragView" DragMode="LongPress" DragDirection="All" Grid.Row="3" Grid.RowSpan="3" Grid.Column="3" >
                <local:DraggableView.Content>
                    <BoxView x:Name="image" BackgroundColor="Pink" />
                </local:DraggableView.Content>
            </local:DraggableView>
        </Grid>

跨平台代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  public partial class DraggableView : ContentView
        {
            public event EventHandler DragStart = delegate { };
            public event EventHandler DragEnd = delegate { };

        public static readonly BindableProperty DragDirectionProperty = BindableProperty.Create(
        propertyName: "DragDirection",
        returnType: typeof(DragDirectionType),
        declaringType: typeof(DraggableView),
        defaultValue: DragDirectionType.All,
        defaultBindingMode: BindingMode.TwoWay);

    public DragDirectionType DragDirection
    {
        get { return (DragDirectionType)GetValue(DragDirectionProperty); }
        set { SetValue(DragDirectionProperty, value); }
    }


    public static readonly BindableProperty DragModeProperty = BindableProperty.Create(
       propertyName: "DragMode",
       returnType: typeof(DragMode),
       declaringType: typeof(DraggableView),
       defaultValue: DragMode.LongPress,
       defaultBindingMode: BindingMode.TwoWay);

    public DragMode DragMode
    {
        get { return (DragMode)GetValue(DragModeProperty); }
        set { SetValue(DragModeProperty, value); }
    }

    public static readonly BindableProperty IsDraggingProperty = BindableProperty.Create(
      propertyName: "IsDragging",
      returnType: typeof(bool),
      declaringType: typeof(DraggableView),
      defaultValue: false,
      defaultBindingMode: BindingMode.TwoWay);

    public bool IsDragging
    {
        get { return (bool)GetValue(IsDraggingProperty); }
        set { SetValue(IsDraggingProperty, value); }
    }

    public static readonly BindableProperty RestorePositionCommandProperty = BindableProperty.Create(nameof(RestorePositionCommand), typeof(ICommand), typeof(DraggableView), default(ICommand), BindingMode.TwoWay, null, OnRestorePositionCommandPropertyChanged);

    static void OnRestorePositionCommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var source = bindable as DraggableView;
        if (source == null)
        {
            return;
        }
        source.OnRestorePositionCommandChanged();
    }

    private void OnRestorePositionCommandChanged()
    {
        OnPropertyChanged("RestorePositionCommand");
    }

    public ICommand RestorePositionCommand
    {
        get
        {
            return (ICommand)GetValue(RestorePositionCommandProperty);
        }
        set
        {
            SetValue(RestorePositionCommandProperty, value);
        }
    }

    public void DragStarted()
    {
        DragStart(this, default(EventArgs));
        IsDragging = true;
    }

    public void DragEnded()
    {
        IsDragging = false;
        DragEnd(this, default(EventArgs));
    }

代码中的Android部分

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DraggableViewRenderer : VisualElementRenderer<Xamarin.Forms.View>
    {
        float originalX;
        float originalY;
        float dX;
        float dY;
        bool firstTime = true;
        bool touchedDown = false;
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {
            LongClick -= HandleLongClick;
        }
        if (e.NewElement != null)
        {
            LongClick += HandleLongClick;
            var dragView = Element as DraggableView;
            dragView.RestorePositionCommand = new Command(() =>
            {
                if (!firstTime)
                {
                    SetX(originalX);
                    SetY(originalY);
                }

            });
        }
    }
    private void HandleLongClick(object sender, LongClickEventArgs e)
    {
        var dragView = Element as DraggableView;
        if (firstTime)
        {
            originalX = GetX();
            originalY = GetY();
            firstTime = false;
        }
        dragView.DragStarted();
        touchedDown = true;
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        var dragView = Element as DraggableView;
        base.OnElementPropertyChanged(sender, e);

    }
    protected override void OnVisibilityChanged(AView.View changedView, [GeneratedEnum] ViewStates visibility)
    {
        base.OnVisibilityChanged(changedView, visibility);
        if (visibility == ViewStates.Visible)
        {



        }
    }

    // What happens when you toch
    public override bool OnTouchEvent(MotionEvent e)
    {
        float x = e.RawX;
        float y = e.RawY;
        var dragView = Element as DraggableView;
        switch (e.Action)
        {
            case MotionEventActions.Down:
                if (dragView.DragMode == DragMode.Touch)
                {
                    if (!touchedDown)
                    {
                        if (firstTime)
                        {
                            originalX = GetX();
                            originalY = GetY();
                            firstTime = false;
                        }
                        dragView.DragStarted();
                    }
                    touchedDown = true;
                }
                dX = x - this.GetX();
                dY = y - this.GetY();
                break;
            case MotionEventActions.Move:
                if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Horizontal)
                {
                    SetX(x - dX);
                }

                if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Vertical)
                {
                    SetY(y - dY);
                }
                break;
            case MotionEventActions.Up:
                touchedDown = false;
                dragView.DragEnded();
                break;
            case MotionEventActions.Cancel:
                touchedDown = false;
                break;
        }
        return true;
    }
    public override bool OnInterceptTouchEvent(MotionEvent e)
    {

        BringToFront();
        return true;
    }
}

iOS零件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DraggableViewRenderer : VisualElementRenderer<View>
{
    bool longPress = false;
    bool firstTime = true;
    double lastTimeStamp = 0f;
    UIPanGestureRecognizer panGesture;
    CGPoint lastLocation;
    CGPoint originalPosition;
    UIGestureRecognizer.Token panGestureToken;
    void DetectPan()
    {
        var dragView = Element as DraggableView;
        if (longPress || dragView.DragMode == DragMode.Touch)
        {
            if (panGesture.State == UIGestureRecognizerState.Began)
            {
                dragView.DragStarted();
                if (firstTime)
                {
                    originalPosition = Center;
                    firstTime = false;
                }
            }

            CGPoint translation = panGesture.TranslationInView(Superview);
            var currentCenterX = Center.X;
            var currentCenterY = Center.Y;
            if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Horizontal)
            {
                currentCenterX = lastLocation.X + translation.X;
            }

            if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Vertical)
            {
                currentCenterY = lastLocation.Y + translation.Y;
            }

            Center = new CGPoint(currentCenterX, currentCenterY);

            if (panGesture.State == UIGestureRecognizerState.Ended)
            {
                dragView.DragEnded();
                longPress = false;
            }
        }
    }

    protected override void OnElementChanged(ElementChangedEventArgs<View> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {
            RemoveGestureRecognizer(panGesture);
            panGesture.RemoveTarget(panGestureToken);
        }
        if (e.NewElement != null)
        {
            var dragView = Element as DraggableView;
            panGesture = new UIPanGestureRecognizer();
            panGestureToken = panGesture.AddTarget(DetectPan);
            AddGestureRecognizer(panGesture);


            dragView.RestorePositionCommand = new Command(() =>
            {
                if (!firstTime)
                {

                    Center = originalPosition;
                }
            });

        }

    }
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        var dragView = Element as DraggableView;
        base.OnElementPropertyChanged(sender, e);

    }

    public override void TouchesBegan(NSSet touches, UIEvent evt)
    {
        base.TouchesBegan(touches, evt);
        lastTimeStamp = evt.Timestamp;
        Superview.BringSubviewToFront(this);
        lastLocation = Center;
    }
    public override void TouchesMoved(NSSet touches, UIEvent evt)
    {
        if (evt.Timestamp - lastTimeStamp >= 0.5)
        {
            longPress = true;
        }
        base.TouchesMoved(touches, evt);
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-22 22:20:40

问题是,当touchevent结束时,应该调用restore position命令,并将其还原回原来的位置。我认为问题在于我的财产变更事件。

  1. 如果您想要一个DraggableView,那么您应该尝试使用ViewRenderer而不是VisualElementRenderer<Xamarin.Forms.View>
  2. Renderer不是一个自定义视图,您不应该试图在呈现器中覆盖OnTouchEvent,它不会工作,您可以在本机项目中创建一个自定义视图,然后在您的ViewRenderer中使用SetNativeControl: //在Xamarin.Android项目中创建此自定义视图。公共类DragView本机:视图{公共DragViewNative(上下文上下文):基类(上下文){}公共覆盖bool OnTouchEvent(MotionEvent e) {//在这里实现您的OnTouchEvent逻辑.}公共类DraggableViewRenderer : ViewRenderer {.保护覆盖OnElementChanged(ElementChangedEventArgs e) { base.OnElementChanged(e);//将本机控件设置为自定义视图SetNativeControl(新的DragViewNative(Xamarin.Forms.Forms.Context));//此处的其他逻辑}}

更新:用于解决RestorePositionCommand未触发的问题:

该命令不会被触发,因为您没有手动调用它。由于它是您在控件中定义的自定义ICommand,因此需要手动调用它来触发它。例如,下面的代码将让它在您的DragEnded函数中执行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Inside DraggableView.cs
public void DragEnded()
{
    IsDragging = false;

    //add this line and your command will be triggered
    this.RestorePositionCommand.Execute(null);
    DragEnd(this, default(EventArgs));
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47437239

复制
相关文章
Android入门教程 | EditText 用户输入
使用EditText时,有时候我们会需要监听输入的回车,以做出一些操作。 或者需要把回车变成“搜索”,“发送”或“完成”等等。
Android_anzi
2021/11/05
8390
Android 实现EditText输入金额
Android中EditText是一个InputType类型有很多的控件,可以来达到不同的软键盘效果。如下图:
网罗开发
2021/01/29
3.1K0
Android 实现EditText输入金额
Android edittext InputFilter 输入控制
InputFilter 可能需要对用户的输入进行一些限制,可以为EditText Widget设置一个InputFilter以实现这一功能
程思扬
2022/01/10
7350
EditText输入密码的显示和隐藏
密码的显示和隐藏是一个很常见的小知识点,主要包括2个部分:小图标的变化和EditText输入密码的显示和隐藏
AntDream
2019/07/15
2.5K0
jQuery实现用户输入自动完成功能
利用jQuery UI中Auto-complete插件实现输入自动完成功能,大家在使用诸如淘宝、京东等电商平台搜索商品时,往往只要输入商品的一些特殊字符,就可以显示出和该字符相近的列表菜单,用户使用鼠标或者键盘方向键就可以快速选择,实现了很好的用户体验。
Sindsun
2019/12/10
1.6K0
jQuery实现用户输入自动完成功能
android开发(十六) 如何限制 EditText 最大输入字符数
//editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(20)}); 即限定最大输入字符数为20
Java架构师必看
2021/05/27
1.2K0
mysql 如何修改用户密码_MySQL如何更改用户密码
2、正在更改密码的用户正在使用该应用程序,因为如果在不更改应用程序的连接字符串的情况下更改密码,则应用程序将无法连接到数据库服务器。
全栈程序员站长
2022/09/07
4.7K0
问与答121:如何让用户输入密码后才能使用Excel文件?
Q:有没有一种方法可以通过给用户提供密码来许可用户使用Excel文件?例如,在没有到规定的日期之前,可以正常使用,超过规定日期,则需要输入密码,如果密码不正确,将删除Excel文件。
fanjy
2021/05/07
1.2K0
详解EditText输入监听TextWatcher「建议收藏」
日常开发中,我们可能会遇到需要监听EditText输入,比如判断输入是否为电话号码,获取输入的数据长度来限定字数等。这就需要监听EditText的输入状态。EditText使用TextWatcher实现类似按钮监听事件:
全栈程序员站长
2022/07/31
3.1K0
详解EditText输入监听TextWatcher「建议收藏」
Android开发之输入框EditText介绍
这篇文章主要为大家详细介绍了Android布局之输入框EditText设计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
wangweijun
2020/02/13
2.1K0
如何在Linux中更改用户ID?
在Linux系统中,每个用户都有一个唯一的用户ID(User ID),用于标识和管理用户的权限和资源访问。有时候,我们需要更改用户ID,可能是为了解决冲突、重组用户组或其他管理需求。本文将详细介绍如何在Linux中更改用户ID的几种方法。
网络技术联盟站
2023/06/08
8.5K0
如何在Linux中更改用户ID?
用户输入
大多数程序都在解决最终用户问题,为此通常需要从用户那里获取一些信息。在程序需要一个名字时,你需要提示用户输入该名字;程序需要一个名字时,你需要提示用户输入一系列名字。
狼啸风云
2019/01/18
9710
点击加载更多

相似问题

Android:用户完成编辑后评估EditText

43

用户输入后的EditText事件生成

43

如何在动画完成后更改QGraphicsPixmapItem的可见性?

13

如何检测用户何时完成在EditText中输入RecyclerView值?

11

EditText:检测用户输入更改与加载数据更改

21
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文