Xamarin.Formsでリング状にボタンを表示させる
UIのアニメーションについていくつか記事をかきました.
今回作ったのはボタンを押すと,その周りに複数のボタンが表示される,たまに見るやつです.
アニメーション自体はScaleTo,FadeTo,TranslateToの3つを組み合わせた簡単なものです.
Xamarin.Formsで下のレイヤーのコントロールを操作できるようにする
どういうことかというと,画面の表面に透明なレイヤーを設けて,そこにメッセージを重ねるといった表現をしたい場合,上(表)のレイヤーがユーザーの操作を拾うため,下のレイヤーのコントロールを操作できません.
例えば以下のようにテキストボックスやボタンを配置したレイヤー(例えばGridなど)の上に,画像やテキストを重ねて表示させるためのレイヤーを配置した場合,上のレイヤーを透明にして下のレイヤーが見えるようにしても,下のレイヤーのボタンを押したりテキストボックスに入力したりすることができません.
このとき,ユーザーの操作が上のレイヤーを透過するようにする設定が,コントロールには設けられています.
それがInputTransparent
です.
以下のように上のレイヤーとなるGridコントロールにInputTransparent="True"
を設定すると,ユーザーの操作は上のGridを透過して下のボタンやテキストボックスに届くようになります.
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="XFInputTransparent.MainPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid> <StackLayout> <!-- Place new controls here --> <Label HorizontalOptions="Center" Text="Welcome to Xamarin.Forms!" VerticalOptions="CenterAndExpand" /> <Entry Placeholder="入力できる" VerticalOptions="CenterAndExpand" /> <Button Text="押せる" VerticalOptions="CenterAndExpand" /> </StackLayout> <Grid BackgroundColor="Pink" InputTransparent="True" Opacity="0.5"> <Label Text="これはオーバーレイしたGridに表示させているメッセージです" /> </Grid> </Grid> </ContentPage>
今回のコードはこちら.
C#である値以上またはある値以下に変数の値を維持する
ある変数があって,それは例えばスクロールの位置だったり,増減する数値を格納されるものとする.
で,ある値以上または以下に値が行かないようにしたい,つまり下限や上限を決めたいとする.
このとき,値が変化するたびに発生するイベントを利用し,イベントハンドラで値を制限する処理を行うとする.
この例ではSliderコントロールを使って,0~100の間で変化するスライダーの値を,表示時に20~80に制限する.
if文を使う
private void Slider_ValueChanged(object sender, ValueChangedEventArgs e) { double val = e.NewValue; //e.NewValueは0~100で変化するが //表示させる値としては上限80,下限20に制限する if(val>80) { val = 80; } if(val<20) { val = 20; } SliderValue = val; }
Math.Max(),Min()メソッドを使う
private void Slider_ValueChanged(object sender, ValueChangedEventArgs e) { double val = e.NewValue; //e.NewValueは0~100で変化するが //表示させる値としては上限80,下限20に制限する val = Math.Max(20, Math.Min(80, val)); SliderValue = val; }
こちらのほうがシンプルに書ける.
実行
ソースコード
Xamarin.FormsのLabelは色々できることを知った
Labelに収まらない文字列を「...」で省略する3種類のTruncationがとても便利.
<StackLayout> <Frame HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="200"> <Label Text="何も指定しない場合は,テキストは折り返される." /> </Frame> <Frame HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="200"> <Label LineBreakMode="TailTruncation" Text="Truncationを指定すると,収まらない分は「...」で省略される." /> </Frame> <Frame HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="200"> <Label LineBreakMode="HeadTruncation" Text="Truncationを指定すると,収まらない分は「...」で省略される." /> </Frame> <Frame HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="200"> <Label LineBreakMode="MiddleTruncation" Text="Truncationを指定すると,収まらない分は「...」で省略される." /> </Frame> </StackLayout>
Xamarin.Formsでコントロールの見た目をResourceDictionaryで指定する
CSSと同様に,コントロールの見た目を予め定義し,それを各コントロールに指定することで,見た目を変更することができます.
基本的にはResourceDictionaryにStyleとして定義して使用します.
これによって同じ見た目の定義を1回行うだけで,同じ見た目のコントロールを作成することができ,UI作成,編集の効率が上がります.
例えば,以下のような見た目のラベルを作る場合,このコントロール1つだけであれば以下のようにするでしょう.
<Label BackgroundColor="LightBlue" FontSize="Large" HorizontalOptions="CenterAndExpand" Text="Label1" TextColor="LightPink" VerticalOptions="CenterAndExpand" />
しかし,同じ見た目のラベルを複数用意する場合,すべてのラベルに上記の指定を行うのは手間です.
また,見た目を変更する際にすべてのラベルに対して変更を行わなければならず,手間であるとともに変更の見落としも発生しやすくなります.
そこで,以下のようにStyleとして予め定義しておくことで,見た目の指定が容易になります.
<ContentPage x:Class="XFStylePractice.MainPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <ContentPage.Resources> <ResourceDictionary> <Style x:Key="labelStyle" TargetType="Label"> <Setter Property="BackgroundColor" Value="LightBlue" /> <Setter Property="FontSize" Value="Large" /> <Setter Property="HorizontalOptions" Value="CenterAndExpand" /> <Setter Property="VerticalOptions" Value="CenterAndExpand" /> <Setter Property="TextColor" Value="LightPink" /> </Style> </ResourceDictionary> </ContentPage.Resources> <StackLayout> <Label BackgroundColor="LightBlue" FontSize="Large" HorizontalOptions="CenterAndExpand" Text="Label1" TextColor="LightPink" VerticalOptions="CenterAndExpand" /> <Label Style="{StaticResource labelStyle}" Text="Label2" /> <Label Style="{StaticResource labelStyle}" Text="Label3" /> <Label Style="{StaticResource labelStyle}" Text="Label4" /> <Label Style="{StaticResource labelStyle}" Text="Label5" /> </StackLayout> </ContentPage>
Style指定の種類
Styleの定義,指定の仕方にはざっくりわけて明示的な指定と暗黙的な指定の2種類があります.
明示的な指定
ResourceDictionaryにStyleとして定義し,そのStyleに名前(x:Key)をつけておき,コントロール側で適用したいStyleを名前で指定します.対象とするコントロールの種類(TargetType)は必須です.
CSSで言えばclass属性でスタイルを指定するのと同じです.
上の例は,この明示的な指定になります.
暗黙的な指定
ResourceDictionaryにStyleを定義しますが,ここでは対象とするコントロールの種類だけを指定し,名前はつけません.指定したコントロールに自動的にそのStyleが適用されます.
使い方
明示的な指定
冒頭の例のとおりです.
暗黙的な指定
こちらはResourceDictionary内でのStyleの定義の際にx:Key
を指定しません.
<Style TargetType="Label"> <Setter Property="BackgroundColor" Value="LightBlue" /> <Setter Property="FontSize" Value="Large" /> <Setter Property="HorizontalOptions" Value="CenterAndExpand" /> <Setter Property="VerticalOptions" Value="CenterAndExpand" /> <Setter Property="TextColor" Value="LightPink" /> </Style>
そして,Labelを配置する際に,明示的な指定とは異なり,適用するStyleを指定しません.
<StackLayout> <Label Text="Label1" /> <Label Text="Label2" /> <Label Text="Label3" /> <Label Text="Label4" /> <Label Text="Label5" /> </StackLayout>
明示的な指定はTargetTypeで指定したコントロールの種類に対して一律で適用されます.
Xamarin.FormsでNavigationPageのナビゲーションバーの背景色や文字色を変更する
Setting the NavigationBar colors in Xamarin.Formstheconfuzedsourcecode.wordpress.com
NavigationPageのBarBackgroundColor
とBarTextColor
というプロパティで変更することができます.
指定の方法は,C#であればApp.xaml.csでNavigationPageをインスタンス化する際に指定する事ができます.
MainPage = new NavigationPage(new MainPage()) { BarBackgroundColor = Color.Green[f:id:shuhelohelo:20200313181801p:plain], BarTextColor = Color.Yellow, };
または,Xaml側でResourceDictionaryにStyleを設定します.
<ResourceDictionary> <Style TargetType="NavigationPage"> <Setter Property="BarBackgroundColor" Value="Green" /> <Setter Property="BarTextColor" Value="Yellow" /> </Style> </ResourceDictionary>
これで以下のようにナビゲーションバーの背景色,文字色が変更されます.
Xamarin.FormsでAndroidのステータスバーを半透明にする
追記
この記事はNavigationPageを使う場合には有効だけれども,Shellを使う場合は有効ではない.
ShellのNavigationBarの色を変更するには以下の記事にあるように,Android側のMainActivity.csでWindow.SetStatusBarColor(Android.Graphics.Color.Argb(255, 44, 0, 0));
というように色を指定することができるけれど,透明にはできない...
Jamesさんのこの記事が参考になるだろうか...
追記前
protected override void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); global::Xamarin.Forms.FormsMaterial.Init(this, savedInstanceState); Window.SetStatusBarColor(Android.Graphics.Color.Argb(0, 44, 0, 0));//これ LoadApplication(Startup.Init(ConfigureServices)); }
Androidにおいて画面上部の時刻やバッテリー残量などの情報を表示する領域がステータスバーです.
デフォルトではステータスバーは以下のように,透過率0で表示されます.(ステータスバーがわかりやすいようにナビゲーションバーの色を変えてあります)
しかし,アプリケーションの中にはこのステータスバーが半透明になっているものがあります.
この記事は,Androidアプリでステータスバーを半透明にする方法です.
AndroidプロジェクトのResources > values > styles.xml
内に次の1行を追加します.
<item name="android:windowTranslucentStatus">true</item>
どこに追加するのが正しい作法なのか不勉強でわかっていませんが,私は以下のとおりにして期待どおりの結果になりました.
<?xml version="1.0" encoding="utf-8" ?> <resources> <style name="MainTheme" parent="MainTheme.Base"> <item name="android:windowTranslucentStatus">true</item> </style> ...略
ナビゲーションバーが表示されている場合は,これで問題ありません.
ナビゲーションバーを非表示のときにステータスバーを半透明にするときは注意が必要です.
まずはナビゲーションバー表示の場合.
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="XFStatusBar.Views.SecondPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="ナビゲーションバー" mc:Ignorable="d"> <ContentPage.Content> <StackLayout> <Frame BackgroundColor="Pink"> <Label Text="Frameだよ" /> </Frame> </StackLayout> </ContentPage.Content> </ContentPage>
このように上から順にステータスバー
,ナビゲーションバー
,ページのコンテンツ
が表示されています.
では次にナビゲーションバーを非表示にします.NavigationPage.HasNavigationBar="False"
を追加します.
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="XFStatusBar.Views.SecondPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" NavigationPage.HasNavigationBar="False" Title="ナビゲーションバー" mc:Ignorable="d"> <ContentPage.Content> <StackLayout> <Frame BackgroundColor="Pink"> <Label Text="Frameだよ" /> </Frame> </StackLayout> </ContentPage.Content> </ContentPage>
ナビゲーションバーがなくなった分,ページのコンテンツが上に来ましたが,ご覧のとおりステータスバー
とページのコンテンツが重なるように表示されています.
このように,ステータスバーを半透明にし,ナビゲーションバーを非表示にするときはステータスバーとの重なりを考慮してページを作る必要があります.