Search code examples
androidkotlinandroid-fragmentsonclicklistener

override setOnClickListener in a fragment stop working


I m a novice programmer and I have a problem with my app.

Its an activity with 4 fragment with a viewpager. I have 1 button in each fragment that do something when you click on it.

when I click on the button in fragment 1 and scroll down to fragment 4 and go back to fragment 1. The button in fragment 1 stop working.

if you dont click the button in fragment 1 and and scroll down to fragment 4 and go back to fragment 1. The button works fine.

The problem appears when I click the button and after scrolling to a distant fragment and return I click again.

Main:

 class MainActivity : AppCompatActivity(), OnFragmentActionsListener   {
    override fun onCreate(savedInstanceState: Bundle?) {
        setTheme(R.style.AppTheme)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val fragmentAdapter = PageAdapter(this, supportFragmentManager)
        viewPager.adapter = fragmentAdapter
        val mPager: ViewPager = findViewById(R.id.viewPager)
        mPager.setPageTransformer(true, PageAdapter.ZoomOutPageTransformer())
        tablayout.setupWithViewPager(viewPager)

}
       override fun onClickFragment1btn1() {
        //here i do something when click the button like do a
            }

viewpager:

class PageAdapter  (val context: Context, fm: FragmentManager): FragmentStatePagerAdapter(fm) {
    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 -> {FOne()}
            1 -> {FTwo()}
            2 -> {FThree()}
            else -> {return FFour()}
        }
    }
    override fun getCount(): Int {
        return 4
    }
    override fun getPageTitle(position: Int): CharSequence? {
        return when (position) {
            0 -> "tab1"
            1 -> "tab2"
            2 -> "tab3"
            else -> {
                return "tab4"
            }
        }
    }

Interface:

interface OnFragmentActionsListener {
    //Fragment 1:
    fun onClickFragment1btn1()
    //Fragment 2:
    fun onClickFragment1btn2()
    //Fragment 3:
    fun onClickFragment1btn3()
    //Fragment 4:
    fun onClickFragment1btn4()
}

Fragment:

class FOne : Fragment() {
    private var listener: OnFragmentActionsListener? = null
    val TAG = "FragmentOne"
    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.d(TAG, "onAtach")
        if (context is OnFragmentActionsListener) {
            listener = context
        } else {
            throw   RuntimeException(context!!.toString() +"must implement OnFragmentInteractionListener")
        }
    }
    override fun onCreate(savedInstanceState: Bundle?){
        super.onCreate(savedInstanceState)
        Log.d(TAG, "onCreate")
    }
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View?{
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_f_one, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        btn1.setOnClickListener{listener?.onClickFragment1btn1() }
    }
  
    override fun onDetach() {
        super.onDetach()
        listener = null
    }
}

Solution

  • The best approach for this are :

    Approach 1:

    Set this line on your viewpager :

    viewPager.setOffscreenPageLimit(4);
    

    This will keep 4 fragment in your memory.