Merging this How do I add elements dynamically to a view created with XML with https://mcmap.net/q/189199/-how-to-programmatically-add-views-and-constraints-to-a-constraintlayout
I have discovered an 'easier' solution. This works best for adding multiple consistent views that uses Viewbinding and ViewModel
- Create the fragment_home.xml
- Add a LinearLayout to the bottom of fragment_home.xml
- Create an dynamic_view.xml that you will inflate
- Get elements from ViewModel/Array or whatever source of data available
- Inflate and add elements
In this case I am creating a textview(title) with a recyclerview[there are libs for this, however, I found more control doing this]
Step 1,2
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.hometab.HomeFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraint_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- otherviews here -->
<LinearLayout
android:id="@+id/dynamic_linear_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_large"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/curated_recycler" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
Step 3
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/dynamic_constraint"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="@dimen/margin_large"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/title_view"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/shop_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/diary"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/title_view"
app:layout_constraintStart_toStartOf="@id/guideline"
app:layout_constraintTop_toTopOf="@+id/title_view" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/shop_recycler"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/guideline"
app:layout_constraintTop_toBottomOf="@+id/title_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4,5
binding = FragmentHomeBinding.inflate(getLayoutInflater());
ShopViewModel shopViewModel = new ViewModelProvider(this).get(ShopViewModel.class);
shopViewModel.getAllShops(false).observe(getViewLifecycleOwner(), shopEntities -> {
List<ConstraintLayout> shopConstraints = new ArrayList<>();
for (ShopEntity shopEntity : shopEntities) {
// get an instance of the dynamic_view.xml
DynamicViewBinding dynamicViewBinding = DynamicViewBinding.inflate(getLayoutInflater());
// add text view content
dynamicViewBinding.shopName.setText(shopEntity.getName());
// initialize the recycler layout adapter
dynamicViewBinding.shopRecycler.setLayoutManager(new ProductCardLayoutManager(getContext(), 1,
GridLayoutManager.HORIZONTAL, false, 80));
// get all products and add them to recycler view
productViewModel.getAllProductsByShop(shopEntity.getShopId(), 10).observe(getViewLifecycleOwner(), productEntities ->
dynamicViewBinding.shopRecycler.setAdapter(new ProductAdapter(getActivity(), productEntities)));
// attach dynamic view to list of dynamic constraint layouts
shopConstraints.add(dynamicViewBinding.getRoot());
}
// remove all previous views from the linear layout
binding.dynamicLinearLayout.removeAllViews();
// add the new views
for (ConstraintLayout shopConstraint : shopConstraints) {
binding.dynamicLinearLayout.addView(shopConstraint);
}
});