How to programmatically add views and constraints to a ConstraintLayout? How to programmatically add views and constraints to a ConstraintLayout? android android

How to programmatically add views and constraints to a ConstraintLayout?


I think you should clone the layout after adding your ImageView.

    ConstraintLayout parentLayout = (ConstraintLayout)findViewById(R.id.mainConstraint);    ConstraintSet set = new ConstraintSet();    ImageView childView = new ImageView(this);    // set view id, else getId() returns -1    childView.setId(View.generateViewId());    parentLayout.addView(childView, 0);    set.clone(parentLayout);    // connect start and end point of views, in this case top of child to top of parent.    set.connect(childView.getId(), ConstraintSet.TOP, parentLayout.getId(), ConstraintSet.TOP, 60);    // ... similarly add other constraints    set.applyTo(parentLayout);


Merging this How do I add elements dynamically to a view created with XML with https://stackoverflow.com/a/40527407/4991437

I have discovered an 'easier' solution. This works best for adding multiple consistent views that uses Viewbinding and ViewModel

  1. Create the fragment_home.xml
  2. Add a LinearLayout to the bottom of fragment_home.xml
  3. Create an dynamic_view.xml that you will inflate
  4. Get elements from ViewModel/Array or whatever source of data available
  5. 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);        }    });