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