EMDI는 지금도 개발중

Android with Kotlin : 안드로이드 기초편 - Intent 활용 데이터 함께 화면전환 본문

네이티브/Android

Android with Kotlin : 안드로이드 기초편 - Intent 활용 데이터 함께 화면전환

EMDI 2020. 9. 21. 10:07

저번 글에서는 로그인 화면에 있는 [가입하기]버튼을 클릭 시 가입화면으로 화면을 이동하는 방법에 대해 공부를 해보았습니다. 이번 글에서는 화면을 전환할 때 사용하는 Intent Action에 대해 조금 더 알아보도록 하겠습니다.

 

// 기본적인 Intent 사용법 - 데이터 포함 안하고 이동한 상태
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 가입하기 버튼을 눌렀을 때 회원가입화면으로 이동하게 버튼 클릭이벤트 만들기
        joinBtn.setOnClickListener {

            // 가입하기 버튼을 누르면 들어오는 로직
            // 회원가입(JoinActivity) 화면으로 이동하게 Intent 사용
            val myIntent = Intent(this, JoinActivity::class.java)

            // startActivity를 해야 화면이동 **
            startActivity(myIntent)
        }
    }
}

위의 소스는 저번 글에서 배웠던 Intent 사용 방법입니다. 우리는 val myIntent라하여 변수를 하나 생성하였고 그 안에 Intent(packageContext, 이동할 Activity::class.java) 넣어서 화면을 이동시켜주는 startActivity를 실행시켰습니다. 하지만 이 소스에서는 어떠한 데이터도 넘기지 않고 그냥 화면이동만 했죠.

val myIntent(변수이름변경가능) = Intent(출발지this, 도착액티비티::class.java)
startActivity(myIntent)
* 실제로는 액티비티 이동이 아니라, 새 액티비티를 하나 더 만들어서 기존의 액티비티 위에 얹어주는 기능
Intent 비행기 티켓 발권(출발지/도착지가 명시)
startActivity 실제 비행기 탑승(출발)
finish() 현재 액티비티 종료

​이번 시간에는 단순히 화면이동만 하는게 아니라 데이터도 같이 담아서 보내보도록 하겠습니다.

 

​새로운 프로젝트를 생성하도록 하겠습니다. 저는 프로젝트를 Review_Intent라고 이름 짓고 생성하였습니다.

* 연습내용 : MainActivity에 총 3개의 버튼을 만들었는데 [액티비티로 이동]버튼은 단순 이동버튼이고 [액티비티로 메시지 들고 이동]버튼은 상단에 있는 Text 내용을 들고 이동할 버튼 그리고 마지막 [닉네임 변경]버튼은 이동한 페이지에서 변경한 닉네임을 들고 다시 MainActivity로 와서 닉네임 보이는 Text에 뿌려주는 연습을 할 계획입니다.

 

<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:padding="15dp"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/moveToBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="25dp"
        android:text="액티비티로 이동" />

    <EditText
        android:id="@+id/messageEdt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="화면에 전달할 메세지 입력" />

    <Button
        android:id="@+id/bringToBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="25dp"
        android:text="액티비티로 메세지 들고 이동" />

    <TextView
        android:id="@+id/nickNameTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="닉네임 보이는 Text" />

    <Button
        android:id="@+id/changeNickNameBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="닉네임 변경" />

</LinearLayout>

1. 버튼을 클릭했을 때 화면이동 및 데이터를 주고받을 수 있는 화면을 새로 생성합니다. 저는 데이터를 넘겨받을 액티비티를 DataActivity로 생성하겠습니다. 정상적으로 생성하셨으면 java에는 DataActivity layout폴더에는 activity_data.xml이 생성되셨을겁니다.

 

<!-- activity_data.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:padding="15dp"
    android:gravity="center"
    tools:context=".DataActivity">

    <TextView
        android:id="@+id/receivedMessageTxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="전달 받은 내용 출력 자리"
        android:layout_marginBottom="50dp"
        android:textSize="18sp"/>

    <Button
        android:id="@+id/goBackToMainBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="메인으로 돌아가기" />

</LinearLayout>

2. [액티비티로 이동] 버튼은 화면만 이동하는 버튼이라 출력자리에는 변경사항이 없고

​3. 두 번째 [액티비티로 메시지 들고 이동] 버튼은 들고 갈 데이터가 있기 때문 [전달받은 내용을 출력하는 자리]에 해당 내용을 뿌려주는 형식으로 하겠습니다.

 

package com.mwsniper.review_intent

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //1. 액티비티로 그냥 이동 버튼
        // moveToBtn 클릭이벤트
        moveToBtn.setOnClickListener {

            // 이동할 액티비티 경로 잡기
            val myIntent = Intent(this, DataActivity::class.java)

            // 이동하기
            startActivity(myIntent)

        }

        //2. 이동할 화면에 전달할 메시지 들고가는 버튼
        // bringToBtn
        bringToBtn.setOnClickListener {

            // 우선 들고갈 메시지 변수에 담기
            val inputMsg = messageEdt.text.toString()

            // 이동할 액티비티 경로 잡기
            val myIntent = Intent(this, DataActivity::class.java)

            // 가지고 갈 메시지를 putExtra에 담기
            myIntent.putExtra("message", inputMsg)

            // 이동하기
            startActivity(myIntent)
        }
    }
}

​​4. 메시지 전달하는 버튼(bringToBtn)은 그냥 화면 이동하는 버튼과는 달리 데이터를 담아야하기 때문에 Intent 변수에 .putExtra("담을데이터name", 데이터) 형식으로 보내기 전 넣어줘야 합니다.

 

package com.mwsniper.review_intent

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_data.*

class DataActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_data)

        // 액티비티에 들어오자마자 바로 첨부된 값을 받아서 텍스트뷰에 반영
        val receivedMessage = intent.getStringExtra("message")
        receivedMessageTxt.text = receivedMessage

        goBackToMainBtn.setOnClickListener {
            // 메인으로 돌아기기 버튼을 누른 경우 finish()
            finish()
        }

    }
}

5. 그 다음은 데이터를 받는 화면에서 처리해줘야합니다 intent.getStringExtra("데이터이름")을 사용하여 보냈던 메시지를 변수 담고 TextView에 뿌려주면 성공!!

 

그 다음은 이제 마지막 연습인 닉네임 변경하는 것에 대해 공부해보도록 하겠습니다. 우선 닉네임변경 처리하는 화면을 추가로 생성하도록 하겠습니다. 해당 액티비티의 이름은 EditNicknameActivity

<!-- activity_edit_nickname.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:padding="15dp"
    tools:context=".EditNicknameActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="변경할 닉네임" />

    <EditText
        android:id="@+id/nickNameEdt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="새 닉네임을 입력해주세요."
        android:singleLine="true"/>

    <Button
        android:id="@+id/okBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="입력 완료" />

</LinearLayout>
package com.mwsniper.review_intent

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //3. 닉네임 변경 버튼 클릭
        //changeNickNameBtn
        changeNickNameBtn.setOnClickListener {

            // 닉네임 변경 액티비티로 이동한다고 명시
            val myIntent = Intent(this, EditNicknameActivity::class.java)

            // 지금까지한 내용과 다르게 여기서는 결과값을 받고 다시 돌아와야함
            // 그래서 기존에는 startActivity를 사용했지만 여기서는 startActivityForResult를 사용함
            // requestCode는 저와 같이 직접 입력하지 않고 멤버변수로 담아서 가독성을 높여주는걸 추천
            startActivityForResult(myIntent, 200)
        }
    }

    // 결과를 받아올 때 실행되는 함수 오버라이딩
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        // resultCode를 우선 검사해야합니다.
        // 화면에 들어가기 전 200이라는 resultCode를 주어줬는데 해당 값이 맞는지 체크
        if(requestCode == 200)
        {
            //setResult(Activity.RESULT_OK, resultsIntent) 에서 부여했던 result_OK 값이 맞는지
            if(resultCode == Activity.RESULT_OK)
            {
                // 모든 것이 맞으면 새로 변경한 닉네임으로 text반영
                val newNickName = data?.getStringExtra("newNickname")

                // 메인화면에 있는 닉네임 TextView 변경
                nickNameTxt.text = newNickName
            }
        }
    }
}
package com.mwsniper.review_intent

import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_edit_nickname.*

class EditNicknameActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_edit_nickname)

        // 닉네임 수정 후 완료버튼을 눌렀을 때
        okBtn.setOnClickListener {

            // 돌아갈 때 첨부할 데이터를 들고 있어주는 Intent와는 별개로 생성
            val resultsIntent = Intent()

            // 입력한 닉네임을 resultsIntent에 첨부 = putExtra
            val input = nickNameEdt.text.toString()
            resultsIntent.putExtra("newNickname", input)

            // OK 버튼을 눌렀을 때 데이터 담고있는 resultsIntent를 갖고 복귀처리
            // 기존에는 그냥 finish()처리만 해줬지만 이번에는
            // 결과값을 들고 가야하기에 꼭 필요
            // public static final int RESULT_OK = -1;
            setResult(Activity.RESULT_OK, resultsIntent)

            // 복귀한다는 의미
            finish()
        }
    }
}

​닉네임변경 화면으로 이동 후 새로 변경할 닉네임을 입력한 뒤 OK버튼을 누르면 새로 변경할 닉네임 데이터를 resultsIntent에 담고 setResult 함수로 복귀처리 하는 것을 알 수 있습니다.

 

  // 결과를 받아올 때 실행되는 함수 오버라이딩
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        // resultCode를 우선 검사해야합니다.
        // 화면에 들어가기 전 200이라는 resultCode를 주어줬는데 해당 값이 맞는지 체크
        if(requestCode == 200)
        {
            //setResult(Activity.RESULT_OK, resultsIntent) 에서 부여했던 result_OK 값이 맞는지
            if(resultCode == Activity.RESULT_OK)
            {
                // 모든 것이 맞으면 새로 변경한 닉네임으로 text반영
                val newNickName = data?.getStringExtra("newNickname")

                // 메인화면에 있는 닉네임 TextView 변경
                nickNameTxt.text = newNickName
            }
        }
    }

복귀하면 결과값을 받아올 때 실행되는 오버라이딩 함수 MainActivity에 있어야하는 함수이고 해당 함수를 보면 알 수 있듯이 내가 요청한내용이 맞는지에 대한 requestCode == 200체크와 해당 resultCode가 정상인지에 대한 유무체크를 한 다음 둘다 정상로직을 탔을 때 새로 변경한 닉네임을 적용하는 것을 확인할 수 있습니다.

Comments