-1

I'm currently developing an application using android-studio with Kotlin.

This app has

  • a common value I can use through fragments

  • a fragment class for main content

  • a fragment class for bottom sheet

I want to show a new value on the main fragment view right after I change the common value at edittext in bottom sheet.

But in the case of my codes, the common value doesn't change when I' back to the main fragment view from the bottom sheet...

How can I solve this situation?


Here are the codes:

build.gradle

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.sample.bottomsheetvalue"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0-beta01'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'

    implementation "androidx.fragment:fragment-ktx:1.3.0-alpha04"
    implementation "com.google.android.material:material:1.1.0-alpha06"

}

AppState.kt

package com.sample.bottomsheetvalue

import androidx.lifecycle.ViewModel

class AppState: ViewModel()  {

    var value:String = "initialValue"
}

MainActivity.kt

package com.sample.bottomsheetvalue

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button

class MainActivity : AppCompatActivity() {

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

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout
        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"
        tools:context=".MainActivity">
    
    <fragment
            android:id="@+id/main_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name="com.tomato_love.bottomsheetvalue.MainFragment"
    />

</androidx.constraintlayout.widget.ConstraintLayout>

MainFragment.kt

package com.sample.bottomsheetvalue

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider

class MainFragment : Fragment() {

    lateinit var appState: AppState

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        activity?.run {
            appState = ViewModelProvider(this).get(AppState::class.java)
        }
        val view = inflater.inflate(R.layout.fragment_main, container, false)

        val button = view.findViewById<Button>(R.id.button)
        val textView = view.findViewById<TextView>(R.id.textView)

        textView.text = appState.value

        button.setOnClickListener {

            val fm = activity!!.supportFragmentManager
            val bottomSheet =BottomSheet()
            bottomSheet.show(fm, "navigation_bottom_sheet")
        }
        return view
    }
}

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
        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=".MainFragment"
        android:id="@+id/constraintLayoutFragment">

    <Button
            android:id="@+id/button"
            android:text="show bottom sheet"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
    />
    <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="32sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginTop="32dp"
            app:layout_constraintTop_toBottomOf="@+id/button"/>
</androidx.constraintlayout.widget.ConstraintLayout>

BottomSheet.kt

package com.sample.bottomsheetvalue

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

class BottomSheet : BottomSheetDialogFragment() {

    lateinit var appState: AppState

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        activity?.run {
            appState = ViewModelProvider(this).get(AppState::class.java)
        }

        val view = inflater.inflate(R.layout.fragment_bottom_sheet, container, false)

        val editText = view.findViewById<EditText>(R.id.editText)

        editText.setOnEditorActionListener { v, actionId, event ->
            when (actionId) {
                EditorInfo.IME_ACTION_DONE -> {
                    appState.value = editText.text.toString()
                    println(appState.value)
                    true
                }
                else -> false
            }
        }
        return view
    }
}

fragment_bottom_sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
             tools:context=".BottomSheet">
    <EditText
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="500dp"
            android:inputType="textPersonName"
            android:ems="10"
            android:imeOptions="actionDone"
    />
</FrameLayout>

Android Studio : 3.3.2

Tio
  • 944
  • 3
  • 15
  • 35
  • You can share the `ViewModel` and pass the Value using `LiveData`. But `LiveData` is not the complete replacement for callback listener Also it will make you bottom sheet tightly coupled with this `Fragment` only. Your use case should be fulfill with a listener . Have a look at [This answer](https://stackoverflow.com/a/59350738/4168607) . I think its the right way to do it with this your botom sheet can be reusable in other fragments as well . – ADM Sep 22 '20 at 06:08

1 Answers1

1

Add a Livedata to your view model class:

val data: MutableLiveData<String> = MutableLiveData("Initial Value")

And observe that in your fragment:

appState.data.observe(viewLifecycleOwner, Observer {
            // Update your ui here
})

And also in your bottom sheet update the data:

data.postValue("newValue")
Mohammad Zarei
  • 1,773
  • 14
  • 33