Xamarin.Forms Pickerの右端に画像を表示する方法

今回はXamarin.Forms Pickerの右端に画像を表示する方法についてです。
Rendererを使うことで実装できます。

1.iOSのResourcesフォルダとAndroidのdrawableフォルダ内に画像(今回はpicker_image.pngという画像)を追加

2.CustomPickerを共通プロジェクトに追加

using System;
using Xamarin.Forms;

namespace testPrj {
    public class CustomPicker : Picker {
        public CustomPicker(){}

        public static readonly BindableProperty ImageProperty =
            BindableProperty.Create(nameof(Image), typeof(string), typeof(CustomPicker), string.Empty);
        public string Image {
            get { return (string)GetValue(ImageProperty); }
            set { SetValue(ImageProperty, value); }
        }

        public static readonly BindableProperty ImageWidthProperty =
            BindableProperty.Create(nameof(ImageWidth), typeof(double), typeof(CustomPicker),10d);
        public double ImageWidth {
            get { return (double)GetValue(ImageWidthProperty); }
            set { SetValue(ImageWidthProperty, value); }
        }

        public static readonly BindableProperty ImageHeightProperty =
            BindableProperty.Create(nameof(ImageHeight), typeof(double), typeof(CustomPicker), 10d);
        public double ImageHeight {
            get { return (double)GetValue(ImageHeightProperty); }
            set { SetValue(ImageWidthProperty, value); }
        }
    }
}

3.iOSプロジェクトにCustomPickerのレンダラーを追加

using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using testPrj.iOS;
using testPrj;
using CoreGraphics;

[assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
namespace testPrj.iOS {
    public class CustomPickerRenderer : PickerRenderer {
        public CustomPickerRenderer() {}

        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e) {
            base.OnElementChanged(e);

            if (Control != null) {
                var element = (CustomPicker)Element;
                if (!string.IsNullOrWhiteSpace(element.Image)) {
                    var uIImageView = new UIImageView(new UIImage(element.Image));
                    uIImageView.ContentMode = UIViewContentMode.ScaleAspectFit;
                    uIImageView.Frame = new CGRect(0, 0, element.ImageWidth, element.ImageHeight);
                    var uiView = new UIView(new CGRect(0, 0, element.ImageWidth, element.ImageHeight));
                    uiView.BackgroundColor = UIColor.Clear;
                    uiView.AddSubview(uIImageView);
                    Control.RightView = uiView;
                    Control.RightViewMode = UITextFieldViewMode.Always;
                }
            }
        }
    }
}

4.AndroidプロジェクトにCustomPickerのレンダラーを追加

using testPrj;
using testPrj.Droid;
using Xamarin.Forms;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Support.V4.Content;
using Xamarin.Forms.Platform.Android;
using Android.Content;

[assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
namespace testPrj.Droid {
    public class CustomPickerRenderer : PickerRenderer {
        CustomPicker element;
        public CustomPickerRenderer(Context context) : base(context) {}

        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e) {
            base.OnElementChanged(e);
            element = (CustomPicker)this.Element;
            if (Control != null && this.Element != null && !string.IsNullOrEmpty(element.Image))
                Control.Background = SetBackground(element.Image, element.ImageWidth, element.ImageHeight);
        }

        public LayerDrawable SetBackground(string imagePath, double imageWidth, double imageHeight) {
            Drawable[] layers = { GetDrawable(imagePath, imageWidth, imageHeight) };
            LayerDrawable layerDrawable = new LayerDrawable(layers);
            layerDrawable.SetLayerInset(0, 0, 0, 0, 0);
            return layerDrawable;
        }

        private BitmapDrawable GetDrawable(string imagePath, double imageWidth, double imageHeight) {
            int resID = Resources.GetIdentifier(imagePath, "drawable", this.Context.PackageName);
            var drawable = ContextCompat.GetDrawable(this.Context, resID);
            var bitmap = ((BitmapDrawable)drawable).Bitmap;
            var context = Xamarin.Essentials.Platform.AppContext;
            var resources = context.Resources;
            var result = new BitmapDrawable(Resources, Bitmap.CreateScaledBitmap(bitmap, (int)(imageWidth * resources.DisplayMetrics.Density), (int)(imageHeight * resources.DisplayMetrics.Density), true));
            result.Gravity = Android.Views.GravityFlags.Right;
            return result;
        }
    }
}

5.CustomPickerをImage,ImageWidth,ImageHeightを指定して使用する

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="test1.MainPage"
    xmlns:local="clr-namespace:test1">
    <StackLayout
        HorizontalOptions="FillAndExpand"
        VerticalOptions="FillAndExpand">
        <local:CustomPicker
            Margin="20,10"
            Image="picker_image"
            ImageWidth="40"
            ImageHeight="20"
            BackgroundColor="LightGray"
            VerticalOptions="CenterAndExpand"
            HorizontalOptions="FillAndExpand"
            HeightRequest="50"/>
    </StackLayout>
</ContentPage>

↓iOS

↓Android

タイトルとURLをコピーしました