Xamarin.Forms使用自定义文本描边渲染器后无法设置TextColor问题
问题根因
- 自定义Renderer构造函数名称与类名不匹配,导致初始化逻辑异常
- 替换原生控件为
StrokeTextView后,未处理XAML/ViewModel中TextColor属性变更的同步逻辑,属性变化无法通知到自定义原生控件 StrokeTextView中内容文本颜色、描边颜色未暴露可设置入口,描边颜色被硬编码为白色,内容颜色未和上层属性绑定
修改方案
1. 修正CustomTextStrokeRenderer代码
using System.ComponentModel; using Android.Content; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; using Project11.CustomForms; using Project11.Droid.CustomRenderer; [assembly: ExportRenderer(typeof(CustomTextStroke), typeof(CustomTextStrokeRenderer))] namespace Project11.Droid.CustomRenderer { public class CustomTextStrokeRenderer : LabelRenderer { Context context; // 修正构造函数名称,和类名保持一致 public CustomTextStrokeRenderer(Context context) : base(context) { this.context = context; } protected override void OnElementChanged(ElementChangedEventArgs<Label> e) { base.OnElementChanged(e); if (e.NewElement != null) { StrokeTextView strokeTextView = new StrokeTextView(context); // 初始化同步所有基础属性 strokeTextView.Text = e.NewElement.Text; strokeTextView.SetTextColor(e.NewElement.TextColor.ToAndroid()); strokeTextView.TextSize = e.NewElement.FontSize; // 可自行调整描边宽度、描边颜色参数 strokeTextView.SetStrokeConfig(5, Android.Graphics.Color.White); SetNativeControl(strokeTextView); } } // 监听上层属性变更,同步到原生控件 protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (Control == null || Element == null) return; if (e.PropertyName == Label.TextColorProperty.PropertyName) { Control.SetTextColor(Element.TextColor.ToAndroid()); } else if (e.PropertyName == Label.TextProperty.PropertyName) { Control.Text = Element.Text; } else if (e.PropertyName == Label.FontSizeProperty.PropertyName) { Control.TextSize = Element.FontSize; } } } }
2. 优化StrokeTextView,暴露配置入口
using Android.Content; using Android.Graphics; using Android.Util; using Android.Widget; namespace Project11.CustomForms { public class StrokeTextView : TextView { private TextView borderText = null; private Color _strokeColor = Color.White; private float _strokeWidth = 5; public StrokeTextView(Context context) : base(context) { borderText = new TextView(context); Init(); } public StrokeTextView(Context context, IAttributeSet attrs) : base(context, attrs) { borderText = new TextView(context, attrs); Init(); } public StrokeTextView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle) { borderText = new TextView(context, attrs, defStyle); Init(); } // 新增描边配置方法 public void SetStrokeConfig(float strokeWidth, Color strokeColor) { _strokeWidth = strokeWidth; _strokeColor = strokeColor; if (borderText != null) { TextPaint tp1 = borderText.Paint; tp1.StrokeWidth = _strokeWidth; borderText.SetTextColor(_strokeColor); Invalidate(); } } public void Init() { TextPaint tp1 = borderText.Paint; tp1.StrokeWidth = _strokeWidth; tp1.SetStyle(Paint.Style.Stroke); borderText.SetTextColor(_strokeColor); borderText.Gravity = Gravity; } public override ViewGroup.LayoutParams LayoutParameters { get => base.LayoutParameters; set => base.LayoutParameters = value; } protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) { string tt = borderText.Text; if (tt == null || !tt.Equals(this.Text)) { borderText.Text = Text; PostInvalidate(); } base.OnMeasure(widthMeasureSpec, heightMeasureSpec); borderText.Measure(widthMeasureSpec, heightMeasureSpec); } protected override void OnLayout(bool changed, int left, int top, int right, int bottom) { base.OnLayout(changed, left, top, right, bottom); borderText.Layout(left, top, right, bottom); } protected override void OnDraw(Canvas canvas) { borderText.Draw(canvas); base.OnDraw(canvas); } } }
3. 可选扩展
如果需要在XAML中直接设置描边颜色、宽度,可以在CustomTextStroke中添加对应可绑定属性,然后在Renderer中监听属性变更同步到StrokeTextView即可。
修改后XAML中的静态TextColor设置和ViewModel绑定的TextColor都可以正常生效。
内容的提问来源于stack exchange,提问作者Steven-Carrot
相关产品推荐
相关产品推荐

