/*
* Copyright (C) 2018 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.os.Build;
import android.view.View;
import android.view.ViewGroup;
/**
* <b>Added in 2.0</b>
* <p>
* ConstraintProperties provides an easy to use api to update the layout params
* of {@link ConstraintLayout} children
* </p>
*/
public class ConstraintProperties {
ConstraintLayout.LayoutParams mParams;
View mView;
/**
* The left side of a view.
*/
public static final int LEFT = ConstraintLayout.LayoutParams.LEFT;
/**
* The right side of a view.
*/
public static final int RIGHT = ConstraintLayout.LayoutParams.RIGHT;
/**
* The top of a view.
*/
public static final int TOP = ConstraintLayout.LayoutParams.TOP;
/**
* The bottom side of a view.
*/
public static final int BOTTOM = ConstraintLayout.LayoutParams.BOTTOM;
/**
* The baseline of the text in a view.
*/
public static final int BASELINE = ConstraintLayout.LayoutParams.BASELINE;
/**
* The left side of a view in left to right languages.
* In right to left languages it corresponds to the right side of the view
*/
public static final int START = ConstraintLayout.LayoutParams.START;
/**
* The right side of a view in right to left languages.
* In right to left languages it corresponds to the left side of the view
*/
public static final int END = ConstraintLayout.LayoutParams.END;
/**
* Used to indicate a parameter is cleared or not set
*/
public static final int UNSET = ConstraintLayout.LayoutParams.UNSET;
/**
* References the id of the parent.
*/
public static final int PARENT_ID = ConstraintLayout.LayoutParams.PARENT_ID;
/**
* Dimension will be controlled by constraints
*/
public static final int MATCH_CONSTRAINT = ConstraintLayout.LayoutParams.MATCH_CONSTRAINT;
/**
* Dimension will set by the view's content
*/
public static final int WRAP_CONTENT = ConstraintLayout.LayoutParams.WRAP_CONTENT;
/**
* How to calculate the size of a view in 0 dp by using its wrap_content size
*/
public static final int MATCH_CONSTRAINT_WRAP = ConstraintLayout.LayoutParams.MATCH_CONSTRAINT_WRAP;
/**
* Calculate the size of a view in 0 dp by reducing the constrains gaps as much as possible
*/
public static final int MATCH_CONSTRAINT_SPREAD = ConstraintLayout.LayoutParams.MATCH_CONSTRAINT_SPREAD;
/**
* Center view between the other two widgets.
*
* @param firstID ID of the first widget to connect the left or top of the widget to
* @param firstSide the side of the widget to connect to
* @param firstMargin the connection margin
* @param secondId the ID of the second widget to connect to right or top of the widget to
* @param secondSide the side of the widget to connect to
* @param secondMargin the connection margin
* @param bias the ratio between two connections
* @return this
*/
public ConstraintProperties center(int firstID, int firstSide, int firstMargin, int secondId, int secondSide, int secondMargin, float bias) {
// Error checking
if (firstMargin < 0) {
throw new IllegalArgumentException("margin must be > 0");
}
if (secondMargin < 0) {
throw new IllegalArgumentException("margin must be > 0");
}
if (bias <= 0 || bias > 1) {
throw new IllegalArgumentException("bias must be between 0 and 1 inclusive");
}
if (firstSide == LEFT || firstSide == RIGHT) {
connect(LEFT, firstID, firstSide, firstMargin);
connect(RIGHT, secondId, secondSide, secondMargin);
mParams.horizontalBias = bias;
} else if (firstSide == START || firstSide == END) {
connect(START, firstID, firstSide, firstMargin);
connect(END, secondId, secondSide, secondMargin);
mParams.horizontalBias = bias;
} else {
connect(TOP, firstID, firstSide, firstMargin);
connect(BOTTOM, secondId, secondSide, secondMargin);
mParams.verticalBias = bias;
}
return this;
}
/**
* Centers the widget horizontally to the left and right side on another widgets sides.
*
* @param leftId The Id of the widget on the left side
* @param leftSide The side of the leftId widget to connect to
* @param leftMargin The margin on the left side
* @param rightId The Id of the widget on the right side
* @param rightSide The side of the rightId widget to connect to
* @param rightMargin The margin on the right side
* @param bias The ratio of the space on the left vs. right sides 0.5 is centered (default)
* @return this
*/
public ConstraintProperties centerHorizontally(int leftId, int leftSide, int leftMargin, int rightId, int rightSide, int rightMargin, float bias) {
connect(LEFT, leftId, leftSide, leftMargin);
connect(RIGHT, rightId, rightSide, rightMargin);
mParams.horizontalBias = bias;
return this;
}
/**
* Centers the widgets horizontally to the left and right side on another widgets sides.
*
* @param startId The Id of the widget on the start side (left in non rtl languages)
* @param startSide The side of the startId widget to connect to
* @param startMargin The margin on the start side
* @param endId The Id of the widget on the start side (left in non rtl languages)
* @param endSide The side of the endId widget to connect to
* @param endMargin The margin on the end side
* @param bias The ratio of the space on the start vs end side 0.5 is centered (default)
* @return this
*/
public ConstraintProperties centerHorizontallyRtl(int startId, int startSide, int startMargin, int endId, int endSide, int endMargin, float bias) {
connect(START, startId, startSide, startMargin);
connect(END, endId, endSide, endMargin);
mParams.horizontalBias = bias;
return this;
}
/**
* Centers the widgets Vertically to the top and bottom side on another widgets sides.
*
* @param topId The Id of the widget on the top side
* @param topSide The side of the leftId widget to connect to
* @param topMargin The margin on the top side
* @param bottomId The Id of the widget on the bottom side
* @param bottomSide The side of the bottomId widget to connect to
* @param bottomMargin The margin on the bottom side
* @param bias The ratio of the space on the top vs. bottom sides 0.5 is centered (default)
* @return this
*/
public ConstraintProperties centerVertically(int topId, int topSide, int topMargin, int bottomId, int bottomSide, int bottomMargin, float bias) {
connect(TOP, topId, topSide, topMargin);
connect(BOTTOM, bottomId, bottomSide, bottomMargin);
mParams.verticalBias = bias;
return this;
}
/**
* Centers the view horizontally relative to toView's position.
*
* @param toView ID of view to center on (or in)
* @return this
*/
public ConstraintProperties centerHorizontally(int toView) {
if (toView == PARENT_ID) {
center(PARENT_ID, ConstraintSet.LEFT, 0, PARENT_ID, ConstraintSet.RIGHT, 0, 0.5f);
} else {
center(toView, ConstraintSet.RIGHT, 0, toView, ConstraintSet.LEFT, 0, 0.5f);
}
return this;
}
/**
* Centers the view horizontally relative to toView's position.
*
* @param toView ID of view to center on (or in)
* @return this
*/
public ConstraintProperties centerHorizontallyRtl(int toView) {
if (toView == PARENT_ID) {
center(PARENT_ID, ConstraintSet.START, 0, PARENT_ID, ConstraintSet.END, 0, 0.5f);
} else {
center(toView, ConstraintSet.END, 0, toView, ConstraintSet.START, 0, 0.5f);
}
return this;
}
/**
* Centers the view vertically relative to toView's position.
*
* @param toView ID of view to center on (or in)
* @return this
*/
public ConstraintProperties centerVertically(int toView) {
if (toView == PARENT_ID) {
center(PARENT_ID, ConstraintSet.TOP, 0, PARENT_ID, ConstraintSet.BOTTOM, 0, 0.5f);
} else {
center(toView, ConstraintSet.BOTTOM, 0, toView, ConstraintSet.TOP, 0, 0.5f);
}
return this;
}
/**
* Remove a constraint from this view.
*
* @param anchor the Anchor to remove constraint from
* @return this
*/
public ConstraintProperties removeConstraints(int anchor) {
switch (anchor) {
case LEFT:
mParams.leftToRight = mParams.UNSET;
mParams.leftToLeft = mParams.UNSET;
mParams.leftMargin = mParams.UNSET;
mParams.goneLeftMargin = mParams.GONE_UNSET;
break;
case RIGHT:
mParams.rightToRight = mParams.UNSET;
mParams.rightToLeft = mParams.UNSET;
mParams.rightMargin = mParams.UNSET;
mParams.goneRightMargin = mParams.GONE_UNSET;
break;
case TOP:
mParams.topToBottom = mParams.UNSET;
mParams.topToTop = mParams.UNSET;
mParams.topMargin = mParams.UNSET;
mParams.goneTopMargin = mParams.GONE_UNSET;
break;
case BOTTOM:
mParams.bottomToTop = mParams.UNSET;
mParams.bottomToBottom = mParams.UNSET;
mParams.bottomMargin = mParams.UNSET;
mParams.goneBottomMargin = mParams.GONE_UNSET;
break;
case BASELINE:
mParams.baselineToBaseline = mParams.UNSET;
break;
case START:
mParams.startToEnd = mParams.UNSET;
mParams.startToStart = mParams.UNSET;
mParams.setMarginStart(mParams.UNSET);
mParams.goneStartMargin = mParams.GONE_UNSET;
break;
case END:
mParams.endToStart = mParams.UNSET;
mParams.endToEnd = mParams.UNSET;
mParams.setMarginEnd(mParams.UNSET);
mParams.goneEndMargin = mParams.GONE_UNSET;
break;
default:
throw new IllegalArgumentException("unknown constraint");
}
return this;
}
/**
* Sets the margin.
*
* @param anchor The side to adjust the margin on
* @param value The new value for the margin
* @return this
*/
public ConstraintProperties margin(int anchor, int value) {
switch (anchor) {
case LEFT:
mParams.leftMargin = value;
break;
case RIGHT:
mParams.rightMargin = value;
break;
case TOP:
mParams.topMargin = value;
break;
case BOTTOM:
mParams.bottomMargin = value;
break;
case BASELINE:
throw new IllegalArgumentException("baseline does not support margins");
case START:
mParams.setMarginStart(value);
break;
case END:
mParams.setMarginEnd(value);
break;
default:
throw new IllegalArgumentException("unknown constraint");
}
return this;
}
/**
* Sets the gone margin.
*
* @param anchor The side to adjust the margin on
* @param value The new value for the margin
* @return this
*/
public ConstraintProperties goneMargin(int anchor, int value) {
switch (anchor) {
case LEFT:
mParams.goneLeftMargin = value;
break;
case RIGHT:
mParams.goneRightMargin = value;
break;
case TOP:
mParams.goneTopMargin = value;
break;
case BOTTOM:
mParams.goneBottomMargin = value;
break;
case BASELINE:
throw new IllegalArgumentException("baseline does not support margins");
case START:
mParams.goneStartMargin = value;
break;
case END:
mParams.goneEndMargin = value;
break;
default:
throw new IllegalArgumentException("unknown constraint");
}
return this;
}
/**
* Adjust the horizontal bias of the view (used with views constrained on left and right).
*
* @param bias the new bias 0.5 is in the middle
* @return this
*/
public ConstraintProperties horizontalBias(float bias) {
mParams.horizontalBias = bias;
return this;
}
/**
* Adjust the vertical bias of the view (used with views constrained on left and right).
*
* @param bias the new bias 0.5 is in the middle
* @return this
*/
public ConstraintProperties verticalBias(float bias) {
mParams.verticalBias = bias;
return this;
}
/**
* Constrains the views aspect ratio.
* For Example a HD screen is 16 by 9 = 16/(float)9 = 1.777f.
*
* @param ratio The ratio of the width to height (width / height)
* @return this
*/
public ConstraintProperties dimensionRatio(String ratio) {
mParams.dimensionRatio = ratio;
return this;
}
/**
* Adjust the visibility of a view.
*
* @param visibility the visibility (View.VISIBLE, View.INVISIBLE, View.GONE)
* @return this
*/
public ConstraintProperties visibility(int visibility) {
mView.setVisibility(visibility);
return this;
}
/**
* Adjust the alpha of a view.
*
* @param alpha the alpha
* @return this
*/
public ConstraintProperties alpha(float alpha) {
mView.setAlpha(alpha);
return this;
}
/**
* Set the elevation of a view.
*
* @param elevation the elevation
* @return this
*/
public ConstraintProperties elevation(float elevation) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mView.setElevation(elevation);
}
return this;
}
/**
* Adjust the post-layout rotation about the Z axis of a view.
*
* @param rotation the rotation about the Z axis
* @return this
*/
public ConstraintProperties rotation(float rotation) {
mView.setRotation(rotation);
return this;
}
/**
* Adjust the post-layout rotation about the X axis of a view.
*
* @param rotationX the rotation about the X axis
* @return this
*/
public ConstraintProperties rotationX(float rotationX) {
mView.setRotationX(rotationX);
return this;
}
/**
* Adjust the post-layout rotation about the Y axis of a view.
*
* @param rotationY the rotation about the Y axis
* @return this
*/
public ConstraintProperties rotationY(float rotationY) {
mView.setRotationY(rotationY);
return this;
}
/**
* Adjust the post-layout scale in X of a view.
*
* @param scaleX the scale in X
* @return this
*/
public ConstraintProperties scaleX(float scaleX) {
mView.setScaleY(scaleX);
return this;
}
/**
* Adjust the post-layout scale in Y of a view.
*
* @param scaleY the scale in Y
* @return this
*/
public ConstraintProperties scaleY(float scaleY) {
return this;
}
/**
* Set X location of the pivot point around which the view will rotate and scale.
*
* @param transformPivotX X location of the pivot point.
* @return this
*/
public ConstraintProperties transformPivotX(float transformPivotX) {
mView.setPivotX(transformPivotX);
return this;
}
/**
* Set Y location of the pivot point around which the view will rotate and scale.
*
* @param transformPivotY Y location of the pivot point.
* @return this
*/
public ConstraintProperties transformPivotY(float transformPivotY) {
mView.setPivotY(transformPivotY);
return this;
}
/**
* Set X and Y location of the pivot point around which the view will rotate and scale.
*
* @param transformPivotX X location of the pivot point.
* @param transformPivotY Y location of the pivot point.
* @return this
*/
public ConstraintProperties transformPivot(float transformPivotX, float transformPivotY) {
mView.setPivotX(transformPivotX);
mView.setPivotY(transformPivotY);
return this;
}
/**
* Adjust the post-layout X translation of a view.
*
* @param translationX the translation in X
* @return this
*/
public ConstraintProperties translationX(float translationX) {
mView.setTranslationX(translationX);
return this;
}
/**
* Adjust the post-layout Y translation of a view.
*
* @param translationY the translation in Y
* @return this
*/
public ConstraintProperties translationY(float translationY) {
mView.setTranslationY(translationY);
return this;
}
/**
* Adjust the post-layout X and Y translation of a view.
*
* @param translationX the translation in X
* @param translationY the translation in Y
* @return this
*/
public ConstraintProperties translation(float translationX, float translationY) {
mView.setTranslationX(translationX);
mView.setTranslationY(translationY);
return this;
}
/**
* Adjust the post-layout translation in Z of a view. This is the preferred way to adjust the shadow.
*
* @param translationZ the translationZ
* @return this
*/
public ConstraintProperties translationZ(float translationZ) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mView.setTranslationZ(translationZ);
}
return this;
}
/**
* Sets the height of the view.
*
* @param height the height of the view
* @return this
*/
public ConstraintProperties constrainHeight(int height) {
mParams.height = height;
return this;
}
/**
* Sets the width of the view.
*
* @param width the width of the view
* @return this
*/
public ConstraintProperties constrainWidth(int width) {
mParams.width = width;
return this;
}
/**
* Sets the maximum height of the view. It is a dimension, It is only applicable if height is
* #MATCH_CONSTRAINT}.
*
* @param height the maximum height of the view
* @return this
*/
public ConstraintProperties constrainMaxHeight(int height) {
mParams.matchConstraintMaxHeight = height;
return this;
}
/**
* Sets the maximum width of the view. It is a dimension, It is only applicable if height is
* #MATCH_CONSTRAINT}.
*
* @param width the maximum width of the view
* @return this
*/
public ConstraintProperties constrainMaxWidth(int width) {
mParams.matchConstraintMaxWidth = width;
return this;
}
/**
* Sets the minimum height of the view. It is a dimension, It is only applicable if height is
* #MATCH_CONSTRAINT}.
*
* @param height the minimum height of the view
* @return this
*/
public ConstraintProperties constrainMinHeight(int height) {
mParams.matchConstraintMinHeight = height;
return this;
}
/**
* Sets the minimum width of the view. It is a dimension, It is only applicable if height is
* #MATCH_CONSTRAINT}.
*
* @param width the minimum width of the view
* @return this
*/
public ConstraintProperties constrainMinWidth(int width) {
mParams.matchConstraintMinWidth = width;
return this;
}
/**
* Sets how the height is calculated ether MATCH_CONSTRAINT_WRAP or MATCH_CONSTRAINT_SPREAD.
* Default is spread.
*
* @param height MATCH_CONSTRAINT_WRAP or MATCH_CONSTRAINT_SPREAD
* @return this
*/
public ConstraintProperties constrainDefaultHeight(int height) {
mParams.matchConstraintDefaultHeight = height;
return this;
}
/**
* Sets how the width is calculated ether MATCH_CONSTRAINT_WRAP or MATCH_CONSTRAINT_SPREAD.
* Default is spread.
*
* @param width MATCH_CONSTRAINT_WRAP or MATCH_CONSTRAINT_SPREAD
* @return this
*/
public ConstraintProperties constrainDefaultWidth(int width) {
mParams.matchConstraintDefaultWidth = width;
return this;
}
/**
* The child's weight that we can use to distribute the available horizontal space
* in a chain, if the dimension behaviour is set to MATCH_CONSTRAINT
*
* @param weight the weight that we can use to distribute the horizontal space
* @return this
*/
public ConstraintProperties horizontalWeight(float weight) {
mParams.horizontalWeight = weight;
return this;
}
/**
* The child's weight that we can use to distribute the available vertical space
* in a chain, if the dimension behaviour is set to MATCH_CONSTRAINT
*
* @param weight the weight that we can use to distribute the vertical space
* @return this
*/
public ConstraintProperties verticalWeight(float weight) {
mParams.verticalWeight = weight;
return this;
}
/**
* How the elements of the horizontal chain will be positioned. If the dimension
* behaviour is set to MATCH_CONSTRAINT. The possible values are:
* <p>
* <ul>
* <li>CHAIN_SPREAD -- the elements will be spread out</li>
* <li>CHAIN_SPREAD_INSIDE -- similar, but the endpoints of the chain will not be spread out</li>
* <li>CHAIN_PACKED -- the elements of the chain will be packed together. The horizontal
* bias attribute of the child will then affect the positioning of the packed elements</li>
* </ul>
*
* @param chainStyle the weight that we can use to distribute the horizontal space
* @return this
*/
public ConstraintProperties horizontalChainStyle(int chainStyle) {
mParams.horizontalChainStyle = chainStyle;
return this;
}
/**
* How the elements of the vertical chain will be positioned. in a chain, if the dimension
* behaviour is set to MATCH_CONSTRAINT
* <p>
* <ul>
* <li>CHAIN_SPREAD -- the elements will be spread out</li>
* <li>CHAIN_SPREAD_INSIDE -- similar, but the endpoints of the chain will not be spread out</li>
* <li>CHAIN_PACKED -- the elements of the chain will be packed together. The horizontal
* bias attribute of the child will then affect the positioning of the packed elements</li>
* </ul>
*
* @param chainStyle the weight that we can use to distribute the horizontal space
* @return this
*/
public ConstraintProperties verticalChainStyle(int chainStyle) {
mParams.verticalChainStyle = chainStyle;
return this;
}
/**
* Adds the view to a horizontal chain.
*
* @param leftId id of the view in chain to the left
* @param rightId id of the view in chain to the right
* @return this
*/
public ConstraintProperties addToHorizontalChain(int leftId, int rightId) {
connect(LEFT, leftId, (leftId == PARENT_ID) ? LEFT : RIGHT, 0);
connect(RIGHT, rightId, (rightId == PARENT_ID) ? RIGHT : LEFT, 0);
if (leftId != PARENT_ID) {
View leftView = ((ViewGroup) (mView.getParent())).findViewById(leftId);
ConstraintProperties leftProp = new ConstraintProperties(leftView);
leftProp.connect(RIGHT, mView.getId(), LEFT, 0);
}
if (rightId != PARENT_ID) {
View rightView = ((ViewGroup) (mView.getParent())).findViewById(rightId);
ConstraintProperties rightProp = new ConstraintProperties(rightView);
rightProp.connect(LEFT, mView.getId(), RIGHT, 0);
}
return this;
}
/**
* Adds the view to a horizontal chain using RTL attributes.
*
* @param leftId id of the view in chain to the left
* @param rightId id of the view in chain to the right
* @return this
*/
public ConstraintProperties addToHorizontalChainRTL(int leftId, int rightId) {
connect(START, leftId, (leftId == PARENT_ID) ? START : END, 0);
connect(END, rightId, (rightId == PARENT_ID) ? END : START, 0);
if (leftId != PARENT_ID) {
View leftView = ((ViewGroup) (mView.getParent())).findViewById(leftId);
ConstraintProperties leftProp = new ConstraintProperties(leftView);
leftProp.connect(END, mView.getId(), START, 0);
}
if (rightId != PARENT_ID) {
View rightView = ((ViewGroup) (mView.getParent())).findViewById(rightId);
ConstraintProperties rightProp = new ConstraintProperties(rightView);
rightProp.connect(START, mView.getId(), END, 0);
}
return this;
}
/**
* Adds a view to a vertical chain.
*
* @param topId view above.
* @param bottomId view below
* @return this
*/
public ConstraintProperties addToVerticalChain(int topId, int bottomId) {
connect(TOP, topId, (topId == PARENT_ID) ? TOP : BOTTOM, 0);
connect(BOTTOM, bottomId, (bottomId == PARENT_ID) ? BOTTOM : TOP, 0);
if (topId != PARENT_ID) {
View topView = ((ViewGroup) (mView.getParent())).findViewById(topId);
ConstraintProperties topProp = new ConstraintProperties(topView);
topProp.connect(BOTTOM, mView.getId(), TOP, 0);
}
if (bottomId != PARENT_ID) {
View bottomView = ((ViewGroup) (mView.getParent())).findViewById(bottomId);
ConstraintProperties bottomProp = new ConstraintProperties(bottomView);
bottomProp.connect(TOP, mView.getId(), BOTTOM, 0);
}
return this;
}
/**
* Removes a view from a vertical chain.
* This assumes the view is connected to a vertical chain.
* Its behaviour is undefined if not part of a vertical chain.
*
* @return this
*/
public ConstraintProperties removeFromVerticalChain() {
int topId = mParams.topToBottom;
int bottomId = mParams.bottomToTop;
if (topId != mParams.UNSET || bottomId != mParams.UNSET) {
View topView = ((ViewGroup) (mView.getParent())).findViewById(topId);
ConstraintProperties topProp = new ConstraintProperties(topView);
View bottomView = ((ViewGroup) (mView.getParent())).findViewById(bottomId);
ConstraintProperties bottomProp = new ConstraintProperties(bottomView);
if (topId != mParams.UNSET && bottomId != mParams.UNSET) {
// top and bottom connected to views
topProp.connect(BOTTOM, bottomId, TOP, 0);
bottomProp.connect(TOP, topId, BOTTOM, 0);
} else if (topId != mParams.UNSET || bottomId != mParams.UNSET) {
if (mParams.bottomToBottom != mParams.UNSET) {
// top connected to view. Bottom connected to parent
topProp.connect(BOTTOM, mParams.bottomToBottom, BOTTOM, 0);
} else if (mParams.topToTop != mParams.UNSET) {
// bottom connected to view. Top connected to parent
bottomProp.connect(TOP, mParams.topToTop, TOP, 0);
}
}
}
removeConstraints(TOP);
removeConstraints(BOTTOM);
return this;
}
/**
* Removes a view from a vertical chain.
* This assumes the view is connected to a vertical chain.
* Its behaviour is undefined if not part of a vertical chain.
*
* @return this
*/
public ConstraintProperties removeFromHorizontalChain() {
int leftId = mParams.leftToRight;
int rightId = mParams.rightToLeft;
if (leftId != mParams.UNSET || rightId != mParams.UNSET) {
View leftView = ((ViewGroup) (mView.getParent())).findViewById(leftId);
ConstraintProperties leftProp = new ConstraintProperties(leftView);
View rightView = ((ViewGroup) (mView.getParent())).findViewById(rightId);
ConstraintProperties rightProp = new ConstraintProperties(rightView);
if (leftId != mParams.UNSET && rightId != mParams.UNSET) {
// left and right connected to views
leftProp.connect(RIGHT, rightId, LEFT, 0);
rightProp.connect(LEFT, leftId, RIGHT, 0);
} else if (leftId != mParams.UNSET || rightId != mParams.UNSET) {
if (mParams.rightToRight != mParams.UNSET) {
// left connected to view. right connected to parent
leftProp.connect(RIGHT, mParams.rightToRight, RIGHT, 0);
} else if (mParams.leftToLeft != mParams.UNSET) {
// right connected to view. left connected to parent
rightProp.connect(LEFT, mParams.leftToLeft, LEFT, 0);
}
}
removeConstraints(LEFT);
removeConstraints(RIGHT);
} else {
int startId = mParams.startToEnd;
int endId = mParams.endToStart;
if (startId != mParams.UNSET || endId != mParams.UNSET) {
View startView = ((ViewGroup) (mView.getParent())).findViewById(startId);
ConstraintProperties startProp = new ConstraintProperties(startView);
View endView = ((ViewGroup) (mView.getParent())).findViewById(endId);
ConstraintProperties endProp = new ConstraintProperties(endView);
if (startId != mParams.UNSET && endId != mParams.UNSET) {
// start and end connected to views
startProp.connect(END, endId, START, 0);
endProp.connect(START, leftId, END, 0);
} else if (leftId != mParams.UNSET || endId != mParams.UNSET) {
if (mParams.rightToRight != mParams.UNSET) {
// left connected to view. right connected to parent
startProp.connect(END, mParams.rightToRight, END, 0);
} else if (mParams.leftToLeft != mParams.UNSET) {
// right connected to view. left connected to parent
endProp.connect(START, mParams.leftToLeft, START, 0);
}
}
}
removeConstraints(START);
removeConstraints(END);
}
return this;
}
/**
* Create a constraint between two widgets.
*
* @param startSide the side of the widget to constrain
* @param endID the id of the widget to constrain to
* @param endSide the side of widget to constrain to
* @param margin the margin to constrain (margin must be positive)
*/
public ConstraintProperties connect(int startSide, int endID, int endSide, int margin) {
switch (startSide) {
case LEFT:
if (endSide == LEFT) {
mParams.leftToLeft = endID;
mParams.leftToRight = mParams.UNSET;
} else if (endSide == RIGHT) {
mParams.leftToRight = endID;
mParams.leftToLeft = mParams.UNSET;
} else {
throw new IllegalArgumentException("Left to " + sideToString(endSide) + " undefined");
}
mParams.leftMargin = margin;
break;
case RIGHT:
if (endSide == LEFT) {
mParams.rightToLeft = endID;
mParams.rightToRight = mParams.UNSET;
} else if (endSide == RIGHT) {
mParams.rightToRight = endID;
mParams.rightToLeft = mParams.UNSET;
} else {
throw new IllegalArgumentException("right to " + sideToString(endSide) + " undefined");
}
mParams.rightMargin = margin;
break;
case TOP:
if (endSide == TOP) {
mParams.topToTop = endID;
mParams.topToBottom = mParams.UNSET;
mParams.baselineToBaseline = mParams.UNSET;
mParams.baselineToTop = mParams.UNSET;
mParams.baselineToBottom = mParams.UNSET;
} else if (endSide == BOTTOM) {
mParams.topToBottom = endID;
mParams.topToTop = mParams.UNSET;
mParams.baselineToBaseline = mParams.UNSET;
mParams.baselineToTop = mParams.UNSET;
mParams.baselineToBottom = mParams.UNSET;
} else {
throw new IllegalArgumentException("right to " + sideToString(endSide) + " undefined");
}
mParams.topMargin = margin;
break;
case BOTTOM:
if (endSide == BOTTOM) {
mParams.bottomToBottom = endID;
mParams.bottomToTop = mParams.UNSET;
mParams.baselineToBaseline = mParams.UNSET;
mParams.baselineToTop = mParams.UNSET;
mParams.baselineToBottom = mParams.UNSET;
} else if (endSide == TOP) {
mParams.bottomToTop = endID;
mParams.bottomToBottom = mParams.UNSET;
mParams.baselineToBaseline = mParams.UNSET;
mParams.baselineToTop = mParams.UNSET;
mParams.baselineToBottom = mParams.UNSET;
} else {
throw new IllegalArgumentException("right to " + sideToString(endSide) + " undefined");
}
mParams.bottomMargin = margin;
break;
case BASELINE:
if (endSide == BASELINE) {
mParams.baselineToBaseline = endID;
mParams.bottomToBottom = mParams.UNSET;
mParams.bottomToTop = mParams.UNSET;
mParams.topToTop = mParams.UNSET;
mParams.topToBottom = mParams.UNSET;
} if (endSide == TOP) {
mParams.baselineToTop = endID;
mParams.bottomToBottom = mParams.UNSET;
mParams.bottomToTop = mParams.UNSET;
mParams.topToTop = mParams.UNSET;
mParams.topToBottom = mParams.UNSET;
} else if (endSide == BOTTOM) {
mParams.baselineToBottom = endID;
mParams.bottomToBottom = mParams.UNSET;
mParams.bottomToTop = mParams.UNSET;
mParams.topToTop = mParams.UNSET;
mParams.topToBottom = mParams.UNSET;
} else {
throw new IllegalArgumentException("right to " + sideToString(endSide) + " undefined");
}
mParams.baselineMargin = margin;
break;
case START:
if (endSide == START) {
mParams.startToStart = endID;
mParams.startToEnd = mParams.UNSET;
} else if (endSide == END) {
mParams.startToEnd = endID;
mParams.startToStart = mParams.UNSET;
} else {
throw new IllegalArgumentException("right to " + sideToString(endSide) + " undefined");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mParams.setMarginStart(margin);
}
break;
case END:
if (endSide == END) {
mParams.endToEnd = endID;
mParams.endToStart = mParams.UNSET;
} else if (endSide == START) {
mParams.endToStart = endID;
mParams.endToEnd = mParams.UNSET;
} else {
throw new IllegalArgumentException("right to " + sideToString(endSide) + " undefined");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mParams.setMarginEnd(margin);
}
break;
default:
throw new IllegalArgumentException(
sideToString(startSide) + " to " + sideToString(endSide) + " unknown");
}
return this;
}
private String sideToString(int side) {
switch (side) {
case LEFT:
return "left";
case RIGHT:
return "right";
case TOP:
return "top";
case BOTTOM:
return "bottom";
case BASELINE:
return "baseline";
case START:
return "start";
case END:
return "end";
}
return "undefined";
}
public ConstraintProperties(View view) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (params instanceof ConstraintLayout.LayoutParams) {
mParams = (ConstraintLayout.LayoutParams) params;
mView = view;
} else {
throw new RuntimeException("Only children of ConstraintLayout.LayoutParams supported");
}
}
public void apply() {
}
}