| /* |
| * 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 android.support.constraint; |
| |
| import android.content.Context; |
| import android.content.res.Configuration; |
| import android.content.res.TypedArray; |
| import android.os.Build; |
| import android.util.AttributeSet; |
| import android.view.View; |
| |
| /** |
| * <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 |
| * <android.support.constraint.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 = android.support.constraint.solver.widgets.Barrier.LEFT; |
| |
| /** |
| * Top direction constant |
| */ |
| public static final int TOP = android.support.constraint.solver.widgets.Barrier.TOP; |
| |
| /** |
| * Right direction constant |
| */ |
| public static final int RIGHT = android.support.constraint.solver.widgets.Barrier.RIGHT; |
| |
| /** |
| * Bottom direction constant |
| */ |
| public static final int BOTTOM = android.support.constraint.solver.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 android.support.constraint.solver.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; |
| 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 |
| Configuration config = getResources().getConfiguration(); |
| boolean isRtl = (View.LAYOUT_DIRECTION_RTL == config.getLayoutDirection()); |
| 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; |
| } |
| } |
| } |
| mBarrier.setBarrierType(mResolvedType); |
| } |
| |
| /** |
| * @param attrs |
| * @hide |
| */ |
| @Override |
| protected void init(AttributeSet attrs) { |
| super.init(attrs); |
| mBarrier = new android.support.constraint.solver.widgets.Barrier(); |
| if (attrs != null) { |
| TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ConstraintLayout_Layout); |
| final int N = a.getIndexCount(); |
| for (int i = 0; i < N; 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)); |
| } |
| } |
| } |
| mHelperWidget = mBarrier; |
| validateParams(); |
| } |
| |
| public void setAllowsGoneWidget(boolean supportGone) { |
| mBarrier.setAllowsGoneWidget(supportGone); |
| } |
| |
| public boolean allowsGoneWidget() { |
| return mBarrier.allowsGoneWidget(); |
| } |
| |
| } |