Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically add views and constraints to a ConstraintLayout?

I'm having a problem to programmatically add views to a ConstraintLayout, and set up all the constraints required for the layout to work.

What I have at the moment doesn't work:

ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.mainConstraint); ConstraintSet set = new ConstraintSet(); set.clone(layout);  ImageView view = new ImageView(this); layout.addView(view,0); set.connect(view.getId(), ConstraintSet.TOP, layout.getId(), ConstraintSet.TOP, 60); set.applyTo(layout); 

The ImageView doesn't even appear on the layout. When adding to a RelativeLayout, it works like a charm.

What can I do to create the constraints I need, so that my layout work again?

like image 908
LeoColman Avatar asked Oct 27 '16 02:10

LeoColman


People also ask

How do I add a view in constraint layout?

Add constraints to the parent layout To add a constraint to the left edge of the ImageView , click and hold the constraint handle and drag the line to the left edge of the parent layout. To add the right edge constraint for the ImageView , drag from the constraint handle to the right edge of the parent layout.

Which is better RelativeLayout or ConstraintLayout?

If you have the choice start with ConstraintLayout, but if you already have your app in RelativeLayout, stay with it. That's all I have been following. RelativeLayout is very limited in functionality and many complex layouts can't be made using it, especially when ratios are involved.

Can we use LinearLayout in ConstraintLayout?

Most of what can be achieved in LinearLayout and RelativeLayout can be done in ConstraintLayout. However, learning the basics of LinearLayout and RelativeLayout is important before trying to understand how to use it with ConstraintLayout.

What is the difference between ConstraintLayout and LinearLayout?

ConstraintLayout has dual power of both Relative Layout as well as Linear layout: Set relative positions of views ( like Relative layout ) and also set weights for dynamic UI (which was only possible in Linear Layout). Despite the fact that it's awesome, it fails to serve the purpose with simple UI layouts.


2 Answers

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

ConstraintLayout layout = (ConstraintLayout)findViewById(R.id.mainConstraint); ConstraintSet set = new ConstraintSet();  ImageView view = new ImageView(this); view.setId(View.generateViewId());  // cannot set id after add layout.addView(view,0); set.clone(layout); set.connect(view.getId(), ConstraintSet.TOP, layout.getId(), ConstraintSet.TOP, 60); set.applyTo(layout);``` 
like image 195
rerashhh Avatar answered Sep 21 '22 13:09

rerashhh


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);         }     }); 
like image 36
Phillip Kigenyi Avatar answered Sep 20 '22 13:09

Phillip Kigenyi