Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

前回はカスタムレンダラーを使用しましたが、やはり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

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

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

とりあえずは以上です。

sudachi808
2017年4月から Xamarin + C# をはじめました。 2018年あたりから Android + Kotlin をはじめました。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした