Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by IntrudeN313 · Jan 05, 2017 at 05:37 PM · c#uiinputfieldformattingform

Masked InputField on Unity UI

I am making a player registration menu in a game using data such as: Name, Email, Password, Gender, Date of Birth and Phone Number.

The problem is when I add the UI InputField for the Date of Birth and Phone Number, I would need to apply a formatting mask such as "##/ ##/####" for the Date and "(##) #####-####" for the Phone.

I can limit the InputField to typing just numbers, however I did not find any way to add formatted masks or to create a component akin to C#'s MaskedTextBox. Is it possible to do something similar to this in Unity?

Example of MaskedTextBox: alt text

maskedtextbox.jpg (19.7 kB)
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image IntrudeN313 · Jan 05, 2017 at 06:37 PM 0
Share

The mask's behaviour I need is exactly like this: https://raw.githubusercontent.com/viniciusmo/V$$anonymous$$askTextField/master/Resources/vmasktextfield.gif

4 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Nokaut · Feb 03, 2017 at 08:37 PM

Hi @IntrudeN313, i had a similar problem with Dates. Maybe this code can help you

 private char OnValidateInput(string text, int charIndex, char addedChar)
 {
     if (addedChar == '/')
         return addedChar;
     if (!char.IsNumber(addedChar))
         return '\0';
 
     //I Want date format like (dd/mm/yyyy)
     switch(text.Length)
     {
         case 2: //User typed 'dd'
             DataInicial.text = text + "/";
             DataInicial.caretPosition = DataInicial.text.Length;
             break;
 
         case 5: //User typed 'dd/mm'
             DataInicial.text = text + "/";
             DataInicial.caretPosition = DataInicial.text.Length;
             break;
     }
     return addedChar;
 }
 


Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by xxShana · Apr 24, 2020 at 11:34 AM

 public class PhoneInputMask : MonoBehaviour
 {
     public InputField inputField;
 
     private void OnValidate()
     {
         inputField = GetComponent<InputField>();
     }
 
     public void Start()
     {
         inputField.onValueChanged.AddListener(delegate { OnValueChangeEvent(); });
     }
 
     // Invoked when the value of the text field changes.
     public void OnValueChangeEvent()
     {
         if (string.IsNullOrEmpty(inputField.text))
         {
             inputField.text = string.Empty;
         }
         else
         {
             string input = inputField.text;
             string MatchPattern = @"^((\d{2}\.){0,4}(\d{1,2})?)$";
             string ReplacementPattern = "$1.$3";
             string ToReplacePattern = @"((\.?\d{2})+)(\d)";
 
             input = Regex.Replace(input, ToReplacePattern, ReplacementPattern);
             Match result = Regex.Match(input, MatchPattern);
             if (result.Success)
             {
                 inputField.text = input;
                 inputField.caretPosition++;
             }
         }
     }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Hellium · Jan 05, 2017 at 05:38 PM

UPDATED ANSWER

 public void OnValueChanged(string input) // Supposing input = "953"
 {
     int index = 0 ;
     string format = "##/##/####" ;
     string output = format;
     
     for( int i = 0 ; i < input.Length ; ++i )
     {
         index = output.IndexOf("#");
         if( index < 0 )
             break ;
         if( index == 0 )
             output = input[i] + output.Substring ( 1 );
         else if( index == output.Length - 1 )
             output = output.Substring ( 0, index ) + input[i] ;
         else
             output = output.Substring ( 0, index ) + input[i] + output.Substring ( index + 1 );
     }
     if( index >= 0 )
         output = output.Substring( 0, index + 1 );
     
     Debug.Log( output ); // Will output 95/3
 }


2nd UPDATE

     public UnityEngine.UI.InputField inputField;

     // The Text component showing your formatted string
     public UnityEngine.UI.Text text;

     private string lastValidInput = string.Empty;

     private void Awake()
     {
         inputField.onValueChanged.AddListener( OnValueChanged );
     }

     private void OnValueChanged( string input ) // Supposing input = "9534"
     {
         string format = "{0}{1}/{2}{3}/{4}{5}{6}{7}" ;
         string[] array = new string[input.Length];
         int index = format.IndexOf("{" + (input.Length - 1) + "}");

         if ( input.Length == 0 )
         {
             text.text = string.Empty;
             return;
         }

         if ( index >= 0 )
         {
             format = format.Substring( 0, index + 3 );
         }
         else
         {
             inputField.text = lastValidInput;
             return;
         }

         for ( index = 0 ; index < input.Length ; ++index )
             array[index] = string.Empty + input[index];

         lastValidInput = input;

         text.text = string.Format( format, array ); // Will output 95/34
     }

2nd Update' (different output)

     private void OnValueChanged( string input ) // Supposing input = "9534"
     {
         string format = "{0}{1}/{2}{3}/{4}{5}{6}{7}" ;
         string[] array = new string[input.Length];
         int index = format.IndexOf("{" + (input.Length) + "}");

         if ( input.Length == 0 )
         {
             text.text = string.Empty;
             return;
         }

         if ( index >= 0 )
         {
             format = format.Substring( 0, index );
         }
         else
         {
             inputField.text = lastValidInput;
             return;
         }

         for ( index = 0 ; index < input.Length ; ++index )
             array[index] = string.Empty + input[index];

         lastValidInput = input;

         text.text = string.Format( format, array ); // Will output 95/34/
     }

IMPORTANT NOTE :

The functions I gave you will only accept a string containing numbers only. Thus, you will need an input field with invisible characters to accept the input and a Text component to show the formatted result (See 2nd Update)


INITIAL ANSWER

I think regular expressions is the way to go. I prepared you an example for your first case :

         System.Text.RegularExpressions.Match match = System.Text.RegularExpressions.Regex.Match("9545551212", @"(\d{3})(\d{3})(\d{4})");
         if ( match.Success )
         {
             // match.Groups[0] will return the whole input
             string output = string.Format("({0}) {1}-{2}", match.Groups[1], match.Groups[2], match.Groups[3]);
             Debug.Log( output ); // Will log "(954) 555-1212"
         }


Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image IntrudeN313 · Jan 05, 2017 at 06:34 PM 0
Share

Unfortunately that doesn't work because to build the desired effect, I need to use it on InputField's Dynamic String callback OnValueChanged like that:

 using UnityEngine;
 using UnityEngine.UI;
 using System.Text.RegularExpressions;
 
 public class $$anonymous$$askedInputField : $$anonymous$$onoBehaviour {
     private InputField _inputField;
 
     private void Awake()
     {
         _inputField = GetComponent<InputField>();
     }
 
     public void OnValueChanged(string value)
     {
         var match = Regex.$$anonymous$$atch(value, @"(\d{3})(\d{3})(\d{4})");
         if (match.Success) {
             string output = string.Format("({0}) {1}-{2}", match.Groups[1], match.Groups[2], match.Groups[3]);
             _inputField.text = output;
         }
     }
 }
 

This way I did, the mask would be put only when I've inputted the last number, when it matches the Regex... I'm searching for something more dynamic on UI, maybe I'm using the wrong strategy. Anyway thanks for the help!

avatar image Hellium IntrudeN313 · Jan 06, 2017 at 09:40 AM 0
Share

@IntrudeN313 : I gave you two other solutions. Tell me if it fits your needs this time ;)

avatar image IntrudeN313 Hellium · Jan 06, 2017 at 01:39 PM -1
Share

I tested both solutions and the two works well, the only problem I found was on the caret and the selection that gets on InputField's invisible text and not on the OutputText: With CaretWith Selection

Now code I'm using based on the first solution:

 using UnityEngine;
 using UnityEngine.UI;
 
 public class $$anonymous$$askedInputField : $$anonymous$$onoBehaviour
 {
     [SerializeField] private Text _outputField;
     private InputField _inputField;
     
     private void Awake()
     {
         _inputField = GetComponent<InputField>();
     }
 
     public void OnValueChanged(string input)
     {
         int index = 0;
         string format = "##/##/####";
         string output = format;
 
         for (int i = 0; i < input.Length; ++i) {
             index = output.IndexOf("#");
             if (index < 0) break;
 
             if (index == 0)
                 output = input[i] + output.Substring(1);
             else if (index == output.Length - 1)
                 output = output.Substring(0, index) + input[i];
             else
                 output = output.Substring(0, index) + input[i] + output.Substring(index + 1);
         }
 
         if (index >= 0)
             output = output.Substring(0, index + 1);
 
         _outputField.text = output;
     }
 }

And the second solution:

 using UnityEngine;
 using UnityEngine.UI;
 
 public class $$anonymous$$askedInputField : $$anonymous$$onoBehaviour
 {
     [SerializeField] private Text _outputField;
     private InputField _inputField;
     
     private string _lastValidInput = string.Empty;
     
     private void Awake()
     {
         _inputField = GetComponent<InputField>();
     }
 
     public void OnValueChanged(string input)
     {
         string format = "{0}{1}/{2}{3}/{4}{5}{6}{7}";
         string[] array = new string[input.Length];
 
         int index = format.IndexOf("{" + (input.Length - 1) + "}");
         if (input.Length == 0) {
             _outputField.text = string.Empty;
             return;
         }
 
         if (index >= 0) {
             format = format.Substring(0, index + 3);
         } else {
             _inputField.text = _lastValidInput;
             return;
         }
 
         for (index = 0 ; index < input.Length; ++index)
             array[index] = string.Empty + input[index];
 
         _lastValidInput = input;
         _outputField.text = string.Format(format, array);
     }
 }

with-caret.png (10.5 kB)
with-selection.png (10.6 kB)
Show more comments
avatar image Mukabr · Aug 05, 2017 at 04:26 PM 0
Share

Thanks for the answer @Hellium I try using the "2nd update" option but does not work for formats that have more than 9 digits, so I made a little change to your code and now it works as expected:

      public UnityEngine.UI.InputField inputField;
      // The Text component showing your formatted string
      public UnityEngine.UI.Text text;
      private string lastValidInput = string.Empty;
      private void Awake()
      {
          inputField.onValueChanged.AddListener( OnValueChanged );
      }
      private void OnValueChanged( string input ) // Supposing input = "12345678901"
      {
          string format = "{0}{1}/{2}{3}/{4}{5}{6}{7}/{8}{9}{10}" ;
          string[] array = new string[input.Length];
          int index = format.IndexOf("{" + (input.Length - 1) + "}");
          if ( input.Length == 0 )
          {
              text.text = string.Empty;
              return;
          }
          if ( index >= 0 )
          {
              int n = inputField.text.Length;
              int toAdd = (n == 1) ? 3 : $$anonymous$$athf.CeilToInt($$anonymous$$athf.Log10(n)) + 2;
          format = format.Substring( 0, index + toAdd );
          }
          else
          {
              inputField.text = lastValidInput;
              return;
          }
          for ( index = 0 ; index < input.Length ; ++index )
              array[index] = string.Empty + input[index];
          lastValidInput = input;
          text.text = string.Format( format, array ); // Will output 12/34/5678/901
      }
avatar image
0

Answer by RobAnthem · Jan 05, 2017 at 05:59 PM

Take a look at .NET's formatting System.String,Format It should cover basically everything you are looking to do.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image IntrudeN313 · Jan 05, 2017 at 06:38 PM 0
Share

I looked at it, but the problem isn't the format, it's how I can make the Unity UI InputField work like the ones in this GIF: https://raw.githubusercontent.com/viniciusmo/V$$anonymous$$askTextField/master/Resources/vmasktextfield.gif

Thank you for the help!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

14 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Catching get focused for UI InputField 0 Answers

Deactivate input field, NOT set interactable to false 1 Answer

Cannot clear the Input Field from Inspector 1 Answer

Multiple Cars not working 1 Answer

UI Input field that grows in size with each return line 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges