Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
EditText.Android.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 #if SILICONSTUDIO_PLATFORM_ANDROID
5 using Android.Content;
6 using Android.Text;
7 using Android.Views;
8 using Android.Views.InputMethods;
9 using Android.Widget;
10 using Android.Text.Method;
11 using SiliconStudio.Core;
12 using Exception = System.Exception;
13 
14 namespace SiliconStudio.Paradox.UI.Controls
15 {
16  public partial class EditText
17  {
18  private static MyAndroidEditText staticEditText;
19  private static EditText activeEditText;
20 
21  private MyAndroidEditText editText;
22 
23  private InputMethodManager inputMethodManager;
24 
25  private class MyAndroidEditText : Android.Widget.EditText
26  {
27  public MyAndroidEditText(Context context)
28  : base(context)
29  {
30  }
31 
32  public override bool OnKeyPreIme(Keycode keyCode, KeyEvent e)
33  {
34  if (e.KeyCode == Keycode.Back)
35  {
36  if (activeEditText != null)
37  activeEditText.IsSelectionActive = false;
38 
39  return true;
40  }
41 
42  return base.OnKeyPreIme(keyCode, e);
43  }
44 
45  protected override void OnDetachedFromWindow()
46  {
47  base.OnDetachedFromWindow();
48 
49  // Edit text is invalidated and need to be recreated when application is shut down with back key
50  staticEditText = null;
51  }
52  }
53 
54  private static void InitializeStaticImpl()
55  {
56  }
57 
58  protected override void OnUISystemChanged(UISystem system)
59  {
60  base.OnUISystemChanged(system);
61 
62  // create the Android OS edit text only when element is inserted into hierarchy.
63  if (staticEditText == null)
64  {
65  // create and add the edit text
66  staticEditText = new MyAndroidEditText(PlatformAndroid.Context);
67 
68  var editLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
69  editLayoutParams.SetMargins(75, 200, 75, 0);
70  game.Context.EditTextLayout.AddView(staticEditText, editLayoutParams);
71  }
72  }
73 
74  private void InitializeImpl()
75  {
76  // nothing to do here
77  }
78 
79  private void AndroidEditTextOnAfterTextChanged(object sender, AfterTextChangedEventArgs afterTextChangedEventArgs)
80  {
81  if(editText == null)
82  return;
83 
84  var newText = editText.Text;
85  var oldStart = selectionStart;
86  var newStart = SelectionStart;
87 
88  if (newStart <= oldStart) // we erased characters
89  {
90  SetTextInternal(newText, false);
91  }
92  else // we add or replaced characters
93  {
94  // check that new characters are correct.
95  builder.Clear();
96  var predicate = CharacterFilterPredicate;
97  for (int i = oldStart; i < newStart; i++)
98  {
99  var character = newText[i];
100  if (predicate == null || predicate(character))
101  builder.Append(character);
102  }
103 
104  SetTextInternal(newText.Substring(0, oldStart) + builder + newText.Substring(newStart), false);
105  newStart = Math.Min(oldStart + builder.Length, text.Length);
106  }
107 
108  UpdateTextToEditImpl();
109  Select(newStart, 0);
110  }
111 
112  private void AndroidEditTextOnEditorAction(object sender, TextView.EditorActionEventArgs editorActionEventArgs)
113  {
114  if (editorActionEventArgs.ActionId == ImeAction.Done)
115  IsSelectionActive = false;
116  }
117 
118  private int GetLineCountImpl()
119  {
120  if (editText == null)
121  return 0;
122 
123  return editText.LineCount;
124  }
125 
126  private void OnMaxLinesChangedImpl()
127  {
128  if (editText == null)
129  return;
130 
131  editText.SetMaxLines(MaxLines);
132  }
133 
134  private void OnMinLinesChangedImpl()
135  {
136  if (editText == null)
137  return;
138 
139  editText.SetMinLines(MinLines);
140  }
141 
142  private void ActivateEditTextImpl()
143  {
144  if(activeEditText != null)
145  throw new Exception("Internal error: Can not activate edit text, another edit text is already active");
146 
147  activeEditText = this;
148  editText = staticEditText;
149 
150  // set up the initial state of the android EditText
151  UpdateInputTypeImpl();
152 
153  editText.SetMaxLines(MaxLines);
154  editText.SetMinLines(MinLines);
155 
156  UpdateTextToEditImpl();
157  UpdateSelectionToEditImpl();
158 
159  // add callbacks
160  editText.EditorAction += AndroidEditTextOnEditorAction;
161  editText.AfterTextChanged += AndroidEditTextOnAfterTextChanged;
162 
163  // add the edit to the overlay layout and show the layout
164  game.Context.EditTextLayout.Visibility = ViewStates.Visible;
165 
166  // set the focus to the edit box
167  editText.RequestFocus();
168 
169  // activate the ime (show the keyboard)
170  inputMethodManager = (InputMethodManager)PlatformAndroid.Context.GetSystemService(Context.InputMethodService);
171  inputMethodManager.ShowSoftInput(staticEditText, ShowFlags.Forced);
172  }
173 
174  private void DeactivateEditTextImpl()
175  {
176  if (activeEditText == null)
177  throw new Exception("Internal error: Can not deactivate the EditText, it is already nullified");
178 
179  // remove callbacks
180  editText.EditorAction -= AndroidEditTextOnEditorAction;
181  editText.AfterTextChanged -= AndroidEditTextOnAfterTextChanged;
182 
183  editText.ClearFocus();
184 
185  editText = null;
186  activeEditText = null;
187 
188  // remove the edit text from the layout and hide the layout
189  game.Context.EditTextLayout.Visibility = ViewStates.Gone;
190 
191  // deactivate the ime (hide the keyboard)
192  if (staticEditText != null) // staticEditText can be null if window have already been detached.
193  inputMethodManager.HideSoftInputFromWindow(staticEditText.WindowToken, HideSoftInputFlags.None);
194  inputMethodManager = null;
195 
196  FocusedElement = null;
197  }
198 
199  private static void OnTouchMoveImpl(TouchEventArgs args)
200  {
201  }
202 
203  private static void OnTouchDownImpl(TouchEventArgs args)
204  {
205  }
206 
207  private void UpdateInputTypeImpl()
208  {
209  if (editText == null)
210  return;
211 
212  if (ShouldHideText)
213  {
214  editText.TransformationMethod = new PasswordTransformationMethod();
215  editText.InputType = InputTypes.ClassText | InputTypes.TextVariationPassword;
216  }
217  else
218  {
219  editText.TransformationMethod = null;
220  editText.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
221  }
222  }
223 
224  private void UpdateTextToEditImpl()
225  {
226  if(editText == null)
227  return;
228 
229  if(editText.Text != Text) // avoid infinite text changed triggering loop.
230  editText.Text = text;
231  }
232 
233  private void UpdateSelectionFromEditImpl()
234  {
235  if (editText == null)
236  return;
237 
238  selectionStart = editText.SelectionStart;
239  selectionStop = editText.SelectionEnd;
240  }
241 
242  private void UpdateSelectionToEditImpl()
243  {
244  if (editText == null)
245  return;
246 
247  editText.SetSelection(selectionStart, selectionStop);
248  }
249  }
250 }
251 
252 #endif