ActionMenuView.java revision e43340c80dc66c45edc793ecd0343774aa34d108
1/* 2 * Copyright (C) 2010 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 */ 16package android.widget; 17 18import android.content.Context; 19import android.content.res.Configuration; 20import android.util.AttributeSet; 21import android.view.Gravity; 22import android.view.Menu; 23import android.view.MenuItem; 24import android.view.View; 25import android.view.ViewDebug; 26import android.view.ViewGroup; 27import android.view.accessibility.AccessibilityEvent; 28import com.android.internal.view.menu.ActionMenuItemView; 29import com.android.internal.view.menu.MenuBuilder; 30import com.android.internal.view.menu.MenuItemImpl; 31import com.android.internal.view.menu.MenuPresenter; 32import com.android.internal.view.menu.MenuView; 33 34/** 35 * ActionMenuView is a presentation of a series of menu options as a View. It provides 36 * several top level options as action buttons while spilling remaining options over as 37 * items in an overflow menu. This allows applications to present packs of actions inline with 38 * specific or repeating content. 39 */ 40public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView { 41 private static final String TAG = "ActionMenuView"; 42 43 static final int MIN_CELL_SIZE = 56; // dips 44 static final int GENERATED_ITEM_PADDING = 4; // dips 45 46 private MenuBuilder mMenu; 47 48 private boolean mReserveOverflow; 49 private ActionMenuPresenter mPresenter; 50 private boolean mFormatItems; 51 private int mFormatItemsWidth; 52 private int mMinCellSize; 53 private int mGeneratedItemPadding; 54 55 private OnMenuItemClickListener mOnMenuItemClickListener; 56 57 public ActionMenuView(Context context) { 58 this(context, null); 59 } 60 61 public ActionMenuView(Context context, AttributeSet attrs) { 62 super(context, attrs); 63 setBaselineAligned(false); 64 final float density = context.getResources().getDisplayMetrics().density; 65 mMinCellSize = (int) (MIN_CELL_SIZE * density); 66 mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density); 67 } 68 69 /** @hide */ 70 public void setPresenter(ActionMenuPresenter presenter) { 71 mPresenter = presenter; 72 } 73 74 @Override 75 public void onConfigurationChanged(Configuration newConfig) { 76 super.onConfigurationChanged(newConfig); 77 mPresenter.updateMenuView(false); 78 79 if (mPresenter != null && mPresenter.isOverflowMenuShowing()) { 80 mPresenter.hideOverflowMenu(); 81 mPresenter.showOverflowMenu(); 82 } 83 } 84 85 public void setOnMenuItemClickListener(OnMenuItemClickListener listener) { 86 mOnMenuItemClickListener = listener; 87 } 88 89 @Override 90 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 91 // If we've been given an exact size to match, apply special formatting during layout. 92 final boolean wasFormatted = mFormatItems; 93 mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; 94 95 if (wasFormatted != mFormatItems) { 96 mFormatItemsWidth = 0; // Reset this when switching modes 97 } 98 99 // Special formatting can change whether items can fit as action buttons. 100 // Kick the menu and update presenters when this changes. 101 final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 102 if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) { 103 mFormatItemsWidth = widthSize; 104 mMenu.onItemsChanged(true); 105 } 106 107 final int childCount = getChildCount(); 108 if (mFormatItems && childCount > 0) { 109 onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec); 110 } else { 111 // Previous measurement at exact format may have set margins - reset them. 112 for (int i = 0; i < childCount; i++) { 113 final View child = getChildAt(i); 114 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 115 lp.leftMargin = lp.rightMargin = 0; 116 } 117 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 118 } 119 } 120 121 private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) { 122 // We already know the width mode is EXACTLY if we're here. 123 final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 124 int widthSize = MeasureSpec.getSize(widthMeasureSpec); 125 int heightSize = MeasureSpec.getSize(heightMeasureSpec); 126 127 final int widthPadding = getPaddingLeft() + getPaddingRight(); 128 final int heightPadding = getPaddingTop() + getPaddingBottom(); 129 130 final int itemHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding, 131 ViewGroup.LayoutParams.WRAP_CONTENT); 132 133 widthSize -= widthPadding; 134 135 // Divide the view into cells. 136 final int cellCount = widthSize / mMinCellSize; 137 final int cellSizeRemaining = widthSize % mMinCellSize; 138 139 if (cellCount == 0) { 140 // Give up, nothing fits. 141 setMeasuredDimension(widthSize, 0); 142 return; 143 } 144 145 final int cellSize = mMinCellSize + cellSizeRemaining / cellCount; 146 147 int cellsRemaining = cellCount; 148 int maxChildHeight = 0; 149 int maxCellsUsed = 0; 150 int expandableItemCount = 0; 151 int visibleItemCount = 0; 152 boolean hasOverflow = false; 153 154 // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64. 155 long smallestItemsAt = 0; 156 157 final int childCount = getChildCount(); 158 for (int i = 0; i < childCount; i++) { 159 final View child = getChildAt(i); 160 if (child.getVisibility() == GONE) continue; 161 162 final boolean isGeneratedItem = child instanceof ActionMenuItemView; 163 visibleItemCount++; 164 165 if (isGeneratedItem) { 166 // Reset padding for generated menu item views; it may change below 167 // and views are recycled. 168 child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0); 169 } 170 171 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 172 lp.expanded = false; 173 lp.extraPixels = 0; 174 lp.cellsUsed = 0; 175 lp.expandable = false; 176 lp.leftMargin = 0; 177 lp.rightMargin = 0; 178 lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText(); 179 180 // Overflow always gets 1 cell. No more, no less. 181 final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining; 182 183 final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, 184 itemHeightSpec, heightPadding); 185 186 maxCellsUsed = Math.max(maxCellsUsed, cellsUsed); 187 if (lp.expandable) expandableItemCount++; 188 if (lp.isOverflowButton) hasOverflow = true; 189 190 cellsRemaining -= cellsUsed; 191 maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()); 192 if (cellsUsed == 1) smallestItemsAt |= (1 << i); 193 } 194 195 // When we have overflow and a single expanded (text) item, we want to try centering it 196 // visually in the available space even though overflow consumes some of it. 197 final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2; 198 199 // Divide space for remaining cells if we have items that can expand. 200 // Try distributing whole leftover cells to smaller items first. 201 202 boolean needsExpansion = false; 203 while (expandableItemCount > 0 && cellsRemaining > 0) { 204 int minCells = Integer.MAX_VALUE; 205 long minCellsAt = 0; // Bit locations are indices of relevant child views 206 int minCellsItemCount = 0; 207 for (int i = 0; i < childCount; i++) { 208 final View child = getChildAt(i); 209 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 210 211 // Don't try to expand items that shouldn't. 212 if (!lp.expandable) continue; 213 214 // Mark indices of children that can receive an extra cell. 215 if (lp.cellsUsed < minCells) { 216 minCells = lp.cellsUsed; 217 minCellsAt = 1 << i; 218 minCellsItemCount = 1; 219 } else if (lp.cellsUsed == minCells) { 220 minCellsAt |= 1 << i; 221 minCellsItemCount++; 222 } 223 } 224 225 // Items that get expanded will always be in the set of smallest items when we're done. 226 smallestItemsAt |= minCellsAt; 227 228 if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop. 229 230 // We have enough cells, all minimum size items will be incremented. 231 minCells++; 232 233 for (int i = 0; i < childCount; i++) { 234 final View child = getChildAt(i); 235 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 236 if ((minCellsAt & (1 << i)) == 0) { 237 // If this item is already at our small item count, mark it for later. 238 if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i; 239 continue; 240 } 241 242 if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) { 243 // Add padding to this item such that it centers. 244 child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0); 245 } 246 lp.cellsUsed++; 247 lp.expanded = true; 248 cellsRemaining--; 249 } 250 251 needsExpansion = true; 252 } 253 254 // Divide any space left that wouldn't divide along cell boundaries 255 // evenly among the smallest items 256 257 final boolean singleItem = !hasOverflow && visibleItemCount == 1; 258 if (cellsRemaining > 0 && smallestItemsAt != 0 && 259 (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) { 260 float expandCount = Long.bitCount(smallestItemsAt); 261 262 if (!singleItem) { 263 // The items at the far edges may only expand by half in order to pin to either side. 264 if ((smallestItemsAt & 1) != 0) { 265 LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams(); 266 if (!lp.preventEdgeOffset) expandCount -= 0.5f; 267 } 268 if ((smallestItemsAt & (1 << (childCount - 1))) != 0) { 269 LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams()); 270 if (!lp.preventEdgeOffset) expandCount -= 0.5f; 271 } 272 } 273 274 final int extraPixels = expandCount > 0 ? 275 (int) (cellsRemaining * cellSize / expandCount) : 0; 276 277 for (int i = 0; i < childCount; i++) { 278 if ((smallestItemsAt & (1 << i)) == 0) continue; 279 280 final View child = getChildAt(i); 281 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 282 if (child instanceof ActionMenuItemView) { 283 // If this is one of our views, expand and measure at the larger size. 284 lp.extraPixels = extraPixels; 285 lp.expanded = true; 286 if (i == 0 && !lp.preventEdgeOffset) { 287 // First item gets part of its new padding pushed out of sight. 288 // The last item will get this implicitly from layout. 289 lp.leftMargin = -extraPixels / 2; 290 } 291 needsExpansion = true; 292 } else if (lp.isOverflowButton) { 293 lp.extraPixels = extraPixels; 294 lp.expanded = true; 295 lp.rightMargin = -extraPixels / 2; 296 needsExpansion = true; 297 } else { 298 // If we don't know what it is, give it some margins instead 299 // and let it center within its space. We still want to pin 300 // against the edges. 301 if (i != 0) { 302 lp.leftMargin = extraPixels / 2; 303 } 304 if (i != childCount - 1) { 305 lp.rightMargin = extraPixels / 2; 306 } 307 } 308 } 309 310 cellsRemaining = 0; 311 } 312 313 // Remeasure any items that have had extra space allocated to them. 314 if (needsExpansion) { 315 for (int i = 0; i < childCount; i++) { 316 final View child = getChildAt(i); 317 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 318 319 if (!lp.expanded) continue; 320 321 final int width = lp.cellsUsed * cellSize + lp.extraPixels; 322 child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 323 itemHeightSpec); 324 } 325 } 326 327 if (heightMode != MeasureSpec.EXACTLY) { 328 heightSize = maxChildHeight; 329 } 330 331 setMeasuredDimension(widthSize, heightSize); 332 } 333 334 /** 335 * Measure a child view to fit within cell-based formatting. The child's width 336 * will be measured to a whole multiple of cellSize. 337 * 338 * <p>Sets the expandable and cellsUsed fields of LayoutParams. 339 * 340 * @param child Child to measure 341 * @param cellSize Size of one cell 342 * @param cellsRemaining Number of cells remaining that this view can expand to fill 343 * @param parentHeightMeasureSpec MeasureSpec used by the parent view 344 * @param parentHeightPadding Padding present in the parent view 345 * @return Number of cells this child was measured to occupy 346 */ 347 static int measureChildForCells(View child, int cellSize, int cellsRemaining, 348 int parentHeightMeasureSpec, int parentHeightPadding) { 349 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 350 351 final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) - 352 parentHeightPadding; 353 final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec); 354 final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode); 355 356 final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? 357 (ActionMenuItemView) child : null; 358 final boolean hasText = itemView != null && itemView.hasText(); 359 360 int cellsUsed = 0; 361 if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) { 362 final int childWidthSpec = MeasureSpec.makeMeasureSpec( 363 cellSize * cellsRemaining, MeasureSpec.AT_MOST); 364 child.measure(childWidthSpec, childHeightSpec); 365 366 final int measuredWidth = child.getMeasuredWidth(); 367 cellsUsed = measuredWidth / cellSize; 368 if (measuredWidth % cellSize != 0) cellsUsed++; 369 if (hasText && cellsUsed < 2) cellsUsed = 2; 370 } 371 372 final boolean expandable = !lp.isOverflowButton && hasText; 373 lp.expandable = expandable; 374 375 lp.cellsUsed = cellsUsed; 376 final int targetWidth = cellsUsed * cellSize; 377 child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), 378 childHeightSpec); 379 return cellsUsed; 380 } 381 382 @Override 383 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 384 if (!mFormatItems) { 385 super.onLayout(changed, left, top, right, bottom); 386 return; 387 } 388 389 final int childCount = getChildCount(); 390 final int midVertical = (top + bottom) / 2; 391 final int dividerWidth = getDividerWidth(); 392 int overflowWidth = 0; 393 int nonOverflowWidth = 0; 394 int nonOverflowCount = 0; 395 int widthRemaining = right - left - getPaddingRight() - getPaddingLeft(); 396 boolean hasOverflow = false; 397 final boolean isLayoutRtl = isLayoutRtl(); 398 for (int i = 0; i < childCount; i++) { 399 final View v = getChildAt(i); 400 if (v.getVisibility() == GONE) { 401 continue; 402 } 403 404 LayoutParams p = (LayoutParams) v.getLayoutParams(); 405 if (p.isOverflowButton) { 406 overflowWidth = v.getMeasuredWidth(); 407 if (hasDividerBeforeChildAt(i)) { 408 overflowWidth += dividerWidth; 409 } 410 411 int height = v.getMeasuredHeight(); 412 int r; 413 int l; 414 if (isLayoutRtl) { 415 l = getPaddingLeft() + p.leftMargin; 416 r = l + overflowWidth; 417 } else { 418 r = getWidth() - getPaddingRight() - p.rightMargin; 419 l = r - overflowWidth; 420 } 421 int t = midVertical - (height / 2); 422 int b = t + height; 423 v.layout(l, t, r, b); 424 425 widthRemaining -= overflowWidth; 426 hasOverflow = true; 427 } else { 428 final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin; 429 nonOverflowWidth += size; 430 widthRemaining -= size; 431 if (hasDividerBeforeChildAt(i)) { 432 nonOverflowWidth += dividerWidth; 433 } 434 nonOverflowCount++; 435 } 436 } 437 438 if (childCount == 1 && !hasOverflow) { 439 // Center a single child 440 final View v = getChildAt(0); 441 final int width = v.getMeasuredWidth(); 442 final int height = v.getMeasuredHeight(); 443 final int midHorizontal = (right - left) / 2; 444 final int l = midHorizontal - width / 2; 445 final int t = midVertical - height / 2; 446 v.layout(l, t, l + width, t + height); 447 return; 448 } 449 450 final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1); 451 final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0); 452 453 if (isLayoutRtl) { 454 int startRight = getWidth() - getPaddingRight(); 455 for (int i = 0; i < childCount; i++) { 456 final View v = getChildAt(i); 457 final LayoutParams lp = (LayoutParams) v.getLayoutParams(); 458 if (v.getVisibility() == GONE || lp.isOverflowButton) { 459 continue; 460 } 461 462 startRight -= lp.rightMargin; 463 int width = v.getMeasuredWidth(); 464 int height = v.getMeasuredHeight(); 465 int t = midVertical - height / 2; 466 v.layout(startRight - width, t, startRight, t + height); 467 startRight -= width + lp.leftMargin + spacerSize; 468 } 469 } else { 470 int startLeft = getPaddingLeft(); 471 for (int i = 0; i < childCount; i++) { 472 final View v = getChildAt(i); 473 final LayoutParams lp = (LayoutParams) v.getLayoutParams(); 474 if (v.getVisibility() == GONE || lp.isOverflowButton) { 475 continue; 476 } 477 478 startLeft += lp.leftMargin; 479 int width = v.getMeasuredWidth(); 480 int height = v.getMeasuredHeight(); 481 int t = midVertical - height / 2; 482 v.layout(startLeft, t, startLeft + width, t + height); 483 startLeft += width + lp.rightMargin + spacerSize; 484 } 485 } 486 } 487 488 @Override 489 public void onDetachedFromWindow() { 490 super.onDetachedFromWindow(); 491 mPresenter.dismissPopupMenus(); 492 } 493 494 /** @hide */ 495 public boolean isOverflowReserved() { 496 return mReserveOverflow; 497 } 498 499 /** @hide */ 500 public void setOverflowReserved(boolean reserveOverflow) { 501 mReserveOverflow = reserveOverflow; 502 } 503 504 @Override 505 protected LayoutParams generateDefaultLayoutParams() { 506 LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, 507 LayoutParams.WRAP_CONTENT); 508 params.gravity = Gravity.CENTER_VERTICAL; 509 return params; 510 } 511 512 @Override 513 public LayoutParams generateLayoutParams(AttributeSet attrs) { 514 return new LayoutParams(getContext(), attrs); 515 } 516 517 @Override 518 protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 519 if (p != null) { 520 final LayoutParams result = p instanceof LayoutParams 521 ? new LayoutParams((LayoutParams) p) 522 : new LayoutParams(p); 523 if (result.gravity <= Gravity.NO_GRAVITY) { 524 result.gravity = Gravity.CENTER_VERTICAL; 525 } 526 return result; 527 } 528 return generateDefaultLayoutParams(); 529 } 530 531 @Override 532 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 533 return p != null && p instanceof LayoutParams; 534 } 535 536 /** @hide */ 537 public LayoutParams generateOverflowButtonLayoutParams() { 538 LayoutParams result = generateDefaultLayoutParams(); 539 result.isOverflowButton = true; 540 return result; 541 } 542 543 /** @hide */ 544 public boolean invokeItem(MenuItemImpl item) { 545 return mMenu.performItemAction(item, 0); 546 } 547 548 /** @hide */ 549 public int getWindowAnimations() { 550 return 0; 551 } 552 553 /** @hide */ 554 public void initialize(MenuBuilder menu) { 555 mMenu = menu; 556 } 557 558 /** 559 * Returns the Menu object that this ActionMenuView is currently presenting. 560 * 561 * <p>Applications should use this method to obtain the ActionMenuView's Menu object 562 * and inflate or add content to it as necessary.</p> 563 * 564 * @return the Menu presented by this view 565 */ 566 public Menu getMenu() { 567 if (mMenu == null) { 568 final Context context = getContext(); 569 mMenu = new MenuBuilder(context); 570 mMenu.setCallback(new MenuBuilderCallback()); 571 mPresenter = new ActionMenuPresenter(context); 572 mPresenter.setMenuView(this); 573 mPresenter.setCallback(new ActionMenuPresenterCallback()); 574 mMenu.addMenuPresenter(mPresenter); 575 } 576 577 return mMenu; 578 } 579 580 /** 581 * @hide Private LinearLayout (superclass) API. Un-hide if LinearLayout API is made public. 582 */ 583 @Override 584 protected boolean hasDividerBeforeChildAt(int childIndex) { 585 if (childIndex == 0) { 586 return false; 587 } 588 final View childBefore = getChildAt(childIndex - 1); 589 final View child = getChildAt(childIndex); 590 boolean result = false; 591 if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) { 592 result |= ((ActionMenuChildView) childBefore).needsDividerAfter(); 593 } 594 if (childIndex > 0 && child instanceof ActionMenuChildView) { 595 result |= ((ActionMenuChildView) child).needsDividerBefore(); 596 } 597 return result; 598 } 599 600 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 601 return false; 602 } 603 604 /** 605 * Interface responsible for receiving menu item click events if the items themselves 606 * do not have individual item click listeners. 607 */ 608 public interface OnMenuItemClickListener { 609 /** 610 * This method will be invoked when a menu item is clicked if the item itself did 611 * not already handle the event. 612 * 613 * @param item {@link MenuItem} that was clicked 614 * @return <code>true</code> if the event was handled, <code>false</code> otherwise. 615 */ 616 public boolean onMenuItemClick(MenuItem item); 617 } 618 619 private class MenuBuilderCallback implements MenuBuilder.Callback { 620 @Override 621 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 622 return mOnMenuItemClickListener != null && 623 mOnMenuItemClickListener.onMenuItemClick(item); 624 } 625 626 @Override 627 public void onMenuModeChange(MenuBuilder menu) { 628 } 629 } 630 631 private class ActionMenuPresenterCallback implements ActionMenuPresenter.Callback { 632 @Override 633 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 634 } 635 636 @Override 637 public boolean onOpenSubMenu(MenuBuilder subMenu) { 638 return false; 639 } 640 } 641 642 /** @hide */ 643 public interface ActionMenuChildView { 644 public boolean needsDividerBefore(); 645 public boolean needsDividerAfter(); 646 } 647 648 public static class LayoutParams extends LinearLayout.LayoutParams { 649 /** @hide */ 650 @ViewDebug.ExportedProperty(category = "layout") 651 public boolean isOverflowButton; 652 653 /** @hide */ 654 @ViewDebug.ExportedProperty(category = "layout") 655 public int cellsUsed; 656 657 /** @hide */ 658 @ViewDebug.ExportedProperty(category = "layout") 659 public int extraPixels; 660 661 /** @hide */ 662 @ViewDebug.ExportedProperty(category = "layout") 663 public boolean expandable; 664 665 /** @hide */ 666 @ViewDebug.ExportedProperty(category = "layout") 667 public boolean preventEdgeOffset; 668 669 /** @hide */ 670 public boolean expanded; 671 672 public LayoutParams(Context c, AttributeSet attrs) { 673 super(c, attrs); 674 } 675 676 public LayoutParams(ViewGroup.LayoutParams other) { 677 super(other); 678 } 679 680 public LayoutParams(LayoutParams other) { 681 super((LinearLayout.LayoutParams) other); 682 isOverflowButton = other.isOverflowButton; 683 } 684 685 public LayoutParams(int width, int height) { 686 super(width, height); 687 isOverflowButton = false; 688 } 689 690 /** @hide */ 691 public LayoutParams(int width, int height, boolean isOverflowButton) { 692 super(width, height); 693 this.isOverflowButton = isOverflowButton; 694 } 695 } 696} 697