티스토리 뷰


* 이번에는 간단한 인터페이스 구현과 다른 Activity로 넘어가는 방법을 알아보자.


2012/11/05 - [Android(안드로이드) 앱 개발 기초] Eclipse 개발환경 설정하기, Android SDK 설치하기

2012/11/07 - [Android(안드로이드) 앱 개발 기초] 안드로이드 프로젝트 생성하고 에뮬레이터로 앱 실행하기



* 인터페이스 구성

: 안드로이드의 인터페이스는 XML을 기반으로한 문법으로 ViewGroup과 View가 구조적 엮어져 있는 구성을 하고 있다.



: ViewGroup은 Linear layout과 같이 보이지 않는 컨테이너를 나타내고, View는 button 또는 text field와 같은 UI 위젯을 나타낸다. 



* Linear layout 구성하기

: 다시 Eclipse를 실행해서 res/layout에 있는 activity_main.xml을 열어보자. 그럼 아래와 같이 WYSIWYG의 그래픽 에디터를 보여줄 것이다.



: 중앙 하단에 Graphical Layout옆에 있는 activity_main.xml을 누르면 직접 xml도 수정이 가능하다. 나중에 폭을 설정한다던지, weight를 부여하던지 할 때 직접 수정하는 것도 유용하다.




: 여기서는 직접 xml을 고치는 방법을 사용할 것이지 activity_main.xml 창으로 유지하고 수정 추가하자. 직접 xml을 고치면서 하다보면 어떻게 동작하는지 파악이 쉽게 가능할 것이다.



* TextField 추가하기

: 다음과 같이 activity_main.xml을 작성해보자. 일단 LinearLayout을 만들어서 방향을 horizontal로 설정을 한 다음, EditText를 하나 추가한 다음 id와 hint를 설정하자.


<LinearLayout 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" 
    android:orientation="horizontal">
	<EditText android:id="@+id/edit_message"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:hint="@string/edit_message" />
</LinearLayout>

: 여기서 중요한 내용을 설정하자면, android:id="@+id/edit_message" 이 부분의 android:id는 이 View를 위해 유니크한 id를 생성하여 부여하게 된다. 나중에  빌드를 하게 되면 R.java 파일에 자동으로 생성되며, 자바에서 이 View에 접근을 할 때 이 R.java 안에 있는 이 id를 이용해서 접근하면 된다. 그리고 아이디 내부에 스트링을 정의하는 부분에서 xml에 있는 리소스를 접근할 때에는 앞에 @를 붙여줘야한다. 그리고 처음으로 아이디를 정의할 때에는 @ 뒤에 +를 붙여줌으로써 정의를 하면 된다. 이후 이 아이디를 쓸 때에는 +는 생략해도 된다. 즉, +는 gen/R.java안에 변수 선언(생성)을 하는 것과 비슷한 개념이라고 생각하면 된다. 


android:layout_width="wrap_content" 과 android:layout_height="wrap_content" 는 현재 View의 넓이와 높이가 현재 content에 딱 맞도록 설정하는 것이다.


android:hint="@string/edit_message"는 EditText View가 비어있을 때 기본적으로 보여주는 스트링을 설정하는 것으로 아까 id를 설정할때와 같은 @가 붙어있다. 이것은 xml을 통해서 리소스를 가져온다는 것을 명시하고 있고, res/values/string.xml 안에 있는 edit_message 스트링 인용하겠다는 것이다. 하지만 현재는 이 파일 안에 edit_message가 정의되어있지 않기 때문에 에러로 표시되어있을 것이다. 너무 놀라지 말고 차분하게 string 리소스를 추가하면 된다.



* String 리소스 추가

: 만약 UI에 스트링을 추가하고 싶다면, 각 String을 리소스에 추가할 것을 권장한다. UI의 텍스트를 한곳에서 관리하는 것이 스트링을 찾고 수정하는데 매우 유리하기 때문이다. 그리고 나중에 언어를 변경할 때에도 UI의 텍스트를 옮기는 일이 수월해지기 때문이다. 


: 일단 res/values/string.xml 파일을 열어보면 기본적으로 정의되어있는 String들이 있을 것이다. 이것을 보면 스트링 입력 인터페이스를 이용해서 입력/수정을 할수도 있고, 중앙 하단에 있는 string.xml을 눌러서 직접 xml을 수정할수도 있다.


: 중앙 하단의 "string.xml" 탭을 누르면 아래처럼 어떻게 구성되었는지 xml이 표시된다.



: 여기서 hello_world의 name을 위에서 사용하고자하는 edit_message로 바꾸고 메시지도 바꿔주고, 다음에 사용할 Button의 텍스트도 같이 미리 입력해주자.

<resources>

    <string name="app_name">ToDo</string>
    <string name="edit_message">Enter a Message</string>
    <string name="send_button">Send</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">MainActivity</string>

</resources>


: 수정을 하고 저장하면 gen/R.java 파일에 위에서 정의한 id안의 edit_message와 string 안의 edit_message와 send_button의 변수들이 자동으로  생성된 것을 확인할 수 있을 것이다. 앞으로 xml에 있는 리소스를 접근할 때에는 여기 R.java 파일에 있는 리소스를 접근하면 된다.





* 버튼 추가하기

: 이번에는 다시 activity_main.xml을 열어서 버튼을 추가해보자. LinearLayout이 horizontal로 되어있기 떄문에 EditText 아래에 Button을 추가한다면 EdiText의 옆으로 가게 될 것이다.


<LinearLayout 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" 
    android:orientation="horizontal">
	<EditText android:id="@+id/edit_message"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:hint="@string/edit_message" />
	<Button
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:text="@string/send_button" />
</LinearLayout>

: 그리고 실행을 해보자. 프로젝트를 선택하고 Run As... > Android Application을 하면 에뮬레이터가 실행된다. 그럼 아래와 같이 에디트박스와 버튼이 추가된 것을 볼 수 있다.






: 하지만 인터페이스가 화면에 꽉차지 않은 것이 왠지 불만이다. 화면에 꽉차게 한번 수정해보자.



* 인터페이스가 화면에 차게 설정하기

: 인터페이스를 화면의 비율에 맞게 설정하기 위해서는 layout_weight를 설정하면 된다. 다음과 같이 android:layout_weight="1" 설정하면 된다. layout_weight는 같은 ViewGroup에 설정된 weight의 총합을 더하여 각 View의 비율만큼을 부여하게 된다. 즉, 1을 부여한 View와 2를 부여한 View가 있다면, 1은 1/3만큼차지하고, 2를 부여한 View는 2/3만큼 차지하게 되는 것이다. 하지만 만약 하나만 설정하고 나머지를 설정안한다면 1을 부여한 View는 자신이 가질 수 있는 최대한의 공간을 차지하게 된다. 즉, EditText에 layout_weight를 설정하게 된다면 EditText의 길이가 늘어나 화면을 꽉차게 구성될것이다.


: 다시 activity_main.xml을 열어서 EditText에 layout_weight를 추가하고, layout_width를 0dp로 설정하자.

<LinearLayout 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" 
    android:orientation="horizontal">
	<EditText android:id="@+id/edit_message"
	    android:layout_width="0dp"
	    android:layout_height="wrap_content"
	    android:hint="@string/edit_message" 
	    android:layout_weight="1"
	    />
	<Button
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:text="@string/send_button" />
</LinearLayout>

: 여기서 layout_width를 0dp로 설정하는 이유는 layout_weight를 이용하는 경우 wrap_content를 하게 된다면 해당하는 View가 얼마나 차지해야할지 계산을 하는 과정이 들어가고, 그 결과와 상관없이 다시 weight를 기준으로 계산하기 때문에 고정적인 0dp를 설정하여 계산량을 줄여 퍼포먼스를 늘려주는 효과가 있다. 이런식으로 View들간의 layout_weight를 정확하게 조절하기 위해서는 Graphical Layout 인터페이스를 사용하는것보다 이렇게 직접 xml을 수정하는 것이 더욱 편리할 것이다.


: 이렇게 수정하면 아래와 같이 인터페이스가 수정된다.





: 이제는 EditText가 화면을 꽉차게 늘어난 것을 볼 수 있다. 이러한 layout_weight를 잘 다루는 것이 보기에 깔끔하고 정돈된 인터페이스를 구성하는데 필수 요건일 것이다. 그럼 이번에는 Button과 연동하여 다른 새로운 Activity로 넘어가는 것을 구현해보자.



* Button의 onClick 이벤트 콜백 함수 설정

: 옛날에는 button을 가져와서 일일이 addActionListener를 부여했던 것이 기억나지만, 이제는 xml상에서 콜백함수를 설정할 수 있다. (원래부터 있었는지는 모르겠다. 워낙 야메로 익혀온 안드로이드 앱 개발을 이번에 제대로 정석적으로 기본 개념까지 공부하고 있기 때문에;;)


: 열어두었던 activity_main.xml 파일의 Button에 onClick 속성을 추가하면 된다.


<LinearLayout 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" 
    android:orientation="horizontal">

	<EditText
	    android:id="@+id/edit_message"
	    android:layout_width="0dp"
	    android:layout_height="wrap_content"
	    android:layout_weight="1"
	    android:hint="@string/edit_message" />

	<Button
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:text="@string/send_button" 
	    android:onClick="sendMessage"/>
</LinearLayout>


: 이렇게 android:onClick="sendMessage"를 설정하게 되면 Button이 클릭되었을 때 현재 Activity 안의 sendMessage 함수를 호출하게 되는 것이다. 그럼 MainActivity.java를 열어서 sendMessage 함수를 구현해야할 것이다. 맨 아래에 sendMessage 함수를 추가해야하는데, 이벤트로 호출된 함수는 다음과 같은 포맷을 지켜야한다.

  • public이어야한다.
  • void의 리턴 타입을 가져야한다.
  • 인자로는 View 하나를 가지고, 이 View는 클릭된 View를 인자로 넘겨주게 되는 것이다.

: 위의 포맷대로 함수를 MainActivity.java에 추가하자


    public void sendMessage(View view) {
    	//클릭하면 호출된다.
    }



* Intent 만들기

: Intent 객체는 두가지 컴포넌트 사이를 엮어주는 역할을 하는 객체로, 주로 두 개의 Activity를 엮어주는 역할을 담당하는 객체이다. Intent를 이용하여 다양한 기능들을 구현할 수 있지만 가장 기본적인 기능은 바로 새로운 Activity를 시작할 때 사용하는 것이다.


: sendMessage 함수 안에 새로운 Activity를 시작하기 위한 Intent를 생성하는 코드를 작성하자. 여기서 사용할 Intent의 목적은 DisplayMessageActivity라는 새로운 Activity 화면으로 넘어가기 위한 Intent로 생성하는 것이다.


    public void sendMessage(View view) {
    	Intent intent = new Intent(this, DisplayMessageActivity.class);
    }


: Intent 객체의 생성자는 2개의 인자를 받게 되는데, 첫 인자는 Context를 받는데, Activity가 Context를 확장하고 있으므로 this를 설정하면 되고, 2번째 인자는 시스템이 현재의 Intent를 보내고자하는 클래스를 넣으면 된다. 이 경우는 새로 시작할 Activity의 클래스를 넣은 셈이다. 현재는 DisplayMessageActivity가 에러가 날텐데 조금 뒤에 생성할 것이므로 무시하자.


: Intent에는 여러 가지 데이터들도 넣을 수 있는 구조를 가지고 있다. 한 Activity에서 데이터를 넣으면 다른 Activity에서 그 데이터를 접근하는 것이다. 아래와 같이 EditText의 입력된 내용을 가져와서 Intent에 넣어두는 소스를 구현하자.

    public void sendMessage(View view) {
    	Intent intent = new Intent(this, DisplayMessageActivity.class);
    	EditText editText = (EditText) findViewById(R.id.edit_message);
    	String message = editText.getText().toString();
    	intent.putExtra(EXTRA_MESSAGE, message);
    }

: findViewById는 리소스의 아이디를 이용하여 그에 해당하는 View 객체를 가져오는 함수이다. EditText에 맞게 생성했던 R.id.edit_message를 인자로 넘겨주면 해당하는 id와 일치하는 View를 리턴한다. 이렇게 얻어온 EditText 객체에 getText함수를 호출함으로써 EditText에 입력된 값을 가져올 수 있다.


: Intent 객체에 데이터를 저장하는 putExtra 함수는 2개의 인자로 데이터를 저장하게 된다. 첫번째 인자는 key 값으로 다음 Activity에서 데이터를 받게 될 때 이 key 값을 기준으로 데이터를 가져올 수 있다. 두번째 인자는 넘겨주고자하는 실제 데이터 value 값이다. value에는 어떠한 값들도 사용가능하지만 serialize 가능한 객체이어야한다.


: 이렇게 작성하고나면 에러가 하나더 생겼을 것이다. EXTRA_MESSAGE가 정의되지 않았기 때문이다. 이러한 중요한 key값은 항상 일치가능하게 잘 유지하는 것이 나중에 앱이 커졌을 때 관리하기 쉬울 것이다. 따라서 Activity의 변수로 키를 저장해두는 것이 좋은 습관이 될 것이다. MainActivity.java의 static 변수로 정의하자.

public class MainActivity extends Activity {

	public final static String EXTRA_MESSAGE = "unikys.todo.MESSAGE";
	// 이하 생략
}

: 메시지는 다른 앱과 메시지를 주고받을 경우를 대비해서 자신만의 패키지이름으로 정의를 해두는 것이 좋을 것이다. 왜냐하면 Intent는 이러한 단순한 기능 이외에도 다른 Activity에 특정한 기능을 수행하게 하고 결과를 돌려준다던지 (예: QRCode 인식 Activity에 QRCode 인식하게하고 결과를 요청, 사진 찍는 Activity에서 사진을 찍고 결과를 요청 등) 다른 앱에 있는 Activity를 요청한다던지의 다양한 기능들이 가능하다.


: 이렇게 새로운 Activity에 넘겨줄 Intent에 정보를 넣었다면 이제 새로운 Activity를 시작하도록 함수를 호출하면 된다.

    public void sendMessage(View view) {
    	Intent intent = new Intent(this, DisplayMessageActivity.class);
    	EditText editText = (EditText) findViewById(R.id.edit_message);
    	String message = editText.getText().toString();
    	intent.putExtra(EXTRA_MESSAGE, message);
    	startActivity(intent);
    }

: startActivity 함수를 호출하면 인자로 넘겨준 intent가 생성자에서 두번째로 받았던 클래스를 새로 시작하게 된다. 그럼 이제 Intent에서 생성하고자 했던 DisplayMessageActivity가 필요하다.



 * 새로운 Activity 생성하기

: 프로젝트에 대고 우클릭 >  New > Other... > Android Activity 선택 > Next

: BlankActivity 선택 > Next

: Activity Name에는 반드시 위에 Intent에서 정의했던 클래스명과 일치하도록 설정하고, Hierarchical Parent는 Intent를 호출하는 MainActivity로 현재 Activity의 부모를 설정하자. 우측에 있는 "..." 버튼을 누른다면 검색 기능도 제공하므로 이용하자. 정보들을 입력하고 "Finish" 버튼을 누르면 새로운 Activity가 생성된다.

: 생성하고난 뒤에 Layout Name으로 입력했던 activity_display_message.xml 이라는 이름으로 xml 파일이 생성되고, AndroidManifest.xml에 자동으로 Activity 정보가 입력된것을 볼 수 있다(!!). 예전에는 Activity를 새로 생성하고나면 일일이 AndroidManifest.xml에 추가를 했는데 이제는 자동이다! 만세!



: 아래와 같이 AndroidManifest.xml에도 자동으로 추가된다! SDK가 점점 진화하고 있다!



* Intent로부터 정보 받기

: 그럼 이제 생성되는 Activity에서 이전에 보냈던 Intent의 내용을 받아야할 것이다. Intent를 가져와서 정보를 저장하는 것을 구현하자.

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display_message);
        getActionBar().setDisplayHomeAsUpEnabled(true);
        
        Intent intent = getIntent();
        String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
    }

: getIntent함수는 현재 Activity로 넘어온 Intent를 가져오는 것이고 Intent객체의 getStringExtra 함수는 key를 인자로 받아 Extra로 저장한 정보를 String 형태로 받는 함수이다. 이렇게 되면 앞에서 저장했던 데이터가 새로운 Activity 로 넘어오게 된 것이다.



* 텍스트 보여주기

: 위의 message에 받아온 뒤 간단하게 텍스트뷰에 넣고 표시를 해주자. 일단 생성된 activity_display_message.xml 파일을 열어서 id를 부여해주자.

<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/text_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="@string/hello_world"
        tools:context=".DisplayMessageActivity" />

</RelativeLayout>

: 그리고 DisplayMessageActivity.java 안에서 Intent로 얻어온 message를 해당하는 TextView에 넣어주자.

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display_message);
        getActionBar().setDisplayHomeAsUpEnabled(true);
        
        Intent intent = getIntent();
        String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

        TextView textView = (TextView)findViewById(R.id.text_message);
        textView.setText(message);
    }


* 구현 결과

: 이제 구현 결과를 테스트해보자. 먼저 넘겨줄 텍스트를 입력한다음 Send 버튼을 누르면,



: 아래와 같이 텍스트가 넘어가서 화면에 표시된다! 테스트 끝!



: 이렇게 간단하게 인터페이스를 구현하는 방법과 다른 Activity로 데이터를 넘기는 방법을 살펴봤는데, 기존에는 이유도 모르고 사용했던, 단순히 경고가 뜨기때문에 사용했던 내용들에 대해서 더 잘 알 수 있었던 것 같다. 앞으로 인터페이스를 구성할 때에는 일단 Graphical Layout에 추가를 하고 상세한 디자인 구성은 xml에서 하는 방식으로 하는 것이 유용할 것이다.


- 다음에는 Activity의 라이프사이클(Life Cycle)에 대해서 이론적으로 상세하게 공부해보자.


* 간단한 인터페이스 구현과 다른 Activity로 넘어가기 끝.



- 다음 글

2012/11/21 - [Android(안드로이드) 앱 개발 기초] Activity 라이프사이클 공부

2012/11/24 - [Android(안드로이드) 앱 개발 응용] Google Map API로 지도 보여주기(MapView), Overlay Item 그려주기 예제

2012/11/28 - [Android(안드로이드) 앱 개발 응용] Location GPS 위치 가져오기 및 최적화

2012/12/05 - [Android(안드로이드) 앱 개발 기초] 런타임 설정(로테이션, orientation) 변환 라이프사이클

2012/12/19 - [Android(안드로이드) 앱 개발 응용] 쉽게 Google Map 위에 말풍선 띄우기

2013/03/03 - [Android(안드로이드) 앱 개발 기초] Fragment 기초

2014/09/24 - [Android(안드로이드) 앱 개발 기초] ContentProvider 앱 간 데이터 공유 기본

2014/10/20 - [Android(안드로이드) 앱 개발 기초] MediaPlayer 음악 재생하기



Portions of this page are reproduced from work created and shared by the Android Open Source Project and used according to terms described in theCreative Commons 2.5 Attribution License.

원문: http://developer.android.com/training/basics/firstapp/starting-activity.html

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함