Search code examples
androidkotlinonbackpressed

Unintended behaviour as a result of pressing back button


I have two activities. Activity A contains a recycler view of card view elements with images in them. On selecting an element in Activity A. The full landscape version of the image is displayed in Activity B.

The layout file for Activity B is a follows:

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

The codebase for Activity B is as follows:

class PosterViewActivity : AppCompatActivity()
{

    private lateinit var imageView: AppCompatImageView

    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_poster_view)
        init()
    }

    private fun init()
    {
        findViewsByID()
        getBundle()
        toggleHide()
    }  

    private fun getBundle()
    {
        if (intent != null)
        {
            var imageUrl = intent.getStringExtra(ARG_IMAGE_URL)
            if (imageUrl != null)
            {
                Glide.with(this).load(imageUrl).centerInside().into(imageView)
            }
        }
    }

 private fun findViewsByID()
    {
        imageView = findViewById(R.id.imageView)
       }

    override fun onOptionsItemSelected(item: MenuItem): Boolean
    {
        if (item.itemId == android.R.id.home)
        {
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onBackPressed()
    {
        super.onBackPressed()
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
    }

    override fun onWindowFocusChanged(hasFocus: Boolean)
    {
        super.onWindowFocusChanged(hasFocus)

}

    private fun toggleHide()
    {
        val uiOptions = window.decorView.systemUiVisibility
        var newUiOptions = uiOptions
        val isImmersiveModeEnabled = uiOptions or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY == uiOptions
        if (isImmersiveModeEnabled)
        {
            Log.i("PosterViewActivity", "Turning immersive mode mode off. ")
        }
        else
        {
            Log.i("PosterViewActivity", "Turning immersive mode mode on.")
        }

        if (Build.VERSION.SDK_INT >= 14)
        {
            newUiOptions = newUiOptions xor View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        }

        // Status bar hiding: Backwards compatible to Jellybean
        if (Build.VERSION.SDK_INT >= 16)
        {
            newUiOptions = newUiOptions xor View.SYSTEM_UI_FLAG_FULLSCREEN
        }

        if (Build.VERSION.SDK_INT >= 18)
        {
            newUiOptions = newUiOptions xor View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        }

        window.decorView.systemUiVisibility = newUiOptions
    }
}

However, when I press the back button on the device instead of returning to Activity A. The status and navigation buttons are displayed and hidden and it takes 4 presses of the back button to return to Activity A. I have checked the Back stack and two activities are in the stack namely A and B

The code from Activity A calling Activity B:

if(promoList.size >0)
        {
            noPromoImageView.visibility = View.GONE
            noPromoTextView.visibility = View.GONE

            promoAdapter = PromotionsAdapter(this, promoList!!)
            promoRecyclerView.layoutManager = GridLayoutManager(this, 3)
            promoRecyclerView.adapter = promoAdapter
            promoRecyclerView.addOnItemTouchListener(
                RecyclerTouchListener(applicationContext,
                    promoRecyclerView,
                    object : ClickListener
                    {
                        override fun onClick(view: View, position: Int)
                        {
                            openPosterView(position)
                        }

                        override fun onLongClick(view: View?, position: Int)
                        {

                        }
                    }))
        }
        else
        {
            noPromoImageView.visibility = View.VISIBLE
            noPromoTextView.visibility = View.VISIBLE
        }
    }

 private fun openPosterView(position: Int)
    {
        val posterImageDetails = displayedRules!![position]!!.imageDetails
        if (posterImageDetails.isNotEmpty())
        {
            var cur = -1
            for ((pos, item) in posterImageDetails.withIndex())
            {
                val key = item.containsValue("Fullscreen")
                if (key)
                {
                    cur = pos
                }
            }
            var imagesLink: Map<String, String>
            if (cur > -1)
            {
                imagesLink = posterImageDetails[cur]
                var imageUrl = imagesLink?.get("ImageUrl")
                if (imageUrl!!.isNotEmpty())
                {
                    var intent = Intent(this, PosterViewActivity::class.java)
                    var bundle = Bundle()
                    bundle.putString(ARG_IMAGE_URL, imageUrl)
                    intent.putExtras(bundle)

                    this.startActivity(intent)
                }
            }
        }
    }

 internal class RecyclerTouchListener(context: Context, recyclerView: RecyclerView, private val clickListener: ClickListener) : RecyclerView.OnItemTouchListener
    {

        private val gestureDetector: GestureDetector

        init
        {
            gestureDetector = GestureDetector(
                context,
                object : GestureDetector.SimpleOnGestureListener()
                {
                    override fun onSingleTapUp(e: MotionEvent): Boolean
                    {
                        return true
                    }

                    override fun onLongPress(e: MotionEvent)
                    {
                        val child = recyclerView.findChildViewUnder(e.x, e.y)
                        if (child != null && clickListener != null)
                        {
                            clickListener.onLongClick(child, recyclerView.getChildPosition(child))
                        }
                    }
                })
        }

        override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean
        {

            val child = rv.findChildViewUnder(e.x, e.y)
            if (child != null && clickListener != null && gestureDetector.onTouchEvent(e))
            {
                clickListener.onClick(child, rv.getChildPosition(child))
            }
            return false
        }

        override fun onTouchEvent(rv: RecyclerView, e: MotionEvent)
        {
        }

        override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean)
        {

        }
    }

Solution

  • In my opinion Activity A's clickListener is wrong. The count of items can be 4 and when the item is clicked, the item's onClickListener can call activity B 4 times.