読者です 読者をやめる 読者になる 読者になる

ぴよぴよエンジニアの日記

ぴよぴよエンジニアの日記です 技術系のことや日常のことをつぶやきます

DroidKaigi 2017 に参加してきました

Android Xamarin

DroidKaigi 2017に参加してきました.

droidkaigi.github.io

印象に残ったことについていくつか挙げてみたいと思います.
完全に思ったことを垂れ流す形ですが、よろしければご覧下さい.



会場・運営などについて

  • 各ルームは入口と出口を分けており、扉で人が溜まることが少なかった
  • 大部屋には前方と後方それぞれにスクリーンを配備.これはすごく見やすくて良かった
  • セッション間の休憩時間、ランチタイムはわりと長く設定されていて、余裕を持って移動できた



Android について

  • MVVM, Rx が主流になっていた
  • Kotlin がかなりフォーカスされていた
  • Kotlin + RxJava + Dagger2 + Orma + Retrofit(セッションタイトルの一部です)みたいに、色々知っていないとスタートラインにすら立てないのでは...(最近の Web 界隈に似てる)
  • L がリリースされて2年経つが、Material Design がけっこう取り上げられていて重要性を感じた
  • Material Design で重要なのはアニメーションだ!
  • Android 2.X は消滅したと見てよさそう
  • Android 4.X はまだ現役

以上のようなことを思いつつ、DroidKaigi で登壇される方々は Android 界隈でも最先端を行っていると思うので、市場全体で見ると、もしかしたら違うのかもしれないとも思いました.


speakerdeck.com

私のお気に入りセッションは @operandoOS さんの"Androidアプリ開発の体力づくり💪"です.

Android 開発ってなにすればいいのー?という基本的なところから、Android ガチ勢は日々どのように情報収集しているのかまで書いてあります.リンク多めです.
公式ドキュメント読むの大事ですね.
セッション内で様々な補足をされていらっしゃいますので、ぜひ資料だけでなく録画も見ると良いと思います.



モダン Android と Xamarin の比較

あくまで私見です.

Xamarin.Android

  • Kotlin と比べて C# の利点って...?
  • MVVM は共通概念.ここにアドバンテージはない.
  • それでも Model 層を共通化できる恩恵はある
  • C# .NET の学習コストを考えるとそれも微妙かも...
  • @amay077 さんが述べられていたように Android ガチ勢には勧めずらいかも


Xamarin.Forms

  • Material Design ガチでやるのは Forms じゃ無理だよね(とくにアニメーションがきつい)
  • 関連して、デザインにこだわるなら Forms 向いてないよね
  • M 対応とか N 対応とかガチでやるなら Forms(ry
  • React Native とは 元々の専門分野が JavaScript .NET かで適正が決まりそう



その他

  • .NET 発の MVVM や Rx が Android でも使われているというのは面白い
  • Android のカンファレンスで WPF という単語が出てくるとは思わなかったw




Android について色々と勉強させていただきました.
運営がしっかりされていて、とても過ごしやすかったです.運営者の皆様ありがとうございました.
来年もまた参加させていただきたいと思います.

Lottie で Xamarin.Forms のスプラッシュページを作ってみた.

Xamarin Android iOS C#

Airbnb の Lottie が話題です.

motida-japan.hatenablog.com

Lottie の説明はこちらがわかりやすいです.


github.com

Lottie ですが、じつは Xamarin(Android/iOS/Forms)でも使えます!

今回は Lottie を使って Xamarin.Forms の スプラッシュページを実装してみます.



Android プロジェクト

Android では MainActivity の前に SplashActivity を一枚挟むことでスプラッシュページを実現します.

ただの画像を表示するだけならば Activity のスタイルに android:windowBackground を指定するだけでよいのですが、Lottie のアニメーションは LottieAnimationView というビューとして実装されているので、Activity のレイアウトにこちらのビューを設定することで実現します.


Resources.values.styles.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources>
  <style name="MyTheme" parent="MyTheme.Base">
  </style>
	
  <style name="MyTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primaryDark</item>
    <item name="colorAccent">@color/accent</item>
    <item name="android:windowBackground">@color/window_background</item>
    <item name="colorButtonNormal">@color/primary</item>
    <item name="android:textColorPrimary">@color/white</item>
    <item name="android:colorActivatedHighlight">@android:color/transparent</item>
  </style>

  <style name="Theme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowActionBar">false</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
	<item name="android:windowBackground">@drawable/bg_color</item>  
  </style>
</resources>

まず、MainActivity とは別にスプラッシュページ用のテーマを用意します.
今回はフルスクリーンの設定に加えて、背景を設定しています.

背景の android:windowBackground ですが、android:colorBackground でも同様のことは行えますが、こちらだと一瞬黒い画面が表示されてしまうので、あえて android:windowBackground を使用しています.


Resources.values.colors.xml

<resources>
  <color name="primary">#2196F3</color>
  <color name="primaryDark">#1976D2</color>
  <color name="white">#FFF</color>
  <color name="black">#000</color>
  <color name="accent">#FFC107</color>
  <color name="window_background">#F5F5F5</color>
  <drawable name="bg_color">#02d1c4</drawable> 
</resources>

背景色は colors.xml に定義しています.


SplashActivity.cs

using Android.Animation;
using Android.App;
using Android.Content;
using Android.OS;
using Com.Airbnb.Lottie;

namespace LottieSample.Droid
{
    [Activity(Theme = "@style/Theme.Splash",
        MainLauncher = true,
        NoHistory = true)]
    public class SplashActivity : Activity, Animator.IAnimatorListener
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.Activity_Splash);

            var animationView = FindViewById<LottieAnimationView>(Resource.Id.animation_view);
            animationView.AddAnimatorListener(this);
        }

        public void OnAnimationCancel(Animator animation)
        {
        }

        public void OnAnimationEnd(Animator animation)
        {
            StartActivity(new Intent(Application.Context, typeof(MainActivity)));
        }

        public void OnAnimationRepeat(Animator animation)
        {
        }

        public void OnAnimationStart(Animator animation)
        {
        }
    }
}

SplashActivity.cs の実装です.
Animator.IAnimatorListener を継承して、アニメーション終了時に MainActivity に遷移するようにしています.


Resources.layout.Activity_Splash.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:lottie_fileName="LottieLogo1.json"
        app:lottie_autoPlay="true"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

レイアウトは上記のようになっています.


f:id:Santea:20170308174003p:plain

レイアウトで指定している JSON ファイルは Assets に BuildAction = "AndroidAsset" で配置しています.


実装結果です.
android:windowBackground が表示されてからアニメーションが始まるまで1秒少し遅延がありますが、おおよそいい感じかと思います.


以上が Android プロジェクトの実装です.



iOS プロジェクト

iOSAndroid と同様に SplashViewController を一枚挟むことでスプラッシュページを実現します.

iOS では LaunchScreen があるので、そこに Lottie のビュー(iOS では LOTAnimationView になります)を追加すればよいかと思ったのですが、LaunchScreen にはカスタムビューを使えないという制限があったので、Android と同様に SplashViewController を用います.


AppDelegate.cs

using System;
using System.Collections.Generic;
using System.Linq;

using Foundation;
using Lottie.Forms.iOS.Renderers;
using UIKit;

namespace LottieSample.iOS
{
	[Register("AppDelegate")]
	public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
	{
		public override UIWindow Window { get; set; }

		public override bool FinishedLaunching(UIApplication app, NSDictionary options)
		{
		    if (Window == null)
		    {
		        Window = new UIWindow(frame: UIScreen.MainScreen.Bounds);
		        var initialViewController = new SplashViewController();
		        Window.RootViewController = initialViewController;
		        Window.MakeKeyAndVisible();

		        return true;
		    }
		    else
		    {
		        global::Xamarin.Forms.Forms.Init();
		        AnimationViewRenderer.Init();
		        LoadApplication(new App());
		        return base.FinishedLaunching(app, options);
		    }
		}
	}
}

まず、AppDelegate です.
Window = null ならば SplashViewController に遷移します.
そうでないならば Forms の初期化を行います.



using Airbnb.Lottie;
using UIKit;

namespace LottieSample.iOS
{
	public partial class SplashViewController : UIViewController
	{
		public SplashViewController() : base("SplashViewController", null)
		{
		}

		public override void ViewDidLoad()
		{
			base.ViewDidLoad();
			var animationView = LOTAnimationView.AnimationNamed("LottieLogo1");
			this.View.AddSubview(animationView);
			animationView.PlayWithCompletion((animationFinished) =>
			{
			    UIApplication.SharedApplication.Delegate.FinishedLaunching(UIApplication.SharedApplication,
				                                                           new Foundation.NSDictionary());
			});
		}

		public override void DidReceiveMemoryWarning()
		{
			base.DidReceiveMemoryWarning();
		}
	}
}

SplashViewController では、LOTAnimationView を追加し、アニメーション終了時のイベントで再度 FinishedLaunching をコールし、Forms の初期化を行います.

FinishedLaunching の引数の LaunchOptions が null の場合、NRE でクラッシュしたのでインスタンスを設定していますが、どこかにグローバル変数が定義されていませんかね?


f:id:Santea:20170308175333p:plain

LOTAnimationView.AnimationNamed("LottieLogo1") で指定した JSON ファイルはプロジェクト直下に BuildAction = "BundleResource" で配置しています.


こちらが実装結果です.
Android と同様に、LaucheScreen が表示されてから少し遅延がありますが、おおよそいい感じかと思います.


以上が iOS プロジェクトの実装です.



まとめ

今回は Lottie を使って Xamarin.Forms のスプラッシュページを実装してみました.

Lottie は高度なアニメーションを簡単に実装できるのでとても便利ですね!
Xamarin.Native、Xamarin.Forms 両方で使えるのもポイント高いです.

スプラッシュページの実装としては、Android はおおよそ問題ないかと思うのですが、iOS の Forms 初期化部分はだいぶ怪しいと思っています.
Forms 初期化部分で正しい実装がありましたら、教えていただけると嬉しいです.


以上です.


参考