public class

Barrier

extends ConstraintHelper

 java.lang.Object

↳View

androidx.constraintlayout.widget.ConstraintHelper

↳androidx.constraintlayout.widget.Barrier

Gradle dependencies

compile group: 'androidx.constraintlayout', name: 'constraintlayout', version: '2.2.0-alpha01'

  • groupId: androidx.constraintlayout
  • artifactId: constraintlayout
  • version: 2.2.0-alpha01

Artifact androidx.constraintlayout:constraintlayout:2.2.0-alpha01 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.constraintlayout:constraintlayout com.android.support.constraint:constraint-layout

Androidx class mapping:

androidx.constraintlayout.widget.Barrier android.support.constraint.Barrier

Overview

Added in 1.1

A Barrier references multiple widgets as input, and creates a virtual guideline based on the most extreme widget on the specified side. For example, a left barrier will align to the left of all the referenced views.

Example

Let's have two buttons, @id/button1 and @id/button2. The constraint_referenced_ids field will reference them by simply having them as comma-separated list:
     
         
     
     

With the barrier direction set to start, we will have the following result:

Reversely, with the direction set to end, we will have:

If the widgets dimensions change, the barrier will automatically move according to its direction to get the most extreme widget:

Other widgets can then be constrained to the barrier itself, instead of the individual widget. This allows a layout to automatically adapt on widget dimension changes (e.g. different languages will end up with different length for similar worlds).

GONE widgets handling

If the barrier references GONE widgets, the default behavior is to create a barrier on the resolved position of the GONE widget. If you do not want to have the barrier take GONE widgets into account, you can change this by setting the attribute barrierAllowsGoneWidgets to false (default being true).

Summary

Fields
public static final intBOTTOM

Bottom direction constant

public static final intEND

End Barrier constant

public static final intLEFT

Left direction constant

public static final intRIGHT

Right direction constant

public static final intSTART

Start direction constant

public static final intTOP

Top direction constant

from ConstraintHelpermCount, mHelperWidget, mIds[], mMap, mReferenceIds, mReferenceTags, mUseViewMeasure, myContext
Constructors
publicBarrier(Context context)

publicBarrier(Context context, AttributeSet attrs)

publicBarrier(Context context, AttributeSet attrs, int defStyleAttr)

Methods
public booleanallowsGoneWidget()

Find if this barrier supports gone widgets.

public booleangetAllowsGoneWidget()

Find if this barrier supports gone widgets.

public intgetMargin()

Returns the barrier margin

public intgetType()

Get the barrier type (Barrier.LEFT, Barrier.TOP, Barrier.RIGHT, Barrier.BOTTOM, Barrier.END, Barrier.START)

protected voidinit(AttributeSet attrs)

public voidloadParameters(ConstraintSet.Constraint constraint, HelperWidget child, ConstraintLayout.LayoutParams layoutParams, <any> mapIdToWidget)

Load the parameters

public voidresolveRtl(ConstraintWidget widget, boolean isRtl)

resolve the RTL

public voidsetAllowsGoneWidget(boolean supportGone)

allows gone widgets to be included in the barrier

public voidsetDpMargin(int margin)

Set a margin on the barrier

public voidsetMargin(int margin)

Set the barrier margin

public voidsetType(int type)

Set the barrier type (Barrier.LEFT, Barrier.TOP, Barrier.RIGHT, Barrier.BOTTOM, Barrier.END, Barrier.START)

from ConstraintHelperaddView, applyLayoutFeatures, applyLayoutFeatures, applyLayoutFeaturesInConstraintSet, containsId, getReferencedIds, getViews, indexFromId, onAttachedToWindow, onDraw, onMeasure, removeView, setIds, setReferencedIds, setReferenceTags, setTag, updatePostConstraints, updatePostLayout, updatePostMeasure, updatePreDraw, updatePreLayout, updatePreLayout, validateParams
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

public static final int LEFT

Left direction constant

public static final int TOP

Top direction constant

public static final int RIGHT

Right direction constant

public static final int BOTTOM

Bottom direction constant

public static final int START

Start direction constant

public static final int END

End Barrier constant

Constructors

public Barrier(Context context)

public Barrier(Context context, AttributeSet attrs)

public Barrier(Context context, AttributeSet attrs, int defStyleAttr)

Methods

public int getType()

Get the barrier type (Barrier.LEFT, Barrier.TOP, Barrier.RIGHT, Barrier.BOTTOM, Barrier.END, Barrier.START)

public void setType(int type)

Set the barrier type (Barrier.LEFT, Barrier.TOP, Barrier.RIGHT, Barrier.BOTTOM, Barrier.END, Barrier.START)

public void resolveRtl(ConstraintWidget widget, boolean isRtl)

resolve the RTL

Parameters:

widget:
isRtl:

protected void init(AttributeSet attrs)

Parameters:

attrs:

public void setAllowsGoneWidget(boolean supportGone)

allows gone widgets to be included in the barrier

Parameters:

supportGone:

public boolean allowsGoneWidget()

Deprecated: This method should be called getAllowsGoneWidget such that allowsGoneWidget can be accessed as a property from Kotlin; . Use Barrier.getAllowsGoneWidget() instead.

Find if this barrier supports gone widgets.

Returns:

true if this barrier supports gone widgets, otherwise false

public boolean getAllowsGoneWidget()

Find if this barrier supports gone widgets.

Returns:

true if this barrier supports gone widgets, otherwise false

public void setDpMargin(int margin)

Set a margin on the barrier

Parameters:

margin: in dp

public int getMargin()

Returns the barrier margin

Returns:

the barrier margin (in pixels)

public void setMargin(int margin)

Set the barrier margin

Parameters:

margin: in pixels

public void loadParameters(ConstraintSet.Constraint constraint, HelperWidget child, ConstraintLayout.LayoutParams layoutParams, <any> mapIdToWidget)

Load the parameters

Parameters:

constraint:
child:
layoutParams:
mapIdToWidget:

Source

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.constraintlayout.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.View;

import androidx.constraintlayout.core.widgets.ConstraintWidget;
import androidx.constraintlayout.core.widgets.ConstraintWidgetContainer;
import androidx.constraintlayout.core.widgets.HelperWidget;

/**
 * <b>Added in 1.1</b>
 * <p>
 * A Barrier references multiple widgets as input,
 * and creates a virtual guideline based on the most
 * extreme widget on the specified side. For example,
 * a left barrier will align to the left of all the referenced views.
 * </p>
 * <p>
 * <h2>Example</h2>
 *     <p><div align="center" >
 *       <img width="325px" src="resources/images/barrier-buttons.png">
 *     </div>
 *     Let's have two buttons, @id/button1 and @id/button2.
 *     The constraint_referenced_ids field will reference
 *     them by simply having them as comma-separated list:
 *     <pre>
 *     {@code
 *         <androidx.constraintlayout.widget.Barrier
 *              android:id="@+id/barrier"
 *              android:layout_width="wrap_content"
 *              android:layout_height="wrap_content"
 *              app:barrierDirection="start"
 *              app:constraint_referenced_ids="button1,button2" />
 *     }
 *     </pre>
 *     <p>
 *         With the barrier direction set to start, we will have the following result:
 *     <p><div align="center" >
 *       <img width="325px" src="resources/images/barrier-start.png">
 *     </div>
 *     <p>
 *         Reversely, with the direction set to end, we will have:
 *     <p><div align="center" >
 *       <img width="325px" src="resources/images/barrier-end.png">
 *     </div>
 *     <p>
 *         If the widgets dimensions change,
 *         the barrier will automatically move according to its direction to get
 *         the most extreme widget:
 *     <p><div align="center" >
 *       <img width="325px" src="resources/images/barrier-adapt.png">
 *     </div>
 *
 *     <p>
 *         Other widgets can then be constrained to the barrier itself,
 *         instead of the individual widget. This allows a layout
 *         to automatically adapt on widget dimension changes
 *         (e.g. different languages will end up with different length for similar worlds).
 *     </p>
 * <h2>GONE widgets handling</h2>
 * <p>If the barrier references GONE widgets,
 * the default behavior is to create a barrier on the resolved position of the GONE widget.
 * If you do not want to have the barrier take GONE widgets into account,
 * you can change this by setting the attribute <i>barrierAllowsGoneWidgets</i>
 * to false (default being true).</p>
 *     </p>
 * </p>
 *
 */
public class Barrier extends ConstraintHelper {

    /**
     * Left direction constant
     */
    public static final int LEFT = androidx.constraintlayout.core.widgets.Barrier.LEFT;

    /**
     * Top direction constant
     */
    public static final int TOP = androidx.constraintlayout.core.widgets.Barrier.TOP;

    /**
     * Right direction constant
     */
    public static final int RIGHT = androidx.constraintlayout.core.widgets.Barrier.RIGHT;

    /**
     * Bottom direction constant
     */
    public static final int BOTTOM = androidx.constraintlayout.core.widgets.Barrier.BOTTOM;

    /**
     * Start direction constant
     */
    public static final int START = BOTTOM + 2;

    /**
     * End Barrier constant
     */
    public static final int END = START + 1;

    private int mIndicatedType;
    private int mResolvedType;
    private androidx.constraintlayout.core.widgets.Barrier mBarrier;

    public Barrier(Context context) {
        super(context);
        super.setVisibility(View.GONE);
    }

    public Barrier(Context context, AttributeSet attrs) {
        super(context, attrs);
        super.setVisibility(View.GONE);
    }

    public Barrier(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        super.setVisibility(View.GONE);
    }

    /**
     * Get the barrier type ({@code Barrier.LEFT}, {@code Barrier.TOP},
     * {@code Barrier.RIGHT}, {@code Barrier.BOTTOM}, {@code Barrier.END},
     * {@code Barrier.START})
     */
    public int getType() {
        return mIndicatedType;
    }

    /**
     * Set the barrier type ({@code Barrier.LEFT}, {@code Barrier.TOP},
     * {@code Barrier.RIGHT}, {@code Barrier.BOTTOM}, {@code Barrier.END},
     * {@code Barrier.START})
     */
    public void setType(int type) {
        mIndicatedType = type;
    }

    private void updateType(ConstraintWidget widget, int type, boolean isRtl) {
        mResolvedType = type;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            // Pre JB MR1, left/right should take precedence, unless they are
            // not defined and somehow a corresponding start/end constraint exists
            if (mIndicatedType == START) {
                mResolvedType = LEFT;
            } else if (mIndicatedType == END) {
                mResolvedType = RIGHT;
            }
        } else {
            // Post JB MR1, if start/end are defined, they take precedence over left/right
            if (isRtl) {
                if (mIndicatedType == START) {
                    mResolvedType = RIGHT;
                } else if (mIndicatedType == END) {
                    mResolvedType = LEFT;
                }
            } else {
                if (mIndicatedType == START) {
                    mResolvedType = LEFT;
                } else if (mIndicatedType == END) {
                    mResolvedType = RIGHT;
                }
            }
        }
        if (widget instanceof androidx.constraintlayout.core.widgets.Barrier) {
            androidx.constraintlayout.core.widgets.Barrier barrier =
                    (androidx.constraintlayout.core.widgets.Barrier) widget;
            barrier.setBarrierType(mResolvedType);
        }
    }

    @Override
    public void resolveRtl(ConstraintWidget widget, boolean isRtl) {
        updateType(widget, mIndicatedType, isRtl);
    }

    /**
     * @param attrs
     * @DoNotShow
     */
    @Override
    protected void init(AttributeSet attrs) {
        super.init(attrs);
        mBarrier = new androidx.constraintlayout.core.widgets.Barrier();
        if (attrs != null) {
            TypedArray a = getContext().obtainStyledAttributes(attrs,
                    R.styleable.ConstraintLayout_Layout);
            final int count = a.getIndexCount();
            for (int i = 0; i < count; i++) {
                int attr = a.getIndex(i);
                if (attr == R.styleable.ConstraintLayout_Layout_barrierDirection) {
                    setType(a.getInt(attr, LEFT));
                } else if (attr == R.styleable.ConstraintLayout_Layout_barrierAllowsGoneWidgets) {
                    mBarrier.setAllowsGoneWidget(a.getBoolean(attr, true));
                } else if (attr == R.styleable.ConstraintLayout_Layout_barrierMargin) {
                    int margin = a.getDimensionPixelSize(attr, 0);
                    mBarrier.setMargin(margin);
                }
            }
            a.recycle();
        }
        mHelperWidget = mBarrier;
        validateParams();
    }

    /**
     * allows gone widgets to be included in the barrier
     * @param supportGone
     */
    public void setAllowsGoneWidget(boolean supportGone) {
        mBarrier.setAllowsGoneWidget(supportGone);
    }

    /**
     * Find if this barrier supports gone widgets.
     *
     * @return true if this barrier supports gone widgets, otherwise false
     *
     * @deprecated This method should be called
     * {@code getAllowsGoneWidget} such that {@code allowsGoneWidget}
     * can be accessed as a property from Kotlin;
     * {@see https://android.github.io/kotlin-guides/interop.html#property-prefixes}.
     * Use {@link #getAllowsGoneWidget()} instead.
     */
    @Deprecated
    public boolean allowsGoneWidget() {
        return mBarrier.getAllowsGoneWidget();
    }

    /**
     * Find if this barrier supports gone widgets.
     *
     * @return true if this barrier supports gone widgets, otherwise false
     */
    public boolean getAllowsGoneWidget() {
        return mBarrier.getAllowsGoneWidget();
    }

    /**
     * Set a margin on the barrier
     *
     * @param margin in dp
     */
    public void setDpMargin(int margin) {
        float density = getResources().getDisplayMetrics().density;
        int px = (int) (0.5f + margin * density);
        mBarrier.setMargin(px);
    }

    /**
     * Returns the barrier margin
     *
     * @return the barrier margin (in pixels)
     */
    public int getMargin() {
        return mBarrier.getMargin();
    }

    /**
     * Set the barrier margin
     *
     * @param margin in pixels
     */
    public void setMargin(int margin) {
        mBarrier.setMargin(margin);
    }

    @Override
    public void loadParameters(ConstraintSet.Constraint constraint,
                               HelperWidget child,
                               ConstraintLayout.LayoutParams layoutParams,
                               SparseArray<ConstraintWidget> mapIdToWidget) {
        super.loadParameters(constraint, child, layoutParams, mapIdToWidget);
        if (child instanceof androidx.constraintlayout.core.widgets.Barrier) {
            androidx.constraintlayout.core.widgets.Barrier barrier =
                    (androidx.constraintlayout.core.widgets.Barrier) child;
            ConstraintWidgetContainer container = (ConstraintWidgetContainer) child.getParent();
            boolean isRtl = container.isRtl();
            updateType(barrier, constraint.layout.mBarrierDirection, isRtl);
            barrier.setAllowsGoneWidget(constraint.layout.mBarrierAllowsGoneWidgets);
            barrier.setMargin(constraint.layout.mBarrierMargin);
        }
    }
}