Windows系のあれこれ

港区の SIer で Windows 系の開発に従事している SE みたいな人です。Xamarin 中心です。

Xamarin.FormsでiOSのEditorの枠線をEntryみたいにしたい

Xamarin.Forms で複数行のテキストボックス(Editor)を配置した場合、以下の様になります。
f:id:ShunsukeKawai:20170209173238p:plain:w300

ちゃんと置いてあるのに真っ白です。

<StackLayout Margin="20">
    <Editor HeightRequest="150"/>
</StackLayout>

入力はもちろんできます。
f:id:ShunsukeKawai:20170209173530p:plain:w300

うーん(´・ω・`)これが iOS では標準なのか?

Xamarin.Forms の標準コントロールがどのネイティブコントロールマッピングされているかは以下のページに書いてあります。
Renderer Base Classes and Native Controls - Xamarin
Entry は UITextField に Editor は UITextView にマッピングされてます。


ということで Effect です。
といっても標準の UITextField の Border がどうなってるのかよくわからなかったので、アナログ戦法で寄せました。

  • iOS のプロジェクトに以下を追加します。

BorderEffect.cs

using EditorBorder.iOS.Effects;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ResolutionGroupName("Effects")]
[assembly: ExportEffect(typeof(BorderEffect), "BorderEffect")]
namespace EditorBorder.iOS.Effects
{
    public class BorderEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            Control.Layer.BorderWidth = 0.6f;
            Control.Layer.BorderColor = Color.FromRgb(209, 209, 209).ToCGColor();
            Control.Layer.CornerRadius = 5;
        }

        protected override void OnDetached()
        {
            Control.Layer.BorderWidth = 0.0f;
        }
    }
}
  • PCL のプロジェクトに以下を追加します。

BorderEffect.cs

using Xamarin.Forms;

namespace EditorBorder.Effects
{
    public class BorderEffect : RoutingEffect
    {
        public BorderEffect() : base("Effects.BorderEffect")
        {
        }
    }
}
  • 画面の XAML に作成した Effect を適用します。

Effect は違うコントロールにも適用できるので、とりあえず見た目を確認するため生の Entry と適用した Entry を並べます。
MainPage.xaml

<StackLayout Margin="20">
    <Entry Text="標準のEntry" />
    <Entry Text="EffectしたEntry">
        <Entry.Effects>
            <effects:BorderEffect />
        </Entry.Effects>
    </Entry>
</StackLayout>

で実行すると…
f:id:ShunsukeKawai:20170209174941p:plain:w300

お!いい感じやん!

って事で、本来の目的である Editor に Effect を適用します。
MainPage.xaml

<StackLayout Margin="20">
    <Entry Text="標準のEntry" />
    <Entry Text="EffectしたEntry">
        <Entry.Effects>
            <effects:BorderEffect />
        </Entry.Effects>
    </Entry>
    <Editor HeightRequest="150">
        <Editor.Effects>
            <effects:BorderEffect />
        </Editor.Effects>
    </Editor>
</StackLayout>

結果

f:id:ShunsukeKawai:20170209175625p:plain:w300

いいんじゃないでしょうか。
違うコントロールに適用できる Effect の便利さを改めて認識しました。