如何在Xamarin按钮自定义渲染器的C#类中添加第二张图片
嘿,这事儿我熟!要在Xamarin的自定义ButtonRenderer里给按钮左右各加一张图,核心思路是在对应平台的渲染器里,把原生按钮的内容替换成包含左图、文本、右图的组合布局(因为原生Button默认只支持单图+文本)。下面分Android和iOS两个平台给你具体实现代码:
Android平台实现
在Android项目里,咱们可以用LinearLayout来组合左ImageView、文本TextView、右ImageView,然后把这个LinearLayout作为原生按钮的内容容器:
using Android.Content; using Android.Widget; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRenderer))] namespace YourAppName.Droid.Renderers { public class CustomButtonRenderer : ButtonRenderer { public CustomButtonRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<Button> e) { base.OnElementChanged(e); if (Control != null && e.NewElement != null) { // 保存原按钮的背景样式,避免自定义布局后丢失原有样式 var originalBackground = Control.Background; // 创建左右图片控件,替换成你的实际资源ID var leftImage = new ImageView(Context); leftImage.SetImageResource(Resource.Drawable.left_icon); var rightImage = new ImageView(Context); rightImage.SetImageResource(Resource.Drawable.right_icon); // 创建文本控件,继承原按钮的文本和大小 var textView = new TextView(Context) { Text = Control.Text, Gravity = Android.Views.GravityFlags.Center, TextSize = Control.TextSize / Resources.DisplayMetrics.Density }; // 用线性布局组合三个元素,水平排列且整体居中 var layout = new LinearLayout(Context) { Orientation = Orientation.Horizontal, Gravity = Android.Views.GravityFlags.Center }; // 设置布局参数:左右图固定宽高,文本占剩余空间,添加间距 var imageParams = new LinearLayout.LayoutParams(50, 50); imageParams.SetMargins(10, 0, 10, 0); var textParams = new LinearLayout.LayoutParams(0, LayoutParams.MatchParent) { Weight = 1 }; layout.AddView(leftImage, imageParams); layout.AddView(textView, textParams); layout.AddView(rightImage, imageParams); // 替换按钮原有内容,恢复原背景 Control.RemoveAllViews(); Control.AddView(layout); Control.Background = originalBackground; } } // 处理文本动态更新的情况 protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName == Button.TextProperty.PropertyName && Control != null) { var textView = ((LinearLayout)Control.GetChildAt(0)).GetChildAt(1) as TextView; textView.Text = Element.Text; } } } }
iOS平台实现
iOS的UIButton本身可以通过调整边距实现单图+文本,但要左右双图的话,直接给按钮添加两个UIImageView子视图会更灵活:
using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRenderer))] namespace YourAppName.iOS.Renderers { public class CustomButtonRenderer : ButtonRenderer { private UIImageView _leftImageView; private UIImageView _rightImageView; protected override void OnElementChanged(ElementChangedEventArgs<Button> e) { base.OnElementChanged(e); if (Control != null && e.NewElement != null) { // 隐藏按钮默认的图片和文本容器,改用自定义布局 Control.ImageView.Hidden = true; Control.TitleLabel.Hidden = true; // 创建左右图片视图,替换成你的实际图片文件名 _leftImageView = new UIImageView(UIImage.FromBundle("left_icon.png")); _rightImageView = new UIImageView(UIImage.FromBundle("right_icon.png")); _leftImageView.ContentMode = UIViewContentMode.ScaleAspectFit; _rightImageView.ContentMode = UIViewContentMode.ScaleAspectFit; // 添加到按钮的子视图列表 Control.AddSubview(_leftImageView); Control.AddSubview(_rightImageView); // 触发布局更新 Control.SetNeedsLayout(); } } // 手动调整各元素的位置和大小 public override void LayoutSubviews() { base.LayoutSubviews(); if (Control == null) return; var buttonBounds = Control.Bounds; var imageSize = new CoreGraphics.CGSize(40, 40); // 按需调整图片尺寸 var padding = 10; // 图片与文本的间距 // 左图位置:左内边距+垂直居中 _leftImageView.Frame = new CoreGraphics.CGRect( padding, (buttonBounds.Height - imageSize.Height)/2, imageSize.Width, imageSize.Height ); // 右图位置:右内边距+垂直居中 _rightImageView.Frame = new CoreGraphics.CGRect( buttonBounds.Width - imageSize.Width - padding, (buttonBounds.Height - imageSize.Height)/2, imageSize.Width, imageSize.Height ); // 文本位置:左图右侧到右图左侧之间,垂直居中 var textFrame = new CoreGraphics.CGRect( _leftImageView.Frame.Right + padding, 0, _rightImageView.Frame.Left - _leftImageView.Frame.Right - 2*padding, buttonBounds.Height ); Control.TitleLabel.Frame = textFrame; Control.TitleLabel.Hidden = false; Control.TitleLabel.TextAlignment = UITextAlignment.Center; } // 处理文本动态更新的情况 protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName == Button.TextProperty.PropertyName) { Control.TitleLabel.Text = Element.Text; Control.SetNeedsLayout(); } } } }
额外注意点
- 记得替换代码里的图片资源(Android的
Resource.Drawable.xxx和iOS的xxx.png),并确保图片文件已添加到对应平台项目,设置正确的生成操作(Android设为AndroidResource,iOS设为BundleResource)。 - 如果你的按钮是自定义的Xamarin.Forms控件(不是原生Button),把
typeof(Button)换成你的自定义按钮类型即可。 - 要是需要动态切换图片,可以给自定义按钮添加绑定属性,然后在渲染器的
OnElementPropertyChanged方法里更新图片源。
内容的提问来源于stack exchange,提问作者M_B
相关产品推荐
相关产品推荐

