19a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes/*
29a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * Copyright (C) 2013 The Android Open Source Project
39a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes *
49a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
59a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * you may not use this file except in compliance with the License.
69a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * You may obtain a copy of the License at
79a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes *
89a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
99a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes *
109a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * Unless required by applicable law or agreed to in writing, software
119a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
129a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * See the License for the specific language governing permissions and
149a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * limitations under the License.
159a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes */
169a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
179a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banespackage android.support.v7.internal.widget;
189a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
199a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.content.Context;
209a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.content.res.TypedArray;
219a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.graphics.Canvas;
229a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.graphics.drawable.Drawable;
239a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.support.v7.appcompat.R;
249a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.util.AttributeSet;
259a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.view.View;
269a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banesimport android.widget.LinearLayout;
279a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
289a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes/**
299a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes * @hide
309a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes */
319a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banespublic class LinearLayoutICS extends LinearLayout {
329a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
339a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private static final int SHOW_DIVIDER_NONE = 0;
349a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private static final int SHOW_DIVIDER_BEGINNING = 1;
359a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private static final int SHOW_DIVIDER_MIDDLE = 2;
369a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private static final int SHOW_DIVIDER_END = 4;
379a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
389a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private final Drawable mDivider;
399a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private final int mDividerWidth, mDividerHeight;
409a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private final int mShowDividers;
419a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    private final int mDividerPadding;
429a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
439a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    public LinearLayoutICS(Context context, AttributeSet attrs) {
449a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        super(context, attrs);
459a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
469a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinearLayoutICS);
479a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
489a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        mDivider = a.getDrawable(R.styleable.LinearLayoutICS_divider);
499a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        if (mDivider != null) {
509a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            mDividerWidth = mDivider.getIntrinsicWidth();
519a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            mDividerHeight = mDivider.getIntrinsicHeight();
529a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        } else {
539a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            mDividerHeight = mDividerWidth = 0;
549a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
559a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
569a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        mShowDividers = a.getInt(R.styleable.LinearLayoutICS_showDividers, SHOW_DIVIDER_NONE);
579a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayoutICS_dividerPadding, 0);
589a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
599a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        a.recycle();
609a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
619a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        setWillNotDraw(mDivider == null);
629a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
639a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
641582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes    public int getSupportDividerWidth() {
651582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes        return mDividerWidth;
661582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes    }
671582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes
689a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    @Override
699a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    protected void onDraw(Canvas canvas) {
701582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes        if (mDivider == null) {
711582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes            return;
721582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes        }
731582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes
749a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        if (getOrientation() == VERTICAL) {
751582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes            drawSupportDividersVertical(canvas);
769a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        } else {
771582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes            drawSupportDividersHorizontal(canvas);
789a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
799a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
809a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
819a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    @Override
829a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
839a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            int parentHeightMeasureSpec, int heightUsed) {
849a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
859a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        if (mDivider != null) {
869a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            final int childIndex = indexOfChild(child);
879a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            final int count = getChildCount();
889a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            final LayoutParams params = (LayoutParams) child.getLayoutParams();
899a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
909a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            // To display the dividers in-between the child views, we modify their margins
919a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            // to create space.
929a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            if (getOrientation() == VERTICAL) {
931582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                if (hasSupportDividerBeforeChildAt(childIndex)) {
949a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                    params.topMargin = mDividerHeight;
951582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                } else if (childIndex == count - 1 && hasSupportDividerBeforeChildAt(count)) {
969a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                    params.bottomMargin = mDividerHeight;
979a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                }
989a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            } else {
991582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                if (hasSupportDividerBeforeChildAt(childIndex)) {
1009a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                    params.leftMargin = mDividerWidth;
1011582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                } else if (childIndex == count - 1 && hasSupportDividerBeforeChildAt(count)) {
1029a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                    params.rightMargin = mDividerWidth;
1039a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                }
1049a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            }
1059a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
1069a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1079a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
1089a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                parentHeightMeasureSpec, heightUsed);
1099a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
1109a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1111582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes    void drawSupportDividersVertical(Canvas canvas) {
1129a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        final int count = getChildCount();
1139a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        for (int i = 0; i < count; i++) {
1149a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            final View child = getChildAt(i);
1151582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes            if (child != null && child.getVisibility() != GONE &&
1161582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                    hasSupportDividerBeforeChildAt(i)) {
1179a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1181582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                drawSupportHorizontalDivider(canvas, child.getTop() - lp.topMargin);
1199a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            }
1209a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
1219a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1221582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes        if (hasSupportDividerBeforeChildAt(count)) {
1239a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            final View child = getChildAt(count - 1);
1249a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            int bottom = 0;
1259a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            if (child == null) {
1269a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                bottom = getHeight() - getPaddingBottom() - mDividerHeight;
1279a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            } else {
1289a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                bottom = child.getBottom();
1299a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            }
1301582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes            drawSupportHorizontalDivider(canvas, bottom);
1319a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
1329a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
1339a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1341582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes    void drawSupportDividersHorizontal(Canvas canvas) {
1359a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        final int count = getChildCount();
1369a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        for (int i = 0; i < count; i++) {
1379a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            final View child = getChildAt(i);
1381582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes            if (child != null && child.getVisibility() != GONE &&
1391582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                    hasSupportDividerBeforeChildAt(i)) {
1409a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1411582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes                drawSupportVerticalDivider(canvas, child.getLeft() - lp.leftMargin);
1429a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            }
1439a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
1449a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1451582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes        if (hasSupportDividerBeforeChildAt(count)) {
1469a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            final View child = getChildAt(count - 1);
1479a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            int right = 0;
1489a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            if (child == null) {
1499a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                right = getWidth() - getPaddingRight() - mDividerWidth;
1509a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            } else {
1519a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                right = child.getRight();
1529a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            }
1531582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes            drawSupportVerticalDivider(canvas, right);
1549a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
1559a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
1569a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1571582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes    void drawSupportHorizontalDivider(Canvas canvas, int top) {
1589a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        mDivider.setBounds(getPaddingLeft() + mDividerPadding, top,
1599a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight);
1609a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        mDivider.draw(canvas);
1619a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
1629a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1631582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes    void drawSupportVerticalDivider(Canvas canvas, int left) {
1649a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        mDivider.setBounds(left, getPaddingTop() + mDividerPadding,
1659a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding);
1669a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        mDivider.draw(canvas);
1679a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
1689a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1699a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    /**
1709a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes     * Determines where to position dividers between children.
1719a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes     *
1729a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes     * @param childIndex Index of child to check for preceding divider
1739a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes     * @return true if there should be a divider before the child at childIndex
1749a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes     */
1751582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes    protected boolean hasSupportDividerBeforeChildAt(int childIndex) {
1769a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        if (childIndex == 0) {
1779a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0;
1789a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        } else if (childIndex == getChildCount()) {
1799a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            return (mShowDividers & SHOW_DIVIDER_END) != 0;
1809a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) {
1819a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            boolean hasVisibleViewBefore = false;
1829a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            for (int i = childIndex - 1; i >= 0; i--) {
1839a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                if (getChildAt(i).getVisibility() != GONE) {
1849a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                    hasVisibleViewBefore = true;
1859a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                    break;
1869a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes                }
1879a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            }
1889a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes            return hasVisibleViewBefore;
1899a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        }
1909a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes        return false;
1919a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes    }
1929a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes
1939a39a1a106e7cbe6daf6e246dab7e89bbecbab38Chris Banes}
194