Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Views are gone when ConstraintSet.applyTo

I'm trying to extend the ConstraintLayout functionality to have a ProgressBar with fullscreen translucent background color. The idea is that I could reuse this layout and call hideLoading() and showLoading(). Progress bar has to be centered.

Problem is: when constraintSet.applyTo(this) is called all views that had ConstraintSet.connect(...) on them are GONE, or not drawn. As all operations on them are ignored and they are not displayed on the screen at all.

Here is what I have :

public class ConstraintLayout extends android.support.constraint.ConstraintLayout {

    private View background;
    private ProgressBar progressBar;

    public ConstraintLayout(Context context) {
        super(context);
        addLoader();
    }

    public ConstraintLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        addLoader();
    }

    public ConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        addLoader();
    }

    private void addLoader(){
        int wrapContent = LayoutParams.WRAP_CONTENT;
        int matchParent = LayoutParams.MATCH_PARENT;

        ConstraintSet constraintSet = new ConstraintSet();
        constraintSet.clone(this);

        background = new View(getContext());
        background.setBackgroundColor(getResources()
                .getColor(R.color.background_loader_color));
        background.setId(generateViewId());
        addView(background, new ConstraintLayout.LayoutParams(matchParent, matchParent));

        constraintSet.connect(background.getId(), ConstraintSet.TOP, 
                ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0);
        constraintSet.connect(background.getId(), ConstraintSet.BOTTOM, 
                ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0);
        constraintSet.connect(background.getId(), ConstraintSet.LEFT, 
                ConstraintSet.PARENT_ID, ConstraintSet.LEFT, 0);
        constraintSet.connect(background.getId(), ConstraintSet.RIGHT, 
                ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 0);

        progressBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleLarge);
        progressBar.setId(generateViewId());
        addView(progressBar, new ConstraintLayout.LayoutParams(wrapContent, wrapContent));

        constraintSet.connect(progressBar.getId(), ConstraintSet.TOP, 
                ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0);
        constraintSet.connect(progressBar.getId(), ConstraintSet.BOTTOM, 
                ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0);
        constraintSet.connect(progressBar.getId(), ConstraintSet.START, 
                ConstraintSet.PARENT_ID, ConstraintSet.START, 0);
        constraintSet.connect(progressBar.getId(), ConstraintSet.END, 
                ConstraintSet.PARENT_ID, ConstraintSet.END, 0);

        constraintSet.applyTo(this);
    }

    public void showLoading(){
        background.setVisibility(VISIBLE);
        progressBar.setVisibility(VISIBLE);
    }

    public void hideLoading(){
        background.setVisibility(GONE);
        progressBar.setVisibility(GONE);
    }
}

Here is what I have img and what I want what i want

like image 409
Dannie Avatar asked May 01 '18 13:05

Dannie


2 Answers

The problem seems to be that you’re setting your Background constraints as MATCH_PARENT which is invalid in ConstraintLayouts. I assume you meant LayoutParams.MATCH_CONSTRAINT.

I assume you want your layout to “simulate” this XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/bkg"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_red_dark"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

Which looks like:

enter image description here

tl;dr: Change the line int matchParent = LayoutParams.MATCH_PARENT; to int matchParent = LayoutParams.MATCH_CONSTRAINT;

UPDATE: I tried my own solution and didn’t work, so I spend a few minutes looking at your code and found the problem. I am using ConstraintLayout 1.1.0

  1. Yes, use MATCH CONSTRAINT.
  2. You are setting constraints for views that don’t yet exist… so I recreated your “custom layout” and here’s mine:

Main Activity just inflates this via setContentView(R.layout.demo_layout)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="@+id/root"
                                             android:layout_width="match_parent"
                                             android:layout_height="match_parent"
                                             tools:context=".MainActivity"
    >
    <com.so.ProgressConstraintLayout
        android:id="@+id/demo_progress_container"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />
</android.support.constraint.ConstraintLayout>

And my ProgressConstraintLayout… which I copied from yours and modified:

package com.so;

import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ProgressBar;

public class ProgressConstraintLayout extends ConstraintLayout {

    private View background;
    private ProgressBar progressBar;

    public ProgressConstraintLayout(Context context) {
        super(context);
        addLoader();
    }

    public ProgressConstraintLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        addLoader();
    }

    public ProgressConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        addLoader();
    }

    private void addLoader() {
        int wrapContent = LayoutParams.WRAP_CONTENT;
        int matchConstraint = LayoutParams.MATCH_CONSTRAINT;

        ConstraintSet constraintSet = new ConstraintSet();

        background = new View(getContext());
        background.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_bright, getContext().getTheme()));
        background.setId(generateViewId());
        addView(background, new ConstraintLayout.LayoutParams(matchConstraint, matchConstraint));

        progressBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleLarge);
        progressBar.setIndeterminate(true);
        progressBar.setId(generateViewId());
        addView(progressBar, new ConstraintLayout.LayoutParams(wrapContent, wrapContent));

        constraintSet.clone(this);
        constraintSet.connect(background.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP);
        constraintSet.connect(background.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM);
        constraintSet.connect(background.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
        constraintSet.connect(background.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
        constraintSet.connect(progressBar.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP);
        constraintSet.connect(progressBar.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM);
        constraintSet.connect(progressBar.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
        constraintSet.connect(progressBar.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
        constraintSet.applyTo(this);
    }

    public void showLoading() {
        background.setVisibility(VISIBLE);
        progressBar.setVisibility(VISIBLE);
    }

    public void hideLoading() {
        background.setVisibility(GONE);
        progressBar.setVisibility(GONE);
    }
}

And if you’re wondering how it looks… pretty boring but who am I to judge: enter image description here

like image 92
Martin Marconcini Avatar answered Sep 24 '22 23:09

Martin Marconcini


There has been a change since 1.1.0-beta5 that now requires code to explicitly set the width and height of views to manually defined a ConstraintLayout and its ConstraintSet. I am not sure exactly the reason, but the code goes as follows:

After connecting background add

    constraintSet.constrainWidth(background.getId(),matchParent);
    constraintSet.constrainHeight(background.getId(),matchParent);

After connecting progressBar add

    constraintSet.constrainWidth(progressBar.getId(),wrapContent);
    constraintSet.constrainHeight(progressBar.getId(),wrapContent);

Without this code, the width and height of the views are not set within the constraints. This code makes sure the width and height are set.

See the documentation for constraining width and height.

like image 22
Cheticamp Avatar answered Sep 24 '22 23:09

Cheticamp