ScrollViewコントロールを使うことで、画面サイズには収まりきらないUI要素をスクロールして表示する方法を解説する。
対象:Visual Studio 2015以降
Xamarin.FormsでUIコントロールを配置するとき、画面に収まりきらないこともあるだろう。そんなとき、ScrollViewコントロール(Xamarin.Forms名前空間)を使ってスクロール可能にできる。
本稿では、ScrollViewコントロールの記述方法と、コードビハインドからスクロールさせる方法を解説する*1。
*1 本稿で使用したXamarin.Formsのバージョン
Xamarin 4.2.1.60 (47830f6)/Xamarin.Forms 2.2.0.45
ScrollViewコントロールの使用例を次の画像に示す。中央部分(背景色が黄色の部分)が、ScrollViewコントロールだ。その中にStackLayoutコントロールを置き、さらにその中に複数のLabelコントロールを配置している。このデバイスの場合(Windows 10のデスクトップ)、ScrollViewコントロール上にマウスをホバーさせると、スクロールバーが表示される。
なお、ScrollViewコントロールの中にスクロール可能なコントロール(ScrollViewコントロール/ListViewコントロール/WebViewコントロールなど)を配置すると、スクロールできなくなるので注意しよう*2。
*2 これを解決するには、中に配置するスクロール可能なUIコントロールでNestedScrollingEnabledプロパティをtrueに設定すればよいようだ。
参照:「Xamarin.Forms(Android)ScrollViewの中にあるListViewをスクロールさせる - Qiita」
ScrollViewコントロールには、UIコントロールを1個だけ格納できる。複数のUIコントロールを配置するには、ScrollViewコントロールにGridコントロールやStackLayoutコントロールなどを置いてから、その中に配置する。
ScrollViewコントロールに特徴的なプロパティとして、Orientationプロパティがある。Orientationプロパティには、次に示す3種類の値のいずれかを設定できる(冒頭の画像の例では「Both」を指定してある)。
その他に、次に示す読み取り専用のプロパティもある。
特定の位置までコードビハインドからスクロールさせるには、ScrollViewコントロールのScrollToAsyncメソッドを使えばよい。このメソッドには、2通りのオーバーロードがある。
スクロール位置を指定してスクロールする:
ここで、引数のxとyは、スクロールし終わったときにScrollViewコントロールの左上隅に来る座標だ(epx単位)。また、3番目の引数animatedにtrueを与えると、スクロール中にアニメーションする。
UIコントロールを指定してスクロールする:
こちらは、第1引数に指定したUIコントロールが見えるようにスクロールさせるメソッドだ。第2引数positionで、スクロールし終わったときに指定したUIコントロールがどのように見えるかを指定する(次の4つのいずれか)。
また、3番目の引数animatedの意味は前のオーバーロードと同じだ。
なお、ScrollToAsyncメソッドはどちらのオーバーロードも非同期で実行される。スクロールが終わってから実行したい処理を書くときには、async/awaitキーワードが必要だ。
実際の例として、冒頭の画像に示したアプリのコードを紹介しよう。
ソリューションを新しく作るときに[Blank Xaml App (Xamarin.Forms Portable)]を選ぶ。以下ではソリューション名(=PCLプロジェクトの名前)は「dotNetTips1171」としている。
そうしたら、PCLプロジェクトにあるMainPage.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:dotNetTips1171"
x:Class="dotNetTips1171.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage">
<Setter Property="Padding">
<OnPlatform x:TypeArguments="Thickness" iOS="0,20,0,0" />
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="HeightRequest" Value="100" />
<Setter Property="WidthRequest" Value="600" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="White" />
<Setter Property="BackgroundColor" Value="Accent" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalTextAlignment" Value="Center" />
</Style>
<Style TargetType="Button">
<Setter Property="TextColor" Value="White" />
<Setter Property="BackgroundColor" Value="Accent" />
<Setter Property="HeightRequest" Value="75" />
<Setter Property="WidthRequest" Value="250" />
<Setter Property="Margin" Value="0,5,0,15" />
<Setter Property="HorizontalOptions" Value="Center" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Label Text="ScrollView サンプル" TextColor="Accent"
BackgroundColor="Transparent" />
<ScrollView x:Name="ScrollView1" BackgroundColor="Yellow"
Orientation="Both">
<StackLayout Spacing="10" Padding="10">
<Label Text="Label01" />
……省略(Label02〜Label06)……
<Label Text="Label07" x:Name="Label07" />
……省略(Label08〜Label11)……
<Label Text="Label12" />
</StackLayout>
</ScrollView>
<Button Clicked="Button_Clicked" Text="Label07までスクロール" />
</StackLayout>
</ContentPage>
次に、コードビハインドにイベントハンドラーを追加しよう。PCLプロジェクトにあるMainPage.xaml.csファイルの内容を次のように変更する。
using System;
using Xamarin.Forms;
namespace dotNetTips1171
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, EventArgs e)
{
ScrollView1.ScrollToAsync(Label07, ScrollToPosition.Center, true);
}
}
}
以上で完成だ。実行してボタンをタップすると、次の画像のようになる。
スクロールできるようにするには、ScrollViewコントロールを使う。Orientationプロパティの設定で、縦にも横にもスクロールできる。また、コードビハインドからスクロールさせるには、ScrollToAsyncメソッドを使用する。
利用可能バージョン:Visual Studio 2015以降
カテゴリ:Xamarin 処理対象:Xamarin.Forms
関連TIPS:Xamarin.Forms:プラットフォームに応じて画面の一部を変えるには?
関連TIPS:Xamarin.Forms:プラットフォームに応じたフォントサイズを指定するには?
Copyright© Digital Advantage Corp. All Rights Reserved.