PageRenderTime 34ms CodeModel.GetById 18ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/ABSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java

https://bitbucket.org/ayastrebov/android-actionbarsherlock
Java | 248 lines | 173 code | 26 blank | 49 comment | 56 complexity | b285683bfbab61431c15e186499a53bb MD5 | raw file
  1package com.actionbarsherlock.internal.widget;
  2
  3import android.content.Context;
  4import android.content.res.TypedArray;
  5import android.graphics.Canvas;
  6import android.graphics.drawable.Drawable;
  7import android.util.AttributeSet;
  8import android.view.View;
  9import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout;
 10
 11/**
 12 * A simple extension of a regular linear layout that supports the divider API
 13 * of Android 4.0+. The dividers are added adjacent to the children by changing
 14 * their layout params. If you need to rely on the margins which fall in the
 15 * same orientation as the layout you should wrap the child in a simple
 16 * {@link android.widget.FrameLayout} so it can receive the margin.
 17 */
 18public class IcsLinearLayout extends NineLinearLayout {
 19    private static final int[] LinearLayout = new int[] {
 20        /* 0 */ android.R.attr.divider,
 21        /* 1 */ android.R.attr.showDividers,
 22        /* 2 */ android.R.attr.dividerPadding,
 23    };
 24    private static final int LinearLayout_divider = 0;
 25    private static final int LinearLayout_showDividers = 1;
 26    private static final int LinearLayout_dividerPadding = 2;
 27
 28    /**
 29     * Don't show any dividers.
 30     */
 31    public static final int SHOW_DIVIDER_NONE = 0;
 32    /**
 33     * Show a divider at the beginning of the group.
 34     */
 35    public static final int SHOW_DIVIDER_BEGINNING = 1;
 36    /**
 37     * Show dividers between each item in the group.
 38     */
 39    public static final int SHOW_DIVIDER_MIDDLE = 2;
 40    /**
 41     * Show a divider at the end of the group.
 42     */
 43    public static final int SHOW_DIVIDER_END = 4;
 44
 45
 46    private Drawable mDivider;
 47    private int mDividerWidth;
 48    private int mDividerHeight;
 49    private int mShowDividers;
 50    private int mDividerPadding;
 51
 52
 53    public IcsLinearLayout(Context context, AttributeSet attrs) {
 54        super(context, attrs);
 55
 56        TypedArray a = context.obtainStyledAttributes(attrs, /*com.android.internal.R.styleable.*/LinearLayout);
 57
 58        setDividerDrawable(a.getDrawable(/*com.android.internal.R.styleable.*/LinearLayout_divider));
 59        mShowDividers = a.getInt(/*com.android.internal.R.styleable.*/LinearLayout_showDividers, SHOW_DIVIDER_NONE);
 60        mDividerPadding = a.getDimensionPixelSize(/*com.android.internal.R.styleable.*/LinearLayout_dividerPadding, 0);
 61
 62        a.recycle();
 63    }
 64
 65    /**
 66     * Set how dividers should be shown between items in this layout
 67     *
 68     * @param showDividers One or more of {@link #SHOW_DIVIDER_BEGINNING},
 69     *                     {@link #SHOW_DIVIDER_MIDDLE}, or {@link #SHOW_DIVIDER_END},
 70     *                     or {@link #SHOW_DIVIDER_NONE} to show no dividers.
 71     */
 72    public void setShowDividers(int showDividers) {
 73        if (showDividers != mShowDividers) {
 74            requestLayout();
 75            invalidate(); //XXX This is required if you are toggling a divider off
 76        }
 77        mShowDividers = showDividers;
 78    }
 79
 80    /**
 81     * @return A flag set indicating how dividers should be shown around items.
 82     * @see #setShowDividers(int)
 83     */
 84    public int getShowDividers() {
 85        return mShowDividers;
 86    }
 87
 88    /**
 89     * Set a drawable to be used as a divider between items.
 90     * @param divider Drawable that will divide each item.
 91     * @see #setShowDividers(int)
 92     */
 93    public void setDividerDrawable(Drawable divider) {
 94        if (divider == mDivider) {
 95            return;
 96        }
 97        mDivider = divider;
 98        if (divider != null) {
 99            mDividerWidth = divider.getIntrinsicWidth();
100            mDividerHeight = divider.getIntrinsicHeight();
101        } else {
102            mDividerWidth = 0;
103            mDividerHeight = 0;
104        }
105        setWillNotDraw(divider == null);
106        requestLayout();
107    }
108
109    /**
110     * Get the width of the current divider drawable.
111     *
112     * @hide Used internally by framework.
113     */
114    public int getDividerWidth() {
115        return mDividerWidth;
116    }
117
118    @Override
119    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
120        final int index = indexOfChild(child);
121        final int orientation = getOrientation();
122        final LayoutParams params = (LayoutParams) child.getLayoutParams();
123        if (hasDividerBeforeChildAt(index)) {
124            if (orientation == VERTICAL) {
125                //Account for the divider by pushing everything up
126                params.topMargin = mDividerHeight;
127            } else {
128                //Account for the divider by pushing everything left
129                params.leftMargin = mDividerWidth;
130            }
131        }
132
133        final int count = getChildCount();
134        if (index == count - 1) {
135            if (hasDividerBeforeChildAt(count)) {
136                if (orientation == VERTICAL) {
137                    params.bottomMargin = mDividerHeight;
138                } else {
139                    params.rightMargin = mDividerWidth;
140                }
141            }
142        }
143        super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
144    }
145
146    @Override
147    protected void onDraw(Canvas canvas) {
148        if (mDivider != null) {
149            if (getOrientation() == VERTICAL) {
150                drawDividersVertical(canvas);
151            } else {
152                drawDividersHorizontal(canvas);
153            }
154        }
155        super.onDraw(canvas);
156    }
157
158    void drawDividersVertical(Canvas canvas) {
159        final int count = getChildCount();
160        for (int i = 0; i < count; i++) {
161            final View child = getChildAt(i);
162
163            if (child != null && child.getVisibility() != GONE) {
164                if (hasDividerBeforeChildAt(i)) {
165                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
166                    final int top = child.getTop() - lp.topMargin/* - mDividerHeight*/;
167                    drawHorizontalDivider(canvas, top);
168                }
169            }
170        }
171
172        if (hasDividerBeforeChildAt(count)) {
173            final View child = getChildAt(count - 1);
174            int bottom = 0;
175            if (child == null) {
176                bottom = getHeight() - getPaddingBottom() - mDividerHeight;
177            } else {
178                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
179                bottom = child.getBottom()/* + lp.bottomMargin*/;
180            }
181            drawHorizontalDivider(canvas, bottom);
182        }
183    }
184
185    void drawDividersHorizontal(Canvas canvas) {
186        final int count = getChildCount();
187        for (int i = 0; i < count; i++) {
188            final View child = getChildAt(i);
189
190            if (child != null && child.getVisibility() != GONE) {
191                if (hasDividerBeforeChildAt(i)) {
192                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
193                    final int left = child.getLeft() - lp.leftMargin/* - mDividerWidth*/;
194                    drawVerticalDivider(canvas, left);
195                }
196            }
197        }
198
199        if (hasDividerBeforeChildAt(count)) {
200            final View child = getChildAt(count - 1);
201            int right = 0;
202            if (child == null) {
203                right = getWidth() - getPaddingRight() - mDividerWidth;
204            } else {
205                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
206                right = child.getRight()/* + lp.rightMargin*/;
207            }
208            drawVerticalDivider(canvas, right);
209        }
210    }
211
212    void drawHorizontalDivider(Canvas canvas, int top) {
213        mDivider.setBounds(getPaddingLeft() + mDividerPadding, top,
214                getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight);
215        mDivider.draw(canvas);
216    }
217
218    void drawVerticalDivider(Canvas canvas, int left) {
219        mDivider.setBounds(left, getPaddingTop() + mDividerPadding,
220                left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding);
221        mDivider.draw(canvas);
222    }
223
224    /**
225     * Determines where to position dividers between children.
226     *
227     * @param childIndex Index of child to check for preceding divider
228     * @return true if there should be a divider before the child at childIndex
229     * @hide Pending API consideration. Currently only used internally by the system.
230     */
231    protected boolean hasDividerBeforeChildAt(int childIndex) {
232        if (childIndex == 0) {
233            return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0;
234        } else if (childIndex == getChildCount()) {
235            return (mShowDividers & SHOW_DIVIDER_END) != 0;
236        } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) {
237            boolean hasVisibleViewBefore = false;
238            for (int i = childIndex - 1; i >= 0; i--) {
239                if (getChildAt(i).getVisibility() != GONE) {
240                    hasVisibleViewBefore = true;
241                    break;
242                }
243            }
244            return hasVisibleViewBefore;
245        }
246        return false;
247    }
248}