[Xamarin.Forms] AbsoluteLayoutでプロポーショナルレイアウト


`AbsoluteLayout` を使うと画像の上にボタンやラベルといったコントロールを重ねることができます。さらに、Xamarin.FormsのAbsoluteLayoutは「LayoutFlags」と「LayoutBounds」を駆使することでとても柔軟なレイアウトが可能となっています。

自分で絶対座標を計算しなくても良いのは素敵ですね。


## LayoutFlags と LayoutBounds

LayoutFlags、LayoutBoundsを適切に設定することで親要素(AbsoluteLayout)に対する位置、サイズを比率で指定することができます。

LayoutFlagsは `AbsoluteLayoutFlags` 列挙型として定義されています。

```c#:
public enum AbsoluteLayoutFlags
{
	None = 0,
	XProportional = 1,
	YProportional = 2,
	WidthProportional = 4,
	HeightProportional = 8,
	PositionProportional = 3,
	SizeProportional = 12,
	All = -1
}
```

`AbsoluteLayoutFlags` の指定によって  `Rectangle`の解釈が変わり、「〜Proportional」に対応する部分は絶対値ではなく、座標やサイズを0〜1の比率で指定したものとして扱われます。例えば、 `WidthProportional` が指定されている場合に `Rectangle.Width` を 1 に設定すると、子要素の幅は親要素(AbsoluteLayout)に対する100%(親要素の幅と同じ)となります。

`Rectangle.Width` 、 `Rectangle.Height` には絶対値の代わりに `AbsoluteLayout.AutoSize` を指定することができます。(XAMLの場合は `AutoSize` ) これにより、要素の動的なサイズ変化にも対応してくれます。

LayoutFlags、LayoutBoundsの指定はC#で書くとこうなります。

```c#:
AbsoluteLayout.SetLayoutFlags (
	label, 
	AbsoluteLayoutFlags.PositionProportional
);
 
AbsoluteLayout.SetLayoutBounds (
    label, 
	new Rectangle (
		0.5, 				        // X
		0.5, 				        // Y
		AbsoluteLayout.AutoSize, 	// Width
		AbsoluteLayout.AutoSize)	// Height
);
```

同じことをXAMLで書くとこうなります。

```xml:
<Label Text="中心に配置" 
	   AbsoluteLayout.LayoutFlags="PositionProportional"
	   AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"/>
```

### LayoutFlagsの複数指定

`AbsoluteLayoutFlags` は組み合わせることができます。例えば、 `PositionProportional` を指定するのは `XProportional` と `YProportional` を同時に指定するのと等しく、 `SizeProportional` を指定するのは `WidthProportional` と `HeightProportional` を同時に指定するのと等しくなります。

C#で書く場合は論理和を使います。

```c#:
AbsoluteLayout.SetLayoutFlags (
	boxView, 
	AbsoluteLayoutFlags.XProportional | 
	AbsoluteLayoutFlags.YProportional);
AbsoluteLayout.SetLayoutBounds (boxView, new Rectangle (0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
```

XAMLで書く場合はカンマ(,)で区切ります。

```xml:
<BoxView Color="#88D3381C"
 		 AbsoluteLayout.LayoutFlags="XProportional, YProportional"
		 AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"/>
```

## サンプル:帯状に配置

`AbsoluteLayout` の上下左右の領域に配置するサンプル。メニューやキャプションを置く場所として使うイメージ。うまく調整すれば四角いフレームなんかも作れそうですね。

こんな感じ。

![スクリーンショット 2015-09-24 13.35.14.jpg](https://qiita-image-store.s3.amazonaws.com/0/40121/afc4567d-b83f-9b83-d163-6aab60b481ea.jpeg "スクリーンショット 2015-09-24 13.35.14.jpg")

### 上付き

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (boxView, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds (boxView, new Rectangle (0.5, 0, 1, 0.25));
```

__XAML__

```xml:
<BoxView Color="#88D3381C"
 		 AbsoluteLayout.LayoutFlags="All"
		 AbsoluteLayout.LayoutBounds="0.5, 0, 1, 0.25"/>
```

### 下付き

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (boxView, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds (boxView, new Rectangle (0.5, 1, 1, 0.25));
```

__XAML__

```xml:
<BoxView Color="#88AACF53"
 		 AbsoluteLayout.LayoutFlags="All"
		 AbsoluteLayout.LayoutBounds="0.5, 1, 1, 0.25"/>
```

### 左付き

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (boxView, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds (boxView, new Rectangle (0, 0.5, 0.25, 1));
```

__XAML__

```xml:
<BoxView Color="#881E50A2"
 		 AbsoluteLayout.LayoutFlags="All"
		 AbsoluteLayout.LayoutBounds="0, 0.5, 0.25, 1"/>
```

### 右付き

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (boxView, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds (boxView, new Rectangle (1, 0.5, 0.25, 1));
```

__XAML__

```xml:
<BoxView Color="#88EBD842"
 		 AbsoluteLayout.LayoutFlags="All"
		 AbsoluteLayout.LayoutBounds="1, 0.5, 0.25, 1"/>
```

## サンプル:隅に配置

`AbsoluteLayout` の中央と四隅に配置するサンプル。幅、高さに `AbsoluteLayout.AutoSize` を指定することで要素のサイズ変化にも対応してくれます。例えば、右下の要素が大きくなった場合でも画面外にはみ出ることなく、収まるように再配置してくれます。

こんな感じ。

![スクリーンショット 2015-09-24 11.16.00.jpg](https://qiita-image-store.s3.amazonaws.com/0/40121/5bf516a0-a104-b4b6-2c5a-f2daff3c9df6.jpeg "スクリーンショット 2015-09-24 11.16.00.jpg")


### 中心に配置

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (label, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds (label, new Rectangle (0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
```

__XAML__

```xml:
<Label Text="中心に配置" 
	   AbsoluteLayout.LayoutFlags="PositionProportional"
	   AbsoluteLayout.LayoutBounds="0.5, 0.5, AutoSize, AutoSize"/>
```

### 左上に配置

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (label, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds (label, new Rectangle (0, 0, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
```

__XAML__

```xml:
<Label Text="左上に配置" 
	   AbsoluteLayout.LayoutFlags="PositionProportional"
	   AbsoluteLayout.LayoutBounds="0, 0, AutoSize, AutoSize"/>
```

### 右上に配置

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (label, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds (label, new Rectangle (1, 0, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
```

__XAML__

```xml:
<Label Text="右上に配置" 
	   AbsoluteLayout.LayoutFlags="PositionProportional"
	   AbsoluteLayout.LayoutBounds="1, 0, AutoSize, AutoSize"/>
```
### 右下に配置

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (label, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds (label, new Rectangle (1, 1, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
```

__XAML__

```xml:
<Label Text="右下に配置" 
	   AbsoluteLayout.LayoutFlags="PositionProportional"
	   AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"/>
```

### 左下に配置

__C#__

```c#:
AbsoluteLayout.SetLayoutFlags (label, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds (label, new Rectangle (0, 1, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
```

__XAML__

```xml:
<Label Text="左下に配置" 
	   AbsoluteLayout.LayoutFlags="PositionProportional"
	   AbsoluteLayout.LayoutBounds="0, 1, AutoSize, AutoSize"/>
```


## 参考

[Xamarin.Forms AbsoluteLayout Recipe](https://www.syntaxismyui.com/xamarin-forms-absolutelayout-recipe/)

[Demystifying Xamarin Forms AbsoluteLayout and RelativeLayout positioning. | Adventures in Xamarin Forms](http://adventuresinxamarinforms.com/2015/05/05/demystifying-xamarin-forms-absolutelayout-and-relativelayout-positioning/)