1 /* 2 * Copyright (C) 2015 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 17 package com.android.layoutlib.bridge.impl; 18 19 import com.android.ide.common.rendering.api.HardwareConfig; 20 import com.android.ide.common.rendering.api.RenderResources; 21 import com.android.ide.common.rendering.api.ResourceNamespace; 22 import com.android.ide.common.rendering.api.ResourceReference; 23 import com.android.ide.common.rendering.api.ResourceValue; 24 import com.android.ide.common.rendering.api.SessionParams; 25 import com.android.layoutlib.bridge.Bridge; 26 import com.android.layoutlib.bridge.android.BridgeContext; 27 import com.android.layoutlib.bridge.android.RenderParamsFlags; 28 import com.android.layoutlib.bridge.bars.AppCompatActionBar; 29 import com.android.layoutlib.bridge.bars.BridgeActionBar; 30 import com.android.layoutlib.bridge.bars.Config; 31 import com.android.layoutlib.bridge.bars.FrameworkActionBar; 32 import com.android.layoutlib.bridge.bars.NavigationBar; 33 import com.android.layoutlib.bridge.bars.StatusBar; 34 import com.android.layoutlib.bridge.bars.TitleBar; 35 import com.android.resources.Density; 36 import com.android.resources.ResourceType; 37 import com.android.resources.ScreenOrientation; 38 39 import android.R.id; 40 import android.annotation.NonNull; 41 import android.annotation.Nullable; 42 import android.graphics.Color; 43 import android.graphics.drawable.Drawable; 44 import android.util.DisplayMetrics; 45 import android.util.TypedValue; 46 import android.view.AttachInfo_Accessor; 47 import android.view.View; 48 import android.view.ViewRootImpl; 49 import android.view.ViewRootImpl_Accessor; 50 import android.widget.FrameLayout; 51 import android.widget.LinearLayout; 52 import android.widget.RelativeLayout; 53 54 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 55 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; 56 import static android.widget.LinearLayout.VERTICAL; 57 import static com.android.layoutlib.bridge.impl.ResourceHelper.getBooleanThemeFrameworkAttrValue; 58 import static com.android.layoutlib.bridge.impl.ResourceHelper.getBooleanThemeValue; 59 60 /** 61 * The Layout used to create the system decor. 62 * <p> 63 * The layout inflated will contain a content frame where the user's layout can be inflated. 64 * <pre> 65 * +-------------------------------------------------+---+ 66 * | Status bar | N | 67 * +-------------------------------------------------+ a | 68 * | Title/Framework Action bar (optional) | v | 69 * +-------------------------------------------------+ | 70 * | AppCompat Action bar (optional) | | 71 * +-------------------------------------------------+ | 72 * | Content, vertical extending | b | 73 * | | a | 74 * | | r | 75 * +-------------------------------------------------+---+ 76 * </pre> 77 * or 78 * <pre> 79 * +--------------------------------------+ 80 * | Status bar | 81 * +--------------------------------------+ 82 * | Title/Framework Action bar (optional)| 83 * +--------------------------------------+ 84 * | AppCompat Action bar (optional) | 85 * +--------------------------------------+ 86 * | Content, vertical extending | 87 * | | 88 * | | 89 * +--------------------------------------+ 90 * | Nav bar | 91 * +--------------------------------------+ 92 * </pre> 93 */ 94 class Layout extends FrameLayout { 95 96 // Theme attributes used for configuring appearance of the system decor. 97 private static final String ATTR_WINDOW_FLOATING = "windowIsFloating"; 98 private static final String ATTR_WINDOW_BACKGROUND = "windowBackground"; 99 private static final String ATTR_WINDOW_FULL_SCREEN = "windowFullscreen"; 100 private static final String ATTR_NAV_BAR_HEIGHT = "navigation_bar_height"; 101 private static final String ATTR_NAV_BAR_WIDTH = "navigation_bar_width"; 102 private static final String ATTR_STATUS_BAR_HEIGHT = "status_bar_height"; 103 private static final String ATTR_WINDOW_ACTION_BAR = "windowActionBar"; 104 private static final String ATTR_ACTION_BAR_SIZE = "actionBarSize"; 105 private static final String ATTR_WINDOW_NO_TITLE = "windowNoTitle"; 106 private static final String ATTR_WINDOW_TITLE_SIZE = "windowTitleSize"; 107 private static final String ATTR_WINDOW_TRANSLUCENT_STATUS = StatusBar.ATTR_TRANSLUCENT; 108 private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT; 109 110 // Default sizes 111 private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; 112 private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; 113 private static final int DEFAULT_NAV_BAR_SIZE = 48; 114 115 // Ids assigned to components created. This is so that we can refer to other components in 116 // layout params. 117 private static final String ID_NAV_BAR = "navBar"; 118 private static final String ID_STATUS_BAR = "statusBar"; 119 private static final String ID_APP_COMPAT_ACTION_BAR = "appCompatActionBar"; 120 private static final String ID_FRAMEWORK_BAR = "frameworkBar"; 121 // Prefix used with the above ids in order to make them unique in framework namespace. 122 private static final String ID_PREFIX = "android_layoutlib_"; 123 124 /** 125 * Temporarily store the builder so that it doesn't have to be passed to all methods used 126 * during inflation. 127 */ 128 private Builder mBuilder; 129 130 /** 131 * SysUI layout 132 */ 133 private RelativeLayout mSysUiRoot; 134 135 /** 136 * This holds user's layout. 137 */ 138 private FrameLayout mContentRoot; 139 Layout(@onNull Builder builder)140 public Layout(@NonNull Builder builder) { 141 super(builder.mContext); 142 143 mBuilder = builder; 144 View frameworkActionBar = null; 145 View appCompatActionBar = null; 146 TitleBar titleBar = null; 147 StatusBar statusBar = null; 148 NavigationBar navBar = null; 149 150 if (builder.mWindowBackground != null) { 151 Drawable d = ResourceHelper.getDrawable(builder.mWindowBackground, builder.mContext); 152 setBackground(d); 153 } 154 155 int simulatedPlatformVersion = getParams().getSimulatedPlatformVersion(); 156 HardwareConfig hwConfig = getParams().getHardwareConfig(); 157 Density density = hwConfig.getDensity(); 158 boolean isRtl = Bridge.isLocaleRtl(getParams().getLocale()); 159 setLayoutDirection(isRtl ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR); 160 161 if (mBuilder.hasNavBar()) { 162 navBar = createNavBar(getContext(), density, isRtl, getParams().isRtlSupported(), 163 simulatedPlatformVersion, false); 164 } 165 166 if (builder.hasStatusBar()) { 167 statusBar = createStatusBar(getContext(), density, isRtl, getParams().isRtlSupported(), 168 simulatedPlatformVersion); 169 } 170 171 if (mBuilder.hasAppCompatActionBar()) { 172 BridgeActionBar bar = createActionBar(getContext(), getParams(), true); 173 mContentRoot = bar.getContentRoot(); 174 appCompatActionBar = bar.getRootView(); 175 } 176 177 // Title bar must appear on top of the Action bar 178 if (mBuilder.hasTitleBar()) { 179 titleBar = createTitleBar(getContext(), getParams().getAppLabel(), 180 simulatedPlatformVersion); 181 } else if (mBuilder.hasFrameworkActionBar()) { 182 BridgeActionBar bar = createActionBar(getContext(), getParams(), false); 183 if(mContentRoot == null) { 184 // We only set the content root if the AppCompat action bar did not already 185 // provide it 186 mContentRoot = bar.getContentRoot(); 187 } 188 frameworkActionBar = bar.getRootView(); 189 } 190 191 mSysUiRoot = new RelativeLayout(builder.mContext); 192 addSystemUiViews(titleBar, mContentRoot == null ? (mContentRoot = createContentFrame()) : frameworkActionBar, 193 statusBar, navBar, appCompatActionBar); 194 addView(mSysUiRoot); 195 //addView(createSysUiOverlay(mBuilder.mContext)); 196 // Done with the builder. Don't hold a reference to it. 197 mBuilder = null; 198 } 199 200 @NonNull createSysUiOverlay(@onNull BridgeContext context)201 private static View createSysUiOverlay(@NonNull BridgeContext context) { 202 SysUiOverlay overlay = new SysUiOverlay(context, 20, 10, 50, 40, 60); 203 overlay.setNotchColor(Color.BLACK); 204 overlay.setLayoutParams(new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); 205 return overlay; 206 } 207 208 @NonNull createContentFrame()209 private FrameLayout createContentFrame() { 210 FrameLayout contentRoot = new FrameLayout(getContext()); 211 RelativeLayout.LayoutParams params = createSysUiLayoutParams(MATCH_PARENT, MATCH_PARENT); 212 int rule = mBuilder.isNavBarVertical() ? RelativeLayout.START_OF : RelativeLayout.ABOVE; 213 if (mBuilder.hasSolidNavBar()) { 214 params.addRule(rule, getId(ID_NAV_BAR)); 215 } 216 int below = -1; 217 if (mBuilder.mAppCompatActionBarSize > 0) { 218 below = getId(ID_APP_COMPAT_ACTION_BAR); 219 } else if (mBuilder.hasFrameworkActionBar() || mBuilder.hasTitleBar()) { 220 below = getId(ID_FRAMEWORK_BAR); 221 } else if (mBuilder.hasSolidStatusBar()) { 222 below = getId(ID_STATUS_BAR); 223 } 224 if (below != -1) { 225 params.addRule(RelativeLayout.BELOW, below); 226 } 227 contentRoot.setLayoutParams(params); 228 contentRoot.setId(id.content); 229 return contentRoot; 230 } 231 232 @NonNull createSysUiLayoutParams(int width, int height)233 private RelativeLayout.LayoutParams createSysUiLayoutParams(int width, int height) { 234 DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); 235 if (width > 0) { 236 width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, metrics); 237 } 238 if (height > 0) { 239 height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics); 240 } 241 return new RelativeLayout.LayoutParams(width, height); 242 } 243 244 @NonNull getContentRoot()245 public FrameLayout getContentRoot() { 246 return mContentRoot; 247 } 248 249 @NonNull getParams()250 private SessionParams getParams() { 251 return mBuilder.mParams; 252 } 253 254 @NonNull 255 @Override getContext()256 public BridgeContext getContext() { 257 return (BridgeContext) super.getContext(); 258 } 259 260 /** 261 * @param isRtl whether the current locale is an RTL locale. 262 * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true in the 263 * manifest and targetSdkVersion >= 17. 264 */ 265 @NonNull createStatusBar(BridgeContext context, Density density, boolean isRtl, boolean isRtlSupported, int simulatedPlatformVersion)266 private StatusBar createStatusBar(BridgeContext context, Density density, boolean isRtl, 267 boolean isRtlSupported, int simulatedPlatformVersion) { 268 StatusBar statusBar = 269 new StatusBar(context, density, isRtl, isRtlSupported, simulatedPlatformVersion); 270 RelativeLayout.LayoutParams params = createSysUiLayoutParams(MATCH_PARENT, mBuilder 271 .mStatusBarSize); 272 if (mBuilder.isNavBarVertical()) { 273 params.addRule(RelativeLayout.START_OF, getId(ID_NAV_BAR)); 274 } 275 statusBar.setLayoutParams(params); 276 statusBar.setId(getId(ID_STATUS_BAR)); 277 return statusBar; 278 } 279 createActionBar(@onNull BridgeContext context, @NonNull SessionParams params, boolean appCompatActionBar)280 private BridgeActionBar createActionBar(@NonNull BridgeContext context, 281 @NonNull SessionParams params, boolean appCompatActionBar) { 282 boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); 283 String id; 284 285 // For the framework action bar, we set the height to MATCH_PARENT only if there is no 286 // AppCompat ActionBar below it 287 int heightRule = appCompatActionBar || !mBuilder.hasAppCompatActionBar() ? MATCH_PARENT : 288 WRAP_CONTENT; 289 RelativeLayout.LayoutParams layoutParams = createSysUiLayoutParams(MATCH_PARENT, heightRule); 290 int rule = mBuilder.isNavBarVertical() ? RelativeLayout.START_OF : RelativeLayout.ABOVE; 291 if (mBuilder.hasSolidNavBar()) { 292 // If there 293 if(rule == RelativeLayout.START_OF || appCompatActionBar || !mBuilder.hasAppCompatActionBar()) { 294 layoutParams.addRule(rule, getId(ID_NAV_BAR)); 295 } 296 } 297 298 299 BridgeActionBar actionBar; 300 if (appCompatActionBar && !isMenu) { 301 actionBar = new AppCompatActionBar(context, params); 302 id = ID_APP_COMPAT_ACTION_BAR; 303 304 if (mBuilder.hasTitleBar() || mBuilder.hasFrameworkActionBar()) { 305 layoutParams.addRule(RelativeLayout.BELOW, getId(ID_FRAMEWORK_BAR)); 306 } else if (mBuilder.hasSolidStatusBar()) { 307 layoutParams.addRule(RelativeLayout.BELOW, getId(ID_STATUS_BAR)); 308 } 309 } else { 310 actionBar = new FrameworkActionBar(context, params); 311 id = ID_FRAMEWORK_BAR; 312 if (mBuilder.hasSolidStatusBar()) { 313 layoutParams.addRule(RelativeLayout.BELOW, getId(ID_STATUS_BAR)); 314 } 315 } 316 317 actionBar.getRootView().setLayoutParams(layoutParams); 318 actionBar.getRootView().setId(getId(id)); 319 actionBar.createMenuPopup(); 320 return actionBar; 321 } 322 323 @NonNull createTitleBar(BridgeContext context, String title, int simulatedPlatformVersion)324 private TitleBar createTitleBar(BridgeContext context, String title, 325 int simulatedPlatformVersion) { 326 TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion); 327 RelativeLayout.LayoutParams params = createSysUiLayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize); 328 if (mBuilder.hasSolidStatusBar()) { 329 params.addRule(RelativeLayout.BELOW, getId(ID_STATUS_BAR)); 330 } 331 if (mBuilder.isNavBarVertical() && mBuilder.hasSolidNavBar()) { 332 params.addRule(RelativeLayout.START_OF, getId(ID_NAV_BAR)); 333 } 334 titleBar.setLayoutParams(params); 335 titleBar.setId(getId(ID_FRAMEWORK_BAR)); 336 return titleBar; 337 } 338 339 /** 340 * @param isRtl whether the current locale is an RTL locale. 341 * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true in the 342 * manifest and targetSdkVersion >= 17. 343 */ 344 @NonNull createNavBar(BridgeContext context, Density density, boolean isRtl, boolean isRtlSupported, int simulatedPlatformVersion, boolean isQuickStepEnabled)345 private NavigationBar createNavBar(BridgeContext context, Density density, boolean isRtl, 346 boolean isRtlSupported, int simulatedPlatformVersion, boolean isQuickStepEnabled) { 347 int orientation = mBuilder.mNavBarOrientation; 348 int size = mBuilder.mNavBarSize; 349 // Only allow quickstep in the latest version or >= 28 350 isQuickStepEnabled = isQuickStepEnabled && 351 (simulatedPlatformVersion == 0 || simulatedPlatformVersion >= 28); 352 NavigationBar navBar = 353 new NavigationBar(context, density, orientation, isRtl, isRtlSupported, 354 simulatedPlatformVersion, isQuickStepEnabled); 355 boolean isVertical = mBuilder.isNavBarVertical(); 356 int w = isVertical ? size : MATCH_PARENT; 357 int h = isVertical ? MATCH_PARENT : size; 358 RelativeLayout.LayoutParams params = createSysUiLayoutParams(w, h); 359 params.addRule(isVertical ? RelativeLayout.ALIGN_PARENT_END : RelativeLayout.ALIGN_PARENT_BOTTOM); 360 navBar.setLayoutParams(params); 361 navBar.setId(getId(ID_NAV_BAR)); 362 return navBar; 363 } 364 addSystemUiViews(@onNull View... views)365 private void addSystemUiViews(@NonNull View... views) { 366 for (View view : views) { 367 if (view != null) { 368 mSysUiRoot.addView(view); 369 } 370 } 371 } 372 getId(String name)373 private int getId(String name) { 374 return Bridge.getResourceId(ResourceType.ID, ID_PREFIX + name); 375 } 376 377 @SuppressWarnings("deprecation") 378 @Override requestFitSystemWindows()379 public void requestFitSystemWindows() { 380 // The framework call would usually bubble up to ViewRootImpl but, in layoutlib, Layout will 381 // act as view root for most purposes. That way, we can also save going through the Handler 382 // to dispatch the new applied insets. 383 ViewRootImpl root = AttachInfo_Accessor.getRootView(this); 384 if (root != null) { 385 ViewRootImpl_Accessor.dispatchApplyInsets(root, this); 386 } 387 } 388 389 /** 390 * A helper class to help initialize the Layout. 391 */ 392 static class Builder { 393 @NonNull 394 private final SessionParams mParams; 395 @NonNull 396 private final BridgeContext mContext; 397 private final RenderResources mResources; 398 399 private final boolean mWindowIsFloating; 400 private ResourceValue mWindowBackground; 401 private int mStatusBarSize; 402 private int mNavBarSize; 403 private int mNavBarOrientation; 404 private int mAppCompatActionBarSize; 405 private int mFrameworkActionBarSize; 406 private int mTitleBarSize; 407 private boolean mTranslucentStatus; 408 private boolean mTranslucentNav; 409 Builder(@onNull SessionParams params, @NonNull BridgeContext context)410 public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) { 411 mParams = params; 412 mContext = context; 413 mResources = mParams.getResources(); 414 mWindowIsFloating = 415 getBooleanThemeFrameworkAttrValue(mResources, ATTR_WINDOW_FLOATING, true); 416 417 findBackground(); 418 419 if (!mParams.isForceNoDecor()) { 420 findStatusBar(); 421 findFrameworkBar(); 422 findAppCompatActionBar(); 423 findNavBar(); 424 } 425 } 426 findBackground()427 private void findBackground() { 428 if (!mParams.isTransparentBackground()) { 429 mWindowBackground = mResources.findItemInTheme( 430 BridgeContext.createFrameworkAttrReference(ATTR_WINDOW_BACKGROUND)); 431 mWindowBackground = mResources.resolveResValue(mWindowBackground); 432 } 433 } 434 findStatusBar()435 private void findStatusBar() { 436 boolean windowFullScreen = 437 getBooleanThemeFrameworkAttrValue(mResources, ATTR_WINDOW_FULL_SCREEN, false); 438 if (!windowFullScreen && !mWindowIsFloating) { 439 mStatusBarSize = 440 getFrameworkAttrDimension(ATTR_STATUS_BAR_HEIGHT, DEFAULT_STATUS_BAR_HEIGHT); 441 mTranslucentStatus = 442 getBooleanThemeFrameworkAttrValue( 443 mResources, ATTR_WINDOW_TRANSLUCENT_STATUS, false); 444 } 445 } 446 447 /** 448 * The behavior is different whether the App is using AppCompat or not. 449 * <h1>With App compat :</h1> 450 * <li> framework ("android:") attributes have to effect 451 * <li> windowNoTile=true hides the AppCompatActionBar 452 * <li> windowActionBar=false throws an exception 453 */ findAppCompatActionBar()454 private void findAppCompatActionBar() { 455 if (mWindowIsFloating || !mContext.isAppCompatTheme()) { 456 return; 457 } 458 459 boolean windowNoTitle = 460 getBooleanThemeValue(mResources, 461 mContext.createAppCompatAttrReference(ATTR_WINDOW_NO_TITLE), false); 462 463 boolean windowActionBar = 464 getBooleanThemeValue(mResources, 465 mContext.createAppCompatAttrReference(ATTR_WINDOW_ACTION_BAR), true); 466 467 if (!windowNoTitle && windowActionBar) { 468 mAppCompatActionBarSize = 469 getDimension(mContext.createAppCompatAttrReference(ATTR_ACTION_BAR_SIZE), 470 DEFAULT_TITLE_BAR_HEIGHT); 471 } 472 } 473 474 /** 475 * Find if we should show either the titleBar or the framework ActionBar 476 * <p> 477 * <h1> Without App compat :</h1> 478 * <li> windowNoTitle has no effect 479 * <li> android:windowNoTile=true hides the <b>ActionBar</b> 480 * <li> android:windowActionBar=true/false toggles between ActionBar/TitleBar 481 * </ul> 482 * <pre> 483 * +------------------------------------------------------------+ 484 * | | android:windowNoTitle | 485 * |android: | TRUE | FALSE | 486 * |windowActionBar|---------------------+----------------------+ 487 * | TRUE | Nothing | ActionBar (Default) | 488 * | FALSE | Nothing | TitleBar | 489 * +---------------+--------------------------------------------+ 490 * </pre> 491 * 492 * @see #findAppCompatActionBar() 493 */ findFrameworkBar()494 private void findFrameworkBar() { 495 if (mWindowIsFloating) { 496 return; 497 } 498 boolean frameworkWindowNoTitle = 499 getBooleanThemeFrameworkAttrValue(mResources, ATTR_WINDOW_NO_TITLE, false); 500 501 // Check if an actionbar is needed 502 boolean isMenu = "menu".equals(mParams.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); 503 504 boolean windowActionBar = 505 getBooleanThemeFrameworkAttrValue(mResources, ATTR_WINDOW_ACTION_BAR, true); 506 507 if (!frameworkWindowNoTitle || isMenu) { 508 if (isMenu || windowActionBar) { 509 mFrameworkActionBarSize = 510 getFrameworkAttrDimension(ATTR_ACTION_BAR_SIZE, DEFAULT_TITLE_BAR_HEIGHT); 511 } else { 512 mTitleBarSize = getDimension( 513 mContext.createAppCompatAttrReference(ATTR_WINDOW_TITLE_SIZE), 514 DEFAULT_TITLE_BAR_HEIGHT); 515 } 516 } 517 } 518 findNavBar()519 private void findNavBar() { 520 if (hasSoftwareButtons() && !mWindowIsFloating) { 521 // get orientation 522 HardwareConfig hwConfig = mParams.getHardwareConfig(); 523 boolean barOnBottom = true; 524 525 if (hwConfig.getOrientation() == ScreenOrientation.LANDSCAPE) { 526 int shortSize = hwConfig.getScreenHeight(); 527 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / 528 hwConfig.getDensity().getDpiValue(); 529 530 // 0-599dp: "phone" UI with bar on the side 531 // 600+dp: "tablet" UI with bar on the bottom 532 barOnBottom = shortSizeDp >= 600; 533 } 534 535 mNavBarOrientation = barOnBottom ? LinearLayout.HORIZONTAL : VERTICAL; 536 mNavBarSize = 537 getFrameworkAttrDimension( 538 barOnBottom ? ATTR_NAV_BAR_HEIGHT : ATTR_NAV_BAR_WIDTH, 539 DEFAULT_NAV_BAR_SIZE); 540 mTranslucentNav = 541 getBooleanThemeFrameworkAttrValue(mResources, ATTR_WINDOW_TRANSLUCENT_NAV, 542 false); 543 } 544 } 545 getDimension(@onNull ResourceReference attrRef, int defaultValue)546 private int getDimension(@NonNull ResourceReference attrRef, int defaultValue) { 547 ResourceValue value = mResources.findItemInTheme(attrRef); 548 value = mResources.resolveResValue(value); 549 if (value != null) { 550 TypedValue typedValue = ResourceHelper.getValue(attrRef.getName(), value.getValue(), 551 true); 552 if (typedValue != null) { 553 return (int) typedValue.getDimension(mContext.getMetrics()); 554 } 555 } 556 return defaultValue; 557 } 558 getFrameworkAttrDimension(@onNull String attr, int defaultValue)559 private int getFrameworkAttrDimension(@NonNull String attr, int defaultValue) { 560 return getDimension(BridgeContext.createFrameworkAttrReference(attr), defaultValue); 561 } 562 hasSoftwareButtons()563 private boolean hasSoftwareButtons() { 564 return mParams.getHardwareConfig().hasSoftwareButtons(); 565 } 566 567 /** 568 * Returns true if the nav bar is present and not translucent. 569 */ hasSolidNavBar()570 private boolean hasSolidNavBar() { 571 return hasNavBar() && !mTranslucentNav; 572 } 573 574 /** 575 * Returns true if the status bar is present and not translucent. 576 */ hasSolidStatusBar()577 private boolean hasSolidStatusBar() { 578 return hasStatusBar() && !mTranslucentStatus; 579 } 580 hasNavBar()581 private boolean hasNavBar() { 582 return Config.showOnScreenNavBar(mParams.getSimulatedPlatformVersion()) && 583 hasSoftwareButtons() && mNavBarSize > 0; 584 } 585 hasTitleBar()586 private boolean hasTitleBar() { 587 return mTitleBarSize > 0; 588 } 589 hasStatusBar()590 private boolean hasStatusBar() { 591 return mStatusBarSize > 0; 592 } 593 hasAppCompatActionBar()594 private boolean hasAppCompatActionBar() { 595 return mAppCompatActionBarSize > 0; 596 } 597 598 /** 599 * Return true if the nav bar is present and is vertical. 600 */ isNavBarVertical()601 private boolean isNavBarVertical() { 602 return hasNavBar() && mNavBarOrientation == VERTICAL; 603 } 604 hasFrameworkActionBar()605 private boolean hasFrameworkActionBar() { 606 return mFrameworkActionBarSize > 0; 607 } 608 hasNotch()609 private boolean hasNotch() { 610 return !mParams.isForceNoDecor(); 611 } 612 } 613 } 614