You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 20:45:04