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 and what I want
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:
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
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:
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.
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