안드로이드 완벽 가이드 - 02 레이아웃과 기본 위젯 사용하기

출처

정재곤, 『Do it! 안드로이드 앱 프로그래밍 - 개정 4판』, 이지스퍼블리싱(주)(2017-06-26), 180-247p

http://wonjerry.tistory.com/5

https://jungwoon.github.io/android/2016/09/22/TextWatcher-Guide/


02-1 대표적인 레이아웃 살펴보기

대표적인 레이아웃 다섯 가지

레이아웃 이름 설명
제약 레이아웃 (ConstraintLayout) 제약 조건(Constraint) 기반 모델
제약 조건을 사용해 화면을 구성하는 방법
안드로이드 스튜디오에서 자동으로 설정하는 디폴트 레이아웃
리니어 레이아웃(LinearLayout) 박스(Box) 모델
한 쪽 방향으로 차례대로 뷰를 추가하며 화면을 구성하는 방법
뷰가 차지할 수 있는 사각형 영역을 할당
상대 레이아웃(ReleativeLayout) 규칙(Rule) 기반 모델
부모 컨테이너나 다른 뷰와의 상대적 위치로 화면을 구성하는 방법
프레임 레이아웃(FrameLayout) 싱글(Single) 모델
가장 상위에 있는 하나의 뷰 또는 뷰그룹만 보여주는 방법
여러 개의 뷰가 들어가면 중첩하여 쌓게 됨
가장 단순하지만 여러 개의 뷰를 중첩한 후 각 뷰를 전환하여 보여주는 방식으로 자주 사용함
테이블 레이아웃(TableLayout) 격자(Grid) 모델
격자 모양의 배열을 사용하여 화면을 구성하는 방법
HTML에서 많이 사용하는 정렬 방식과 유사하지만 많이 사용하지는 않음
  • 스크롤뷰(ScrollView): 스크롤 만드는 방법을 제공, 스크롤뷰 안에 하나의 뷰나 뷰그룹을 넣을 수 있음
  • 모든 레이아웃은 layout_width와 layout_height 속성을 가지고 있음

뷰의 영역

  • 뷰가 레이아웃에 추가될 때 보이지 않는 뷰의 테두리(Border)가 생김 –> 뷰의 영역(Box)
  • 뷰는 테두리를 기준으로 바깥쪽과 안쪽 공간을 띄움
  • 마진(Margin): 테두리 바깥쪽 공간
  • 패딩(Padding): 테두리 안쪽 공간

마진 값 조정 속성

layout_margin
layout_marginTop
layout_marginBottom
layout_marginLeft
layout_marginRight

패딩 값 조정 속성

padding
paddingTop
paddingBottom
paddingLeft
paddingRight

뷰의 배경색

  • background 속성을 설정하여 배경을 그림
  • XML에서 #을 붙이고 ARGB(Alpha, Red, Green, Blue)의 순서대로 색상의 값 기록(16진수)
  • 예를 들면 #ff000은 빨간색, #00ff00은 녹색이며 앞 두 자리 알파를 추가하여 #ffff0000은 빨간색, #88ff0000은 반투명 빨간색
  • 이미지도 배경으로 지정할 수 있으며 이미지 파일은 /res/drawable에 있음 이후 XML에서 android:background=”@drawable/imaegname”

02-2 리니어 레이아웃 사용하기

방항 설정하기

  • orientation: 방향 설정
  • horizontal: 가로 방향
  • vertical: 세로 방향
  • 프로젝트 기본 설정이 ConstraintLayout이여서 XML Text 탭에서 XML 원본 코드 바깥에 있는 태그 이름을 LinearLayout으로 바꿔야 함

1. SampleLinearLayout 프로젝트 만들기(Empty Activity)

2. activity_main.xml에서 Hello World 글자 삭제

3. Text 탭을 누르고 android.support.constraint.ConstraintLayoutLinearLayout으로 변경하기

4. xmlns:app, xmlns:tools, xmlns:context 속성이 있다면 삭제하기

5. andorid:orientation 속성을 추가하고 그 값은 vertical로 입력하기

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

    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    
</LinearLayout>

6. Design 탭으로 가서 버튼 세 개 추가, layout_width 속성은 match_parent, layout_height 속성은 wrap_content

image

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

android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
    >

<Button
    android:id="@+id/button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Button" />

<Button
    android:id="@+id/button2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Button" />

<Button
    android:id="@+id/button3"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Button" />
</LinearLayout>

AndroidManifest.xml 파일을 열고 액티비티를 위해 들어 있는 activity 태그의 android:name 속성 값을 바꾸면 지정한 액티비티 화면을 볼 수 있다. 예를 들어, android:name 송성 값을 바꾸면 MainActivity2.java 파일에서 지정한 화면을 볼 수 있다. <activity android:name=".MainActivity2"></activity>

7. orientation 속성 값을 horizontal로 바꾸기

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

android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
    >

<Button
    android:id="@+id/button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Button" />

<Button
    android:id="@+id/button2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Button" />

<Button
    android:id="@+id/button3"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Button" />
</LinearLayout>

image

XML 파일을 앱의 시작 화면에 띄워보고 싶으면 MainActivity.java 파일을 열고 setContentView() 메소드 안에 들어가는 파라미터 값을 원하는 XML 파일의 이름을 넣으면 됨. 예를 들면 R.layout.activity_main2

  • horizontal로 설정했을 때 버튼이 하나만 보인 이유는 match_parent 속성 때문
  • match_parent는 부모 컨테이너의 남아있는 여유 공간을 채움
  • android:layout_width="match_parent"에서 버튼이 가로 공간을 모두 차지해서 다른 버튼이 추가되지 못한 것

8. 세 버튼의 layout_width 속성을 wrap_content로 바꾸기

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

android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
    >

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Button" />

<Button
    android:id="@+id/button3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Button" />
</LinearLayout>

image

  • wrap_content는 내용물의 크기에 맞게 뷰의 크기가 결정
  • 텍스트뷰, 버튼은 내용물이 텍스트
  • 이미지를 보여주는 뷰의 경우 내용물은 이미지

자바 코드에서 화면 구성하기

  • 만들어진 XML 파일은 액티비티를 위해 만든 자바 소스 파일과 연결
  • MainActivity.java의 setContentView() 메소드가 activity_main.xml을 파라미터로 받아 레이아웃 파일이 액티비티에 설정
  • 화면을 바꿀 때 XML을 바꾸는게 쉽긴하지만 화면 레이아웃을 미리 만들 수 없거나 필요할 때마다 레이아웃을 만들 때는 자바 소스 코드에서 화면을 구성해야 함

1. MainActivity.java 파일을 복사하여 LayoutCodeActivity.jav 파일로 만든 후 수정하기

image

2. 다음과 같이 LayoutCodeActivity.java 파일에 코드 입력

package com.example.kai01.samplelinearlayout;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.LinearLayout;

public class LayoutCodeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // new 연산자로 리니어 레이아웃을 만들고 방향 설정
        LinearLayout mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);

        // new 연산자로 레이아웃 안에 추가될 뷰들에 설정할 파라미터 생성
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT);

        // 버튼에 파라미터 설정하고 레이아웃에 추가
        Button button01 = new Button(this);
        button01.setText("Button 01");
        button01.setLayoutParams(params);
        mainLayout.addView(button01);

        // 새로 만든 레이아웃을 화면에 설정
        setContentView(mainLayout);
    }
}
  • 앱을 실행할 때 처음 보이는 화면을 메인 액티비티라고 함
  • 메인 액티비티를 위한 자바 소스 파일의 이름은 MainActivity.java
  • 메인 액티비티는 AndroidManifest.xml 파일 안에 자동으로 등록됨
  • 메인 액티비티를 LayoutCodeActivity로 변경하면 새로 만든 액티비티가 화면에 나타나게 되는 것

3. app 폴더 안 manifests 폴더 안 AndroidManifest.xml 파일 열어 android:name=".LayoutCodeActivity:>로 수정

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

    <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=".LayoutCodeActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

4. 실행하기

image

  • MainActivity는 setContentView(R.layout.activity_main);으로 XML로 정의된 리소스를 가리키도록 설정
  • LayoutCodeActivity는 setContentView() 메소드의 파라미터에 자바 코드에서 만든 뷰그룹 객체 mainLayout을 넣음
 // new 연산자로 리니어 레이아웃을 만들고 방향 설정
        LinearLayout mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);
  • new LinearLayout()setOrientation() 메소드는 리니어 레이아웃 객체 방향
  • setOrientation(LinearLayout.VERTICAL)과 같이 방향 속성을 정의할 수 있음
  • 뷰 객체를 코드에서 만들 때 뷰의 생성자에는 항상 Context 객체가 전달되어야 함
  • AppCompatActivity 클래스는 Context를 상속하므로 이 클래스 안에서는 this를 Context 객체로 사용할 수 있음

컨텍스트(Context)는 어떤 일이 발생한 상황을 의미하는데 객체의 정보를 담고 있는 개게를 의미하며 안드로이드는 UI 구성 요소인 뷰에 대한 정보를 손쉽게 확인하거나 설정할 수 있도록 뷰의 생성자에 Context 객체를 전달하도록 되어 있음

// new 연산자로 레이아웃 안에 추가될 뷰들에 설정할 파라미터 생성
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT);
  • LayoutParams: 뷰를 만들어 뷰그룹에 추가할 때 뷰의 배치를 위한 속성을 설정
  • LayoutParams 객체를 새로 만들 경우에는 반드시 뷰의 가로와 세로 속성을 지정해야 함
  • LayoutParams.MATCH_PARENTLayoutParams.WRAP_CONTENT외에 가로와 세로의 크기 값을 직접 설정 가능
// 버튼에 파라미터 설정하고 레이아웃에 추가
        Button button01 = new Button(this);
        button01.setText("Button 01");
        button01.setLayoutParams(params);
        mainLayout.addView(button01);

        // 새로 만든 레이아웃을 화면에 설정
        setContentView(mainLayout);
  • 소스 코드에서 레이아웃에 뷰를 추가하고 싶으면 addView() 메소드 사용
  • addView() 메소드에는 추가할 뷰를 파라미터로 전달하며 LayoutParams 객체도 전달 가능
  • 이 코드에서는 addView() 메소드에 LayoutParams 객체를 전달하지 않고 버튼 객체의 setLayoutParams() 메소드를 이용해 레이아웃 파라미터를 버튼 객체에 먼저 설정함
// 버튼에 파라미터 설정하고 레이아웃에 추가
        Button button01 = new Button(this);
        button01.setText("Button 01");
        // button01.setLayoutParams(params);
        mainLayout.addView(button01, params);

        // 새로 만든 레이아웃을 화면에 설정
        setContentView(mainLayout);
  • 이렇게 쓸 수 있다는 말

뷰 정렬하기

  • 정렬(align): 순서대로 놓인다는 의미
  • gravity: 어느 쪽에 무게를 둘 것인가 즉 정렬을 의미

레이아웃에서 정렬 기능이 필요한 경우

정렬 속성 설명
layout_gravity 부모 컨테이너의 여유 공간에 뷰가 모두 채워지지 않아 여유 공간이 생겼을 때 여유 공간 안에서 뷰를 정렬
gravity 뷰 안에 표시하는 내용물을 정렬할 때(텍스트뷰의 경우 내용물은 글자가 되고 이미지뷰의 경우 내용물은 이미지가 됨)

layout_gravity 속성은 layout_으로 시작하고 gravity는 layout_으로 시작하지 않음

1. res/layout 폴더 안에 gravity.xml 만들기

image

  • res/layout 폴더 오른쪽 마우스 –> New –> Layout resource file
  • File name: gravity.xml
  • Root element: LinearLayout

2. gravity.xml에 다음과 같은 코드 입력하기

<?xml version="1.0" encoding="utf-8"?>
<!-- 리니어 레이아웃을 세로방향으로 지정 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 첫 번째 버튼을 왼쪽으로 정렬 -->
    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:text="left"/>

    <!-- 두 번째 버튼을 가운데로 정렬 -->
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="center"/>

    <!-- 세 번째 버튼을 오른쪽으로 정렬 -->
    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="right"/>
</LinearLayout>
  • Design 탭에서 만들 수도 있음

image

  • 여기서 오른쪽 하단 View all attribute를 누르면

image

  • layout_gravity를 설정할 수 있음

3. TextView를 추가하고 gravity 속성과 글자 색을 설정하기 위해 다음과 같이 코드 입력

<?xml version="1.0" encoding="utf-8"?>
<!-- 리니어 레이아웃을 세로방향으로 지정 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 첫 번째 버튼을 왼쪽으로 정렬 -->
    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:text="left"/>

    <!-- 두 번째 버튼을 가운데로 정렬 -->
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="center"/>

    <!-- 세 번째 버튼을 오른쪽으로 정렬 -->
    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="right"/>

    <!-- 텍스트뷰 안의 글자를 왼쪽으로 정렬 -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:textColor="#ffff0000"
        android:textSize="32dp"
        android:text="left"/>

    <!-- 텍스트뷰 안의 글자를 오른쪽으로 정렬 -->
    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="right"
        android:textColor="#ffff0000"
        android:textSize="32dp"
        android:text="right"/>

    <!-- 텍스트뷰 안의 글자를 가로와 세로의 가운데로 정렬 -->
    <TextView
        android:id="@+id/textView3"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal|center_vertical"
        android:textColor="#ffff0000"
        android:textSize="32dp"
        android:text="center" />
</LinearLayout>
  • | 연산자를 이용해 여러 개의 값을 설정할 수 있음 –> android:gravity="center_horizaontal|center_vertical

image

버튼이나 텍스트뷰의 크기를 wrap_content로 지정하면 버튼안에 들어 있는 글자에 맞게 뷰의 크기가 결정되므로 내부의 여유 공간이 없다. 따라서 gravity 속성을 지정해도 아무런 변화가 없다.

gravity 속성으로 지정할 수 있는 대표적인 값

정렬 속성 값 설명
top 대상 객체를 위쪽 끝에 배치하기
bottom 대상 객체를 아래쪽 끝에 배치하기
left 대상 객체를 왼쪽 끝에 배치하기
right 대상 객체를 오른쪽 끝에 배치하기
center_vertical 대상 객체를 수직 방향의 중앙에 배치하기
center_horizontal 대상 객체를 수평 방향의 중앙에 배치하기
fill_vertical 대상 객체를 수직 방향으로 여유 공간만큼 확대하여 채우기
fill_horizaontal 대상 객체를 수평 방향으로 여유 공간만큼 확대하여 채우기
center 대상 객체를 수직 방향과 수평 방향의 중앙에 배치하기
fill 대상 객체를 수직 방향과 수평 방향으로 여유 공간만큼 확대하여 채우기
clip_vertical 대상 객체의 상하 길이가 여유 공간보다 클 경우에 남는 부분을 잘라내기
top|clip_vertical로 설정한 경우 아래쪽에 남는 부분 잘라내기
bottom|clip_vertical로 설정한 경우 위쪽에 남는 부분 잘라내기
center_vertical|clip_vertical로 설정한 경우 위쪽과 아래쪽에 남는 부분 잘라내기
clip_horizontal 대상 객체의 좌우 길이가 여유 공간보다 클 경우에 남는 부분을 잘라내기
right|clip_horizontal로 설정한 경우 왼쪽에 남는 부분 잘라내기
left|clip_horizoantal로 설정한 경우 오른쪽에 남는 부분 잘라내기
center_horizontal|clip_horizontal로 설정한 경우 왼쪽과 오른쪽에 남는 부분 잘라내기
  • 텍스드뷰끼리 높이를 맞출 때 layout_gravity와 gravity만으로 힘들 수도 있음
  • 이 땐 baselineAligned 속성을 이용하면 됨

4. res/layout 폴더 안에 새로운 baseline.xml 파일 만들고 다음과 같은 코드 입력하기

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

    <!-- 텍스트뷰의 글자 크기를 크게 -->
    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="큰 글씨"
        android:textColor="#ffff0000"
        android:textSize="40dp"
        />

    <!-- 텍스트뷰의 글자 크기를 작게 -->
    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="중간 글씨"
        android:textColor="#ff00ff00"
        android:textSize="20dp"/>

    <!-- 버튼의 글자 크기를 좀 더 작게 -->
    <Button
        android:id="@+id/button7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="작은 글씨"
        android:textColor="#ff0000ff"
        android:textSize="14dp" />
</LinearLayout>

image

  • 글씨 크기가 각각 다른데도 불구하고 글씨 밑바닥이 일치함
  • baselineAligned 속성이 기본적으로 true이기 때문
  • 확인하기 위해 baselineAligned 속성을 추가하고 false로 하기
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false">

    <!-- 텍스트뷰의 글자 크기를 크게 -->
    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="큰 글씨"
        android:textColor="#ffff0000"
        android:textSize="40dp"
        />

    <!-- 텍스트뷰의 글자 크기를 작게 -->
    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="중간 글씨"
        android:textColor="#ff00ff00"
        android:textSize="20dp"/>

    <!-- 버튼의 글자 크기를 좀 더 작게 -->
    <Button
        android:id="@+id/button7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="작은 글씨"
        android:textColor="#ff0000ff"
        android:textSize="14dp" />
</LinearLayout>

image

뷰의 마진과 패딩 설정하기

  • 셀(Cell): 뷰의 테두리선 기준으로 바깥, 안쪽 공간을 모두 포함하여 뷰가 가지는 공간
  • 웨젯 셀(Widget Cell): 버튼이나 텍스트뷰를 위젯이라 불러 Cell을 일컫는 말
  • 마진(Margin): 테두리선을 기준으로 바깥의 공간, layout_margin으로 얼마나 띄울지 지정 가능
  • 패딩(Padding): 테두리선 안쪽의 공간

마진 속성

  • layout_marginTop
  • layout_marginLeft
  • layout_marginRight
  • layout_marginBottom

패딩 속성

  • paddingTop
  • paddingLeft
  • paddingRight
  • paddingBottom

1. res/layout 폴더에 padding.xml 파일 만들고 다음과 같은 코드 입력

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

    <!-- 텍스트뷰 위젯 내부의 여백을 20dp로 설정 -->
    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="텍스트"
        android:textColor="#ffff0000"
        android:textSize="24dp"
        android:background="#ffffff00"
        android:padding="20dp"/>

    <!-- 텍스트뷰 위젯과 부모 여유 공간 사이의 여백을 10dp로 설정 -->
    <TextView
        android:id="@+id/textView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="텍스트"
        android:textColor="#ffff0000"
        android:textSize="24dp"
        android:background="#ff00ffff"
        android:layout_margin="10dp"/>

    <!-- 텍스트뷰 내부의 여백을 20dp로 설정 -->
    <TextView
        android:id="@+id/textView8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="텍스트"
        android:textColor="#ffff0000"
        android:textSize="24dp"
        android:background="#ffff00ff"
        android:padding="20dp"/>
</LinearLayout>

image

  • padding이나 layout_margin 속성을 너무 크게 잡으면 이상한 모양이 나오니 잘 설정하기 바람

여유 공간 분할하기

  • layout_weight: 부모 컨테이너에 남아 있는 여유 공간을 분할하여 기존에 추가 했던 뷰들에게 할당 가능
  • layout_widthlayout_height로 지정하는 뷰의 크기는 wrap_content나 숫자 값을 지정되어야 함

layout_weight속성으로 각 뷰에 할당하는 크기는 추가적인 값이다. 즉, layout_widthlayout_height로 지정한 크기에 추가되는 값이다. 예를 들어, 가로 방향으로 두 개의 버튼을 추가했을 때 두 개의 버튼을 제외한 나머지 여유 공간이 있다면 그 여유 공간을 분할한 후 이 두 개의 버튼에 할당하게 된다.

1. res/layout 폴더 안에 weight.xml 파일 만들고 다음과 같은 코드 입력하기

<?xml version="1.0" encoding="utf-8"?>
<!-- 리니어 레이아웃을 수직 방향으로 설정 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 리니어 레이아웃을 수평 방향으로 설정 -->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffff00"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ff00ffff"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>
    </LinearLayout>
    
</LinearLayout>

image

  • 두 개의 텍스트뷰는 layout_width 속성으로 지정된 가로 크기가 동일하므로 여기에 동일한 크기의 여유 공간을 더해주어도 두 개의 텍스트뷰가 동일한 가로 크기를 갖게 됨

2. 두 개의 텍스트뷰를 추가한 후 layout_weight 속성 값을 1과 2로 지정

<?xml version="1.0" encoding="utf-8"?>
<!-- 리니어 레이아웃을 수직 방향으로 설정 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 리니어 레이아웃을 수평 방향으로 설정 -->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffff00"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ff00ffff"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffff00"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>

        <!-- layout_weight를 2로 설정 -->
        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ff00ffff"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="2"/>
    </LinearLayout>
</LinearLayout>

image

  • 오른쪽에 남아있던 여유 공간은 1/3, 2/3씩 분할되어 두 개의 뷰에 할당된 것
  • 하지만 부모 컨테이너의 가로 공간을 두 개의 텍스트 뷰가 1:2로 나누어 가진게 아님
  • 두 개의 뷰가 남아있던 여유 공간을 분할하여 가진 것
  • 부모 컨테이너의 가로 공간을 1:2로 나눠 가지려면 layout_width 속성 값을 0dp로 설정해야 함

3. 방향 속성(orientation 속성) 값이 horizontal인 리니어 레이아웃 추가하고 다음 코드 입력

<?xml version="1.0" encoding="utf-8"?>
<!-- 리니어 레이아웃을 수직 방향으로 설정 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 리니어 레이아웃을 수평 방향으로 설정 -->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffff00"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ff00ffff"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <!-- layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ffffff00"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>

        <!-- layout_weight를 2로 설정 -->
        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ff00ffff"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="2"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <!-- layout_width를 0dp로 한 후 layout_weight를 1로 설정 -->
        <TextView
            android:id="@+id/textView5"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="#ffffff00"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="1"/>

        <!-- layout_width를 0dp로 한 후 layout_weight를 2로 설정 -->
        <TextView
            android:id="@+id/textView6"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="#ff00ffff"
            android:text="텍스트"
            android:textColor="#ffff0000"
            android:textSize="24dp"
            android:layout_weight="2"/>
    </LinearLayout>
</LinearLayout>

image

리니어 레이아웃은 한 방향으로만 뷰를 넣어 원하는 화면을 만들기 어렵다고 생각할 수 있지만 레이아웃 안에는 레이아웃을 추가할 수 있기 때문에 어떤 모양이든 대부분 만들 수 있다. 예를 들머 왼쪽에 이미지가 있고 오른쪽에 글자가 위, 아래로 배치된 모양을 만들고 싶다면 다음과 같이 레이아웃을 만들 수 있다. LinearLayout 태그의 orientation 속성을 제외한 나머지 속성들은 제외하고 표시한 모양이다.

<LinearLayout
    android:orientation="horizontal">
    <ImageView />
    <LinearLayout
        android:orientation="vertical ">
        <TextView />
        <TextView />
    </LinearLayout>
</LinearLayout>
  • 리니어 레이아웃의 정렬, 마진, 패딩 속성은 다른 레이아웃에서도 적용 가능

02-3 상대 레이아웃 사용하기

상대 레이아웃

  • 부모 컨테이너나 다른 뷰와의 상대적인 위치를 이용해 뷰의 위치를 결정
  • 버튼 밑에 버튼을 추가하고 싶으면 이미 추가되어 있는 버튼의 id가 필요

1. 모두 기본값 SampleRelativeLayout을 만들기

2. activity_main.xml에서 ‘Hello World! 글자 삭제

3. text 탭에서 다음과 같이 코드 입력

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_above="@+id/button2"
        android:text="Button"
        android:background="#ff0088ff"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:text="Button" />
</RelativeLayout>
  • 첫 번째 버튼을 보면
  • layout_alignParentLeft, layout_alignParentStart, layout_alignParentTop 속성이 모두 “true”
  • 이 속성은 각각 부모 레이아웃의 왼쪽, 시작 부분, 위쪽에 붙이라는 의미
  • layout_above 속성을 추가하면서 두 번째 버튼의 id를 지정하여 첫 번째 버튼을 두 번째 버튼의 바로 윗부분까지만 공간을 차지하게 함

  • 두 번째 버튼을 보면
  • layout_alignParentBottom: 버튼을 아래쪽으로 정렬하기 위한 속성 –> 부모 레이아웃의 아래쪽으로 붙이라는 속성

image

5. 위쪽 공간에 버튼 배치를 위해 다음과 같은 코드 입력

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_above="@+id/button2"
        android:text="Button"
        android:background="#ff0088ff"
        android:layout_below="@+id/button3"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:text="Button" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:text="Button"/>
</RelativeLayout>

image

상대 레이아웃에서 부모 컨테이너와의 상대 위치를 이용해 뷰를 배치할 수 있는 속성

속성 설명
layout_alignParentTop 부모 컨테이너의 위쪽과 뷰의 위쪽을 맞춤
layout_alignParentBottom 부모 컨테이너의 아래쪽과 뷰의 아래쪽을 맞춤
layout_alignParentLeft 부모 컨테이너의 왼쪽 끝과 뷰의 왼쪽 끝을 맞춤
layout_alignParentRight 부모 컨테이너의 오른쪽 끝과 뷰의 오른쪽 끝을 맞춤
layout_centerHorizontal 부모 컨테이너의 수평 방향 중앙에 배치함
layout_centerVertical 부모 컨테이너의 수직 방향 중앙에 배치함
layout_centerlnParent 부모 컨테이너의 수직 방향 중앙에 배치함

부모 컨테이너가 아닌 다른 뷰와의 상대적 위치를 이용해 뷰를 배치하는 속성

속성 설명
layout_above 지정한 뷰의 위쪽에 배치함
layout_below 지정한 뷰의 아래쪽에 배치함
layout_toLeftOf 지정한 뷰의 왼쪽에 배치함
layout_toRightOf 지정한 뷰의 오른쪽에 배치함
layout_alignTop 지정한 뷰의 위쪽과 맞춤
layout_alignBottom 지정한 뷰의 아래쪽과 맞춤
layout_alignLeft 지정한 뷰의 왼쪽과 맞춤
layout_alignRight 지정한 뷰의 오른쪽과 맞춤
layout_alignBaseline 지정한 뷰와 내용물의 아래쪽 기준선(baseline)을 맞춤
  • 어짜피 안드로이드 스튜디오가 속성을 미리 보여주니 외울 필요는 없음
  • 상대 레이아웃 또한 상대 레이아웃만으로 화면을 만들지 않고 다른 레이아웃과 함께 사용

02-4 테이블 레이아웃

테이블 레이아웃

  • 표나 엑실 시트와 같은 형태로 화면을 구성하는 레이아웃
  • TableRow: 한 행을 의미하며 여러 개의 뷰가 들어가는데 이 뷰들은 각각 하나의 열을 의미

1. 모두 기본 설정 SampleTableLayout 프로젝트 만들기

2. activity_main.xml의 최상위 레이아웃을 TableLayout으로 변경

3. TextView 태그 모두 삭제

4. Design 탭에서 TableRow 2개 추가

image

  • layout_width, layout_height 속성은 모두 match_parent로 자동 설정 됨
  • match_parent로 설정되어 있어도 아래쪽 여유 공간을 다 차지하지 않음
  • TableRow의 높이 값은 내부적으로 항상 wrap_content로 설정되어 있기 때문
  • 반대로 TableRow의 폭은 내부적으로 항상 match_parent로 설정되어 있음

5. 각각의 TableRow 안에 세 개의 버튼 추가하기

image

  • 버튼을 디자인 화면에 추가하기가 힘드므로 위와 같이 Component Tree로 드래그해야 추가 가능

image

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

    <!-- 테이블의 첫 번째 행 -->
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

    </TableRow>

    <!-- 테이블의 두 번째 행 -->
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <Button
            android:id="@+id/button4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />
    </TableRow>
</TableLayout>

6. 테이블 행의 가로 공간을 꽉 채우기 위해 TableLayout 태그에 stretchColumns 속성 추가

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="0,1,2">

    <!-- 테이블의 첫 번째 행 -->
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

    </TableRow>

    <!-- 테이블의 두 번째 행 -->
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <Button
            android:id="@+id/button4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

        <Button
            android:id="@+id/button6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />
    </TableRow>
</TableLayout>
  • 칼럼은 0부터 시작
  • stretchColumns에 0을 넣으면 첫 번째 버튼이 여유 공간 차지
  • stretchColumns에 0, 1을 넣으면 첫, 두 번째 버튼이 여유 공간 차지
  • stretchColumns에 0, 1, 2를 넣으면 첫, 두, 세 번째 버튼이 여유 공간 차지

image

  • shirinkColumns: 부모 컨테이너의 폭에 맞추도록 각 열의 폭을 강제 축소
  • stretchColumns: 부모 컨테이너의 폭에 맞추도록 각 열의 폭을 강제 확대
  • layout_column: TableRow 태그에 추가되는 뷰는 자동으로 0, 1, 2와 같은 칼럼 인덱스를 받지만 이것을 사용해서 칼럼 인덱스를 지정할 수 있음
  • layout_span: 뷰가 여러 칼럼에 걸쳐 있도록 만들기 위한 속성, 몇 개의 칼럼을 차지하게 할 것인지 숫자로 지정

7. activity_input.xml 생성하고 다음 코드 입력하기

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff3366cc"
    android:stretchColumns="0,1,2">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="이름 : "/>

        <EditText
            android:id="@+id/editText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_span="3" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp">
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_column="2"
            android:text="아니오" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="예" />
    </TableRow>

</TableLayout>
  • 테이블 레이아웃 첫 번째 줄에는 하나의 텍스트뷰와 하나의 입력상자
  • layout_span 속성을 추가하고 그 값을 3으로 지정하여 입력상자가 세 개의 칼럼 영역을 차지
  • 다음 TableRow에서는 버튼이 두 개 추가 되었는데 첫 번째 버튼이 layout_column으로 2가 지정됨
  • 따라서 0과 1 인덱스의 위치에는 아무 것도 없고 2와 3 인덱스 위치에 두 개의 버튼이 위치하게 됨

image

  • 그리드뷰가 상위호환이여서 테이블 레이아웃은 잘 사용 안 함 ㅎ

02-5 스크롤뷰 사용하기

스크롤뷰

  • 추가된 뷰의 영역이 한눈에 다 보이지 않을 때 사용
  • 스크롤뷰 안에 뷰를 넣는 방식으로만 스크롤이 가능
  • ScrollView 태그를 사용하여 하나의 뷰를 넣음

1. 기본 설정 SampleScrollView 프로젝트 생성

2. res/drawable 폴더에 두 개의 이미지 넣기(이미지 파일에는 대문자 사용 불가)

3. activity_main.xml에 다음 코드 입력

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

    <!-- 이미지 변경을 위한 버튼 -->
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="이미지 바꾸어 보여주기"
        android:onClick="onButton1Clicked"/>

    <!-- 수평 스크롤을 위한 스크롤 뷰 -->
    <HorizontalScrollView
        android:id="@+id/horScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <ScrollView
            android:id="@+id/scrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >
            <!-- 이미지를 보여주는 이미지뷰 -->
            <ImageView
                android:id="@+id/imageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                />
        </ScrollView>
    </HorizontalScrollView>
    
</LinearLayout>
  • 스크롤뷰는 기본적으로 수직 방향의 스크롤 지원
  • 수평 방향의 스크롤을 사용하려면 HorizontalScrollView를 이용
  • ImageView 태그는 이미지를 화면에 보여줄 때 사용
  • 텍스트뷰나 버튼을 자바 코드에서 추가 가능하듯이 이미지도 new ImageView(this)로 추가 가능
  • 이미지뷰에 설정된 이미지가 큰 경우 수평과 수직 스크롤을 모두 나타나도록 HorizontalScrollView 안에 ScrollView를 추가한 후 그 안에 이미지뷰 추가하기
  • 이미지가 화면을 벗어날 경우 스크롤이 나타남
  • onClickonButton1Clicked는 버튼을 클릭하면 XML 레이아웃 파일과 매칭되는 자바 소스 파일에서 onButton1Clicked라는 이름의 메소드를 찾아 실행

4. MainActivity.java 파일을 열고 다음 코드 추가

package com.example.kai01.samplescrollview;

import android.content.res.Resources;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ScrollView;

public class MainActivity extends AppCompatActivity {
    ScrollView scrollView;
    ImageView imageView;
    BitmapDrawable bitmap;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 레이아웃에 정의된 뷰 객체 참조
        scrollView = (ScrollView) findViewById(R.id.scrollView);
        imageView = (ImageView) findViewById(R.id.imageView);
        // 수평 스크롤바 사용 기능 설정
        scrollView.setHorizontalScrollBarEnabled(true);
        
        // 리소스의 이미지 참조
        Resources res = getResources();
        bitmap = (BitmapDrawable) res.getDrawable(R.drawable.image01);
        int bitmapWidth = bitmap.getIntrinsicWidth();
        int bitmapHeight = bitmap.getIntrinsicHeight();
        
        // 이미지 리소스와 이미지 크기 설정
        imageView.setImageDrawable(bitmap);
        imageView.getLayoutParams().width = bitmapWidth;
        imageView.getLayoutParams().height = bitmapHeight;
    }
    
    public void onButton1Clicked(View v) {
        changeImage();
    }
    
    // 다른 이미지 리소스 변경
    private void changeImage() {
        Resources res = getResources();
        bitmap = (BitmapDrawable) res.getDrawable(R.drawable.image02);
        int bitmapWidth = bitmap.getIntrinsicWidth();
        int bitmapHeight = bitmap.getIntrinsicHeight();
        
        imageView.setImageDrawable(bitmap);
        imageView.getLayoutParams().width = bitmapWidth;
        imageView.getLayoutParams().height = bitmapHeight;
    }
}
  • findViewById() 메소드로 R.id.scrollViewR.id.imageView라는 id 값을 파라미터로 전달
  • XML 레이아웃 파일에서 id 지정: @+id/아이디
  • 자바 소스 코드에서 참조: R.id.아이디
  • 프로젝트에 추가된 이미지는 getDrawable() 메소드를 이용해 코드에서 BitmapDrawable 객체로 만들어짐
  • getDrawable() 메소드는 Resources 객체에 정의되어 있으며 액티비티에 정의된 getResources() 메소드를 이용하면 Resources 객체 참조 가능
  • BitmapDrawable 객체의 getIntrinsicWidth()getIntrinsicHeight() 메소드는 원본 이미지의 가로와 세로 크기를 알아냄
  • 알아낸 가로 세로 크기 값은 이미지뷰에 설정된 LayoutParams 객체의 width, height 속성으로 설정 가능

setImageResource() 메소드는 XML 레이아웃 파일에서 ImageView 태그의 속성으로 src 속성을 추가하면서 그 값으로 R.drawable.image01처럼 이미지 파일을 지정하는 것과 같다. setImageDrawable() 메소드는 이미지 파일을 Drawable 객체로 만든 후 이미지뷰에 설정할 때 사용한다. 그런데 설명한 두 메소드 중 하나를 사용하면 이미지뷰가 이미지의 크기를 화면 크기에 맞게 자동으로 줄이기 땜누에 원본 이미지의 크기 그대로 이미지뷰에 보이게 이미지의 가로와 세로 크기를 직접 설정해야 스크롤뷰 안에서 스크롤을 사용해 원본 이미지를 볼 수 있다.

5. 메인 액티비티 실행하기

실행 화면, 스크롤을 움직일 수 있음

image

이미지 바꾸어 보여주기를 눌렀을 때 화면, 역시 스크롤을 움직일 수 있음

image


02-6 프레임 레이아웃과 뷰의 전환

프레임 레이아웃

  • 가장 기본적이고 단순한 레이아웃
  • 프레임 레이아웃에 뷰를 넣으면 그 중에 하나의 뷰만을 화면에 표시
  • 중첩(Overlay) 기능으로 가시성(Visibility) 속성을 구현할 수 있어 자주 사용
  • 디자이너 도구에서 프레임 레이아웃에 여러 개의 뷰를 추가하거나 자바 소스코드에서 addView()removeView()와 같은 메소드를 사용해 뷰를 추가하거나 삭제할 수 있음
  • 가시성(Visibility) 속성을 사용해서 특정 뷰를 보이거나 보이지 않게 홤녀에 보이는 뷰를 전환하는 효과를 만들 수 있음
  • 하나의 화면으로 표시되는 액티비티 안에서도 여러 개의 뷰가 전환되도록 만들 수 있음

1. 기본 설정 SampleFrameLayout 프로젝트 생성

2. activity_main.xml에 다음 코드 입력

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

    <!-- 이미지 전환 버튼 -->
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="이미지 바꾸기"
        android:onClick="onButton1Clicked" />

    <!-- 프레임 레이아웃으로 나머지 화면 채우기 -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <!-- 첫 번째 이미지뷰를 안 보이도록 설정 -->
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/dream01"
            android:visibility="invisible"
            />
        <!-- 두 번째 이미지뷰를 보이도록 설정 -->
        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/dream02"
            android:visibility="visible"
            />
    </FrameLayout>

</LinearLayout>
  • 화면에 있는 버튼을 누를 때마다 두 개의 이미지가 전환되는 기능을 넣은 것
  • 화면 레이아웃에는 위쪽에 버튼을 하나 두고 그 아래에 이미지가 보이게 함
  • 이미지는 버튼을 누를 때마다 전환되어야 하므로 프레임 레이아웃 안에는 두 개의 이미지뷰를 중첩
  • dream02가 android:visibility="visible"이므로 먼저 보임
  • 물론 이 값을 설정하지 않아도 dream02가 나중에 쌓여서 먼저 보임

3. MainActivity.java에 다음 코드 입력

package com.example.kai01.sampleframelayout;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {
    ImageView imageView;
    ImageView imageView2;
    int imageIndex = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = (ImageView) findViewById(R.id.imageView);
        imageView2 = (ImageView) findViewById(R.id.imageView2);
    }

    public void onButton1Clicked(View v) {
        changeImage();
    }

    private void changeImage() {
        // 첫 번째 이미지뷰가 보이게 설정
        if(imageIndex == 0) {
            imageView.setVisibility(View.VISIBLE);
            imageView2.setVisibility(View.INVISIBLE);

            imageIndex = 1;

            // 두 번째 이미지뷰가 보이게 설정
        } else if (imageIndex == 1) {
            imageView.setVisibility(View.INVISIBLE);
            imageView2.setVisibility(View.VISIBLE);

            imageIndex = 0;
        }
    }
}
  • findViewById() 메소드로 이미지뷰를 찾아 변숭 ㅔ할당
  • 버튼을 눌렀을 때 호출되는 changeImage() 메소드 안에서 두 개의 이미지뷰가 갖는 가시성 속성을 변경
  • View.VISIBLE 또는 View.INVISIBLE 상수로 설정하면 XML에서 “visible”, “invisible”로 설정한 것과 같음
  • imageIndex 변수는 어떤 이미지뷰가 프레임 레이아웃에 보이고 있는지 알 수 있도록 선언한 것(첫 이미지는 0, 두 번째 이미지는 1)

4. 메인 액티비티 실행하기

처음 보여주는 이미지

image

이미지 바꾸기를 눌렀을 때 보여주는 이미지

image


02-7 기본 위젯들

  • 기본 위젯들이 갖고 있는 주요 속성을 정리하겠음
  • 우선 기본 설정 SampleWidget 프로젝트를 만들자

텍스트뷰

  • “Hello World!!!”와 같은 텍스트를 화면에 보여주는 역할

text

  • 보이는 문자열 설정
  • 텍스트뷰가 차지하는 영역을 알 수 있게 문자열은 반드시 지정해야 함
  • XML 레이아웃에 들어 있는 텍스트뷰에 text 속성을 추가할 때 직접 문자열 값을 입력할 수 있음
  • /res/value 폴더 안에 들어 있는 strings.xml 파일 안에 들어 있는 문자열을 지정할 수도 있음
  • strings.xml 파일 안 string 태그 문자열은 다른 곳에서 name 속성 값으로 참조하여 사용 가능
1. strings.xml에 다음 코드를 입력
<resources>
    <string name="app_name">SampleWidget</string>
    <string name="person_name">김진수</string>
</resources>
2. activity_main.xml에 다음 코드를 입력
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/person_name"
       />

</LinearLayout>

image

안드로이드는 다국어를 지원하고 이를 이용하려면 res 폴더안 values-로케일(해당국가 언어) 폴더를 만들고 그 안에 strings.xml을 정의해야 한다. 예를 들어 한국어 로케일을 사용하는 것으로 하려면 res/values-ko 폴더를 만들고 그 안에 들어 있는 strings.xml 파일 안에 한국어로 된 글자를 입력하고 영문 로케일을 사용하는 것으로 하려면 res/values-en 폴더를 만들고 그 안에 들어 있는 strings.xml 파일 안에는 영어로 된 글자를 입력한다. 이렇게 정의하면 단말의 설정(Setting)에서 언어(Language)를 영어에서 한국어로 바꿀 경우에 res/values-ko/strings.xml에 들어 있는 문자열이 화면에 표시된다.

textColor

  • ARGB 두 글자 씩
  • Alpha에서 FF는 투명하지 않게, 88은 반투명하게, 00은 투명하게
  • 예를 들어 빨간색은 #FFFFFFFF

textSize

  • 텍스트뷰에서 표시하는 문자열의 크기를 설정
  • 단위는 dp, sp, px를 사용하는데 정확한 폰트 크기를 사용할 땐 sp를 사용

textStyle

  • “normal”, “bold”, “italic” 등의 값을 지정할 수 있으며 |을 이용하여 여러 개의 속성 값을 지정할 수 있음

typeFace

  • 폰트 설정
  • “normal”, “sans”, “serif”, “monospace”가 있음

maxLines

  • 텍스트뷰에서 표시하는 문자열의 최디 줄 수를 설정
  • 한 줄로만 표시하고 싶은 경우 값을 1로 설정 –> 한 줄의 영역을 넘어가는 부분은 표시되지 않음
1. 화면 레이아웃에 텍스트뷰 추가하기
2. 다음과 같은 속성을 추가하기
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/person_name"
       />

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#88aabbff"
        android:padding="40dp"
        android:text="여기에 사용자 이름을 입력하세요."
        android:textSize="22dp"
        android:textStyle="bold"
        android:textColor="#ffff8888"
        android:maxLines="1"
        android:gravity="center" />

</LinearLayout>

image

버튼

  • 체크 박스나 라디오 버튼도 제공
  • 버튼 위젯에 발생하는 이벤트 처리는 OnClickListener가 간단
  • 체크 박스와 리다오 버튼은 클릭 이벤트와 상태 값을 저장하고 선택/해제 상태를 표시해야 함
  • 이를 위한 CompoundButton 클래스는 다음과 같은 메소드를 가지고 있음
public boolean isChecked()
public void setChecked(boolean checked)
public void toggle()
  • 상태가 바뀔 경우 다음 메소드가 호출
void on CheckedChanged(CompoundButton buttonView, boolean isChecked)

라디오 버튼

  • 라디오 버튼은 하나를 선택하면 다른 것이 해제되어야 함
  • 이를 위해 RadioGroup을 이용해 하나의 그룹으로 묶어주게 됨
  • RadioGroup 태그 안에 포함된 RadioButton은 모두 같은 그룹 안에 있는 라디오 버튼으로 인식
  • check() 메소드에 라디오 버튼 ID 값이 아닌 -1을 파라미터로 전달하면 라디오 버튼 선택 상태를 모두 해제 가능
  • 라디오 버튼 선택 상태가 변경될 때 이벤트를 받아 처리하고자 한다면 OnCheckedChangeListner 인터페이스 구현 후 setOnCheckedChangeListener() 메소드로 설정
1. res/layout 폴더 안에 button.xml 파일을 만들고 다음 코드 입력
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 기본 버튼 -->
    <Button
        android:id="@+id/btnExit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="선택"
        android:textSize="24dp"
        android:textStyle="bold"
        android:gravity="center"
        />
    <!-- 라디오 버튼 두 개를 묶어놓은 라디오 그룹 -->
    <RadioGroup
        android:id="@+id/radioGroup01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="20dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        >
        <!-- 첫 번째 라디오 버튼 -->
        <RadioButton
            android:id="@+id/radio01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="남성"
            android:textColor="#ff55aaff"
            android:textStyle="bold"
            android:textSize="24dp"
            />
        <!-- 두 번째 라디오 버튼 -->
        <RadioButton
            android:id="@+id/radio02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="여성"
            android:textColor="#ff55aaff"
            android:textStyle="bold"
            android:textSize="24dp"
            />
    </RadioGroup>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|center_horizontal"
        android:paddingTop="20dp"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="하루종일"
            android:textSize="24dp"
            android:paddingRight="10dp"
            android:textColor="#ff55aaff"
            />
        <!-- 체크 박스 -->
        <CheckBox
            android:id="@+id/allDay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>

image

2. MainActivity.java 파일에 다음과 같은 코드 입력 후 실행

package com.example.kai01.samplewidget;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.button);
    }
}

image

  • 버튼에 아이콘을 넣고 싶으면 속성 추가로 가능
  • 텍스트가 아예 없는 버튼을 사용하고 싶으면 ImageButton 태그 사용

입력상자

  • 에디트텍스트(EditText)는 사용자의 입력을 받고자 할 때 일반적으로 사용

1. res/layout 폴더 안에 edittext.xml 파일 만들고 다음 코드 입력

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

    <EditText
        android:id="@+id/usernameInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="24dp"
        android:inputText="textCapWords"
        android:hint="이름을 입력하세요."/>
</LinearLayout>
  • hint 속성은 입력하기 전 안내글 표시
  • inputType 속성은 입력되는 글자 유형 정의
  • inputType에 숫자만 넣고 싶으면 “number”

image

이미지뷰

  • 이미지를 화면에 표시하려고 제공되는 가장 간단한 위젯 중 하나
  • 이미지를 로딩하여 설정하려면 /res/drawable 폴더 밑에 이미지 파일을 복사하여 넣은 후
  • 이미지뷰의 src 속성 값으로 이미지 파일을 지정
  • 포멧은 @drawable/이미지명 사용
  • 이미지뷰의 대표적인 속성은 다음과 같음

src

  • 원본 이미지를 설정

maxWidth, maxHeight

  • 이미지가 보일 최대 크기 설정

tint

  • 이미지뷰에 보이는 이미지 위에 색상을 적용하고 싶을 때 설정

scaleType

  • 이미지가 원본 이미지의 크기와 다르게 화면에 보이는 경우 확대/축소를 어떤 방식으로 적용할지 설정
  • fitXY, centerCrop, centerInside 등 여러 가지 값이 미리 정의되어 있음

drawable 폴더는 이름을 다르게 적용하면 화면의 해상도에 따라 서로 다른 이미지를 로딩할 수 있다. 예를 들어 /res/drawable-xhdpi, /res/drawable-hdpi, /res/drawable-mdpi, /res/drawable/idpi 등이 있다.

1. res/layout 폴더 안에 image.xml 파일을 만들고 다음 코드를 입력
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 이미지 버튼을 사용해 이미지 추가 -->
    <ImageButton
        android:id="@+id/imageButton"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginTop="40dp"
        android:layout_marginLeft="40dp"
        android:background="@drawable/ok_btn"
        android:contentDescription="ok button"
        >
    </ImageButton>

    <!-- 이미지뷰를 사용해 이미지 추가 -->
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginTop="160dp"
        android:layout_marginLeft="160dp"
        android:background="@drawable/person"
        android:contentDescription="person button"
        >
    </ImageView>

</LinearLayout>

image

  • 이미지를 화면에 보여주는 가장 간단한 방법은 이미지뷰(ImageView)
  • 버튼처럼 만들고 싶은 경우에 이미지 버튼(ImageButton)

텍스트뷰와 입력상자의 다른 기능들

  • 안드로이드의 뷰가 가지는 속성은 오지게 많음

커서

  • 에디트텍스트는 문자나 숫자를 입력하는 입력상자의 역할을 하므로 커서가 깜박
  • 이 커서는 포커스를 받으면 입력되어 있는 문자열의 제일 끝으로 이동
  • selectAllOnFocus 속성을 설정하면 포커스를 받을 때 문자열 전체가 선택
  • 문자열 전체가 선택되면 새로운 문자를 입력했을 때 입력되어 있던 문자열을 한꺼번에 대체 가능
  • 문자열 전체가 선택되어 있는 상태에서 문자열을 대체하지 않고 추가하고 싶다면 왼쪽이나 오른쪽 이동 키를 한 번 누르고 입력
  • 커서를 보이게 하기 싫다면 cursorVisible 속성을 “false”로 설정
  • 에디트텍스트를 길게 누르면 사용자가 문자열을 선택하거나 복사, 잘라내기 등의 작업을 할 수 있음
  • 이러한 기능을 코드에서 동작하게 하려면 다음과 같은 메소드를 사용해야 함
public int getSelectionStr()
public int getSelectionEnd()
public void setSelection(int start, int stop)
public void setSelection(int index)
public void selectAll()
public void extendSelection(int index)
  • getSelectionStart() 메소드는 선택된 영역이 있을 때 그 시작 위치를 알려줌
  • getSelectionEnd() 메소드는 끝 위치를 알려주는데 두 개의 메소드 모두 선택 영역이 없으면 커서가 있는 현재 위치를 알려줌
  • setSelect() 메소드는 선택 영역을 지정하는데 사용함
  • extendSelection() 메소드는 선택 영역을 확장하는데 사용
  • selectAll() 메소드를 호출하면 전체 문자열이 선택됨

자동 링크

  • 링크가 들어있으면 링크 색상으로 표시하고 링크를 누르면 웹 페이지에 접속하거나 메일 편집기를 띄워주는 기능
  • autoLink 속성을 사용하여 안드로이드에서 만들 수 있음

줄 간격 조정

  • lineSpacingMultiplier는 줄 간격을 배수로 설정할 때 사용
  • lineSpaceExtra는 여유 값으로 설정할 때 사용
  • 배수로 설정할 때 값이 1.0보다 작으면 기본으로 설정되어 있는 값보다 더 좁게 보임
  • 실제론 lineSpacingExtra 속성만으로 충분

대소문자 표시

  • capitalize 속성은 문자를 대문자나 소문자로 바꾸어 표시하는 기능을 제공
  • “characters”, “words”, “sentences”등이 있음
  • 설정하게 되면 글자, 단어, 문장 단위로 맨 앞 글자를 대문자로 표시

줄임 표시

  • 텍스트뷰에서 줄이 넘어가면 문자열의 뒷부분은 잘리고 “…“으로 표시됨
  • 이 때 ellipsize 속성을 이용하면 문자열의 어디를 잘라서 표시할 것인지 설정 가능
  • 디폴트 값은 “none”이고 뒷 부분을 자르고 “start”, “middle”, “end” 값들은 각각 앞부분, 중간부분, 뒷부분을 잘라서 보여줌
  • 텍스트뷰를 한 줄로 표시할 때는 maxLines 속성을 사용

힌트 표시

  • 아무 내용도 입력되지 않았을 때 hint 속성에 입력한 글자가 표시됨
  • 힌트로 표시한 글자의 색상을 바꾸고 싶으면 textColorHint 속성을 이용

편집 기능

  • 에디트텍스트에 입력되어 있는 문자열을 편집하지 못하게 하고 싶으면 editable 속성 값을 “false”로 설정
  • 디폴트 값은 “true”

문자열 변경 처리

  • getText() 메소드: 에디트텍스트에 입력된 문자를 확인하거나 입력된 문자가 필요한 포맷과 맞는지 확인
  • getText() 메소드의 리턴 객체는 Editable인데 이 객체의 toString() 메소드를 이용하면 일반 String 타입의 문자열 확인 가능
  • 문자열이 사용자의 입력에 의해 바뀔 때마다 확인하는 기능을 넣고 싶다면 TextChangedListner를 사용
public void addTextChangedListener(TextWatcher watcher)
  • addTextChangedListener() 메소드를 이용하면 TextWatcher 객체를 설정할 수 있음
  • 이 객체는 테스트가 변경될 때마다 발생하는 이벤트를 처리할 수 있음
  • TextWatcher 인터페이스에는 다음과 같은 메소드가 정의되어 있음
public void beforeTextChanged(CharSequence s, int start, int count, int after)
public void afterTextChanged(Editable s)
public void onTextChanged(CharSequence s, int start, int before, int count)
  • 문자열이 편집되기 전과 후 그리고 편집된 정보를 확인가능
  • 따라서 필요한 기능을 추가해야 함
  • 입력된 문자열의 길이 값을 확인할 때는 setFilters() 메소드를 이용해 InputFilter 객체를 파라미터로 전달
  • InputFilter 객체의 LengthFilter() 메소드를 호출하면 입력된 문자열의 길이 값을 설정할 수 있음

  • TextWatcher 인터페이스의 활용 예는 SMS로 전송하는 경우
  • SMS는 80바이트까지만 전송할 수 있으므로 사용자가 몇 글자를 입력했는지 바로바로 표시해 주고 싶을 때 이 클래스를 사용

도전! 03 두 개의 이미지뷰에 이미지 번갈아 보여주기

프로젝트 소스: DoitMission-03

1. 화면을 위와 아래 두 영역으로 나누고 그 영역에 각각 이미지뷰를 배치

2. 각각의 이미지뷰는 스크롤이 생길 수 있도록 함

3. 상단의 이미지뷰에 하나의 이미지를 보이도록 함

4. 두 개의 이미지뷰 사이에 버튼을 하나 만들고 그 버튼을 누르면 상단의 이미지가 하단으로 옮겨져 보이고 다시 누르면 상단으로 다시 옮겨지는 기능을 추가하기


도전! 03 답

activity_main.xml

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

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="210dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        app:srcCompat="@drawable/image01"
        android:layout_above = "@+id/button"
        android:visibility="visible"
        />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="match_parent"
        android:layout_height="210dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        app:srcCompat="@drawable/image01"
        android:layout_below="@+id/button"
        android:visibility="invisible"
        />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="70dp"
        android:layout_marginStart="70dp"
        android:onClick="onButton1Clicked1"
        android:gravity="center"
        android:text="▲" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="70dp"
        android:layout_marginEnd="70dp"
        android:onClick="onButton1Clicked2"
        android:gravity="center"
        android:text="▼" />

</RelativeLayout>

MainActivity.java

package com.example.kai01.doitmission_03;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {
    ImageView imageView;
    ImageView imageView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = (ImageView) findViewById(R.id.imageView);
        imageView2 = (ImageView) findViewById(R.id.imageView2);
    }

    public void onButton1Clicked1(View v) {
        imageView.setVisibility(View.VISIBLE);
        imageView2.setVisibility(View.INVISIBLE);
    }

    public void onButton1Clicked2(View v) {
        imageView2.setVisibility(View.VISIBLE);
        imageView.setVisibility(View.INVISIBLE);
    }
}

동작 화면

aa


도전! 04 SMS 입력 화면 만들고 글자 수 표시하기

프로젝트 소스: DoitMission-04

1. SMS로 문자를 전송하는 화면은 위쪽에 텍스트 입력상자, 아래쪽에 [전송]과 닫기 버튼을 수평으로 배치하도록 구성

2. 텍스트 입력상자 바로 아래에 입력되는 글자의 바이트 수를 “10/80 바이트”와 같은 포맷으로 표시하되 우측 정렬로 하도록 하고 색상을 눈에 잘 띄는 다른 색으로 설정하기

3. 텍스트 입력상자에 입력되는 글자의 크기와 줄 간격을 조정하여 한 줄에 한글 8글자가 들어가도록 만들어 보기

4. [전송] 버튼을 누르면 입력된 글자를 화면에 토스트로 표시하여 내용을 확인할 수 있도록 하기


도전! 04 답

여기 참고

이것도 참고

가상키보드 숨기기 설정부터 함

image

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <EditText
        android:id="@+id/editText"
        android:layout_width="280dp"
        android:layout_height="280dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="40dp"
        android:background="@drawable/border"
        android:cursorVisible="true"
        android:ems="10"
        android:inputType="textMultiLine|textNoSuggestions"
        android:textSize="40dp"
        />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="110dp"
        android:layout_marginEnd="45dp"
        android:layout_marginRight="45dp"
        android:text="0 / 80 바이트"
        android:textColor="#ffff0000"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="40dp"
        android:layout_marginStart="60dp"
        android:text="전송"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="60dp"
        android:onClick="onButton1Clicked"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="40dp"
        android:layout_marginEnd="60dp"
        android:text="닫기"
        android:layout_alignParentRight="true"
        android:layout_marginRight="60dp" />


</RelativeLayout>

MainActivity.java

package com.example.kai01.doitmission_04;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;

public class MainActivity extends AppCompatActivity {
    TextView textView;
    EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);
        editText = (EditText) findViewById(R.id.editText);

        editText.addTextChangedListener(textWatcher); // TextWatcher 리스너 등록
    }

    // EditText가 눌릴 때마다 감지하는 부분
    TextWatcher textWatcher = new TextWatcher() {
        @Override
        public void afterTextChanged(Editable edit) {
            // Text가 바뀌고 동작할 코드
            // 그런거 없으니 비움
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // Text가 바뀌기 전 동작할 코드
            // 그런거 없으니 비움
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // 입력받은 문자의 개수를 센다.
            int charCount = editText.getText().toString().length();
            // 문자의 개수를 다시 textView에 넣는다.
            textView.setText(charCount + " / 80 바이트");
        }
    };

    public void onButton1Clicked(View v) {
        Toast.makeText(getApplicationContext(), editText.getText(), Toast.LENGTH_LONG).show();
    }
}

동작 화면

aaaaaa

  • 키보드로 한글 입력하고 싶은데 어떻게 하는지 모르겠음…

Comments