Search code examples
xmlandroid-fragmentskotlinandroid-constraintlayoutbottombar

Constrain layout items in fragments to top of main activity bottom bar navigation?


this is my first question posted on here so if I leave anything out, please give me the opportunity to update my question!

So I am a (relatively) experienced swift app developer with several apps on the App Store.

Currently, I am working on moving those apps onto the Google Play store, and am having quite a hard time getting anything to happen nearly as smoothly as in swift. I decided to restart my entire first project from the a blank app, and ask questions along the way to just build up from it.

My app is using one Main Activity to control 4-5 fragments controlled by a bottomBar navigation item. I am wanting to constrain the fragments view space so that it is:

fragment_view_top = titlebar_bottom

fragment_view_bottom = bottomBar_navigation_top

this way nothing is ever hidden behind the top and bottom.

I have tried several different layout constraint options, and nothing is working correctly. Even going as far as adding an empty bottom bar navigation item inside the fragment so I could constrain to the top of that, and it still didn't work!

Any help would be greatly appreciated, thanks!

fragment.xml code:

    <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/fragment_home">

    <android.support.v7.widget.AppCompatImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/newsImage"
        app:layout_constraintBottom_toTopOf="@id/navigation"/>

</android.support.constraint.ConstraintLayout>

and here is my main_activity.xml code:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="@color/colorAccent"
    android:id="@+id/container">

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="0dp"
        android:layout_marginStart="0dp"
        android:layout_gravity="bottom"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/navigation" />

</FrameLayout>

EDIT 09.20.2018:

this is how I am implementing the switching between my fragments in my main activity

MainActivity.kt code:

    class HomeActivity : AppCompatActivity(){

    lateinit var toolbar: ActionBar

    private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        when (item.itemId) {
            R.id.navigation_home -> {
                toolbar.title = "Home"
                val homeFragment = HomeFragment.newInstance()
                openFragment(homeFragment)
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_map -> {
                toolbar.title = "Map"
                val localFragment = LocalFragment.newInstance()
                openFragment(localFragment)
                return@OnNavigationItemSelectedListener true
            }
        }
        false
    }

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

        toolbar = supportActionBar!!
        val bottomNavigation: BottomNavigationView = findViewById(R.id.navigation)
        bottomNavigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
        bottomNavigation.selectedItemId = R.id.navigation_home



    private fun openFragment(fragment: Fragment) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.container, fragment)
        transaction.addToBackStack(null)
        transaction.commit()
    }
}

Solution

  • Issue is : You are replacing fragment with container. put FrameLayout in main_activity.xml and replace fragment from that. Like,

     <?xml version="1.0" encoding="utf-8"?>
        <android.support.constraint.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:background="@color/colorAccent">
    
            <FrameLayout
                android:id="@+id/frmFragment"
                android:layout_width="0dp"
                android:layout_height="0dp"
                app:layout_constraintBottom_toTopOf="@id/navigation"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"/>
    
            <android.support.design.widget.BottomNavigationView
                android:id="@+id/navigation"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="0dp"
                android:layout_marginStart="0dp"
                android:layout_gravity="bottom"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"/>
        </android.support.constraint.ConstraintLayout>
    

    and than change your openFragment Code Like

      private fun openFragment(fragment: Fragment) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.frmFragment, fragment)
        transaction.addToBackStack(null)
        transaction.commit()
      }