0

I'm trying to use startActionMode inside a fragment.

startActionMode works fine in the onActivityCreated method. But outside onActivityCreated method, activity returns null and hence activity?.startActionMode(mActionModeCallback) doesn't work.

package com.akshat.music
import android.app.Activity
import android.content.ContentUris
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.*
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_songs.*
import java.io.File


class SongsFragment : Fragment(), SongListAdapter.OnItemClickListener{

private val allSongs = ArrayList<Songs>()
var activityRef: FragmentActivity? = null


override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    activityRef = activity;
    if (activityRef == null)
        Log.d("MIKE", " $activityRef is empty");
    else
        Log.d("MIKE", " $activityRef is not empty");
    recyclerView.apply {
        layoutManager = LinearLayoutManager(activity)
        adapter = SongListAdapter(allSongs, SongsFragment().apply { this@SongsFragment })
    }
    activity?.startActionMode(mActionModeCallback) // works

}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    getAudioDirectories()
}

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    return inflater!!.inflate(R.layout.fragment_songs, container, false);
}

override fun onItemClicked(song: Songs, position: Int) {
    if (activityRef == null)
        Log.d("MIKE", " $activityRef is empty");
    else
        Log.d("MIKE", " $activityRef is not empty");
    activity?.startActionMode(mActionModeCallback)  // doesn't work
    activityRef?.startActionMode(mActionModeCallback) // activityRef is null
}

private val mActionModeCallback: ActionMode.Callback =
    object : ActionMode.Callback {
        override fun onCreateActionMode(
            actionMode: ActionMode,
            menu: Menu
        ): Boolean {
            val menuInflater = actionMode.menuInflater
            menuInflater.inflate(R.menu.contextual_action_bar, menu)
            return true
        }

        override fun onPrepareActionMode(
            actionMode: ActionMode,
            menu: Menu
        ): Boolean {
            return false
        }

        override fun onActionItemClicked(
            actionMode: ActionMode,
            menuItem: MenuItem
        ): Boolean {
            return false
        }

        override fun onDestroyActionMode(actionMode: ActionMode) {
            var actionMode: ActionMode? = actionMode
            actionMode = null
        }
    }

private fun getAudioDirectories() {
    /////////////
    }
}
}

How can I get reference to activity outside onActivityCreated method? Thanks

Akshat Yadav
  • 33
  • 2
  • 8
  • To get Activity inside androidx.fragment you should use `requireActivity()` method. It's return activity if fragment attach to activity. It's strange why in you get `null` in `onItemClicked` Maybe you call this method from `getAudioDirectories` i.e. Before call `onAttach()`. – R00We Aug 06 '20 at 08:51

2 Answers2

0

you can cast context as Activity and call it from there, e.g.

override fun onItemClicked(song: Songs, position: Int) {
    ...
    (requireContext() as Activity).startActionMode(mActionModeCallback)
}
Stachu
  • 1,614
  • 1
  • 5
  • 17
  • Thanks, but on using this, I get error as : `Fragment SongsFragment{da808fa (17ea0969-4885-4eb9-a8f1-4776ad2521a4)} not attached to an activity.` – Akshat Yadav Aug 06 '20 at 09:33
  • how do you inflate this fragment? if done properly it should be attached to activity, see here https://stackoverflow.com/questions/50257505/fragment-not-attached-to-a-context – Stachu Aug 06 '20 at 09:35
  • I have used following code : `private fun showSongsFragment() { val transaction = manager.beginTransaction() val fragment = SongsFragment() transaction.replace(R.id.fragmentHolder, fragment) transaction.addToBackStack(null) transaction.commit() }` – Akshat Yadav Aug 06 '20 at 09:36
  • and you call that from the Activity, correct? Or maybe from other Fragment? how do you instantiate `manager`? – Stachu Aug 06 '20 at 09:40
  • I'm calling it from Activity – Akshat Yadav Aug 06 '20 at 09:41
0

You should be able to get a reference to the activity from anywhere inside a fragment. there are some cases where activity can be null e.g inside onDetach() or inside OnCreateView(), so activity doesn't always require a value.

try to use the requireContext() like Stachu has mentioned:

    (requireContext() as Activity).startActionMode(mActionModeCallback)