Java 버전은 https://stickode.tistory.com/340 에서 확인해주세요.
오늘은 Fragment 에서 Activity 를 실행시키고 결과를 받아보도록 하겠습니다.
결과는 registerForActivityResult() 메소드를 사용해 등록한 ActivityResultCallback 에서 받도록 하겠습니다.
registerForActivityResult() 에 대한 정보는 아래 링크의 게시글을 확인해주세요.
https://stickode.tistory.com/187
계획은 메인 액티비티에서 프래그먼트를 2개 만들고 하단에 있는 버튼으로 그 프래그먼트들을 교체할 수 있게 만들겠습니다.
그리고 현재 켜져있는 프레그먼트에서 사용자 입력을 받기 위한 액티비티를 켜고 registerForActivityResult() 를 통해 프레그먼트에서 데이터를 받도록 구현해보겠습니다.
먼저 메인 레이아웃 파일입니다.
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"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/mainFragmentContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/mainFragmentChangeButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="프래그먼트 교체 버튼"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
프레그먼트가 들어갈 mainFragmentContainer 와 교체를 위한 버튼인 mainFragmentChangeButton 를 두었습니다.
다음으로 교체 될 프래그먼트의 레이아웃입니다.
fragment_replace.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:gravity="center">
<Button
android:id="@+id/replaceTitleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="제목"
android:textSize="30sp" />
</LinearLayout>
액티비티를 실행하고 받은 결과를 표시할 replaceTitleButton 하나만 두도록 하겠습니다.
마지막으로 사용자 입력을 받기 위한 액티비티의 레이아웃 입니다.
activity_sub.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">
<EditText
android:id="@+id/subEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/subSummitButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="프래그먼트로 보내기" />
</LinearLayout>
값을 입력받는 에딧텍스트와 결과를 전송할 버튼으로 이루어져있습니다.
먼저 SubActivity 클래스를 만들고 manifests 에 등록해주세요.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tstory1">
<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/Theme.Tstory1">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 여기에 SubActivity 를 추가 -->
<activity android:name=".SubActivity" />
</application>
</manifest>
다음으로 서브 클래스 java 코드입니다.
SubActivity.java
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
class SubActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub)
val editText : EditText = findViewById(R.id.subEditText)
val summitButton : Button = findViewById(R.id.subSummitButton)
summitButton.setOnClickListener {
val intent = Intent()
intent.putExtra("key", editText.text)
setResult(RESULT_OK, intent)
finish()
}
}
}
제출 버튼이랑 에딧텍스트를 findViewById 를 통해 찾습니다.
그리고 제출 버튼이 눌리면 인텐트에 에딧텍스트에 들어있는 값을 인텐트에 넣고, setResult() 로 결과를 설정하고, 액티비티를 종료합니다.
다음으로 교체 프래그먼트입니다.
ReplaceFragment.java
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
class ReplaceFragment : Fragment() {
companion object{
fun newInstance(name: String): ReplaceFragment {
val args = Bundle()
args.putString("key", name)
val fragment = ReplaceFragment()
fragment.arguments = args
return fragment
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
return inflater.inflate(R.layout.fragment_replace, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val bundle = arguments ?: return
val title = bundle.getString("key")
val button : Button = view.findViewById(R.id.replaceTitleButton)
button.text = title
val activityResultLauncher = registerForActivityResult(StartActivityForResult()) { result ->
if (result.resultCode == AppCompatActivity.RESULT_OK) {
val data = result.data
val text = data!!.getCharSequenceExtra("key")
button.text = text
}
}
button.setOnClickListener {
activityResultLauncher.launch(Intent(requireActivity(), SubActivity::class.java))
}
}
}
newInstance() 메소드를 통해 ReplaceFragment 를 생성을 합니다.
생성할때 이름을 담은 Bundle 도 같이 넣어주도록 만들었습니다.
onCreateView 에서 레이아웃을 부풀(?)립니다.
그 후 onViewCreated 에서 MainActivity 에서 전달받은(아래 MainActivity 에서 설명할 예정) 프래그먼트의 제목을 버튼에 셋팅하도록 합니다.
그리고 오늘의 주인공인 registerForActivityResult() 를 사용해서 콜백을 등록합니다.
콜백이 RESULT_OK 면 SubActivity 에서 넣은 에딧텍스트 값을 가져와서 Button 에 넣습니다.
마지막으로 button 을 누르면 사용자 입력을 받을 SubActivity 를 실행시킵니다.
마지막으로 메인 액티비티입니다.
MainActivity.java
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private val trueFragment: ReplaceFragment by lazy { ReplaceFragment.newInstance("true") }
private val falseFragment: ReplaceFragment by lazy { ReplaceFragment.newInstance("false") }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button : Button = findViewById(R.id.mainFragmentChangeButton)
button.setOnClickListener {
replaceFragment()
}
button.performClick()
}
private fun replaceFragment() {
val beforeFragment = supportFragmentManager.primaryNavigationFragment
val fragment = if(beforeFragment == trueFragment){
falseFragment
}else{
trueFragment
}
with(supportFragmentManager.beginTransaction()){
if (beforeFragment != null) {
hide(beforeFragment)
}
if (!supportFragmentManager.fragments.contains(fragment)) {
add(R.id.mainFragmentContainer, fragment)
}
setPrimaryNavigationFragment(fragment)
.show(fragment)
.commit()
}
}
}
교체하기 위한 두개의 프래그먼트를 멤버 변수에 선언합니다.
onCreate 에서 프래그먼트 교체 버튼을 찾아서 버튼 클릭 로직을 작성합니다.
클릭하면 replaceFragment() 를 실행시킵니다.
replaceFragement() 는 프래그먼트를 교체해주는 메소드입니다.
교체하기전에 띄워져있던 프레그먼트(beforeFragment)가 있으면 getPrimaryNavigationFragment() 로 가져와 숨깁니다.
beforeFragment 가 trueFragment 면 falseFragment 를 반대면 trueFragment 를 보여주도록 만듭니다.
새로 전달받은 프래그먼트가 FragmentManager 에 추가가 안되어 있으면 FragmentManager 에 추가해줍니다.
마지막으로 보여줄 프래그먼트를 setPrimaryNavigationFragment 에 넣고 액티비티에 띄웁니다.
실행 영상입니다.
'안드로이드 코틀린' 카테고리의 다른 글
[Kotlin][Android] 간단한 중첩 리사이클러뷰 만들기 (0) | 2022.02.27 |
---|---|
[Kotlin][Android] Intent로 객체 전달하기 (4) | 2022.02.25 |
[Kotlin][Android] 리사이클러뷰 (0) | 2022.02.19 |
[Kotlin][Android] 텍스트뷰 생략 옵션 동적으로 변경하기 (0) | 2022.02.15 |
[Kotlin][Android] 녹음기능 구현하기 (0) | 2022.02.10 |