0

Im trying to add some fragments to a FragmentContainerView dynamically using kotlin. The issue I have is each fragment is drawn on top of each other in the top corner whereas I would like them to be next to one another so you can see them all. Is there a standard way to do this? I have tried googling but i'm new to android so im probably using the wrong terms.

The layout;

<HorizontalScrollView
    android:id="@+id/external_threat_container_scroll"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent">
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/external_threat_container"
        android:layout_width="wrap_content"
        android:layout_height="match_parent">

    </androidx.fragment.app.FragmentContainerView>

</HorizontalScrollView>

The activity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(findViewById(R.id.toolbar))

        if(savedInstanceState == null) {
            supportFragmentManager
                .beginTransaction().apply {
                    this.add(R.id.ship_container, ShipFragment.newInstance(), "ship")
                    (1..50).map { Pair(it, Threat.newInstance()) }.forEach { this.add(R.id.external_threat_container, Threat.newInstance(), "thrre$it") }
                    (1..50).forEach { this.add(R.id.internal_threat_container, Threat.newInstance(), "the$it") }
                }.commit()
        }
    }

The fragment xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="@dimen/threat_height"
    android:layout_height="@dimen/threat_width"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".Threat">
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/threat_title"
        android:layout_width="match_parent"
        android:gravity="center_horizontal"
        app:layout_constraintTop_toTopOf="parent"
        android:text="@string/exampleFlagshipTitle"
        android:layout_height="wrap_content" />
    <ImageView
        android:layout_width="20dp"
        android:layout_height="20dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:src="@drawable/die_two"></ImageView>

    <TextView
        android:id="@+id/threat_effect_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="@string/exampleFlagshipText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

The fragment code

class Threat : Fragment() {

    companion object {
        fun newInstance() = Threat()
    }

    private lateinit var viewModel: ThreatViewModel

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

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this).get(ThreatViewModel::class.java)
        // TODO: Use the ViewModel
    }

}
Tom Squires
  • 8,848
  • 12
  • 46
  • 72
  • Can you give me your XML code in which you are adding these fragments? – SlothCoding Feb 07 '21 at 19:58
  • @SlothCoding sure. Edited to add it – Tom Squires Feb 07 '21 at 20:14
  • This is so messy, can you please edit this and make it cleaner? You have two FragmentContainerViews with the same ID there. – SlothCoding Feb 07 '21 at 21:23
  • @SlothCoding can you be more specific about what you want? Im happy to remove more code from the question but when I put only what i thought was relevant you asked for the xml too. Ive tried to edit it to make the diffrent sections easier to identify – Tom Squires Feb 07 '21 at 21:47
  • You did exactly what I asked you to do. It was messy and there was double code and what else. Now it's fine, I hope. I added my answer I guess that's what you want, if you want anything else just comment under my answer. – SlothCoding Feb 07 '21 at 22:04

1 Answers1

1

When using HorizontalScrollView you need to add one child layout that will coordinate other views like yours FragmentContainerView. So, to do this I would simply add LinearLayout inside your HorizontalScrollView and then add as many as FragmentContainerViews you need. Like this:

<HorizontalScrollView
    android:id="@+id/external_threat_container_scroll"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="horizontal" >

        <!-- FIRST FRAGMENT LAYOUT -->
        <androidx.fragment.app.FragmentContainerView
             android:id="@+id/FIRST_CONTAINER"
             android:layout_width="wrap_content"
             android:layout_height="match_parent">
        </androidx.fragment.app.FragmentContainerView>

        <!-- SECOND FRAGMENT LAYOUT -->
        <androidx.fragment.app.FragmentContainerView
             android:id="@+id/SECOND_CONTAINER"
             android:layout_width="wrap_content"
             android:layout_height="match_parent">
        </androidx.fragment.app.FragmentContainerView>
    </LinearLayout>
</HorizontalScrollView>

Now you can simply add your fragments with getSupportFragmentManager inside containers

  • FIRST_CONTAINER
  • SECOND_CONTAINER

which are my IDs for these FragmentContainerViews, you can use whatever you want. This will show your fragments one after another inside HorizontalScrollView

SlothCoding
  • 1,546
  • 7
  • 14
  • Thank you for your answer but that doesn't really solve the problem. Im adding 50 fragments via kotlin. Sure i could manually define each one in xml but that would take forever and is more a work around than a solution – Tom Squires Feb 07 '21 at 22:13
  • You can add them programmatically inside LinearLayout. Just create a new view and add it to LinearLayout. Add an ID to linear layout and go with that. Here, check this: https://stackoverflow.com/q/6216547/14759470 – SlothCoding Feb 07 '21 at 22:20
  • Ill give it a bash tomorrow but i dont really understand how the FragmentContainerView being inside a LinearLayout would make any difference. FragmentContainerView is a valid child of a HorizontalScrollView – Tom Squires Feb 07 '21 at 23:56
  • Well, if you want to show your fragments one next to the other you need LinearLayout. One FragmentContainerView can have only one Fragment as a Child or am I wrong? If thats the truth, than when you dont add linearlayout you will have overlapping issue, if you do you wont. Based on experience with scrollview I guess that horizontalscrollview can also have only one child, thats where layouts like linear, relative or anything else comes to use. – SlothCoding Feb 08 '21 at 06:48
  • I just added the fragments to the LinearLayout as you suggested and it worked. The FragmentContainerView was superfluous. Thanks for your help – Tom Squires Feb 08 '21 at 11:11
  • 1
    No problem man, I am glad I could help. Happy coding! – SlothCoding Feb 08 '21 at 11:11