LoginSignup
2
4

More than 5 years have passed since last update.

Xamarin.Formsで背景色をグラデーション表示 - NControl編

Posted at

前回はカスタムレンダラーを使用しましたが、やはりXamarin.Formsではできるだけネイティブコードを書きたくないので、カスタムレンダラー無しでやってみたいと思います。

NControl というクロスプラットフォームの2D描画パッケージを使うとグラデーションを描画できるっぽいです(実際の描画は依存パッケージである NGraphics が担当)。

パッケージ追加

ソリューション内の各プロジェクト(PCL/iOS/Android)に、下記のパッケージを追加します。

  • NControl
  • NControl.Controls

nuget.png

初期化

NControl の初期化コードを追加します。

iOS

AppDelegate.cs
using System;
using System.Collections.Generic;
using System.Linq;

using Foundation;
using UIKit;

using NControl.iOS; // <-- 追加

namespace MyApp.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            NControlViewRenderer.Init();    // <-- 追加

            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }
    }
}

Android

MainActivity.cs
using System;

using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

using NControl.Droid;   // <-- 追加

namespace MyApp.Droid
{
    [Activity(Label = "MyApp.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);
            NControlViewRenderer.Init();    // <-- 追加

            LoadApplication(new App());
        }
    }
}

実装

GradientView.cs
using System;

using Xamarin.Forms;

using NControl.Abstractions;
using NControl.Controls;
using NGraphics;

namespace MyApp
{
    public class GradientView : NControlView
    {
        public GradientView()
        {
            DrawingFunction = (canvas, rect) =>
            {
                var brush = new LinearGradientBrush(
                    NGraphics.Point.Zero,
                    NGraphics.Point.OneY,
                    this.StartColor.ToNColor(),
                    this.EndColor.ToNColor()
                );
                canvas.FillRectangle(rect, brush);
            };
        }

        protected void OnColorChanged()
        {
            this.Invalidate();
        }

        public static readonly BindableProperty StartColorProperty = BindableProperty.Create(
            "StartColor", typeof(Xamarin.Forms.Color), typeof(GradientView), Xamarin.Forms.Color.Default,
            propertyChanged: (bindable, oldValue, newValue) => ((GradientView)bindable).OnColorChanged()
        );

        public static readonly BindableProperty EndColorProperty = BindableProperty.Create(
            "EndColor", typeof(Xamarin.Forms.Color), typeof(GradientView), Xamarin.Forms.Color.Default,
            propertyChanged: (bindable, oldValue, newValue) => ((GradientView)bindable).OnColorChanged()
        );

        public Xamarin.Forms.Color StartColor {
            get { return (Xamarin.Forms.Color)GetValue(StartColorProperty); }
            set { SetValue(StartColorProperty, value); }
        }

        public Xamarin.Forms.Color EndColor {
            get { return (Xamarin.Forms.Color)GetValue(EndColorProperty); }
            set { SetValue(EndColorProperty, value); }
        }

    }
}
XAML
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MyApp"
    x:Class="MyApp.MyAppPage">

    <local:GradientView StartColor="Olive" EndColor="Teal" />

</ContentPage>

結果

iOS

result_ios.png

Android

result_android.png

できました。
カスタムレンダラーと比べると簡単な感じがしますね。

3色のグラデーション

3色でもグラデーションできます。

GradientView.cs
using System;

using Xamarin.Forms;

using NControl.Abstractions;
using NControl.Controls;
using NGraphics;

namespace MyApp
{
    public class GradientView : NControlView
    {
        public GradientView()
        {
            DrawingFunction = (canvas, rect) =>
            {
                LinearGradientBrush brush;

                if (this.MidColor != Xamarin.Forms.Color.Default) {
                    brush = new LinearGradientBrush(
                        NGraphics.Point.Zero,
                        NGraphics.Point.OneY,
                        this.StartColor.ToNColor(),
                        this.MidColor.ToNColor(),
                        this.EndColor.ToNColor()
                    );
                } else {
                    brush = new LinearGradientBrush(
                        NGraphics.Point.Zero,
                        NGraphics.Point.OneY,
                        this.StartColor.ToNColor(),
                        this.EndColor.ToNColor()
                    );
                }

                canvas.FillRectangle(rect, brush);
            };
        }

        protected void OnColorChanged()
        {
            this.Invalidate();
        }

        public static readonly BindableProperty StartColorProperty = BindableProperty.Create(
            "StartColor", typeof(Xamarin.Forms.Color), typeof(GradientView), Xamarin.Forms.Color.Default,
            propertyChanged: (bindable, oldValue, newValue) => ((GradientView)bindable).OnColorChanged()
        );

        public static readonly BindableProperty MidColorProperty = BindableProperty.Create(
            "MidColor", typeof(Xamarin.Forms.Color), typeof(GradientView), Xamarin.Forms.Color.Default,
            propertyChanged: (bindable, oldValue, newValue) => ((GradientView)bindable).OnColorChanged()
        );

        public static readonly BindableProperty EndColorProperty = BindableProperty.Create(
            "EndColor", typeof(Xamarin.Forms.Color), typeof(GradientView), Xamarin.Forms.Color.Default,
            propertyChanged: (bindable, oldValue, newValue) => ((GradientView)bindable).OnColorChanged()
        );

        public Xamarin.Forms.Color StartColor {
            get { return (Xamarin.Forms.Color)GetValue(StartColorProperty); }
            set { SetValue(StartColorProperty, value); }
        }

        public Xamarin.Forms.Color MidColor {
            get { return (Xamarin.Forms.Color)GetValue(MidColorProperty); }
            set { SetValue(MidColorProperty, value); }
        }

        public Xamarin.Forms.Color EndColor {
            get { return (Xamarin.Forms.Color)GetValue(EndColorProperty); }
            set { SetValue(EndColorProperty, value); }
        }

    }
}
XAML
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MyApp"
    x:Class="MyApp.MyAppPage">

    <local:GradientView StartColor="Olive" MidColor="Red" EndColor="Teal" />

</ContentPage>

iOS

result_ios_2.png

Android

result_android_2.png

若干不自然な感じもしなくはないですが、使いようによっては効果があるのではないでしょうか。

カスタムレンダラーを書かなくても、代わりにやってくれる便利なパッケージを使うと簡単に実装できますね。

とりあえずは以上です。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4