Frame and BoxView
BoxView는 내부가 채워진 사각형입니다. View에서 파생되며, Color 속성을 정의합니다(기본 설정은 Color.Default이며 투명한 색입니다).
Frame은 내용을 둘러싸는 사각형의 테두리입니다. Frame은 ContentView를 통해 Layout으로부터 파생되고, 그 ContentView는 Content 속성을 상속받습니다. Frame의 내용은 단일 view일수도 있으며 여러 개의 view로 이루어진 레이아웃일 수도 있습니다. Frame은 VisualElement로부터 BackgroundColor 속성을 상속받는데 iPhone에서는 흰색이고, Android 및 Windows Phone에서는 투명합니다. 또한 Layout으로부터 Padding 속성을 상속받는데 모든 면에 20unit으로 초기화되어 여백을 줍니다. Frame은 또 HasShadow라는 속성(기본값은 true이지만 iPhone에서만 표시됨)과 OutlineColor라는 속성을 정의합니다. OutlineColor의 기본값은 투명이지만, 언제나 검은색인 iOS shadow에 영향을 미치진 않습니다.
Frame과 BoxView 공히 기본값이 투명이므로 색을 표현하지 않고는 잘 보이지 않을 수 있습니다. Color.Accent를 사용하면 색에 관계없이 눈에 보이게 되고, 혹은 아예 배경색을 표현할 수도 있습니다.
BoxView 또는 Frame의 크기가 제한적이지 않은 경우 (즉, StackLayout 내에 놓여있지 않고, HorizontalOptions 및 VerticalOptions가 LayoutOptions의 기본값으로 설정된 경우) 이 둘의 크기는 컨테이너를 채울때까지 확장됩니다.
Frame의 Content 속성으로 Label을 화면 가운데에 지정한 프로그램의 예를 보겠습니다.
public class FramedTextPage : ContentPage
{
public FramedTextPage()
{
Padding = new Thickness(20);
Content = new Frame
{
OutlineColor=Color.Accent,
Content=new Label
{
Text="I've been framed!",
FontSize=Device.GetNamedSize(NamedSize.Large,typeof(Label)),
HorizontalOptions=LayoutOptions.Center,
VerticalOptions=LayoutOptions.Center
}
};
}
}
| cs |
Label은 Frame에서 중앙에 위치했지만, Frame이 전체 page를 채우고 있습니다. 만약 20의 Padding을 주지 않았다면 Frame이 명확히 어디에 위치했는지도 몰랐을 수 있습니다.
가운데에 프레임된 텍스트를 출력하려면 Label이 아니라 Frame의 HorizontalOptions와 VerticalOptions를 LayoutOptions.Center로 설정해 줍니다.
public class FramedTextPage : ContentPage
{
public FramedTextPage()
{
Padding = new Thickness(20);
Content = new Frame
{
OutlineColor = Color.Accent,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Content = new Label
{
Text = "I've been framed!",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
}
};
}
}
| cs |
이제 Frame이 20 unit의 공백을 두고 가운데에서 텍스트를 둘러싸고 있습니다.
다음과 같이 색상도 자유로이 바꿀 수 있습니다.
public class FramedTextPage : ContentPage
{
public FramedTextPage()
{
BackgroundColor = Color.Aqua;
Padding = new Thickness(20);
Content = new Frame
{
OutlineColor = Color.Black,
BackgroundColor = Color.Yellow,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Content = new Label
{
Text = "I've been framed!",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
FontAttributes = FontAttributes.Italic,
TextColor = Color.Blue
}
};
}
}
| cs |
이제 다음과 같이 BoxView를 ContentPage의 Content 속성으로 설정해 봅시다.
public class SizedBoxViewPage : ContentPage
{
public SizedBoxViewPage()
{
Content = new BoxView
{
Color = Color.Accent
};
}
}
| cs |
눈에 보이도록 Color.Accent로 설정해 주었습니다. BoxView 역시 Frame처럼 디폴트로 전체 컨테이너를 가득 채웁니다.
iOS의 경우는 상태바의 아래까지 다 채웠습니다.
이제 BoxView의 HorizontalOptions와 VerticalOptions를 Fill 말고 다른 것으로 바꿔줍니다.
public class SizedBoxViewPage : ContentPage
{
public SizedBoxViewPage()
{
Content = new BoxView
{
Color = Color.Accent,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
}
}
| cs |
이렇게 코딩하면 BoxView는 자신의 default 사이즈를 40unit으로 설정합니다.
BoxView의 WidthRequest 및 HeightRequest 속성이 40으로 초기화 되기 떄문입니다. 두 속성은 조금 설명이 필요합니다.
VisualElement는 Width, Height의 속성을 정의하는데 읽기 전용입니다. 덧붙여서 settable, gettable한 WidthRequest, heightRequest도 정의합니다. 보통 이 속성은 -1(정의되지 않았다는 뜻)으로 설정되는데, 어떤 View 파생클래스-예를 들어 BoxView같은-는 특별한 값으로 WidthRequest, HightRequest를 지정합니다.
VisualElement는 Width, Height의 속성을 정의하는데 읽기 전용입니다. 덧붙여서 settable, gettable한 WidthRequest, heightRequest도 정의합니다. 보통 이 속성은 -1(정의되지 않았다는 뜻)으로 설정되는데, 어떤 View 파생클래스-예를 들어 BoxView같은-는 특별한 값으로 WidthRequest, HightRequest를 지정합니다.
페이지가 하위의 레이아웃을 구성하고 모든 비주얼을 렌더링 한 후, Width와 Height 속성은 각 뷰의 실제 크기 (화면에서 뷰가 차지하는 영역)를 나타냅니다. Width와 Height는 읽기전용이므로 정보제공의 목적으로만 사용됩니다(5장에서 자세히 다룹니다).
만약 뷰를 특정 크기로 지정하고 싶다면, WidthRequest와 HeightRequest속성을 조절합니다. 그러나 이름에서 알 수 있듯이 이 속성은 "요청" 또는 "선호"크기일 뿐이어서, 뷰가 컨테이너를 채우는 설정이 있다면 무시됩니다.
BoxView는 OnSizeRequest 메서드를 오버라이딩하여 기본 크기를 40으로 설정합니다. BoxView에서 페이지를 채울 수 있게 되면 WidthRequest, HeightRequest가 무시된다는 것을 이미 보았습니다. HorizontalOptions가 LayoutOptions.Left, Center 또는 Right로 설정된 경우, 또는 BoxView가 가로 StackLayout의 자식 인 경우 WidthRequest가 실행됩니다. HeightRequest도 유사합니다.
이번 챕터에 배운 코드가 들어간 새로운 SizedBoxView 프로그램을 보여드리겠습니다.
public class SizedBoxViewPage : ContentPage
{
public SizedBoxViewPage()
{
BackgroundColor = Color.Pink;
Content = new BoxView
{
Color = Color.Navy,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
WidthRequest = 200,
HeightRequest = 100
};
}
}
| cs |
이제 BoxView는 정확한 크기와 색을 가지게 됩니다.
좀 더 다양한 칼라 리스트를 가지고서 Frame과 BoxView를 사용해 봅시다. 아래 ColorBlocks 프로그램은 ReflectedColors의 페이지 생성자와 동일한 페이지 생성자를 사용합니다, 대신 CreateColorLabel 대신 CreateColorView라는 메서드를 호출한다는 점이 다릅니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Reflection;
using Xamarin.Forms;
namespace ColorBlocksPlus
{
public class ColorBlocksPage : ContentPage
{
public ColorBlocksPage()
{
StackLayout stackLayout = new StackLayout();
// Color structure의 필드를 loop
foreach (FieldInfo info in typeof(Color).GetRuntimeFields())
{
// 필요없는 색상(예를 들어 철자가 틀린 색상)은 스킵
if (info.GetCustomAttribute<ObsoleteAttribute>() != null)
continue;
if (info.IsPublic &&
info.IsStatic &&
info.FieldType == typeof(Color))
{
stackLayout.Children.Add(CreateColorView((Color)info.GetValue(null), info.Name));
}
}
// Color structure의 property loop
foreach (PropertyInfo info in typeof(Color).GetRuntimeProperties())
{
MethodInfo methodInfo = info.GetMethod;
if (methodInfo.IsPublic &&
methodInfo.IsStatic &&
methodInfo.ReturnType == typeof(Color))
{
stackLayout.Children.Add(CreateColorView((Color)info.GetValue(null), info.Name));
}
}
Padding = new Thickness(5, Device.OnPlatform(20, 5, 5), 5, 5);
// ScrollView에 StackLayout을 넣음
Content = new ScrollView
{
Content = stackLayout
};
}
View CreateColorView(Color color, string name)
{
return new Frame
{
OutlineColor = Color.Accent,
Padding = new Thickness(5),
Content = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Spacing = 15,
Children =
{
new BoxView
{
Color=color
},
new Label
{
Text=name,
FontSize=Device.GetNamedSize(NamedSize.Large,typeof(Label)),
FontAttributes=FontAttributes.Bold,
VerticalOptions=LayoutOptions.Center,
HorizontalOptions=LayoutOptions.StartAndExpand
},
new StackLayout
{
Children=
{
new Label
{
Text=String.Format("{0:X2}-{1:X2}-{2:X2}",
(int)(255*color.R),
(int)(255*color.G),
(int)(255*color.B)),
VerticalOptions=LayoutOptions.CenterAndExpand,
IsVisible= color!=Color.Default
},
new Label
{
Text=String.Format("{0:F2}-{1:F2}-{2:F2}",
color.Hue,
color.Saturation,
color.Luminosity),
VerticalOptions=LayoutOptions.CenterAndExpand,
IsVisible=color!=Color.Default
}
},
HorizontalOptions=LayoutOptions.End
}
}
}
};
}
}
}
| cs |
CreateColorView 메서드는 색상을 나타내는 BoxView,색상 이름을 나타내는 Label, 그리고 또 하나의 Stacklayout(RGB 컴포지션과 Hue, Saturation, Luminosity값을 출력하는 두 개의 Label 뷰로 이루어진)으로 구성된 Frame을 반환합니다. RGB 및 HSL 디스플레이는 Color.Default에서는 의미가 없으므로 내부 StackLayout의 IsVisible 속성은 false로 설정되고, StakLayout은 여전히 존재하나 렌더링 시에 무시됩니다.
이 프로그램은 위의 세 개의 color 아이템의 높이를 결정하는 것이 어떤 요소인지 알수가 없으므로 모든 Label 뷰를 전부 중앙에 위치시킵니다. 보시다시피, BoxView는 텍스트의 높이를 수용하기 위해 높이가 확장됩니다.
처음으로 좀 자부심을 가질 만한 스크롤 프로그램이 만들어졌습니다.
댓글 없음:
댓글 쓰기