1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v7.internal.widget; 18 19import android.content.Context; 20import android.content.res.TypedArray; 21import android.graphics.Canvas; 22import android.graphics.drawable.Drawable; 23import android.support.v7.appcompat.R; 24import android.util.AttributeSet; 25import android.view.View; 26import android.widget.LinearLayout; 27 28/** 29 * @hide 30 */ 31public class LinearLayoutICS extends LinearLayout { 32 33 private static final int SHOW_DIVIDER_NONE = 0; 34 private static final int SHOW_DIVIDER_BEGINNING = 1; 35 private static final int SHOW_DIVIDER_MIDDLE = 2; 36 private static final int SHOW_DIVIDER_END = 4; 37 38 private final Drawable mDivider; 39 private final int mDividerWidth, mDividerHeight; 40 private final int mShowDividers; 41 private final int mDividerPadding; 42 43 public LinearLayoutICS(Context context, AttributeSet attrs) { 44 super(context, attrs); 45 46 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinearLayoutICS); 47 48 mDivider = a.getDrawable(R.styleable.LinearLayoutICS_divider); 49 if (mDivider != null) { 50 mDividerWidth = mDivider.getIntrinsicWidth(); 51 mDividerHeight = mDivider.getIntrinsicHeight(); 52 } else { 53 mDividerHeight = mDividerWidth = 0; 54 } 55 56 mShowDividers = a.getInt(R.styleable.LinearLayoutICS_showDividers, SHOW_DIVIDER_NONE); 57 mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayoutICS_dividerPadding, 0); 58 59 a.recycle(); 60 61 setWillNotDraw(mDivider == null); 62 } 63 64 public int getSupportDividerWidth() { 65 return mDividerWidth; 66 } 67 68 @Override 69 protected void onDraw(Canvas canvas) { 70 if (mDivider == null) { 71 return; 72 } 73 74 if (getOrientation() == VERTICAL) { 75 drawSupportDividersVertical(canvas); 76 } else { 77 drawSupportDividersHorizontal(canvas); 78 } 79 } 80 81 @Override 82 protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, 83 int parentHeightMeasureSpec, int heightUsed) { 84 85 if (mDivider != null) { 86 final int childIndex = indexOfChild(child); 87 final int count = getChildCount(); 88 final LayoutParams params = (LayoutParams) child.getLayoutParams(); 89 90 // To display the dividers in-between the child views, we modify their margins 91 // to create space. 92 if (getOrientation() == VERTICAL) { 93 if (hasSupportDividerBeforeChildAt(childIndex)) { 94 params.topMargin = mDividerHeight; 95 } else if (childIndex == count - 1 && hasSupportDividerBeforeChildAt(count)) { 96 params.bottomMargin = mDividerHeight; 97 } 98 } else { 99 if (hasSupportDividerBeforeChildAt(childIndex)) { 100 params.leftMargin = mDividerWidth; 101 } else if (childIndex == count - 1 && hasSupportDividerBeforeChildAt(count)) { 102 params.rightMargin = mDividerWidth; 103 } 104 } 105 } 106 107 super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 108 parentHeightMeasureSpec, heightUsed); 109 } 110 111 void drawSupportDividersVertical(Canvas canvas) { 112 final int count = getChildCount(); 113 for (int i = 0; i < count; i++) { 114 final View child = getChildAt(i); 115 if (child != null && child.getVisibility() != GONE && 116 hasSupportDividerBeforeChildAt(i)) { 117 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 118 drawSupportHorizontalDivider(canvas, child.getTop() - lp.topMargin); 119 } 120 } 121 122 if (hasSupportDividerBeforeChildAt(count)) { 123 final View child = getChildAt(count - 1); 124 int bottom = 0; 125 if (child == null) { 126 bottom = getHeight() - getPaddingBottom() - mDividerHeight; 127 } else { 128 bottom = child.getBottom(); 129 } 130 drawSupportHorizontalDivider(canvas, bottom); 131 } 132 } 133 134 void drawSupportDividersHorizontal(Canvas canvas) { 135 final int count = getChildCount(); 136 for (int i = 0; i < count; i++) { 137 final View child = getChildAt(i); 138 if (child != null && child.getVisibility() != GONE && 139 hasSupportDividerBeforeChildAt(i)) { 140 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 141 drawSupportVerticalDivider(canvas, child.getLeft() - lp.leftMargin); 142 } 143 } 144 145 if (hasSupportDividerBeforeChildAt(count)) { 146 final View child = getChildAt(count - 1); 147 int right = 0; 148 if (child == null) { 149 right = getWidth() - getPaddingRight() - mDividerWidth; 150 } else { 151 right = child.getRight(); 152 } 153 drawSupportVerticalDivider(canvas, right); 154 } 155 } 156 157 void drawSupportHorizontalDivider(Canvas canvas, int top) { 158 mDivider.setBounds(getPaddingLeft() + mDividerPadding, top, 159 getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight); 160 mDivider.draw(canvas); 161 } 162 163 void drawSupportVerticalDivider(Canvas canvas, int left) { 164 mDivider.setBounds(left, getPaddingTop() + mDividerPadding, 165 left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding); 166 mDivider.draw(canvas); 167 } 168 169 /** 170 * Determines where to position dividers between children. 171 * 172 * @param childIndex Index of child to check for preceding divider 173 * @return true if there should be a divider before the child at childIndex 174 */ 175 protected boolean hasSupportDividerBeforeChildAt(int childIndex) { 176 if (childIndex == 0) { 177 return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0; 178 } else if (childIndex == getChildCount()) { 179 return (mShowDividers & SHOW_DIVIDER_END) != 0; 180 } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) { 181 boolean hasVisibleViewBefore = false; 182 for (int i = childIndex - 1; i >= 0; i--) { 183 if (getChildAt(i).getVisibility() != GONE) { 184 hasVisibleViewBefore = true; 185 break; 186 } 187 } 188 return hasVisibleViewBefore; 189 } 190 return false; 191 } 192 193} 194