diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj
index f883a241e..d6a695e4c 100644
--- a/src/Android/Android.csproj
+++ b/src/Android/Android.csproj
@@ -68,6 +68,7 @@
+
diff --git a/src/Android/Renderers/BoxedView/Cells/EntryCellRenderer.cs b/src/Android/Renderers/BoxedView/Cells/EntryCellRenderer.cs
new file mode 100644
index 000000000..14700f67c
--- /dev/null
+++ b/src/Android/Renderers/BoxedView/Cells/EntryCellRenderer.cs
@@ -0,0 +1,328 @@
+using Android.Content;
+using Android.Content.Res;
+using Android.OS;
+using Android.Runtime;
+using Android.Text;
+using Android.Text.Method;
+using Android.Views;
+using Android.Views.InputMethods;
+using Android.Widget;
+using Java.Lang;
+using System;
+using System.ComponentModel;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.Android;
+
+[assembly: ExportRenderer(typeof(Bit.App.Controls.BoxedView.EntryCell),
+ typeof(Bit.Droid.Renderers.BoxedView.EntryCellRenderer))]
+namespace Bit.Droid.Renderers.BoxedView
+{
+ [Preserve(AllMembers = true)]
+ public class EntryCellRenderer : BaseCellRenderer
+ { }
+
+ [Preserve(AllMembers = true)]
+ public class EntryCellView : BaseCellView, ITextWatcher, TextView.IOnFocusChangeListener,
+ TextView.IOnEditorActionListener
+ {
+ private CustomEditText _editText;
+
+ public EntryCellView(Context context, Cell cell)
+ : base(context, cell)
+ {
+ _editText = new CustomEditText(context);
+
+ _editText.Focusable = true;
+ _editText.ImeOptions = ImeAction.Done;
+ _editText.SetOnEditorActionListener(this);
+
+ _editText.OnFocusChangeListener = this;
+ _editText.SetSingleLine(true);
+ _editText.Ellipsize = TextUtils.TruncateAt.End;
+
+ _editText.InputType |= InputTypes.TextFlagNoSuggestions; // Disabled spell check
+ _editText.Background.Alpha = 0; // Hide underline
+
+ _editText.ClearFocusAction = DoneEdit;
+ Click += EntryCellView_Click;
+
+ using(var lParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent,
+ ViewGroup.LayoutParams.WrapContent))
+ {
+ CellContent.AddView(_editText, lParams);
+ }
+ }
+
+ App.Controls.BoxedView.EntryCell _EntryCell => Cell as App.Controls.BoxedView.EntryCell;
+
+ public override void UpdateCell()
+ {
+ UpdateValueText();
+ UpdateValueTextColor();
+ UpdateValueTextFontSize();
+ UpdateKeyboard();
+ UpdatePlaceholder();
+ UpdateAccentColor();
+ UpdateTextAlignment();
+ UpdateIsPassword();
+ base.UpdateCell();
+ }
+
+ public override void CellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.CellPropertyChanged(sender, e);
+ if(e.PropertyName == App.Controls.BoxedView.EntryCell.ValueTextProperty.PropertyName)
+ {
+ UpdateValueText();
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.EntryCell.ValueTextFontSizeProperty.PropertyName)
+ {
+ UpdateWithForceLayout(UpdateValueTextFontSize);
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.EntryCell.ValueTextColorProperty.PropertyName)
+ {
+ UpdateWithForceLayout(UpdateValueTextColor);
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.EntryCell.KeyboardProperty.PropertyName)
+ {
+ UpdateKeyboard();
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.EntryCell.PlaceholderProperty.PropertyName)
+ {
+ UpdatePlaceholder();
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.EntryCell.AccentColorProperty.PropertyName)
+ {
+ UpdateAccentColor();
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.EntryCell.TextAlignmentProperty.PropertyName)
+ {
+ UpdateTextAlignment();
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.EntryCell.IsPasswordProperty.PropertyName)
+ {
+ UpdateIsPassword();
+ }
+ }
+
+ public override void ParentPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.ParentPropertyChanged(sender, e);
+ if(e.PropertyName == App.Controls.BoxedView.BoxedView.CellValueTextColorProperty.PropertyName)
+ {
+ UpdateValueTextColor();
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.BoxedView.CellValueTextFontSizeProperty.PropertyName)
+ {
+ UpdateWithForceLayout(UpdateValueTextFontSize);
+ }
+ else if(e.PropertyName == App.Controls.BoxedView.BoxedView.CellAccentColorProperty.PropertyName)
+ {
+ UpdateAccentColor();
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if(disposing)
+ {
+ Click -= EntryCellView_Click;
+ _editText.RemoveFromParent();
+ _editText.SetOnEditorActionListener(null);
+ _editText.RemoveTextChangedListener(this);
+ _editText.OnFocusChangeListener = null;
+ _editText.ClearFocusAction = null;
+ _editText.Dispose();
+ _editText = null;
+ }
+ base.Dispose(disposing);
+ }
+
+ protected override void SetEnabledAppearance(bool isEnabled)
+ {
+ if(isEnabled)
+ {
+ _editText.Enabled = true;
+ _editText.Alpha = 1.0f;
+ }
+ else
+ {
+ _editText.Enabled = false;
+ _editText.Alpha = 0.3f;
+ }
+ base.SetEnabledAppearance(isEnabled);
+ }
+
+ private void EntryCellView_Click(object sender, EventArgs e)
+ {
+ _editText.RequestFocus();
+ ShowKeyboard(_editText);
+ }
+
+ private void UpdateValueText()
+ {
+ _editText.RemoveTextChangedListener(this);
+ if(_editText.Text != _EntryCell.ValueText)
+ {
+ _editText.Text = _EntryCell.ValueText;
+ }
+ _editText.AddTextChangedListener(this);
+ }
+
+ private void UpdateValueTextFontSize()
+ {
+ if(_EntryCell.ValueTextFontSize > 0)
+ {
+ _editText.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)_EntryCell.ValueTextFontSize);
+ }
+ else if(CellParent != null)
+ {
+ _editText.SetTextSize(Android.Util.ComplexUnitType.Sp, (float)CellParent.CellValueTextFontSize);
+ }
+ }
+
+ private void UpdateValueTextColor()
+ {
+ if(_EntryCell.ValueTextColor != Color.Default)
+ {
+ _editText.SetTextColor(_EntryCell.ValueTextColor.ToAndroid());
+ }
+ else if(CellParent != null && CellParent.CellValueTextColor != Color.Default)
+ {
+ _editText.SetTextColor(CellParent.CellValueTextColor.ToAndroid());
+ }
+ }
+
+ private void UpdateKeyboard()
+ {
+ _editText.InputType = _EntryCell.Keyboard.ToInputType() | InputTypes.TextFlagNoSuggestions;
+ }
+
+ private void UpdateIsPassword()
+ {
+ _editText.TransformationMethod = _EntryCell.IsPassword ? new PasswordTransformationMethod() : null;
+ }
+
+ private void UpdatePlaceholder()
+ {
+ _editText.Hint = _EntryCell.Placeholder;
+ _editText.SetHintTextColor(Android.Graphics.Color.Rgb(210, 210, 210));
+ }
+
+ private void UpdateTextAlignment()
+ {
+ _editText.Gravity = _EntryCell.TextAlignment.ToAndroidHorizontal();
+ }
+
+ private void UpdateAccentColor()
+ {
+ if(_EntryCell.AccentColor != Color.Default)
+ {
+ ChangeTextViewBack(_EntryCell.AccentColor.ToAndroid());
+ }
+ else if(CellParent != null && CellParent.CellAccentColor != Color.Default)
+ {
+ ChangeTextViewBack(CellParent.CellAccentColor.ToAndroid());
+ }
+ }
+
+ private void ChangeTextViewBack(Android.Graphics.Color accent)
+ {
+ var colorlist = new ColorStateList(
+ new int[][]
+ {
+ new int[]{Android.Resource.Attribute.StateFocused},
+ new int[]{-Android.Resource.Attribute.StateFocused},
+ },
+ new int[] {
+ Android.Graphics.Color.Argb(255,accent.R,accent.G,accent.B),
+ Android.Graphics.Color.Argb(255, 200, 200, 200)
+ });
+ _editText.Background.SetTintList(colorlist);
+ }
+
+ private void DoneEdit()
+ {
+ var entryCell = (IEntryCellController)Cell;
+ entryCell.SendCompleted();
+ _editText.ClearFocus();
+ ClearFocus();
+ }
+
+ private void HideKeyboard(Android.Views.View inputView)
+ {
+ using(var inputMethodManager = (InputMethodManager)_Context.GetSystemService(Context.InputMethodService))
+ {
+ IBinder windowToken = inputView.WindowToken;
+ if(windowToken != null)
+ {
+ inputMethodManager.HideSoftInputFromWindow(windowToken, HideSoftInputFlags.None);
+ }
+ }
+ }
+
+ private void ShowKeyboard(Android.Views.View inputView)
+ {
+ using(var inputMethodManager = (InputMethodManager)_Context.GetSystemService(Context.InputMethodService))
+ {
+ inputMethodManager.ShowSoftInput(inputView, ShowFlags.Forced);
+ inputMethodManager.ToggleSoftInput(ShowFlags.Forced, HideSoftInputFlags.ImplicitOnly);
+ }
+ }
+
+ bool TextView.IOnEditorActionListener.OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
+ {
+ if(actionId == ImeAction.Done || (actionId == ImeAction.ImeNull && e.KeyCode == Keycode.Enter))
+ {
+ HideKeyboard(v);
+ DoneEdit();
+ }
+ return true;
+ }
+
+ void ITextWatcher.AfterTextChanged(IEditable s)
+ { }
+
+ void ITextWatcher.BeforeTextChanged(ICharSequence s, int start, int count, int after)
+ { }
+
+ void ITextWatcher.OnTextChanged(ICharSequence s, int start, int before, int count)
+ {
+ _EntryCell.ValueText = s?.ToString();
+ }
+
+ void IOnFocusChangeListener.OnFocusChange(Android.Views.View v, bool hasFocus)
+ {
+ if(hasFocus)
+ {
+ // Show underline when on focus.
+ _editText.Background.Alpha = 100;
+ }
+ else
+ {
+ // Hide underline
+ _editText.Background.Alpha = 0;
+ }
+ }
+ }
+
+ [Preserve(AllMembers = true)]
+ internal class CustomEditText : EditText
+ {
+ public CustomEditText(Context context)
+ : base(context)
+ { }
+
+ public Action ClearFocusAction { get; set; }
+
+ public override bool OnKeyPreIme(Keycode keyCode, KeyEvent e)
+ {
+ if(keyCode == Keycode.Back && e.Action == KeyEventActions.Up)
+ {
+ ClearFocus();
+ ClearFocusAction?.Invoke();
+ }
+ return base.OnKeyPreIme(keyCode, e);
+ }
+ }
+}
diff --git a/src/Android/Renderers/BoxedView/Cells/LabelCellRenderer.cs b/src/Android/Renderers/BoxedView/Cells/LabelCellRenderer.cs
index 1337d5f0a..84224ed65 100644
--- a/src/Android/Renderers/BoxedView/Cells/LabelCellRenderer.cs
+++ b/src/Android/Renderers/BoxedView/Cells/LabelCellRenderer.cs
@@ -25,13 +25,12 @@ namespace Bit.Droid.Renderers.BoxedView
ValueLabel = new TextView(context);
ValueLabel.SetSingleLine(true);
ValueLabel.Ellipsize = TextUtils.TruncateAt.End;
- ValueLabel.Gravity = GravityFlags.Right;
+ ValueLabel.Gravity = GravityFlags.Left;
- var textParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent,
- ViewGroup.LayoutParams.WrapContent);
- using(textParams)
+ using(var lParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent,
+ ViewGroup.LayoutParams.WrapContent))
{
- CellContent.AddView(ValueLabel, textParams);
+ CellContent.AddView(ValueLabel, lParams);
}
}
diff --git a/src/Android/Renderers/RendererUtils.cs b/src/Android/Renderers/RendererUtils.cs
index 8a66a58e9..249032922 100644
--- a/src/Android/Renderers/RendererUtils.cs
+++ b/src/Android/Renderers/RendererUtils.cs
@@ -38,7 +38,7 @@ namespace Bit.Droid.Renderers
}
}
- public static GravityFlags ToAndroidVertical(this Xamarin.Forms.TextAlignment formsAlignment)
+ public static GravityFlags ToAndroidHorizontal(this Xamarin.Forms.TextAlignment formsAlignment)
{
switch(formsAlignment)
{
@@ -49,7 +49,7 @@ namespace Bit.Droid.Renderers
case Xamarin.Forms.TextAlignment.End:
return GravityFlags.Right | GravityFlags.CenterVertical;
default:
- return GravityFlags.Right | GravityFlags.CenterVertical;
+ return GravityFlags.Left | GravityFlags.CenterVertical;
}
}
diff --git a/src/App/App.xaml.cs b/src/App/App.xaml.cs
index 69550ff96..87c491658 100644
--- a/src/App/App.xaml.cs
+++ b/src/App/App.xaml.cs
@@ -15,7 +15,7 @@ namespace Bit.App
{
InitializeComponent();
- ThemeManager.SetTheme("dark");
+ ThemeManager.SetTheme("light");
MainPage = new TabsPage();
}
diff --git a/src/App/Controls/BoxedView/Cells/EntryCell.cs b/src/App/Controls/BoxedView/Cells/EntryCell.cs
new file mode 100644
index 000000000..5bcf14d86
--- /dev/null
+++ b/src/App/Controls/BoxedView/Cells/EntryCell.cs
@@ -0,0 +1,102 @@
+using System;
+using Xamarin.Forms;
+
+namespace Bit.App.Controls.BoxedView
+{
+ public class EntryCell : BaseCell, IEntryCellController
+ {
+ public static BindableProperty ValueTextProperty = BindableProperty.Create(
+ nameof(ValueText), typeof(string), typeof(EntryCell), default(string),
+ defaultBindingMode: BindingMode.TwoWay);
+ // propertyChanging: ValueTextPropertyChanging);
+
+ public static BindableProperty ValueTextColorProperty = BindableProperty.Create(
+ nameof(ValueTextColor), typeof(Color), typeof(EntryCell), default(Color),
+ defaultBindingMode: BindingMode.OneWay);
+
+ public static BindableProperty ValueTextFontSizeProperty = BindableProperty.Create(
+ nameof(ValueTextFontSize), typeof(double), typeof(EntryCell), -1.0,
+ defaultBindingMode: BindingMode.OneWay);
+
+ public static BindableProperty KeyboardProperty = BindableProperty.Create(
+ nameof(Keyboard), typeof(Keyboard), typeof(EntryCell), Keyboard.Default,
+ defaultBindingMode: BindingMode.OneWay);
+
+ public static BindableProperty PlaceholderProperty = BindableProperty.Create(
+ nameof(Placeholder), typeof(string), typeof(EntryCell), default(string),
+ defaultBindingMode: BindingMode.OneWay);
+
+ public static BindableProperty TextAlignmentProperty = BindableProperty.Create(
+ nameof(TextAlignment), typeof(TextAlignment), typeof(EntryCell), TextAlignment.Start,
+ defaultBindingMode: BindingMode.OneWay);
+
+ public static BindableProperty AccentColorProperty = BindableProperty.Create(
+ nameof(AccentColor), typeof(Color), typeof(EntryCell), default(Color),
+ defaultBindingMode: BindingMode.OneWay);
+
+ public static BindableProperty IsPasswordProperty = BindableProperty.Create(
+ nameof(IsPassword), typeof(bool), typeof(EntryCell), default(bool),
+ defaultBindingMode: BindingMode.OneWay);
+
+ public string ValueText
+ {
+ get => (string)GetValue(ValueTextProperty);
+ set => SetValue(ValueTextProperty, value);
+ }
+
+ public Color ValueTextColor
+ {
+ get => (Color)GetValue(ValueTextColorProperty);
+ set => SetValue(ValueTextColorProperty, value);
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double ValueTextFontSize
+ {
+ get => (double)GetValue(ValueTextFontSizeProperty);
+ set => SetValue(ValueTextFontSizeProperty, value);
+ }
+
+ public Keyboard Keyboard
+ {
+ get => (Keyboard)GetValue(KeyboardProperty);
+ set => SetValue(KeyboardProperty, value);
+ }
+
+ public string Placeholder
+ {
+ get => (string)GetValue(PlaceholderProperty);
+ set => SetValue(PlaceholderProperty, value);
+ }
+
+ public TextAlignment TextAlignment
+ {
+ get => (TextAlignment)GetValue(TextAlignmentProperty);
+ set => SetValue(TextAlignmentProperty, value);
+ }
+
+ public Color AccentColor
+ {
+ get => (Color)GetValue(AccentColorProperty);
+ set => SetValue(AccentColorProperty, value);
+ }
+
+ public bool IsPassword
+ {
+ get => (bool)GetValue(IsPasswordProperty);
+ set => SetValue(IsPasswordProperty, value);
+ }
+
+ public event EventHandler Completed;
+
+ public void SendCompleted()
+ {
+ Completed?.Invoke(this, EventArgs.Empty);
+ }
+
+ private static void ValueTextPropertyChanging(BindableObject bindable, object oldValue, object newValue)
+ {
+ // Check changes
+ }
+ }
+}
diff --git a/src/App/Pages/SettingsPage.xaml b/src/App/Pages/SettingsPage.xaml
index da33251a0..310d40ad4 100644
--- a/src/App/Pages/SettingsPage.xaml
+++ b/src/App/Pages/SettingsPage.xaml
@@ -11,9 +11,22 @@
-
-
-
+
+
+
+
+
+
+
+