티스토리 뷰

반응형
이 포스트의 내용은 Summary of Chapter 5. Dealing with sizes (https://docs.microsoft.com/en-us/xamarin/xamarin-forms/creating-mobile-apps-xamarin-forms/summaries/chapter05) 을 번역한 자료입니다. 한글로 표현하기 어색하거나 모호한 문장은 임의로 조정하거나 삭제하였으므로 필요한 경우 원문을 참고하시기 바랍니다. 또한 언제든지 원저자의 요청에 의해 게시물이 내려지거나 수정될 수 있음을 알려드립니다. 마지막으로 이 글은 개인적인 학습목적으로 번역한 자료이며, 따라서 오역이나 잘못된 해석이 포함되어 있을 수 있으며 이로인한 어떠한 일체의 보장을 하지 않습니다.

이 문서에서는 다음 주제를 다룹니다.

참고
이 페이지에서  참고 영역은  Xamarin.Forms 책의 내용에서 달라진 부분이 무엇인지 기술하고 있습니다.

지금까지 Xamarin.Forms의 크기에 관해 다음과 같은 내용들이 등장했습니다.

  • iOS의 상태바 높이는 20이다
  • BoxView의 기본 너비와 높이는 40이다
  • Frame의 기본 Padding은 20이다
  • StackLayoutSpacing 기본 값은 6입니다
  • Device.GetNamedSize 메서드는 폰트 크기를 숫자로 반환합니다

이러한 크기들은 Pixel 단위가 아닙니다. 이 크기들은 플렛폼 마다 독립적으로 정의하고 있는 장치 중립적인 크기단위입니다.

Pixels, points, dps, DIPs, DIUs

역사적으로 초기의 Apple Mac과 Microsoft Windows 프로그래머들은 Pixel 단위로 크기 계산을 하였습니다. 그러나 고해상도 디스플레이의 출현으로 인해 좀더 가상화되고 추상화된 스크린 좌표시스템이 필요하게 되었습니다. Mac에서는 1/72 인치 크기의 Point 단위로 작업하였으며, Windows 개발자들은 1/96 인치 크기의 Device-independent units(DIUs) 단위를 사용했습니다.

모바일 장치는 보통 사람의 얼굴에 더 가까이 위치하기 때문에 데스크톱 스크린 보다 더 고해상도 스크린을 사용합니다. 이는 모바일 장치가 더 높은 픽셀 밀도를 사용할 수 있음을 의미합니다.

Apple iPhone과 iPad 장치를 개발하는 개발자들은 동일하게 Point 단위를 사용하지만, Point 크기는 1/160 인치 크기를 가집니다. 모바일 장치에 따라 1 Point는 1~3 Pixel과 대응됩니다.

Android도 유사합니다. 프로그래머들은 Density-independent pixels (dps) 단위를 사용하며 1/160 인치 크기를 가집니다. 1 dps 당 Pixel의 수는 제조사에서 사용하는 스크린의 픽셀밀도에 따라 달라집니다.

Windows Phone이나 Windows 모바일 장치들도 1/160 인치 크기에 가까운 장치 중립적인 단위 시스템을 사용합니다.

참고
Xamarin.Forms는 더 이상 Windows 기반 폰이나 모바일 장치를 지원하지 않습니다.

따라서 Xamarin.Forms의 개발자들이 스마트폰이나 태블릿 앱을 개발할 경우 크기 단위는 다음과 같이 가정할 수 있습니다.

  • 1/160 인치의 크기 단위
  • 1/64 센티미터의 크기 단위

VisualElementWidth, Height Read-only Property는 기본적으로 -1 값을 가지고 있습니다. Element의 크기가 결정되고 레이아웃 공간을 차지할 때 이 Property들은 실제 크기 값으로 변경됩니다. 이 크기 값은 Padding을 포함하지만 Margin을 포함하지는 않습니다.

시각적 Element들은 WidthHeight가 변경될 때 SizeChanged 이벤트를 발생시킵니다. WhatSize 샘플은 이 이벤트를 통해 스크린의 크기를 출력하는 방법을 보여줍니다.

실제 크기

위에서 소개했던 내용을 되집어보면 Xamarin.Forms에서 1인치는 160, 1센티미터는 64로 표현할 수 있습니다. 이를 BoxView로 표현하면 다음과 같습니다.

public class MetricalBoxViewPage : ContentPage
{
    public MetricalBoxViewPage()
    {
        Content = new BoxView
        {
            Color = Color.Accent,
            WidthRequest = 64, //1센티미터
            HeightRequest = 160, //1인치
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };
    }
}

이 프로그램을 실행하면 완전히 일치하지는 않지만 대략적으로 유사한 크기의 BoxView가 나타납니다. 실제 크기단위는 제조사의 설정에 따라 달라지지만 대부분의 장치에서 유사하게 나타납니다. MetricalBoxView 샘플은 WidthRequestHeightRequest를 사용하여 1인치 높이와 1 센티미터 너비를 가지는 BoxView를 출력하는 예제코드를 제공합니다.
1인치 높이 1센티미터 너비의 BoxView

측정된 폰트 크기

FontSize도 1 Point 당 1/160 인치의 크기 단위로 예상하여 설정할 수 있습니다. 참고로 데스크톱이나 인쇄작업에 사용하는 폰트크기 Point(Pt)단위는 1/72 인치 크기를 사용하므로 1/160 인치 크기를 사용하는 모바일 장치와는 크기단위가 다릅니다.

플렛폼 마다 폰트크기가 상이했던 Device.GetNamedSize 메서드 대신에 직접 폰트 크기를 지정하면 플렛폼 마다 일관성있는 결과를 얻을 수 있습니다.

FontSizes 샘플은 1/160 인치 크기단위 계산방법을 이용해 데스크톱의 1/72 인치 크기의 Point(Pt)단위로 변환하는 방법을 소개합니다.

사용 가능한 크기에 텍스트 맞추기

지정된 사각형의 박스에 지정된 텍스트를 모두 담으려면 다음 기준으로 LabelFontSize를 계산해야 합니다.

  • 줄간격(Line spacing)은 폰트 크기의 120% (Windows 플렛폼에서는 130%)
  • 평균적으로 1글자의 너비는 폰트 크기의 50%

EstimatedFontSize 샘플은 이에 관한 예제 코드를 제공합니다. 이 프로그램은 Margin이 등장하기 전에 작성되었으므로 ContentViewPadding Property를 사용하여 Margin을 흉내내었습니다.
사용 가능한 크기에 텍스트 맞추기

크기에 맞는 시계

FitToSizeClock 샘플은 Device.StartTime를 통해 주기적으로 시간을 업데이트 하는 코드를 실행합니다. 폰트 크기는 페이지 너비의 1/6 크기로 지정하여 가능한 가장 크게 나타나도록 하였습니다.

public class FitToSizeClockPage : ContentPage
{
    public FitToSizeClockPage()
    {
        Label clockLabel = new Label
        {
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };

        Content = clockLabel;

        //페이지의 SizeChanged 이벤트를 통해 페이지 너비의 1/6만큼 글자크기를 지정
        SizeChanged += (object sender, EventArgs args) =>
        {
            if (this.Width > 0)
                clockLabel.FontSize = this.Width / 6;
        };

        //1초마다 반복하여 코드가 실행되도록 Time 시작
        Device.StartTimer(TimeSpan.FromSeconds(1), () =>
        {
            clockLabel.Text = DateTime.Now.ToString("h:mm:ss tt");
            return true;
        });
    }
}

접근성 설정에 따른 문제

EstimatedFontSize, FitToSizeClock 프로그램은 다소 알아채기 힘든 문제점이 있습니다. 만약 사용자가 스마트폰의 접근성 설정을 통해 폰트의 크기를 확대하거나 축소한다면, 앱은 적절한 폰트크기를 계산하여 출력할 수 없습니다. AccessibilityTest 샘플은 이러한 접근성 문제를 보여줍니다. 아래 그림처럼 Android와 Windows Phone에서 접근성 설정을 통해 폰트 크기를 확대하면 동일한 FontSize를 지정해도 다르게 나타나게 됩니다.
접근성 설정에 따른 폰트크기 불일치 문제

실증적 텍스트 맞춤

크기가 지정된 공간에 텍스트를 맞추는 방법 중 하나는 실제로 렌더링 되는 텍스트의 너비와 높이를 계산하고 크기를 키우거나 줄이는 작업을 반복하는 것입니다. 책에서는 GetSizeRequest를 통해 렌더링 되는 크기를 요청하지만 이 메서드는 Deprecated 되었습니다. 따라서 GetSizeRequest대신 Measure를 호출해야 합니다.

LabelMeasure 메서드에 전달할 첫번째 매개변수는 Label을 포함하는 부모의 너비로 지정해야 Label이 전달받은 너비 값을 바탕으로 텍스트가 줄바꿈된 크기를 계산할 수 있습니다. 두번째 매개변수는 Double.PositiveInfinity를 전달하여 제한된 높이가 없음을 알려야 합니다. EmpiricalFontSize 샘플은 이러한 방법으로 적절한 FontSize를 계산하는 방법을 보여줍니다.

//SizeChanged 이벤트가 발생할때 마다 루프를 반복하며 적절한 폰트크기를 계산하여 재지정
while (upperFontCalc.FontSize - lowerFontCalc.FontSize > 1)
{
    ... 폰트 크기 계산 코드 ...
}
댓글