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

酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Xamarin.FormsでZXingを使ってQRコード/バーコードを生成する

メモです。Xamarin.FormsでZXingを使ってQRコード/バーコードを生成しました。

NugetにはZXing for Xamarin.Formsと書かれたものがあったのですが、どうもPCL側にライブラリを追加したらバーコードが生成できるというものではなかったみたいです。

今回、DependencyServiceを使ってみました。

f:id:ch3cooh393:20170110172416p:plain

ZXingをインストールする

パッケージを追加します。

f:id:ch3cooh393:20170110165645p:plain

iOS側のプロジェクトのパッケージにZXing.Net.Mobileが追加されました。

f:id:ch3cooh393:20170110165517p:plain

QRコードを生成してImageに表示する

テキストからバーコードを生成する処理

IBarcodeUtilitiy.cs

QRCodeMaker(PCL側)にインターフェイスを定義しておきます。

using System.IO;

namespace QRCodeMaker
{
    public interface IBarcodeUtilitiy
    {
        Stream ConvertImageStream(string text, int width = 300, int height = 300);
    }
}

BarcodeUtilitiy.cs

iOSのプロジェクト側に実装します。

using System;
using System.IO;
using ZXing.Mobile;

[assembly: Xamarin.Forms.Dependency(typeof(QRCodeMaker.iOS.BarcodeUtilitiy))]
namespace QRCodeMaker.iOS
{
    public class BarcodeUtilitiy : IBarcodeUtilitiy
    {
        public Stream ConvertImageStream(string text, int width = 300, int height = 300)
        {
            var barcodeWriter = new BarcodeWriter
            {
                Format = ZXing.BarcodeFormat.QR_CODE,
                Options = new ZXing.Common.EncodingOptions
                {
                    Width = width,
                    Height = height,
                    Margin = 1
                }
            };
            barcodeWriter.Renderer = new BitmapRenderer();
            var bitmap = barcodeWriter.Write(text);
            var stream = bitmap.AsPNG().AsStream();
            stream.Position = 0;

            return stream;
        }
    }
}

これでPCL側のプロジェクトでは、DependencyService.Get<IBarcodeUtilitiy>().ConvertImageStream("test");でバーコードを生成することができます。

画面を表示する

QRCodeMakerPage.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:QRCodeMaker" 
    x:Class="QRCodeMaker.QRCodeMakerPage">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
            iOS="0,20,0,0" />
    </ContentPage.Padding>
    
    <StackLayout Orientation="Vertical">
        <Label Text="Welcome to Xamarin Forms!" 
            VerticalOptions="Center" 
            HorizontalOptions="Center" />

        <Button Text="Generate" Clicked="generateAction" />
        
        <Image x:Name="imageView" 
            BackgroundColor="Aqua"
            HeightRequest="300"
            WidthRequest="300" />
    </StackLayout>
</ContentPage>

QRCodeMakerPage.xaml.cs

using System;
using System.IO;
using Xamarin.Forms;

namespace QRCodeMaker
{
    public partial class QRCodeMakerPage : ContentPage
    {
        public QRCodeMakerPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            imageView.Source = ImageSource.FromStream(() =>
            {
                return DependencyService.Get<IBarcodeUtilitiy>().ConvertImageStream("test");
            });
        }

        // ボタンが押される度にランダムなバーコードを生成する
        void generateAction(object sender, System.EventArgs e)
        {
            var text = DateTime.UtcNow.Ticks.ToString();
            imageView.Source = ImageSource.FromStream(() =>
            {
                return DependencyService.Get<IBarcodeUtilitiy>().ConvertImageStream(text);
            });
        }
    }
}

実行結果

タップする度にバーコードを生成しています。

f:id:ch3cooh393:20170110171718g:plain

Xamarin.Formsでタブ表示させるためにTabbedPageを使う

メモです。この記事で作成したプロジェクトを流用しています。

タブ表示させる

MyTabbedPage.xamlを追加します。

MyTabbedPage.xaml

<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:RealmSample"  
    x:Class="RealmSample.MyTabbedPage">

    <NavigationPage Title="tab1">
        <x:Arguments>
            <local:RealmSamplePage Title="page title"/>
        </x:Arguments>
    </NavigationPage>

</TabbedPage>

MyTabbedPage.xaml.cs

using Xamarin.Forms;

namespace RealmSample
{
    public partial class MyTabbedPage : TabbedPage
    {
        public MyTabbedPage()
        {
            InitializeComponent();
        }
    }
}

App.xaml.cs

using Xamarin.Forms;

namespace RealmSample
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new MyTabbedPage();
        }

        //...
    }
}

実行結果

実行しました。

f:id:ch3cooh393:20170109000914p:plain

Xamarin.Formsで詳細ページへドリルダウンさせるNavigationPageを使う

メモです。この記事で作成したプロジェクトを流用しています。

ページナビゲーションをおこなう

ListViewの項目を選択すると詳細ページにドリルダウンさせたいです。

ナビゲーションページ(iOSでのいうところのUINavigationController、Xamarin.Formsではなんて呼ぶんだろう)に入れたい場合、App.xaml.csでこう実装しました。

using Xamarin.Forms;

namespace RealmSample
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new NavigationPage(new RealmSamplePage());
        }

        //...
    }
}

ページ側ではNavigation.PushAsyncを実行します。

using Xamarin.Forms;

namespace RealmSample
{
    public partial class RealmSamplePage : ContentPage
    {
        public RealmSamplePage()
        {
            InitializeComponent();

            //...

            listView.ItemSelected += (object sender, SelectedItemChangedEventArgs e) =>
            {
                this.Navigation.PushAsync(new DetailPage());
            };
        }

        void AddAction(object sender, System.EventArgs e)
        {
            //...
        }
    }
}

実行結果

実行してみました。

f:id:ch3cooh393:20170109002522p:plain