public class

WidgetGroup

extends java.lang.Object

 java.lang.Object

↳androidx.constraintlayout.core.widgets.analyzer.WidgetGroup

Gradle dependencies

compile group: 'androidx.constraintlayout', name: 'constraintlayout-core', version: '1.1.0-beta01'

  • groupId: androidx.constraintlayout
  • artifactId: constraintlayout-core
  • version: 1.1.0-beta01

Artifact androidx.constraintlayout:constraintlayout-core:1.1.0-beta01 it located at Google repository (https://maven.google.com/)

Overview

Represents a group of widget for the grouping mechanism.

Summary

Constructors
publicWidgetGroup(int orientation)

Methods
public booleanadd(ConstraintWidget widget)

public voidapply()

public voidcleanup(java.util.ArrayList<WidgetGroup> dependencyLists)

public voidclear()

public intgetId()

public intgetOrientation()

public booleanintersectWith(WidgetGroup group)

public booleanisAuthoritative()

public intmeasureWrap(LinearSystem system, int orientation)

public voidmoveTo(int orientation, WidgetGroup widgetGroup)

public voidsetAuthoritative(boolean isAuthoritative)

public voidsetOrientation(int orientation)

public intsize()

public java.lang.StringtoString()

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Constructors

public WidgetGroup(int orientation)

Methods

public int getOrientation()

public int getId()

public boolean add(ConstraintWidget widget)

public void setAuthoritative(boolean isAuthoritative)

public boolean isAuthoritative()

public java.lang.String toString()

public void moveTo(int orientation, WidgetGroup widgetGroup)

public void clear()

public int measureWrap(LinearSystem system, int orientation)

public void setOrientation(int orientation)

public void apply()

public boolean intersectWith(WidgetGroup group)

public int size()

public void cleanup(java.util.ArrayList<WidgetGroup> dependencyLists)

Source

/*
 * Copyright (C) 2020 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.core.widgets.analyzer;

import static androidx.constraintlayout.core.widgets.ConstraintWidget.BOTH;
import static androidx.constraintlayout.core.widgets.ConstraintWidget.HORIZONTAL;
import static androidx.constraintlayout.core.widgets.ConstraintWidget.VERTICAL;

import androidx.constraintlayout.core.LinearSystem;
import androidx.constraintlayout.core.widgets.Chain;
import androidx.constraintlayout.core.widgets.ConstraintWidget;
import androidx.constraintlayout.core.widgets.ConstraintWidgetContainer;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Represents a group of widget for the grouping mechanism.
 */
public class WidgetGroup {
    private static final boolean DEBUG = false;
    ArrayList<ConstraintWidget> mWidgets = new ArrayList<>();
    static int sCount = 0;
    int mId = -1;
    boolean mAuthoritative = false;
    int mOrientation = HORIZONTAL;
    ArrayList<MeasureResult> mResults = null;
    private int mMoveTo = -1;

    public WidgetGroup(int orientation) {
        mId = sCount++;
        this.mOrientation = orientation;
    }

    public int getOrientation() {
        return mOrientation;
    }

    public int getId() {
        return mId;
    }

    // @TODO: add description
    public boolean add(ConstraintWidget widget) {
        if (mWidgets.contains(widget)) {
            return false;
        }
        mWidgets.add(widget);
        return true;
    }

    public void setAuthoritative(boolean isAuthoritative) {
        mAuthoritative = isAuthoritative;
    }

    public boolean isAuthoritative() {
        return mAuthoritative;
    }

    private String getOrientationString() {
        if (mOrientation == HORIZONTAL) {
            return "Horizontal";
        } else if (mOrientation == VERTICAL) {
            return "Vertical";
        } else if (mOrientation == BOTH) {
            return "Both";
        }
        return "Unknown";
    }

    @Override
    public String toString() {
        String ret = getOrientationString() + " [" + mId + "] <";
        for (ConstraintWidget widget : mWidgets) {
            ret += " " + widget.getDebugName();
        }
        ret += " >";
        return ret;
    }

    // @TODO: add description
    public void moveTo(int orientation, WidgetGroup widgetGroup) {
        if (DEBUG) {
            System.out.println("Move all widgets (" + this + ") from "
                    + mId + " to " + widgetGroup.getId() + "(" + widgetGroup + ")");
            System.out.println("" +
                    "do not call  "+ measureWrap(  orientation, new ConstraintWidget()));
        }
        for (ConstraintWidget widget : mWidgets) {
            widgetGroup.add(widget);
            if (orientation == HORIZONTAL) {
                widget.horizontalGroup = widgetGroup.getId();
            } else {
                widget.verticalGroup = widgetGroup.getId();
            }
        }
        mMoveTo = widgetGroup.mId;
    }

    // @TODO: add description
    public void clear() {
        mWidgets.clear();
    }

    private int measureWrap(int orientation, ConstraintWidget widget) {
        ConstraintWidget.DimensionBehaviour behaviour = widget.getDimensionBehaviour(orientation);
        if (behaviour == ConstraintWidget.DimensionBehaviour.WRAP_CONTENT
                || behaviour == ConstraintWidget.DimensionBehaviour.MATCH_PARENT
                || behaviour == ConstraintWidget.DimensionBehaviour.FIXED) {
            int dimension;
            if (orientation == HORIZONTAL) {
                dimension = widget.getWidth();
            } else {
                dimension = widget.getHeight();
            }
            return dimension;
        }
        return -1;
    }

    // @TODO: add description
    public int measureWrap(LinearSystem system, int orientation) {
        int count = mWidgets.size();
        if (count == 0) {
            return 0;
        }
        // TODO: add direct wrap computation for simpler cases instead of calling the solver
        return solverMeasure(system, mWidgets, orientation);
    }

    private int solverMeasure(LinearSystem system,
            ArrayList<ConstraintWidget> widgets,
            int orientation) {
        ConstraintWidgetContainer container =
                (ConstraintWidgetContainer) widgets.get(0).getParent();
        system.reset();
        @SuppressWarnings("unused") boolean prevDebug = LinearSystem.FULL_DEBUG;
        container.addToSolver(system, false);
        for (int i = 0; i < widgets.size(); i++) {
            ConstraintWidget widget = widgets.get(i);
            widget.addToSolver(system, false);
        }
        if (orientation == HORIZONTAL) {
            if (container.mHorizontalChainsSize > 0) {
                Chain.applyChainConstraints(container, system, widgets, HORIZONTAL);
            }
        }
        if (orientation == VERTICAL) {
            if (container.mVerticalChainsSize > 0) {
                Chain.applyChainConstraints(container, system, widgets, VERTICAL);
            }
        }

        try {
            system.minimize();
        } catch (Exception e) {
            //TODO remove fancy version of e.printStackTrace()
            System.err.println(e.toString()+"\n"+Arrays.toString(e.getStackTrace())
                    .replace("[","   at ")
                    .replace(",","\n   at")
                    .replace("]",""));
        }

        // save results
        mResults = new ArrayList<>();
        for (int i = 0; i < widgets.size(); i++) {
            ConstraintWidget widget = widgets.get(i);
            MeasureResult result = new MeasureResult(widget, system, orientation);
            mResults.add(result);
        }

        if (orientation == HORIZONTAL) {
            int left = system.getObjectVariableValue(container.mLeft);
            int right = system.getObjectVariableValue(container.mRight);
            system.reset();
            return right - left;
        } else {
            int top = system.getObjectVariableValue(container.mTop);
            int bottom = system.getObjectVariableValue(container.mBottom);
            system.reset();
            return bottom - top;
        }
    }

    public void setOrientation(int orientation) {
        this.mOrientation = orientation;
    }

    // @TODO: add description
    public void apply() {
        if (mResults == null) {
            return;
        }
        if (!mAuthoritative) {
            return;
        }
        for (int i = 0; i < mResults.size(); i++) {
            MeasureResult result = mResults.get(i);
            result.apply();
        }
    }

    // @TODO: add description
    public boolean intersectWith(WidgetGroup group) {
        for (int i = 0; i < mWidgets.size(); i++) {
            ConstraintWidget widget = mWidgets.get(i);
            if (group.contains(widget)) {
                return true;
            }
        }
        return false;
    }

    private boolean contains(ConstraintWidget widget) {
        return mWidgets.contains(widget);
    }

    // @TODO: add description
    public int size() {
        return mWidgets.size();
    }

    // @TODO: add description
    public void cleanup(ArrayList<WidgetGroup> dependencyLists) {
        final int count = mWidgets.size();
        if (mMoveTo != -1 && count > 0) {
            for (int i = 0; i < dependencyLists.size(); i++) {
                WidgetGroup group = dependencyLists.get(i);
                if (mMoveTo == group.mId) {
                    moveTo(mOrientation, group);
                }
            }
        }
        if (count == 0) {
            dependencyLists.remove(this);
            return;
        }
    }


    static class MeasureResult {
        WeakReference<ConstraintWidget> mWidgetRef;
        int mLeft;
        int mTop;
        int mRight;
        int mBottom;
        int mBaseline;
        int mOrientation;

        MeasureResult(ConstraintWidget widget, LinearSystem system, int orientation) {
            mWidgetRef = new WeakReference<>(widget);
            mLeft = system.getObjectVariableValue(widget.mLeft);
            mTop = system.getObjectVariableValue(widget.mTop);
            mRight = system.getObjectVariableValue(widget.mRight);
            mBottom = system.getObjectVariableValue(widget.mBottom);
            mBaseline = system.getObjectVariableValue(widget.mBaseline);
            this.mOrientation = orientation;
        }

        public void apply() {
            ConstraintWidget widget = mWidgetRef.get();
            if (widget != null) {
                widget.setFinalFrame(mLeft, mTop, mRight, mBottom, mBaseline, mOrientation);
            }
        }
    }
}