如何在 Xamarin.Forms 内的 Android.Widget.EditText 上实现 Android.Text.ISpannable?
How do I implement Android.Text.ISpannable on a Android.Widget.EditText inside of Xamarin.Forms?
如何在 Xamarin.Forms 内的 Android.Widget.EditText 上实现 Android.Text.ISpannable?
我调查了 Previous Post but the native java implementation is very different compared to Xamarin. And I don't know how to code it correctly. I found the ,但没有找到 Android。
目标: 点击文本输入控件:我想执行以下任一操作:
- 无
- 移动光标开始或结束(移动光标)
- Select 所有文字。如果您点击单元格并开始键入,您将删除内容并将其替换为新文本。
这可能吗?
此外,link 对应 repository 有问题。请参阅 android 和 iOS 上的“EntryCellRender”。
public class EntryCell : : CellBaseView, Android.Text.ITextWatcher, Android.Widget.TextView.IOnFocusChangeListener, Android.Widget.TextView.IOnEditorActionListener
{
AiEditText _EditText;
...
void EntryCell_Focused( object sender, EventArgs e )
{
_EditText.RequestFocus();
//
switch ( _EntryCell.OnSelectAction )
{
case AiEntryCell.SelectAction.None:
break;
case AiEntryCell.SelectAction.Start:
Selection.SetSelection(_EditText, 0); // Xamarin requires Android.Text.ISpannable implementation.
break;
case AiEntryCell.SelectAction.End:
int position = _EditText.Length();
Selection.SetSelection(_EditText, position); // Xamarin requires Android.Text.ISpannable implementation.
break;
case AiEntryCell.SelectAction.All:
_EditText.SelectAll();
break;
default: throw new ArgumentOutOfRangeException();
}
ShowKeyboard(_EditText);
}
...
}
AiEditText的实现
[Android.Runtime.Preserve(AllMembers = true)]
internal class AiEditText : Android.Widget.EditText, Android.Text.ISpannable
{
public System.Action ClearFocusAction { get; set; }
public AiEditText( Context context ) : base(context) { }
public override bool OnKeyPreIme( Keycode keyCode, KeyEvent e )
{
if ( keyCode != Keycode.Back ||
e.Action != KeyEventActions.Up ) return base.OnKeyPreIme(keyCode, e);
ClearFocus();
ClearFocusAction?.Invoke();
return base.OnKeyPreIme(keyCode, e);
}
public void RemoveSpan( Java.Lang.Object what )
{
throw new NotImplementedException();
}
public void SetSpan( Java.Lang.Object what,
int start,
int end,
[GeneratedEnum] Android.Text.SpanTypes flags )
{
switch ( flags )
{
case SpanTypes.Composing: break;
case SpanTypes.ExclusiveExclusive: break;
case SpanTypes.ExclusiveInclusive: break;
case SpanTypes.InclusiveExclusive: break;
case SpanTypes.InclusiveInclusive: break;
case SpanTypes.Intermediate: break;
case SpanTypes.Paragraph: break;
case SpanTypes.Priority: break;
case SpanTypes.PriorityShift: break;
case SpanTypes.User: break;
case SpanTypes.UserShift: break;
default: throw new ArgumentOutOfRangeException(nameof(flags), flags, null);
}
}
public int GetSpanEnd( Java.Lang.Object tag )
{
throw new NotImplementedException();
}
[return: GeneratedEnum]
public SpanTypes GetSpanFlags( Java.Lang.Object tag )
{
throw new NotImplementedException();
}
public Java.Lang.Object[] GetSpans( int start, int end, Class type )
{
throw new NotImplementedException();
}
public int GetSpanStart( Java.Lang.Object tag )
{
throw new NotImplementedException();
}
public int NextSpanTransition( int start, int limit, Class type )
{
throw new NotImplementedException();
}
public char CharAt( int index ) => Text[index];
public ICharSequence SubSequenceFormatted( int start, int end )
{
throw new NotImplementedException();
}
public IEnumerator<char> GetEnumerator() { return Text.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
如何使用 custom EntryRenderer 来实现它。
创建自定义条目(MyEntry):
public class MyEntry : Entry
{
}
用于Xaml:
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<local:MyEntry Text="In Shared Code" />
...
</ContentPage>
然后在Android中创建自定义渲染器(CustomEntryRenderer)以使用SpannableString
.
public class CustomEntryRenderer:EntryRenderer
{
public CustomEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
//Control.SetBackgroundColor(global::Android.Graphics.Color.LightGreen);
SpannableString ss = new SpannableString("green call bold deleteline underline Italic BackgroundColorSpan");
//color of font
ss.SetSpan(new ForegroundColorSpan(Android.Graphics.Color.Green), 0, 5, SpanTypes.ExclusiveExclusive);
//telephone- link
ss.SetSpan(new URLSpan("tel:4155551212"), 6, 10, SpanTypes.ExclusiveExclusive);
//bold
ss.SetSpan(new StyleSpan(TypefaceStyle.Bold), 11, 15, SpanTypes.ExclusiveExclusive);
//deleteline
ss.SetSpan(new StrikethroughSpan(), 16, 26, SpanTypes.ExclusiveExclusive);
//underline
ss.SetSpan(new UnderlineSpan(), 27, 36, SpanTypes.ExclusiveExclusive);
ss.SetSpan(new ForegroundColorSpan(Android.Graphics.Color.Red), 25, 34, SpanTypes.ExclusiveExclusive);
//image
//Drawable d = Resources.GetDrawable(Resource.Drawable.notification_template_icon_low_bg);
//d.SetBounds(0, 0, d.IntrinsicWidth, d.IntrinsicHeight);
//ImageSpan span = new ImageSpan(d,SpanAlign.Baseline);
//ss.SetSpan(span, 35, 40, SpanTypes.ExclusiveExclusive); //load image
//Italic
ss.SetSpan(new StyleSpan(TypefaceStyle.Italic), 37, 43, SpanTypes.ExclusiveExclusive);
//BackgroundColorSpan
ss.SetSpan(new BackgroundColorSpan(Android.Graphics.Color.Yellow), 44, 63, SpanTypes.ExclusiveExclusive);
//text worked in EditText
Control.SetText(ss,TextView.BufferType.Editable);
Control.MovementMethod = LinkMovementMethod.Instance;
}
}
}
效果:
点击进入单元格操作适用于 android。
public class EntryCell : : CellBaseView, Android.Text.ITextWatcher, Android.Widget.TextView.IOnFocusChangeListener, Android.Widget.TextView.IOnEditorActionListener
{
AiEditText _EditText;
...
public EntryCellView( Context context, Cell cell ) : base(context, cell)
{
...
Click += EntryCellView_Click;
_EditText.Click += EditTextOnClick;
...
}
private void EditTextOnClick( object sender, EventArgs e ) { PerformSelectAction(); }
private void EntryCellView_Click( object sender, EventArgs e )
{
_EditText.RequestFocus();
PerformSelectAction();
ShowKeyboard(_EditText); // EntryCellView_Click
}
protected void PerformSelectAction()
{
_EditText.Cell = _EntryCell;
switch ( _EntryCell.OnSelectAction )
{
case AiEntryCell.SelectAction.None: break;
case AiEntryCell.SelectAction.Start:
_EditText.SetSelection(0, 0);
break;
case AiEntryCell.SelectAction.End:
_EditText.SetSelection(_EditText.Length(), _EditText.Length());
break;
case AiEntryCell.SelectAction.All:
_EditText.SelectAll();
break;
default: throw new ArgumentOutOfRangeException();
}
}
...
}
如何在 Xamarin.Forms 内的 Android.Widget.EditText 上实现 Android.Text.ISpannable?
我调查了 Previous Post but the native java implementation is very different compared to Xamarin. And I don't know how to code it correctly. I found the
目标: 点击文本输入控件:我想执行以下任一操作:
- 无
- 移动光标开始或结束(移动光标)
- Select 所有文字。如果您点击单元格并开始键入,您将删除内容并将其替换为新文本。
这可能吗?
此外,link 对应 repository 有问题。请参阅 android 和 iOS 上的“EntryCellRender”。
public class EntryCell : : CellBaseView, Android.Text.ITextWatcher, Android.Widget.TextView.IOnFocusChangeListener, Android.Widget.TextView.IOnEditorActionListener
{
AiEditText _EditText;
...
void EntryCell_Focused( object sender, EventArgs e )
{
_EditText.RequestFocus();
//
switch ( _EntryCell.OnSelectAction )
{
case AiEntryCell.SelectAction.None:
break;
case AiEntryCell.SelectAction.Start:
Selection.SetSelection(_EditText, 0); // Xamarin requires Android.Text.ISpannable implementation.
break;
case AiEntryCell.SelectAction.End:
int position = _EditText.Length();
Selection.SetSelection(_EditText, position); // Xamarin requires Android.Text.ISpannable implementation.
break;
case AiEntryCell.SelectAction.All:
_EditText.SelectAll();
break;
default: throw new ArgumentOutOfRangeException();
}
ShowKeyboard(_EditText);
}
...
}
AiEditText的实现
[Android.Runtime.Preserve(AllMembers = true)]
internal class AiEditText : Android.Widget.EditText, Android.Text.ISpannable
{
public System.Action ClearFocusAction { get; set; }
public AiEditText( Context context ) : base(context) { }
public override bool OnKeyPreIme( Keycode keyCode, KeyEvent e )
{
if ( keyCode != Keycode.Back ||
e.Action != KeyEventActions.Up ) return base.OnKeyPreIme(keyCode, e);
ClearFocus();
ClearFocusAction?.Invoke();
return base.OnKeyPreIme(keyCode, e);
}
public void RemoveSpan( Java.Lang.Object what )
{
throw new NotImplementedException();
}
public void SetSpan( Java.Lang.Object what,
int start,
int end,
[GeneratedEnum] Android.Text.SpanTypes flags )
{
switch ( flags )
{
case SpanTypes.Composing: break;
case SpanTypes.ExclusiveExclusive: break;
case SpanTypes.ExclusiveInclusive: break;
case SpanTypes.InclusiveExclusive: break;
case SpanTypes.InclusiveInclusive: break;
case SpanTypes.Intermediate: break;
case SpanTypes.Paragraph: break;
case SpanTypes.Priority: break;
case SpanTypes.PriorityShift: break;
case SpanTypes.User: break;
case SpanTypes.UserShift: break;
default: throw new ArgumentOutOfRangeException(nameof(flags), flags, null);
}
}
public int GetSpanEnd( Java.Lang.Object tag )
{
throw new NotImplementedException();
}
[return: GeneratedEnum]
public SpanTypes GetSpanFlags( Java.Lang.Object tag )
{
throw new NotImplementedException();
}
public Java.Lang.Object[] GetSpans( int start, int end, Class type )
{
throw new NotImplementedException();
}
public int GetSpanStart( Java.Lang.Object tag )
{
throw new NotImplementedException();
}
public int NextSpanTransition( int start, int limit, Class type )
{
throw new NotImplementedException();
}
public char CharAt( int index ) => Text[index];
public ICharSequence SubSequenceFormatted( int start, int end )
{
throw new NotImplementedException();
}
public IEnumerator<char> GetEnumerator() { return Text.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
如何使用 custom EntryRenderer 来实现它。
创建自定义条目(MyEntry):
public class MyEntry : Entry
{
}
用于Xaml:
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<local:MyEntry Text="In Shared Code" />
...
</ContentPage>
然后在Android中创建自定义渲染器(CustomEntryRenderer)以使用SpannableString
.
public class CustomEntryRenderer:EntryRenderer
{
public CustomEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
//Control.SetBackgroundColor(global::Android.Graphics.Color.LightGreen);
SpannableString ss = new SpannableString("green call bold deleteline underline Italic BackgroundColorSpan");
//color of font
ss.SetSpan(new ForegroundColorSpan(Android.Graphics.Color.Green), 0, 5, SpanTypes.ExclusiveExclusive);
//telephone- link
ss.SetSpan(new URLSpan("tel:4155551212"), 6, 10, SpanTypes.ExclusiveExclusive);
//bold
ss.SetSpan(new StyleSpan(TypefaceStyle.Bold), 11, 15, SpanTypes.ExclusiveExclusive);
//deleteline
ss.SetSpan(new StrikethroughSpan(), 16, 26, SpanTypes.ExclusiveExclusive);
//underline
ss.SetSpan(new UnderlineSpan(), 27, 36, SpanTypes.ExclusiveExclusive);
ss.SetSpan(new ForegroundColorSpan(Android.Graphics.Color.Red), 25, 34, SpanTypes.ExclusiveExclusive);
//image
//Drawable d = Resources.GetDrawable(Resource.Drawable.notification_template_icon_low_bg);
//d.SetBounds(0, 0, d.IntrinsicWidth, d.IntrinsicHeight);
//ImageSpan span = new ImageSpan(d,SpanAlign.Baseline);
//ss.SetSpan(span, 35, 40, SpanTypes.ExclusiveExclusive); //load image
//Italic
ss.SetSpan(new StyleSpan(TypefaceStyle.Italic), 37, 43, SpanTypes.ExclusiveExclusive);
//BackgroundColorSpan
ss.SetSpan(new BackgroundColorSpan(Android.Graphics.Color.Yellow), 44, 63, SpanTypes.ExclusiveExclusive);
//text worked in EditText
Control.SetText(ss,TextView.BufferType.Editable);
Control.MovementMethod = LinkMovementMethod.Instance;
}
}
}
效果:
点击进入单元格操作适用于 android。
public class EntryCell : : CellBaseView, Android.Text.ITextWatcher, Android.Widget.TextView.IOnFocusChangeListener, Android.Widget.TextView.IOnEditorActionListener
{
AiEditText _EditText;
...
public EntryCellView( Context context, Cell cell ) : base(context, cell)
{
...
Click += EntryCellView_Click;
_EditText.Click += EditTextOnClick;
...
}
private void EditTextOnClick( object sender, EventArgs e ) { PerformSelectAction(); }
private void EntryCellView_Click( object sender, EventArgs e )
{
_EditText.RequestFocus();
PerformSelectAction();
ShowKeyboard(_EditText); // EntryCellView_Click
}
protected void PerformSelectAction()
{
_EditText.Cell = _EntryCell;
switch ( _EntryCell.OnSelectAction )
{
case AiEntryCell.SelectAction.None: break;
case AiEntryCell.SelectAction.Start:
_EditText.SetSelection(0, 0);
break;
case AiEntryCell.SelectAction.End:
_EditText.SetSelection(_EditText.Length(), _EditText.Length());
break;
case AiEntryCell.SelectAction.All:
_EditText.SelectAll();
break;
default: throw new ArgumentOutOfRangeException();
}
}
...
}