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?
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.
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.
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.
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.
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);```
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
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); } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With