0

What I would like to do

I would like to call Activity from Fragment to realize both transitions among fragments and activities simultaneously in an Android app.

I have succeeded to call one specific method on activity file from fragment file, but I have trouble with calling an entire activity from a fragment.

SampleFragment - MainActivity's fragmentMethod() is called once  the button is clicked on the page
Sample1Fragment - FormActivity is called once the button is clicked on the page
FormActivity - FormActivity2 is called once the button is clicked on the page

The above is same as my former question: How can I fix the code to call Activity from Fragment in Android App?

Errors and Problems

It was succeeded to build a project and run the app on the emulator. However, the screen was suddenly shut down when I click the button to call FormActivity on Sample1Fragment.

I have trouble with fix this problem.

Error Message to the below part on Sample1Fragment.kt

Modifier 'override' is not applicable to 'local function'

Sample1Fragment.kt

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        override fun onViewCreated(view: View, savedInstanceState: Bundle) {
            btnClick2.setOnClickListener(object:View.OnClickListener{

                // here I would like to move to FormActivity
                override fun onClick(v: View?) {
                    activity?.startActivity(Intent(context, FormActivity::class.java))
                }

            })
        }

Current Code

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // make the list of fragment
        val fragmentList = arrayListOf<Fragment>(
            SampleFragment(),
            Sample1Fragment()
        )

        // create instance of adapter
        val adapter = SamplePagerAdapter(supportFragmentManager, fragmentList)
        /// set adapter
        viewPager.adapter = adapter
    }



    public fun fragmentMethod() {
        Toast.makeText(this@MainActivity, "Method called From Fragment", Toast.LENGTH_LONG).show();
    }
}

SampleFragment.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_sample.*

class SampleFragment : Fragment() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {

        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sample, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        btnClick.setOnClickListener(object:View.OnClickListener{
            override fun onClick(v: View?) {
                (activity as MainActivity).fragmentMethod()
            }

        })
    }



}

Sample1Fragment.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_sample1.*
import android.content.Intent

class Sample1Fragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sample1, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        override fun onViewCreated(view: View, savedInstanceState: Bundle) {
            btnClick2.setOnClickListener(object:View.OnClickListener{

                // here I would like to move to FormActivity
                override fun onClick(v: View?) {
                    activity?.startActivity(Intent(context, FormActivity::class.java))
                }

            })
        }

    }

}

Developping Environment

Android Studio 3.6.1

What I tried to do

It tried to use SingleLiveEvent recommended on an answer, but I haven't found the appropriate way to implement it on my current code, ListViewModel.kt and Sample1Fragment.kt.

Reference: LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)

ListViewModel.kt

import android.app.usage.UsageEvents
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class ListViewModel : ViewModel() {
    private val _navigateToDetails = MutableLiveData<UsageEvents.Event<String>>()

    val navigateToDetails : LiveData<UsageEvents.Event<String>>
        get() = _navigateToDetails


    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    fun userClicksOnButton(itemId: String) {
        _navigateToDetails.value =
            UsageEvents.Event(itemId)  // Trigger the event by setting a new Event as a new value
    }
}

These are the error messages I'm facing to

error4 error5

Sample1Fragment.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_sample1.*
import android.content.Intent


class Sample1Fragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sample1, container, false)
    }

    myViewModel.navigateToDetails.observe(this, Observer {
        it.getContentIfNotHandled()?.let { // Only proceed if the event has never been handled
        fun onViewCreated(view: View, savedInstanceState: Bundle) {
            btnClick2.setOnClickListener(object:View.OnClickListener{

                // here I would like to move to FormActivity
                override fun onClick(v: View?) {
                    activity?.startActivity(Intent(context, FormActivity::class.java))
                }

            })
        }
    })

    }

}

This is the error message I'm facing to

Sample1Fragment.kt error

halt
  • 393
  • 5
  • 17

1 Answers1

1

In Sample1Fragment.kt you are overriding onViewCreated() inside onActivityCreated() method.
This is why you get

Modifier 'override' is not applicable to 'local function'


About navigation: there is several possible ways how to navigate between different activities and fragments:

  1. navigation, which is usually the easiest to implement
  2. callbacks, which are already preset when you create a fragment in Android Studio
  3. view model, shared between fragment and it's activity. In this case, I suggest using SingleLiveEvent to trigger the event.
Primož Ivančič
  • 1,984
  • 1
  • 17
  • 29
  • Thank you for your answer. I read this information and tried to implement SingleLiveEvent on ListViewModel and Sample1Fragment.kt. I shared my current code on What I tried to do part. However, I cannot fix the example code in the article, "LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)". It is appreciated if you could give me more specific advice for my code. – halt Mar 11 '20 at 06:38
  • You mean `startActivity(DetailsActivity...)`? This is just an indicator showing that you need to start your activity here. This particular line is not supposed to actually start it. Here, you just start the activity the way you already did before: `activity?.startActivity(Intent(context, FormActivity::class.java))` – Primož Ivančič Mar 11 '20 at 07:08
  • Thank you for your response. I mean how to implement `SingleLiveEvent` to fix the bug that Form Activity is shut down when I click the button. I uploaded the problems on both Sample1Fragment.kt and ListViewModel.kt. – halt Mar 11 '20 at 08:09
  • Looks like your `Event` class doesn't accept arguments and doesn't use generics. – Primož Ivančič Mar 11 '20 at 21:15