ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 안드로이드 그림자(Shadow) 효과 넣기
    개발/안드로이드 2020. 4. 18. 11:43

    안드로이드에서 그림자 효과를 넣는 방법으로는 UI의 elevation 속성 값을 조정하는 것과 직접 그림자용 리소스 파일을 만드는 방법이 있다. 이번 포스트에서는 이 두가지의 사용 방법과 각각의 장단점을 소개해보려고 한다.

     

    1. elevation 값 조정하기 

     

    UI에 가장 쉽게 섀도우 효과를 입힐 수 있는 방법이다. 안드로이드 API21 부터 UI 뷰들에 elevation 이라는 속성값이 추가 됐는데 이 값을 넣으면 UI가 Z축으로 위로 튀어나와 그림자 효과를 줄 수 있게 된다. 

     

    elevation 값을 조정해 그림자 효과를 준 경우.

    코드는 다음과 같다.

     

    <androidx.constraintlayout.widget.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    
            <ImageView
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_margin="50dp"
                android:elevation="20dp"
                android:background="@color/colorPrimary" />
        </FrameLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

     

    elevation 값을 조정해서 효과를 줄 때는 주의해야할 점이 두가지 있는데 첫번째는 elevation 값에 넣어준 수치 만큼 View 주변에 여백을 충분하게 주어야 한다는 것이다. elevation으로 만든 그림자는 View의 width/height 영역 밖에서 발생하기 때문에 이 부분의 여백을 주지 않으면 그림자 효과가 발생하지 않는다. 

     

    미리보기 화면을 통해 확인해보면 FrameLayout 내부의 ImageView 주변에 여백이 있는 것을 확인 할 수 있다.

    두번째로는 background값이 투명하면 안된다. 불투명한 값으로 셋팅을 해줘야한다. 왜 불투명한 background 값을 셋팅해줘야하는지는 아직 잘 모르겠다; 하지만 투명한 값으로 세팅하면 그림자 효과가 나타나지 않는다.

     

    이 방법은 편하긴 하지만 API21 버전부터 사용할 수 있고 하단부에만 그림자 효과를 줄 수 있다는 단점이 있다. 상하좌우 모두 그림자 효과를 주어야 할 때는 사용 할 수 가 없다. 이런 경우에는 직접 리소스 파일로 그림자 효과를 만들어야 한다.

     

    2. 그림자용 리소스 파일 만들기

     

    선이나 사각형을 코드로 만들 때 사용했던 XML 파일을 이용해서 그림자 효과를 줄 수 있다. 설명에 앞서서 아래 예시 코드와 이 코드를 입힌 UI 결과물을 먼저 보자. 코드가 길지만 반복 구문이 많으니 대강 훓어보는 것을 추천한다

     

    shadow_test.xml

     

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <!-- Drop Shadow Stack -->
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#00CCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#06CCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#09CCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#0BCCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#0DCCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#10CCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#12CCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#15CCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#17CCCCCC" />
            </shape>
        </item>
        <item>
            <shape>
                <padding
                    android:bottom="2.5dp"
                    android:left="2.5dp"
                    android:right="2.5dp"
                    android:top="2.5dp" />
    
                <solid android:color="#1ACCCCCC" />
            </shape>
        </item>
    
        <!-- Background -->
        <item>
            <shape>
                <solid android:color="@android:color/white" />
            </shape>
        </item>
    
    </layer-list>

     

    ImageView에 위에서 만든 리소스를 background로 넣었다.

     

    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="RtlSymmetry">
    
            <ImageView
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:background="@drawable/shadow_test"/>
        </androidx.appcompat.widget.LinearLayoutCompat>
    </androidx.constraintlayout.widget.ConstraintLayout>

     

    이 코드를 이용해 그림자 효과를 입혀본 결과는 다음과 같다.

     

    예제 코드를 사용해 그림자 효과를 입힌 결과

    사진을 자세히 보면 흰 사각형 바깥쪽에 촘촘히 작은 선들이 있는 것을 볼 수가 있다. 이건 위 예제 코드에서 2.5dp 기준으로 각각 색깔이 다른 사각형을 넣었기 때문이다. 여러개의 작은 장면들을 조합해서 연속된 애니메이션 효과로 보이게 한 것 처럼 이 그라데이션 효과도 작은 사각형들을 합해서 그림자처럼 보이게 만든 효과다. 

     

    이 방법은 약간의 노가다가 필요하긴 하지만 개발자가 그림자 효과를 자유자재로 커스텀이 가능하다는 장점이 있다. 어떤 부분에 좀더 강조를 세게 주고 싶다거나 좌측 상단, 우측 하단, 상화좌우 전체에 그림자 효과를 선택해서 줄 수 있다. 

     

    elevation을 이용한 방법과 차이가 있다면 이 방법은 그림자 영역이 뷰의 영역에 포함되어 있다는 것이다. 아래 그림을 보면 왼쪽 그림의 보라색 사각형이 elevation을 이용해서 그림자 효과를 준 경우고 하얀색 사각형이 리소스를 이용해서 그림자 효과를 준 경우인데, 미리보기 상으로는 하얀색 사각형이 더 작아보이지만 두 ImageView의 가로 세로 너비 값은 오른쪽 그림에서도 알 수 있듯이 동일하다. 리소스를 사용하면 그림자 영역을 View 내부에서 사용하기 때문에 원래 생각했던 ImageView의 크기와 약간 차이가 발생 할 수 있다. 상황에 따라서 단점이 될 수도 있고 장점이 될 수 도 있는 기능이라 섣불리 판단 할 수는 없을 것 같다. 단 차이점은 유의해서 알고가는 것이 좋을 것 같다.

     

    '개발 > 안드로이드' 카테고리의 다른 글

    MediaCodec - Getting Started  (1) 2020.05.24
    Navigator - Getting Started  (0) 2020.04.20
    Kotlin - Coroutine  (0) 2020.04.15
    Kotlin으로 깔끔한 Builder를 만들어보자  (1) 2020.04.14
    Exoplayer2 사용하기  (0) 2020.04.12

    댓글

Designed by Tistory.