c# iOS 无法将光标定位在 UITextField 中的位置 1

c# iOS Can NOT position cursor in UITextField in position 1

无论我做什么,我都无法将光标设置到此字符串中的位置 1 (___) ___-____ 位置 1 是紧跟在开头 ( 之后的位置。我在委托的 EditingStarted 方法中执行此操作,作为指南,我遵循代码 。目前我的代码是:

    public override void EditingStarted(UITextField textField)
    {
        if (MyParent.EditMask != "")
        {
            textField.Text = MyParent.EditMask.Replace("#", "_");
            // Set cursor position
            NSRange therange = new NSRange(index, 0);
            UITextPosition start = textField.GetPosition(textField.BeginningOfDocument, therange.Length - 1);
            UITextPosition end = textField.GetPosition(start, therange.Length);
            textField.SelectedTextRange = textField.GetTextRange(start, end);
        }
    }

光标总是在关闭 ) 后立即出现,我没有做任何改变。我不知道为什么。我试过获取第一个下划线的位置:

int position = textField.Text.IndexOf("_");
NSRange therange = new NSRange(position, 0);

但同样,这会导致光标紧跟在结束 ) 之后。有人看出我做错了什么吗?

**** 更新 ****

为了让人们理解上下文,上面的代码是我创建的名为 UIMaskedTextField 的 class 的一部分,用于处理用户界面中的所有 mask/text 输入格式。 class 是:

class UIMaskedTextField : UITextField
{
    public string EditMask { get; set; }

    public UIMaskedTextField()
    {
        this.Delegate = new MaskTextViewDelegate(this);
    }

}
class MaskTextViewDelegate : UITextFieldDelegate
{
    private UIMaskedTextField MyParent;
    int index = 0;
    public MaskTextViewDelegate(UIMaskedTextField parent)
    {
        MyParent = parent;
    }

    public override void EditingStarted(UITextField textField)
    {
        if (MyParent.EditMask != "")
        {
            textField.Text = MyParent.EditMask.Replace("#", "_");
            // Set cursor position
            int position = textField.Text.IndexOf("_");

            NSRange therange = new NSRange(position, 0);
            UITextPosition start = textField.GetPosition(textField.BeginningOfDocument, therange.Location);
            UITextPosition end = textField.GetPosition(start, therange.Length);
            textField.SelectedTextRange = textField.GetTextRange(start, end);

        }
    }
    public override bool ShouldChangeCharacters(UITextField textField, NSRange range, string replacementString)
    {
        int fieldlength = 10; // MyParent.EditMask.Length;
        string text = textField.Text;
        int NeedASpace = MyParent.EditMask.IndexOf(" ");
        string newText = "";
        if (text == "")
        {
            newText = MyParent.EditMask.Replace("#", "_");
        } else
        {
            newText = text;
        }

        string totalChar = newText.Replace(" ", "");
        totalChar = totalChar.Replace("(", "");
        totalChar = totalChar.Replace(")", "");
        totalChar = totalChar.Replace("-", "");
        totalChar = totalChar.Replace("_", "");

        int val;
        if ((totalChar + replacementString).Length <= fieldlength) {
            if (replacementString != "")
            {
                index = newText.IndexOf("_");
                StringBuilder sb = new StringBuilder(newText);
                char character = char.Parse(replacementString);
                sb[index] = character;
                newText = sb.ToString();


                textField.Text = newText;

                // Set cursor to next position, this works flawlessly
                NSRange therange = new NSRange(index, 0);
                UITextPosition start = textField.GetPosition(textField.BeginningOfDocument, therange.Location + 1);
                UITextPosition end = textField.GetPosition(start, therange.Length);
                textField.SelectedTextRange = textField.GetTextRange(start, end);

                newText = "";
            }
            else
            { // Still working the backspace key, so not done here yet.
                if (text.Length > 1)
                {
                    newText = text.Substring(0, text.Length - 1);
                }
                else
                {
                    newText = "";
                }
            }
        }

        return Int32.TryParse(newText, out val);
    }
}

要将光标定位在 UITextField 中的位置 1:

public partial class ViewController : UIViewController
{
    public ViewController (IntPtr handle) : base (handle)
    {
    }

    UITextField textfield1 { get; set; }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        // Perform any additional setup after loading the view, typically from a nib.

        var frame = new CGRect(10, 10, 300, 40);
        textfield1 = new UITextField(frame);

        textfield1.Text = "(___) ___-____";
        textfield1.Delegate = new myDelegate();

        View.Add(textfield1);


        textfield1.BecomeFirstResponder();

    }
}

public class myDelegate : UITextFieldDelegate {

    public override void EditingStarted(UITextField textField)
    {
        var arbitraryValue = 1;

        var newPosition = textField.GetPosition(textField.BeginningOfDocument, arbitraryValue);
        textField.SelectedTextRange = textField.GetTextRange(newPosition, newPosition);
    }
}

更新:

public override void DidChangeSelection(UITextField textField)
{
    var arbitraryValue = 1;

    var newPosition = textField.GetPosition(textField.BeginningOfDocument, arbitraryValue);
    textField.SelectedTextRange = textField.GetTextRange(newPosition, newPosition);

}

好的,终于可以使用了。 @Jack Hua 的解决方案对我不起作用,因为我无法将文本字段设置为 FirstResponder,因为滚动视图上有许多 UIMaskedTextField,屏蔽的文本字段不是第一个 sub-views 在滚动视图上,但它确实给了我一些想法!我开始怀疑在设置文本 属性 时文本字段的初始化以某种方式搞砸了光标位置,我相信这就是正在发生的事情,只是无法证明它因为视图的初始化是发生在幕后。但是我怀疑通过 EditMask 属性 设置视图的掩码使初始化发生得更快并且可以设置光标位置。这也从一开始就设置了掩码,消除了用户对字段格式的疑虑。这是我的“最终”代码:

class UIMaskedTextField : UITextField
{
    private string editmask = "";
    public String EditMask
    {
        get => editmask;
        set
        {
            if ((value != ""))
            {
                editmask = value;
                this.Text = editmask.Replace("#", "_"); ;
            }
        }
    }

    public UIMaskedTextField()
    {
        this.Delegate = new PhoneMaskTextViewDelegate(this);
    }
}

class PhoneMaskTextViewDelegate : UITextFieldDelegate
{
    private UIMaskedTextField MyParent;
    int index = 0;
    public PhoneMaskTextViewDelegate(UIMaskedTextField parent)
    {
        MyParent = parent;
    }

    public override void DidChangeSelection(UITextField textField)
    {
        // place the cursor in the first fill podition
        int y = textField.Text.IndexOf("_");

        if (y > -1)
        {
            var newPosition = textField.GetPosition(textField.BeginningOfDocument, y);
            textField.SelectedTextRange = textField.GetTextRange(newPosition, newPosition);
        }

    }
    public override bool ShouldChangeCharacters(UITextField textField, NSRange range, string replacementString)
    {
        const string maskCharacters = "()-/ ";

        string newText = "";
        int val;

        if (replacementString != "")
        {
            int fieldlength = 10; // MyParent.EditMask.Length;
            string text = textField.Text;
            if (text == "")
            {
                newText = MyParent.EditMask.Replace("#", "_");
            }
            else
            {
                newText = text;
            }

            string totalChar = newText.Replace(" ", "");
            totalChar = totalChar.Replace("(", "");
            totalChar = totalChar.Replace(")", "");
            totalChar = totalChar.Replace("-", "");
            totalChar = totalChar.Replace("_", "");

            if (Utils.IsNumeric(replacementString))
            {
                if ((totalChar + replacementString).Length <= fieldlength)
                {
                    if (replacementString != "")
                    {
                        index = newText.IndexOf("_");
                        if (index > -1)
                        {
                            StringBuilder sb = new StringBuilder(newText);
                            char character = char.Parse(replacementString);
                            sb[index] = character;
                            newText = sb.ToString();


                            textField.Text = newText;

                            // Set cursor to next position
                            NSRange therange = new NSRange(index, 0);
                            UITextPosition start = textField.GetPosition(textField.BeginningOfDocument, therange.Location + 1);
                            UITextPosition end = textField.GetPosition(start, therange.Length);
                            textField.SelectedTextRange = textField.GetTextRange(start, end);
                        }
                        newText = "";
                    }
                }
            }
        } else
        { // Backspace/Delete pressed

            UITextRange position = textField.SelectedTextRange;
            string x = position.ToString();
            int positionofcursor = Convert.ToInt32(x.Substring(x.IndexOf("(") + 1, x.IndexOf(",") - x.IndexOf("(") - 1));

            string characterInPosition = "";


            // make sure we're not deleting a mask character
            do {
                positionofcursor -= 1;
                if (positionofcursor > -1)
                {
                    characterInPosition = textField.Text.Substring(positionofcursor, 1);
                    int j = maskCharacters.IndexOf(characterInPosition);
                }else
                {
                    break;
                }
            } while (maskCharacters.IndexOf(characterInPosition) > -1);

            if (positionofcursor > -1)
            {
                StringBuilder sb = new StringBuilder(textField.Text);
                sb[positionofcursor] = char.Parse("_");
                textField.Text = sb.ToString();

                NSRange therange = new NSRange(positionofcursor, 0);
                UITextPosition start = textField.GetPosition(textField.BeginningOfDocument, therange.Location);
                UITextPosition end = textField.GetPosition(start, therange.Length);
                textField.SelectedTextRange = textField.GetTextRange(start, end);
            }
        }

        return Int32.TryParse(newText, out val);
    }
}