다양한 픽셀 밀도 지원

Android 기기는 다양한 화면 크기(핸드셋, 태블릿, TV, 픽셀 크기가 다른 화면도 있습니다. 1개 한 기기에서는 인치당 160픽셀을 사용하지만 다른 기기에서는 480픽셀을 사용할 수 있습니다 같은 공간에 있을 수 있습니다. 이러한 차이를 고려하지 않으면 시스템에서 크기를 조정할 수 있으므로 이미지가 흐릿해지거나 이미지가 손상될 수 잘못된 크기로 표시될 수 있습니다

이 페이지에서는 Android 또는 iOS용 앱을 설계할 수 있는 해상도에 독립적인 측정 단위를 사용하여 다양한 픽셀 밀도 측정 각 픽셀 밀도에 맞는 대체 비트맵 리소스를 제공합니다.

이러한 기법에 대한 개요를 보려면 다음 동영상을 시청하세요.

아이콘 애셋 디자인에 대한 자세한 내용은 머티리얼 디자인 아이콘 가이드라인을 참조하세요.

밀도 독립형 픽셀 사용

거리나 크기를 정의하는 데 픽셀을 사용하지 마세요. 다음을 사용하여 차원 정의 화면마다 픽셀 밀도가 다르기 때문에 동일한 수의 픽셀이 화면의 다른 실제 크기에 대응하기 때문에 사용할 수 있습니다.

<ph type="x-smartling-placeholder">
</ph> 서로 다른 밀도를 사용하는 두 가지 예시 기기 디스플레이를 보여주는 이미지 <ph type="x-smartling-placeholder">
</ph> 그림 1: 크기가 같은 두 화면의 픽셀 수는 서로 다를 수 있습니다.

UI 표시 크기 유지 UI를 디자인하려면 밀도 독립형 픽셀 (dp)을 측정 단위로 사용합니다. 1dp는 중밀도 화면에서 대략 1픽셀과 동일한 가상 픽셀 단위 (160dpi 또는 '기준' 밀도). Android는 이 값을 적절한 수의 실제 픽셀을 서로 결합해야 합니다.

그림 1의 두 기기를 생각해 보세요. 뷰는 100픽셀 너비는 왼쪽 기기에서 훨씬 더 크게 보입니다. 뷰 너비가 100dp로 정의된 경우 두 화면에서 동일한 크기로 표시됩니다.

텍스트 크기를 정의할 때는 대신 scalable 픽셀 (sp)을 단위로 사용할 수 있습니다. sp 단위는 기본적으로 dp와 같은 크기이지만, 사용자가 원하는 값에 따라 크기가 조절됩니다. 지정할 수 있습니다. 레이아웃 크기에 sp를 사용하지 마세요.

예를 들어 두 뷰 사이의 간격을 지정하려면 dp를 사용합니다.

<Button android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/clickme"
    android:layout_marginTop="20dp" />

텍스트 크기를 지정할 때는 sp를 사용합니다.

<TextView android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp" />

dp 단위를 픽셀 단위로 변환

크기를 dp 단위로 표시한 다음 픽셀로 변환할 수 있습니다. dp 단위를 화면 픽셀로 변환 다음과 같습니다.

px = dp * (dpi / 160)

참고: 픽셀을 계산하기 위해 이 수식을 하드코딩하지 마세요. 대신 TypedValue.applyDimension(), 이 함수는 다양한 유형의 크기 (dp, sp 등)를 픽셀로 변환합니다.

스크롤 또는 플링 동작이 인식되는 앱을 가정해 보겠습니다. 사용자가 손가락을 16픽셀 이상 움직인 후 기준치에 해당 화면에서 손가락이 16 pixels / 160 dpi (1/10인치 또는 2.5mm와 같음)를 이동해야 동작 인식

기기에서 고밀도 디스플레이 (240dpi)를 사용할 경우 사용자의 손가락이 16 pixels / 240 dpi 1.7mm (1/15인치)입니다. 거리가 훨씬 짧아지고 따라서 앱이 사용자에게 더 민감해 보입니다.

이 문제를 해결하려면 동작 기준점을 코드에서 dp 단위로 표시하고 실제 픽셀로 변환할 수 있습니다. 예를 들면 다음과 같습니다.

Kotlin

// The gesture threshold expressed in dp
private const val GESTURE_THRESHOLD_DP = 16.0f

private var gestureThreshold: Int = 0

// Convert the dps to pixels, based on density scale
gestureThreshold = TypedValue.applyDimension(
  COMPLEX_UNIT_DIP,
  GESTURE_THRESHOLD_DP + 0.5f,
  resources.displayMetrics).toInt()

// Use gestureThreshold as a distance in pixels...

자바

// The gesture threshold expressed in dp
private final float GESTURE_THRESHOLD_DP = 16.0f;

// Convert the dps to pixels, based on density scale
int gestureThreshold = (int) TypedValue.applyDimension(
  COMPLEX_UNIT_DIP,
  GESTURE_THRESHOLD_DP + 0.5f,
  getResources().getDisplayMetrics());

// Use gestureThreshold as a distance in pixels...

DisplayMetrics.density 필드 dp 단위를 픽셀로 변환될 수 있습니다. 중밀도 화면에서는 DisplayMetrics.density = 1.0이고 고밀도 화면에서는 1.5입니다. 초고밀도 화면에서는 2.0과 같고 저밀도 화면에서는 0.75와 같습니다. 이 수치는 TypedValue.applyDimension()에서 사용하는 용도 현재 화면의 실제 픽셀 수를 가져옵니다.

사전 크기 조정된 구성 값 사용

ViewConfiguration 클래스를 사용하여 거리, 속도 및 시간이 포함됩니다. 예를 들어 프레임워크에서 스크롤 임계값으로 사용하는 거리(픽셀) getScaledTouchSlop()로 다음 명령어를 실행합니다.

Kotlin

private val GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).scaledTouchSlop

자바

private final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();

getScaled 접두사로 시작하는 ViewConfiguration의 메서드 현재 픽셀의 현재 표시 여부와 관계없이 제대로 표시되는 값을 지정할 수 있습니다.

벡터 그래픽 사용

이미지의 여러 밀도별 버전을 만드는 대신 벡터 그래픽을 하나만 만듭니다. 벡터 그래픽은 XML을 사용하여 이미지를 만들어 픽셀 비트맵을 사용하는 대신 경로와 색상을 정의할 수 있습니다. 따라서 벡터는 그래픽은 아티팩트의 크기 조정 없이 모든 크기로 조정할 수 있지만 일반적으로 사진이 아닌 아이콘과 같은 삽화에 적합합니다.

벡터 그래픽은 종종 SVG (Scalable Vector Graphics) 파일로 제공되며 Android는 이 형식을 지원하지 않으므로 SVG 파일을 Android의 벡터 drawable 형식을 지원합니다.

Android 스튜디오의 Vector Asset Studio 방법은 다음과 같습니다.

  1. Project 창에서 res 디렉터리를 마우스 오른쪽 버튼으로 클릭하고 신규 > 벡터 애셋을 선택합니다.
  2. 로컬 파일(SVG, PSD)을 선택합니다.
  3. 가져와 조정할 파일을 찾습니다.

    <ph type="x-smartling-placeholder">
    </ph> Android 스튜디오에서 SVG를 가져오는 방법을 보여주는 이미지 <ph type="x-smartling-placeholder">
    </ph> 그림 2: Android 스튜디오입니다.

    Asset Studio 창에 오류가 표시될 수 있습니다. 는 벡터 드로어블이 파일의 일부 속성을 지원하지 않음을 나타냅니다. 이렇게 해도 파일을 가져올 수 있습니다. 지원되지 않는 속성 무시됩니다.

  4. Next(다음)를 클릭합니다.

  5. 다음 화면에서 프로젝트에서 파일을 사용하려는 소스 세트를 확인합니다. 마침을 클릭합니다.

    하나의 벡터 드로어블을 모든 픽셀 밀도에서 사용할 수 있기 때문에 이 파일은 이 명령어는 다음과 같이 기본 drawables 디렉터리로 이동합니다. 계층 구조로 구성됩니다 밀도별 디렉터리를 사용할 필요는 없습니다.

    res/
      drawable/
        ic_android_launcher.xml
    

벡터 그래픽 만들기에 관한 자세한 내용은 벡터 드로어블을 참고하세요. 문서를 참조하세요.

대체 비트맵 제공

다양한 픽셀 밀도의 기기에서 좋은 그래픽 품질을 제공하기 위해 앱에서 각 비트맵의 여러 버전(각각에 하나씩) 제공 해상도로 설정합니다. 그렇지 않으면 Android는 따라서 비트맵이 각 화면에서 동일한 표시 공간을 차지하여 흐리게 처리와 같은 확장 아티팩트가 있습니다

<ph type="x-smartling-placeholder">
</ph> 다양한 밀도 크기에서 비트맵의 상대적 크기를 보여주는 이미지 <ph type="x-smartling-placeholder">
</ph> 그림 3: 다양한 밀도 버킷에 있는 비트맵의 상대적 크기

앱에서 사용할 수 있는 밀도 버킷은 여러 개가 있습니다. 표 1 사용 가능한 다양한 구성 한정자와 화면 유형에 대해 설명 정의할 수 있습니다

표 1. 다양한 지정할 수 있습니다.

밀도 한정자 설명
ldpi 저밀도 (ldpi)의 화면 (~120dpi)에 대한 리소스입니다.
mdpi 중밀도 (mdpi)의 화면 (~160dpi)에 대한 리소스입니다. 기준입니다. 표시됩니다.
hdpi 고밀도 (hdpi)의 화면 (~240dpi)에 대한 리소스입니다.
xhdpi 초고밀도 (xhdpi)의 화면 (~320dpi)에 대한 리소스입니다.
xxhdpi 초초고밀도 (xxhdpi) 화면 (~480dpi)에 대한 리소스입니다.
xxxhdpi 초초초고밀도 (xxxhdpi) 화면 (~640dpi)에 대한 리소스입니다.
nodpi 모든 밀도에 대한 리소스입니다. 이들은 밀도 독립적 리소스입니다. 시스템은 현재 화면의 밀도에 관계없이 이 한정자로 태깅된 리소스를 조정합니다.
tvdpi mdpi와 hdpi 사이에 있는 화면에 대한 리소스입니다. 대략 ~213dpi '기본' 밀도 그룹으로 간주되지 않습니다. 대부분 대부분의 앱에는 필요하지 않으므로 mdpi 및 hdpi를 제공합니다. 대부분의 앱에는 리소스가 충분하며, 시스템은 필요에 따라 리소스를 확장합니다 있습니다. tvdpi 리소스를 제공해야 하는 경우 1.33 * mdpi의 배율로 크기를 조절합니다. 예를 들어, 300x250 크기의 100x100픽셀 이미지는 mdpi 화면은 tvdpi에서 133x133픽셀입니다.

다른 밀도에 대해 대체 비트맵 드로어블을 만들려면 6가지 기본 밀도 간 조정 비율이 3:4:6:8:12:16입니다. 예를 들어 중밀도 화면에서 48x48 픽셀인 비트맵 드로어블의 경우, 크기는 다음과 같습니다.

  • 저밀도 (ldpi)의 경우 36x36 (0.75x)
  • 중밀도 (mdpi)의 경우 48x48 (1.0x 기준)
  • 고밀도 (hdpi)의 경우 72x72 (1.5x)
  • 초고밀도 (xhdpi)의 경우 96x96 (2.0x)
  • 초초고밀도 (xxhdpi)의 경우 144x144 (3.0x)
  • 초초초고밀도 (xxxhdpi)의 경우 192x192 (4.0x)

생성된 이미지 파일을 적절한 하위 디렉터리에 배치합니다. res/ 아래:

res/
  drawable-xxxhdpi/
    awesome_image.png
  drawable-xxhdpi/
    awesome_image.png
  drawable-xhdpi/
    awesome_image.png
  drawable-hdpi/
    awesome_image.png
  drawable-mdpi/
    awesome_image.png

그런 다음 @drawable/awesomeimage를 참조할 때마다 시스템이 화면의 dpi를 기반으로 적절한 비트맵을 선택합니다. 만약 해당 밀도에 대한 밀도 특정 리소스를 제공하지 않는 경우 시스템은 화면에 맞게 크기를 조정합니다.

팁: 드로어블 리소스가 있는 경우 시스템 확장을 원하지 않는 시간을 예로 들 수 있습니다 이미지를 직접 수정해서 해당 디렉터리에 nodpi 구성 한정자가 있을 수 있습니다. 이 한정자가 있는 리소스는 밀도에 구속받지 않는 것으로 간주됩니다. 시스템에서는 이를 확장하지 않습니다

다른 구성 한정자와 Android가 적합한 리소스를 선택하는 방법 현재 화면 구성은 앱 리소스 개요를 참고하세요.

mipmap 디렉터리에 앱 아이콘 지정

다른 비트맵 애셋과 마찬가지로 앱 아이콘을 탭합니다. 하지만 일부 앱 런처는 최대 25%까지 앱 아이콘을 표시합니다. 장치의 밀도 버킷에 의해 요구되는 것보다 더 큽니다.

예를 들어, 기기의 밀도 버킷이 xxhdpi이고 가장 큰 앱 아이콘인 경우 drawable-xxhdpi에 있는 경우 앱 런처가 이 아이콘을 확장합니다. 이미지가 덜 선명하게 보입니다.

이를 방지하려면 앱 아이콘이 drawable 디렉터리가 아닌 mipmap 디렉터리에 있습니다. 좋아요 취소 디렉터리 drawable개, 디렉터리 mipmap개가 모두 APK에 유지됨 빌드에 사용하는 방법을 파악할 수 있습니다 이렇게 하면 런처 앱이 최적의 이미지를 해상도 아이콘을 탭합니다.

res/
  mipmap-xxxhdpi/
    launcher_icon.png
  mipmap-xxhdpi/
    launcher_icon.png
  mipmap-xhdpi/
    launcher_icon.png
  mipmap-hdpi/
    launcher_icon.png
  mipmap-mdpi/
    launcher_icon.png

xxhdpi 기기의 이전 예에서는 mipmap-xxxhdpi 디렉터리에 있는 고밀도 런처 아이콘

아이콘 디자인 가이드라인은 시스템 아이콘을 참고하세요.

앱 아이콘 빌드에 대한 도움말은 Image Asset Studio로 앱 아이콘 만들기를 참고하세요.

특수한 밀도 문제에 관한 조언

이 섹션에서는 Android에서 비트맵 크기 조정을 실행하는 방법을 설명합니다. 픽셀 밀도의 조정에 대해 알아보고, 해상도를 조정하여 다른 밀도에 그려집니다. 앱에서 그래픽을 조작하지 않는 경우 다른 픽셀 밀도에서 실행할 때 문제가 발생한 경우 이 섹션을 무시할 수 있습니다

그래픽을 조작할 때 여러 밀도를 지원할 수 있는 방법을 더 잘 이해하려면 시스템이 비트맵의 적절한 크기를 보장하는 방법을 알아야 합니다. 이 작업은 다음과 같은 방법으로 수행됩니다.

  1. 비트맵 드로어블과 같은 리소스의 사전 크기 조정

    시스템은 현재 화면의 밀도를 기반으로 하여 밀도별 리소스를 정의할 수 있습니다 리소스 가용성이 시스템이 기본 리소스를 로드하고 필요에 따라 리소스를 확장하거나 축소합니다. 시스템은 기본 리소스 (기본 리소스)가 구성 한정자가 없는 디렉터리)는 기준을 위해 디자인됩니다. 픽셀 밀도 (mdpi)를 사용하여 비트맵을 해상도 설정으로 현재 픽셀 밀도를 반환합니다.

    사전 크기 조정된 리소스의 크기를 요청하면 시스템에서 값을 반환합니다. 크기 조정 의 크기를 나타냅니다. 예를 들어 50x50픽셀로 디자인된 비트맵은 mdpi 화면의 경우 hdpi 화면에서 75x75 픽셀로 조정됩니다 (대체 리소스가 없는 경우). hdpi의 경우) 시스템에서 다음과 같이 크기를 보고합니다.

    Android에서 사전 크기 조정을 진행하지 않아야 하는 상황이 있습니다. 리소스일 수 있습니다 사전 크기 조정을 방지하는 가장 쉬운 방법은 리소스를 리소스 디렉터리에 넣는 것입니다. nodpi 구성 한정자를 사용합니다. 예를 들면 다음과 같습니다.

    res/drawable-nodpi/icon.png

    시스템에서 이 폴더의 icon.png 비트맵을 사용할 때 비트맵의 크기를 조정하지 않음 자동으로 조정될 수 있습니다.

  2. 픽셀 크기 및 좌표 자동 크기 조정

    android:anyDensity 설정을 통해 크기 및 이미지의 사전 크기 조정을 사용 중지할 수 있습니다. 매니페스트에서 "false"로 설정하거나 Bitmap의 경우 프로그래매틱 방식으로 inScaled"false"로 설정합니다. 포함 이 경우 시스템은 절대 픽셀 좌표와 치수 값을 설정할 수 있습니다. 이렇게 하면 픽셀이 화면 요소가 여전히 거의 동일한 실제 크기로 표시됨 기준 픽셀 밀도 (mdpi)로 표시할 수 있습니다. 시스템은 이 크기 조정이 앱에 투명하게 적용되고, 조정된 픽셀을 보고합니다. 앱에 실제 픽셀 크기가 아닌 실제 크기입니다.

    예를 들어 어떤 기기에 480x800인 WVGA 고밀도 화면이 있고 기존 HVGA 화면과 크기가 같지만, 이 화면은 사전 크기 조정을 지원합니다. 이 경우 시스템은 앱이 화면을 쿼리할 때 320x533(픽셀 밀도의 대략적인 mdpi 변환)을 보고합니다.

    그런 다음 앱이 (10,10)에서 (100, 100)인 경우, 시스템은 적절한 양만큼 배율을 조정하여 좌표를 변환하고, 실제로 리전 (15,15)에서 (150, 150)을 무효화합니다. 이러한 불일치로 인해 다음과 같은 경우 예기치 않은 동작이 발생할 수 있습니다. 앱에서 크기 조정된 비트맵을 직접 조작하지만 이는 최적의 앱 성능을 보장하기 위해 이 오류가 발생하면 dp 단위를 픽셀로 변환 단위를 참고하세요.

    일반적으로 사전 크기 조정을 사용 중지하지 않습니다. 여러 이 페이지에 설명된 기본 기법을 따르는 것입니다.

앱이 비트맵을 조작하거나 화면의 픽셀과 직접 상호작용하는 경우 다른 방식으로는 다양한 지원 요청들을 지원하기 위한 추가 조치를 취해야 할 수 있습니다 지정할 수 있습니다. 예를 들어 터치 동작에 반응할 때 사용자가 손가락이 교차하는 픽셀 수를 나타내려면 적절한 밀도 독립형 픽셀 값을 사용하는 대신, dp 및 px 값 사이에서 변환할 수 있습니다.

모든 픽셀 밀도에 관해 테스트

서로 다른 픽셀로 여러 기기에서 앱 테스트 UI의 크기 조정이 올바르게 이루어지도록 합니다. 물리적 서버 사용하지 못하도록 하는 것입니다. Android 에뮬레이터(있는 경우)는 사용할 수 있습니다.

실제 기기에서 테스트하고 싶지만 기기를 구매하지 않으려면 Firebase Test Lab을 Google 데이터 센터의 장치에 액세스 할 수 있습니다.