처음 안드로이드 스튜디오를 설치하고 스마트폰 앱을 개발하는 경우 대부분 AVD 가상 장치를 이용하여로 테스트를 진행 하는데 어느정도 완성이 되면 실제 핸드폰을 이용하여 테스트를 해야 합니다.  이때 핸드폰을 개발자 모드로 설정 하였지만 컴퓨터에 연결을 해도 Android Studio에서 인식을 하지 못하여 테스트를 할 수 없는 상황을 격게 됩니다.  물론 어떤 기종의 스마트폰은 USB로 연결 하자 마자 쉽게 인식이 되는 경우도 있고 어떤 기종은 계속 오류가(오류라기 보다는 연결이 안됨) 발생 합니다.

 

 

위의 그림은 스마트폰을 USB로 연결하여도 디바이스를 찾지 못하고 가상 디바이스만 나타나는 현상 입니다.  이런 경우는 컴퓨터 운영체제 버전이 낮거나 업데이트가 안되어 스마트폰 드라이버를 지원하지 못하여 발생하는 경우가 많습니다스마트폰용 USB 드라이버가 설치되지 않아서 인식을 못하는 상황이 발생한 것입니다.

 

 

확인을 하려면 스마트폰을 USB로 연결하고 [드라이버 소프트웨어 설치] 창을 열어보면 오래된 운영체제 또는 업데이트가 안된 경우 드라이버를 찾지 못하여 계속 찾기를 반복만 하고 있습니다.

 

이 글에서는 제가 사용하고 있는 삼성폰으로 설명을 진행 하지만 다른 제조 회사 제품도 동일한 현상이 발생하면 아래의 방법으로 해결을 하면 되는데 인식이 안되는 스마트폰은 제조사 마다 USB 드라이버를 제공하고 있으니 제조사 홈페이지에 들어가 통합 드라이버를 다운받아 설치를 진행 하면 간단히 해결 할 수 있습니다.

 

삼성 스마트폰 드라이버 다운로드 사이트 접속 주소 입니다.(각 제조사별로 작업합니다.)

https://developer.samsung.com/mobile/android-usb-driver.html

 

 

SAMSUNG_USB_Driver_for_Mobile_Phones.exe 를 클릭 하면 드라이버 다운로드가 바로 진행되고 완료 되면 실행 하여 드라이버 설치를 진행 합니다.  설치 작업은 대부분 기본 설정된 버튼을 클릭 하면 됩니다.

 

 

 

 

여기 까지는 설치를 위한 설정 진행입니다.

 

이제 [설치] 버튼을 클릭 하면 드라이버 설치가 진행 됩니다.

 

 

설치가 진행 되고

 

 

설치가 완료되면 [마침] 버튼을 클릭 하여 종료 합니다.  경우에 따라 바로 장치를 인식하는 경우도 있고 컴퓨터를 재시작 해야 스마트폰을 인식하는 경우도 있습니다.  저는 Windows 7인데 다시 시작을 해야 인식이 되었습니다.  윈도우 창 우측에서 [드리이버 소프트웨어 설치] 창을 열어보면

 

 

 

계속 찾기로 빙빙 돌던 아이콘이 체크로 변하고 상태도 [사용 준비 완료]로 변경 되어 있고 스마트폰을 사용할 수 있는 상태가 된 것 입니다.

 

 

안드로이드 스튜디오를 열어보면 데스트 디바이스가 가상 디바이스에서 연결된 실제 스마트폰으로 변경된 것을 확인 할 수 있습니다.

이제부터는 상황에 따라 가상 디바이스 또는 실제 스마트폰을 선택하여 테스트할 수 있는 환경이 마련 되었습니다.

 

- copy coding -

RelativelayoutView의 상대적 위치를 이용하여 위치를 설정하는 방법입니다.  상대적 위치를 이용하여 View 들을 정렬 하므로 기준이 되는 ViewID 값 설정이 필수적 입니다.RelativeLayout은 중첩된 View 그룹을 없애고 레이아웃 계층 구조를 평면으로 유지하여 성능을 개선 하고 중첩된 LinearLayout을 대체할 수 있습니다.

 

 

1. 기준 View와의 상대적 위치

 

기준 View를 중심으로 추가되는 View의 위치를 위, 아래, 왼쪽, 오른쪽 등 상대적 위치에 위치 시키는 옵션 입니다.  상대적 위치의 설정 값으로 기준 View ID가 사용되므로 기준이 되는 View에는 꼭 아이디 값이 부여되어 있어야 합니다.

 

 

attributes

설명

android:layout_above

기준 View의 위 선에 View의 위 선을 맞춤

layout_below

기준 View의 아래 선에 View의 아래 선을 맞춤

layout_toLeftOf

기준 View의 왼쪽 선에 View의 왼쪽 선을 맞춤

layout_toRightOf

기준 View의 오른쪽 선에 View의 오른쪽 선을 맞춤

 

잠시 잘못된 예제를 하나 보도록 하겠습니다.

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>

    <
TextView
       
android:id="@+id/cntText"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:background="#F6D55C"
       
android:text="중앙"
/>

    <
TextView
        
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_above="@+id/cntText"
       
android:background="#DDED553B"
       
android:text="Above"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_below="@+id/cntText"
       
android:background="#DDED553B"
       
android:text="Below"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_toLeftOf="@+id/cntText"
        
android:background="#E3AA"
       
android:text="toLeftof"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_toRightOf="@+id/cntText"
       
android:background="#E3AA"
       
android:text="toRightof"
/>
</
RelativeLayout>

 

위와 같이 기준이 되는 View가 좌측 상단에 위치하게 되면 상단과 좌측에 있는 View는 보이지 않는 영역으로 나가게 됩니다.  그래서 새로운 예제에서는 android:layout_centerInParent = "true" 를 사용하여 기준 View를 중앙에 위치 시켰고 다른  예제에서도 동일한 현상이 발생하는 경우 기준 View의 위치를 잡아주는 방법을 사용하였습니다.

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>

    <
TextView
       
android:id="@+id/cntText"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:background="#F6D55C"
        
android:text="중앙"
/>

    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:layout_above="@+id/cntText"
       
android:background="#DDED553B"
       
android:text="Above"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:layout_below="@+id/cntText"
       
android:background="#DDED553B"
       
android:text="Below"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:layout_toLeftOf="@+id/cntText"
       
android:background="#E3AA"
       
android:text="toLeftof"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:layout_toRightOf="@+id/cntText"
       
android:background="#E3AA"
       
android:text="toRightof"
/>
</
RelativeLayout>

 

 

좌측, 우측 정렬을 다른 옵션을 사용하여 위치 시킬 수 있습니다.  문장의 시작 위치가 좌측이 아닌 우측에서 시작하는 국가를 위한 방안으로 정렬도 좌측, 우측이 아닌 시작과 끝으로 설정하는 방법입니다.

 

attributes

설명

layout_toStartOf

기준 View의 시작 선에 View의 시작 선을 맞춤

layout_toEndOf

기준 View의 끝 선에 View의 끝 선을 맞춤

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>
    <
TextView
       
android:id="@+id/cntText"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:background="#F6D55C"
       
android:text="중앙"
/>

    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:layout_toStartOf="@+id/cntText"
       
android:background="#E3AA"
       
android:text="toStartOf"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:layout_toEndOf="@+id/cntText"
       
android:background="#E3AA"
       
android:text="toEndOf"
/>

</
RelativeLayout>

 

 

 

2. 기준 View와 정렬

 

기준 View를 기준으로 좌측, 우측, 상단, 하단의 끝 선을 정렬하는 기능입니다.  예제에서는 각 정렬 별로 View를 하나씩만 표현하여 보았습니다.  끝 선을 맞추기 위하여 모든 View에는 기준이 되는 ViewID 값인 android:layout_alignBottom="@+id/cntText" 을 포함하고 있습니다.

 

attributes

설명

layout_alignTop

기준 View의 위쪽 선에 View의 위쪽 선을 맞춤

layout_alignBottom

기준 View의 아래쪽 선에 View의 아래쪽 선을 맞춤

layout_alignLeft

기준 View의 왼쪽 선에 View의 왼쪽 선을 맞춤

layout_alignRight

기준 View의 오른쪽 선에 View의 오른쪽 선을 맞춤

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>

    <
TextView
       
android:id="@+id/cntText"
       
android:layout_width="wrap_content"
       
android:layout_height="200dp"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:background="#F6D55C"
       
android:text="중앙"
/>

    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignTop="@id/cntText"
       
android:background="#E3AA"
       
android:text="alignTop"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignBottom="@+id/cntText"
       
android:background="#E3AA"
        
android:text="alignBottom"
/>
    <
TextView
       
android:id="@+id/alignLeft"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignLeft="@+id/cntText"
       
android:background="#E3AA"
       
android:text="alignLeft"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_below="@+id/alignLeft"
       
android:layout_alignRight="@+id/cntText"
       
android:background="#E3AA"
       
android:text="alignRight"
/>
</
RelativeLayout>

 

 

정렬 방법에서도 시작과 끝을 이용하여 정렬 해줄 수 있습니다.  추가로 기준 View의 텍스트를 이용하여 정렬 하는 방법도 있습니다.

 

attributes

설명

layout_alignStart

기준 View의 시작 선에 View의 시작 선을 맞춤

layout_alignEnd

기준 View의 끝 선에 View의 끝 선을 맞춤

layout_alignBaseline

기준 ViewText 기준선에 맞추어 정렬

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>

    <
TextView
       
android:id="@+id/cntText"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="50dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:background="#F6D55C"
       
android:text="중앙"
/>

    <
TextView
       
android:id="@+id/alignStart"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignStart="@id/cntText"
       
android:background="#E3AA"
       
android:text="alignStart"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_below="@id/alignStart"
       
android:layout_alignEnd="@id/cntText"
       
android:background="#E3AA"
       
android:text="alignEnd"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_below="@id/alignStart"
       
android:layout_alignBaseline="@id/cntText"
       
android:background="#E3AA"
       
android:text="alignBaseline"
/>
</
RelativeLayout>

 

 

 

3. 부모(Parent) 창 기준 정렬

 

부모 창의 좌측, 우측, 상단, 하단에 View을 정렬하는 방법입니다.  기준이 되는 View는 존재하지 않고 부모 창에 원하는 위치를 잡아 View를 배열하는 방법입니다.  여기서도 상대적 위치가 없으면 모든 View Top으로 모여 겹쳐 보이기 때문에 일부 View에 상대적 위치를 추가하여 표현하였습니다.

 

attributes

설명

layout_alignParentTop

true 이면 부모 창의 위쪽 선에 View의 위쪽 선을 맞춤

layout_alignParentBottom

true 이면 부모 창의 아래쪽 선에 View의 아래쪽 선을 맞춤

layout_alignParentLeft

true 이면 부모 창의 시작 선에 View의 시작 선을 맞춤

layout_alignParentRight

true 이면 부모 창의 끝 선에 View의 끝 선을 맞춤

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>

    <
TextView
       
android:id="@+id/alignParentTop"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignParentTop="true"
       
android:background="#E3AA"
       
android:text="alignParentTop"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignParentBottom="true"
       
android:background="#E3AA"
       
android:text="alignParentBottom"
/>
    <
TextView
       
android:id="@+id/alignParentRight"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignParentRight="true"
       
android:layout_below="@id/alignParentTop"
       
android:background="#E3AA"
       
android:text="alignParentRight"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignParentLeft="true"
       
android:layout_below="@id/alignParentRight"
       
android:background="#E3AA"
       
android:text="alignParentLeft"
/>

</
RelativeLayout>

 

 

부모(Parent)창 정렬에도 시작과 끝을 이용하여 좌측, 우측 정렬을 표현할 수 있습니다.

 

attributes

설명

layout_alignParentStart

true 이면 부모 창의 시작 점에 View의 시작 점을 맞춤

layout_alignParentEnd

true 이면 부모 창의 끝점에 View의 끝 점을 맞춤

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>

    <
TextView
       
android:id="@+id/alignParentStart"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignParentStart="true"
       
android:background="#E3AA"
       
android:text="alignParentStart"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_alignParentEnd="true"
       
android:layout_below="@+id/alignParentStart"
       
android:background="#E3AA"
       
android:text="alignParentEnd"
/>
</
RelativeLayout>

 

 

 

 

4. 중앙 정렬

 

지금까지는 어느 끝부분에 맞추어 정렬하는 방법들을 알아 보았는데 이번에는 그냥 중앙에 위치시키는 방법들입니다.

 

attributes

설명

layout_centerVertical

true 이면 부모 창 세로의 중앙에 위치

layout_centerHorizontal

true 이면 부모 창 가로의 중앙에 위치

layout_centerInParent

true 이면 부모 창 가로와 세로의 중앙에 위치

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
>

    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerVertical="true"
       
android:background="#E3AA"
       
android:text="Vertical"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerHorizontal="true"
       
android:background="#E3AA"
       
android:text="Horizontal"
/>
    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:padding="10dp"
       
android:textSize="30sp"
       
android:layout_centerInParent="true"
       
android:background="#E3AA"
       
android:text="center"
/>
</
RelativeLayout>

 

- copy coding -

개인적으로 프로젝트의 성공 여부는 70%가 디자인이라고 생각합니다. 메인 시안이 어떻게 나오는가에 따라 코딩을 하나도 하지 않았어도 고객이 바라보는 시선이 달라지는 경우가 있습니다.  디자인감각도 있고 구현에 대한 기능적인 부분까지 갖추어 진다면 얼마나 좋을까요.

오늘은 리니어레이아웃의 기본적인 옵션들에 대한 사용 방법으로 버튼, 텍스트, 이미지 등을 원하는 곳에 위치시키는 방법에 대해 공부해 봅니다. 설명을 끝내고 나니 아래 글을 읽을 때 위젯과 뷰(View : TextView, Button 등을 가리킴) 단어를 같이 사용하여 혼란이 있을 수 있으나 동일한 내용입니다.

 

LinearLayout에 사용되는 설정 값들은 아래와 같습니다

 

옵션

설명

orientation

layout의 정렬 방향으로 행 "horizontal", "vertical"을 뜻한다.

baselineAligned

기준점을 설정해서 정렬하는 기능으로 false로 설정하면 baselines 정렬을 하지 않는다.

baselineAlignedChildIndex

linear layout이 다른 layout의 부분일 경우 몇 번째 위젯에. 정렬의 기준을 정할 것인가에 대한 순번으로 0부터 시작 한다.

divider

Drawablebutton 사이의 구분자로 사용 한다.

gravity

뷰 자신은 영역 내에서 특정 위치를 설정 한다

measureWithLargestChild

true 로 설정 하면 layout weight을 가지는 모든 뷰의 크기를 가장 큰 뷰의 크기로 변경 시킨다.

weightSum

위젯에 사용된 weight 들의 합계.

 

1. 방향(orientation)

 

LinearLayoutorientation은 가장 기본적이고 필수적인 설정으로 뷰(view)들을 수직(vertical) 또는 수평(horizontal)으로 정렬 하는데 사용 합니다.

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="horizontal"
   
>

    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="View 1" />

    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="View 2" />

</
LinearLayout>

 

xml 예와 같이 android:orientation="horizontal" 로 설정하면 수평으로 정렬을 하고

 

 android:orientation="vertical" 로 설정하면 뷰들을 수직으로 정렬을 합니다.

 

 

2. baselineAligned

 

baselineAligned는 뷰들을 정렬하기 위해 기준점을 설정하고 그 점을 기준으로 평형을 맞추는 방법입니다.  특별히 설정을 하지 않더라도 기본적으로 true 값을 가지고 있습니다.  그러나 높이가 다른 뷰들이 모이면 높낮이에 차이가 발생합니다.

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="horizontal"
   
android:baselineAligned="true"
   
>

    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 1"
/>

    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 2"
/>

    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 3\n test"
/>

    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 4"
/>
</
LinearLayout>

 

베이스라인 정렬을 취소하면 기본적인 상담 맞춤으로 정렬됩니다.

android:baselineAligned="false"

 

베이스라인 정렬 보다는 이게 더 보기 좋습니다.  그렇지만 모든 레이아웃에 설정 값이 반영되기 때문에 가능하면 레이아웃 중첩에서 사용 하는게 좋을 것 같습니다.

 

 

3. baselineAlignedChildIndex

 

뷰들이 뒤 섞여 있는 경우 베이스 라인 정렬 기준을 뷰들 중 하나를 선택해서 적용 하는데 사용하는 옵션입니다.  순서는 0부터 시작됩니다.

다음과 같이 뷰들이 나열되어 있고 내부에 레이아웃 중첩을 사용하고 있는 경우

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="horizontal"
   
android:baselineAligned="true"
   
>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 1"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 2"
/>
    <
Button
       
android:layout_width="wrap_content"
        
android:layout_height="70dp"
       
android:text="View 3\n test"
/>
    <
LinearLayout
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:orientation="vertical"
       
>
        <
Button
            
android:layout_width="wrap_content"
           
android:layout_height="wrap_content"
           
android:text="View 4"
/>
        <
Button
           
android:layout_width="wrap_content"
           
android:layout_height="wrap_content"
           
android:text="View 5"
/>
    </
LinearLayout>
</
LinearLayout>

 

view5 를 기준으로 정렬을 하고 싶다면 view5가 중첩된 레이아웃에서 사용되고 순서가 두 번째 이므로 아래와 같이 선언해 주면 됩니다.

android:baselineAlignedChildIndex="1"

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="horizontal"
   
android:baselineAligned="true"
   
>
    <
Button
       
android:layout_width="wrap_content"
        
android:layout_height="50dp"
       
android:text="View 1"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 2"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="70dp"
       
android:text="View 3\n test"
/>
    <
LinearLayout
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:orientation="vertical"
       
android:baselineAlignedChildIndex="1"
       
>
        <
Button
           
android:layout_width="wrap_content"
           
android:layout_height="wrap_content"
           
android:text="View 4"
/>
        <
Button
           
android:layout_width="wrap_content"
           
android:layout_height="wrap_content"
           
android:text="View 5"
/>
    </
LinearLayout>
</
LinearLayout>

 

자주 사용 되지는 않을 것 같군요.

 

 

4. divider

 

divider는 말 그대로 나누는 건데 뷰 중간에 이미지를 사용하여 좀 더 레이아웃을 예쁘게 꾸며 주는 옵션입니다.  사용하려면 미리 이미지를 만들어 @drawable에 추가를 해야 합니다.   저는 대충 기존에 있는 아이콘을 사용하여 구현을 해 보았습니다.   최악의 디자인이 되겠군요.

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="vertical"
    
android:divider="@mipmap/ic_launcher"
   
android:showDividers="middle"
   
>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 1"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="50dp"
       
android:text="View 2"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="70dp"
       
android:text="View 3\n test"
/>
</
LinearLayout>

 

디바이더를 사용하면 뷰 사이에 이미지 태그를 사용하여 직접 추가하지 않아도 됩니다. 사용 예에서는 중간에만 이미지를 추가 하였는데 구분자를 이용하여 시작과 끝 부분에도 추가가 가능합니다

android:showDividers="middle|beginning|end"

 

 

5. gravity

 

뷰를 정렬 할 때 화면이 아래쪽으로 중력이 작용한다고 가정하여 뷰들을 정렬하는 옵션으로 구분자(|)를 사용하여 여러 개를 설정할 수 있습니다.

 

 

Constant

Value

Description

bottom

50

크기 변화 없이 containerbottom에 정렬

center

11

크기 변화 없이 container의 가로 세로 방향의 중앙에 정렬

center_horizontal

1

크기 변화 없이 container의 가로 방향의 중앙에 정렬

center_vertical

10

크기 변화 없이 container의 세로 방향의 중앙에 정렬

clip_horizontal

8

horizontal gravity를 기준으로 container의 경계를 벗어나는 부분을 잘라 낸다.  left gravity의 경우 오른쪽을 right의 경우 왼쪽을 잘라 낸다. 양쪽에 경우에는 양쪽 모두 잘라 낸다.

clip_vertical

80

clip_horizontal과 반대되는  옵션이다

end

800005

크기 변화 없이 containerend에 정렬

fill

77

위젯의 크기를 container의 크기에 맞추어 확장한다

fill_horizontal

7

container의 크기에 맞추어 위젯의 가로 크기를 확장한다

fill_vertical

70

container의 크기에 맞추어 위젯의 세로 크기를 확장한다

left

3

크기 변화 없이 container의 좌측에 정렬

right

5

크기 변화 없이 container의 우측에 정렬

start

800003

크기 변화 없이 container의 시작 위치에 정렬

top

30

크기 변화 없이 container의 위에 정렬

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="vertical"
   
android:gravity="center"
   
>

    <
Button
       
android:layout_width="wrap_content"
        
android:layout_height="wrap_content"
       
android:text="View 1"
/>

</LinearLayout>

 

 

6. measureWithLargestChild

 

뷰의 높이가 다양할 경우 지저분한 모양을 갖게 됩니다. 이런 경우 가장 큰 뷰의 높이에 모두 맞추어 좀 더 통일된 이미지를 얻는데 사용할 수 있습니다.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="wrap_content"
   
android:orientation="vertical"
   
>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="60dp"
       
android:layout_weight="1"
       
android:text="View 1"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="90dp"
       
android:layout_weight="1"
       
android:text="View 2"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="70dp"
       
android:layout_weight="1"
       
android:text="View 3\n test"
/>
</
LinearLayout>

 

높낮이가 다양한 경우 아래와 같이 옵션을 추가해 줍니다.

android:measureWithLargestChild="true

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="wrap_content"
   
android:orientation="vertical"
   
android:measureWithLargestChild="true"
   
>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="60dp"
       
android:layout_weight="1"
       
android:text="View 1"
/>
    <
Button
       
android:layout_width="wrap_content"
        
android:layout_height="90dp"
       
android:layout_weight="1"
       
android:text="View 2"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="70dp"
       
android:layout_weight="1"
       
android:text="View 3\n test"
/>
</
LinearLayout>

 

 

7. weightSum

 

뷰의 높이를 숫자가 아닌 비율로 설정할 수 있습니다. 이 떄 비율의 총 합을 몇을 기준으로 할 것인지 설정 하는 것으로 100을 기준으로 했다면 비율의 총 합은 100이 되어야 합니다.  1 이라면 비율을 0.5, 0.2... 이렇게 되겠지요.

weightSum 없이 layout_weight을 사용해서 크기를 분할 하여 사용 할 수도 있습니다.

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="vertical"
   
android:weightSum="100"
   
>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:layout_weight="50"
       
android:text="View 1"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:layout_weight="30"
       
android:text="View 2"
/>
    <
Button
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:layout_weight="20"
       
android:text="View 3\n test"
/>
</
LinearLayout>

 

신규 에디터로 글을 쓰고 있는데 글을 쓰기 힘든걸 넘어 더이상 글을 쓰기 싫게 만드는 군요. -_-;;;

flash 지원 중단 때문인지는 모르겠지만 사진 편집 기능 빼고 그냥 예전걸로 글쓰게 해줌 안되나...

 

- copy coding -


안드로이드 앱은 핸드폰의 제한된 공간에서 작동 되는데 앱 외부에 있는 리소스(카메라, SMS, 저장공간 등)에 접속 하기 위해서는 핸드폰 소유자의 접근 허가 권한을 받아야 이용이 가능 합니다물론 Android 5.1(API 수준 22) 이하에서 실행하는 기기에 설치된 앱 이라면 권한이 설정 만으로도 자동으로 부여되므로 허가 요청은 필요하지 않습니다.

권한을 요청하는 순서대로 설명을 하면

 

1. 권한 설정

 

앱에서 필요한 권한을 AndroidManifest.xml 파일에 등록을 해야 합니다문법은

<uses-permission android:name="string" android:maxSdkVersion="integer" />

과 같이 작성 합니다.

Parameters

android:name

요청하려는 권한의 이름.

android:maxSdkVersion

권한이 필요한 최고 레벨 값. (“21” 이라면 API 레벨 21까지만 필요하고 22 이상은 필요 없다는 의미)

 

실제 사용 예를 들면 아래처럼 입력하면 됩니다.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />


권한의 종류는 안드로이드 사이트에 리스트 되어 있으며 양이 많아 링크만 연결해 드립니다.

https://developer.android.com/reference/android/Manifest.permission

 

 

2. 앱에 이미 권한이 부여되었는지 확인


사용하려는 권한을 이미 부여 받았다면 권한 요청을 다시 하지는 않습니다.

ContextCompat.checkSelfPermission() 메서드를 사용하여 앱에 이미 권한을 부여 받았는지 확인을 할 수 있습니다호출 결과로는 PERMISSION_GRANTED 또는 PERMISSION_DENIED를 반환 받게 됩니다.


public static int checkSelfPermission (Context context, String permission)


Parameters

context

Context

permission

String : 필요한 권한 명칭

 

Returns

int

PackageManager.PERMISSION_GRANTED - 이미 권한이 있는 경우

PackageManager.PERMISSION_DENIED – 권한이 없는 경우

 

실제 사용 예는 아래와 같습니다.

ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION);

 

 

3. 앱에 권한이 필요한 이유 설명

 

앱에 필요한 권한을 요청 하려는 경우 사용자가 처음 권한을 요청 받은건지 기존에 요청을 받았는데 거부를 한 것인지에 따라 요청 방식을 달리 해야 하고 요청 화면도 달라지게 됩니다.


shouldShowRequestPermissionRationale() 메서드는 사용자가 이전에 권한 요청을 거부한 경우 true 값을 넘겨주게 되어 있습니다그 결과를 이용하여 앱을 사용하려면 권한이 필요함을 사용자에게 알려 주는 안내를 추가 해야 합니다.


public static boolean shouldShowRequestPermissionRationale (Activity activity, String permission)

 

Parameters

activity

Activity: The target activity.

permission

String : 필요한 권한 명칭

 

Returns

boolean

Whether you should show permission rationale UI.

 

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {

  // 이전에 거부한 경우 권한 필요성 설명 및 권한 요청

} else {

  // 처음 요청하는 경우 그냥 권한 요청

}

 

 

 

4. 권한요청

 

권한 요청은 메소드를 호출 하면서 필요한 권한을 적어주면 됩니다요청 하려는 권한이 한개 이상이면 String 배열에 죽 기입해 주면 되고 너무 많으면 배열을 별도로 작성해서 추가해도 됩니다.


static void requestPermissions(Activity activity, String[] permissions, int requestCode)

 

Parameters

Activity

Activity

permissions

String[p] : 필요한 권한 명칭들

requestCode

실행 후 전달 받을 코드

 

requestCode는 개발자가 임의로 만들어 놓은 코드를 말하고 메소드가 void를 리턴하는데 전달받으려는 값을 설정 한다는 건 메소드 실행 후 onRequestPermissionsResult() 메소드를 이용하여 결과 값을 넘겨 주게 됩니다.

 

- 요청 권한이 한개인 경우


static final int PERMISSIONS_REQUEST_READ_LOCATION = 0x00000001;

 

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},

                        PERMISSIONS_REQUEST_READ_LOCATION);

 

- 요청 권한이 2개 이상인 경우


static final int PERMISSIONS_REQUEST_READ_LOCATION = 0x00000001;

private String[] PERMISSIONS = {

    Manifest.permission.ACCESS_COARSE_LOCATION,

    Manifest.permission.ACCESS_FINE_LOCATION

};

ActivityCompat.requestPermissions(this,PERMISSIONS,PERMISSIONS_REQUEST_READ_LOCATION);

 

 

 

5. 권한요청 응답처리

 

사용자가 권한 요청 대화상자에 응답하면 시스템은 앱의 onRequestPermissionsResult() 메소드를 호출 하게 되고 이곳에서 결과에 대한 다음 작업을 진행하게 됩니다.

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    switch(requestCode) {

        case returnCode:

            if (grantResults.length > 0

                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                 // 권한 허가된 경우 처리

             } else {

                // 권한 거절된 경우 처리

            }

            break;

}

}

 

 

6. 테스트 프로젝트

 

간단한 권한 요청만 진행하는 프로젝트를 하나 생성해 봅니다.


android permission




android permission



 

프로젝트를 생성하고 소스를 입력 합니다.

실제 사용되는 파일은 2개이고 전체 소스 입니다.

 

- AndroidManifest.xml

 

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
   
package="copycoding.tistory.permissiontest">

    <uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
       
android:allowBackup="true"
        
android:icon="@mipmap/ic_launcher"
       
android:label="@string/app_name"
       
android:roundIcon="@mipmap/ic_launcher_round"
       
android:supportsRtl="true"
       
android:theme="@style/AppTheme">
        <activity
android:name=".MainActivity">
            <intent-filter>
                <action
android:name="android.intent.action.MAIN" />

                <category
android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

- MainActivity.java

 

package copycoding.tistory.permissiontest;

import
androidx.annotation.NonNull;
import
androidx.appcompat.app.AppCompatActivity;
import
androidx.core.app.ActivityCompat;
import
android.Manifest;
import
android.content.pm.PackageManager;
import
android.os.Bundle;
import
android.widget.Toast;

public class
MainActivity extends AppCompatActivity {

   
int nCurrentPermission = 0;
    static final int
PERMISSIONS_REQUEST = 0x0000001;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
OnCheckPermission();
   
}
   
public void OnCheckPermission() {
       
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
               
|| ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
           
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
                Toast.makeText(
this, "앱 실행을 위해서는 권한을 설정해야 합니다", Toast.LENGTH_LONG).show();
               
ActivityCompat.requestPermissions(this,
                        new
String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                       
PERMISSIONS_REQUEST);
           
} else {
                ActivityCompat.requestPermissions(
this,
                        new
String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                       
PERMISSIONS_REQUEST);
          
}
        }
    }

   
@Override
   
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
       
switch (requestCode) {
           
case PERMISSIONS_REQUEST :
               
if (grantResults.length > 0
                       
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(
this, "앱 실행을 위한 권한이 설정 되었습니다", Toast.LENGTH_LONG).show();
               
} else {
                    Toast.makeText(
this, "앱 실행을 위한 권한이 취소 되었습니다", Toast.LENGTH_LONG).show();
               
}
               
break;
       
}
    }
}

 

 

7. 결과 화면

 

- 처음 권한 요청


android permission



처음 권한을 요청하면 위 그림과 같이 [거부][허용] 버튼이 나타 납니다.

여기에서 거부를 클릭 했습니다.

 

- 거부 후 다시 실행시


android permission


이번에는 [다시묻지않음]이 추가된 요청 화면이 나타 납니다.


- copy coding -



1···3456789···17

+ Recent posts