RenderSessionImpl.java revision bca9e5623c820c9aa1e959e3874442de9a9a6c32
13bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/* 23bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 33bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 43bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 53bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * you may not use this file except in compliance with the License. 63bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * You may obtain a copy of the License at 73bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 83bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 93bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software 113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * See the License for the specific language governing permissions and 143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * limitations under the License. 153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetpackage com.android.layoutlib.bridge.impl; 183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 197062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding; 2064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig; 21ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener; 22ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser; 235cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perezimport com.android.ide.common.rendering.api.LayoutLog; 24b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport com.android.ide.common.rendering.api.LayoutlibCallback; 250d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 26ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 277062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference; 28ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 29ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 30ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 31d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams; 32b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode; 33d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo; 3470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport com.android.ide.common.rendering.api.ViewType; 3541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView; 3641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl; 3741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView; 3841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView; 3941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl; 4041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuView; 41ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 43ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; 443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 45a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaevimport com.android.layoutlib.bridge.android.RenderParamsFlags; 46259504c6368e44adfffd4f56f7a838b2d5e73ff9Diego Perezimport com.android.layoutlib.bridge.android.graphics.NopCanvas; 47c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsenimport com.android.layoutlib.bridge.android.support.DesignLibUtil; 48b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perezimport com.android.layoutlib.bridge.android.support.SupportPreferencesUtil; 497062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter; 507062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; 511b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohetimport com.android.resources.ResourceType; 52344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Guptaimport com.android.tools.layoutlib.java.System_Delegate; 53947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohetimport com.android.util.Pair; 5418be29a3d14f1b3e840e8ee88b5a1951a6f6e9c8Deepanshu Guptaimport com.android.util.PropertiesMap; 553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 56994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.animation.AnimationThread; 5733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.Animator; 58ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport android.animation.AnimatorInflater; 5933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.LayoutTransition; 6062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 61442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.NonNull; 62442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.Nullable; 633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.app.Fragment_Delegate; 643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap; 653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Canvas; 67e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perezimport android.os.Looper; 688a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Guptaimport android.preference.Preference_Delegate; 69994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.AttachInfo_Accessor; 70994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.BridgeInflater; 71344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Guptaimport android.view.Choreographer_Delegate; 7276f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.IWindowManager; 7364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport android.view.IWindowManagerImpl; 7476f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.Surface; 753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View; 763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View.MeasureSpec; 77d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.view.ViewGroup; 78ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport android.view.ViewGroup.LayoutParams; 796208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams; 8070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.view.ViewParent; 8176f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate; 827062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsListView; 837062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsSpinner; 8470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.widget.ActionMenuView; 857062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AdapterView; 867062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ExpandableListView; 873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.FrameLayout; 88f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.LinearLayout; 897062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ListView; 9062c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohetimport android.widget.QuickContactBadge; 913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.TabHost; 92f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.TabHost.TabSpec; 93d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.widget.TabWidget; 943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 954c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohetimport java.awt.AlphaComposite; 963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Color; 973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Graphics2D; 983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.image.BufferedImage; 993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.ArrayList; 1003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.List; 1013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.Map; 1023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 103b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 104b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 105b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 106b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 107b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 108b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 109baf88de1f5c435a788f6c38720354b2dbaa19e60Deepanshu Guptaimport static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; 110b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta 1113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/** 112ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * Class implementing the render session. 113952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * <p/> 114ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 115ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 1163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * be done on the layout. 1173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 1180fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> { 1193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 120259504c6368e44adfffd4f56f7a838b2d5e73ff9Diego Perez private static final Canvas NOP_CANVAS = new NopCanvas(); 121259504c6368e44adfffd4f56f7a838b2d5e73ff9Diego Perez 1223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // scene state 123ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private RenderSession mScene; 1243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 1253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BridgeInflater mInflater; 126799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet private ViewGroup mViewRoot; 127799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet private FrameLayout mContentRoot; 1281392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private Canvas mCanvas; 1291392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private int mMeasuredScreenWidth = -1; 1301392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private int mMeasuredScreenHeight = -1; 131799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet private boolean mIsAlphaChannelImage; 132344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta /** If >= 0, a frame will be executed */ 133344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta private long mElapsedFrameTimeNanos = -1; 134344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta /** True if one frame has been already executed to start the animations */ 135344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta private boolean mFirstFrameExecuted = false; 136a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // information being returned through the API 1383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BufferedImage mImage; 139e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet private List<ViewInfo> mViewInfoList; 14085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta private List<ViewInfo> mSystemViewInfoList; 1418b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta private Layout.Builder mLayoutBuilder; 1426e1b7e3e383e12d36356841130647b846e4c8467Diego Perez private boolean mNewRenderSize; 1433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final class PostInflateException extends Exception { 1453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final long serialVersionUID = 1L; 1463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 147bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez private PostInflateException(String message) { 1483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet super(message); 1493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 1533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 1543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 1558d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)}, 1568d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * which act as a 157ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 1583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 1598d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * @see Bridge#createSession(SessionParams) 1603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 161b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohet public RenderSessionImpl(SessionParams params) { 1620fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet super(new SessionParams(params)); 163ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 164ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 165ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 166ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 167ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * inflater, and parser. 168ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 169ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 170ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 171ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @return whether the scene was prepared 172ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 173ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @see #acquire(long) 174ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @see #release() 175ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 1760fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet @Override 177ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result init(long timeout) { 1780fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet Result result = super.init(timeout); 179952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 180ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet return result; 181ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 1823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1830fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet SessionParams params = getParams(); 1840fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 1853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 186a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // use default of true in case it's not found to use alpha by default 187300f4893351a9974fa3380c513b29d4a7883cd74Deepanshu Gupta mIsAlphaChannelImage = ResourceHelper.getBooleanThemeValue(params.getResources(), 188300f4893351a9974fa3380c513b29d4a7883cd74Deepanshu Gupta "windowIsFloating", true, true); 189ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 1908b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mLayoutBuilder = new Layout.Builder(params, context); 1913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 19276f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet // FIXME: find those out, and possibly add them to the render params 19376f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet boolean hasNavigationBar = true; 194952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta //noinspection ConstantConditions 19576f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), 1968b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); 19776f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet WindowManagerGlobal_Delegate.setWindowManagerService(iwm); 19876f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet 1993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // build the inflater and parser. 200b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); 2010fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet context.setBridgeInflater(mInflater); 202ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 2038b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); 204ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 2053054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet return SUCCESS.createResult(); 2063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 2096e1b7e3e383e12d36356841130647b846e4c8467Diego Perez * Measures the the current layout if needed (see {@link #invalidateRenderingSize}). 2106e1b7e3e383e12d36356841130647b846e4c8467Diego Perez */ 2117bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez private void measureLayout(@NonNull SessionParams params) { 2126e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // only do the screen measure when needed. 2136e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (mMeasuredScreenWidth != -1) { 2146e1b7e3e383e12d36356841130647b846e4c8467Diego Perez return; 2156e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2166e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2176e1b7e3e383e12d36356841130647b846e4c8467Diego Perez RenderingMode renderingMode = params.getRenderingMode(); 2186e1b7e3e383e12d36356841130647b846e4c8467Diego Perez HardwareConfig hardwareConfig = params.getHardwareConfig(); 2196e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2206e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mNewRenderSize = true; 2216e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); 2226e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); 2236e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2246e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (renderingMode != RenderingMode.NORMAL) { 2256e1b7e3e383e12d36356841130647b846e4c8467Diego Perez int widthMeasureSpecMode = renderingMode.isHorizExpand() ? 2266e1b7e3e383e12d36356841130647b846e4c8467Diego Perez MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 2276e1b7e3e383e12d36356841130647b846e4c8467Diego Perez : MeasureSpec.EXACTLY; 2286e1b7e3e383e12d36356841130647b846e4c8467Diego Perez int heightMeasureSpecMode = renderingMode.isVertExpand() ? 2296e1b7e3e383e12d36356841130647b846e4c8467Diego Perez MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 2306e1b7e3e383e12d36356841130647b846e4c8467Diego Perez : MeasureSpec.EXACTLY; 2316e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2326e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // We used to compare the measured size of the content to the screen size but 2336e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // this does not work anymore due to the 2 following issues: 2346e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // - If the content is in a decor (system bar, title/action bar), the root view 2356e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // will not resize even with the UNSPECIFIED because of the embedded layout. 2366e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // - If there is no decor, but a dialog frame, then the dialog padding prevents 2376e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // comparing the size of the content to the screen frame (as it would not 2386e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // take into account the dialog padding). 2396e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2406e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // The solution is to first get the content size in a normal rendering, inside 2416e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // the decor or the dialog padding. 2426e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // Then measure only the content with UNSPECIFIED to see the size difference 2436e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // and apply this to the screen size. 2446e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 245bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez View measuredView = mContentRoot.getChildAt(0); 246bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez 2476e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // first measure the full layout, with EXACTLY to get the size of the 2486e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // content as it is inside the decor/dialog 2496e1b7e3e383e12d36356841130647b846e4c8467Diego Perez @SuppressWarnings("deprecation") 2506e1b7e3e383e12d36356841130647b846e4c8467Diego Perez Pair<Integer, Integer> exactMeasure = measureView( 251bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez mViewRoot, measuredView, 2526e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenWidth, MeasureSpec.EXACTLY, 2536e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenHeight, MeasureSpec.EXACTLY); 2546e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2556e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // now measure the content only using UNSPECIFIED (where applicable, based on 2566e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // the rendering mode). This will give us the size the content needs. 2576e1b7e3e383e12d36356841130647b846e4c8467Diego Perez @SuppressWarnings("deprecation") 2586e1b7e3e383e12d36356841130647b846e4c8467Diego Perez Pair<Integer, Integer> result = measureView( 2596e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mContentRoot, mContentRoot.getChildAt(0), 2606e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenWidth, widthMeasureSpecMode, 2616e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenHeight, heightMeasureSpecMode); 2626e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 263bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez // If measuredView is not null, exactMeasure nor result will be null. 264bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez assert exactMeasure != null; 265bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez assert result != null; 266bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez 2676e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // now look at the difference and add what is needed. 2686e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (renderingMode.isHorizExpand()) { 2696e1b7e3e383e12d36356841130647b846e4c8467Diego Perez int measuredWidth = exactMeasure.getFirst(); 2706e1b7e3e383e12d36356841130647b846e4c8467Diego Perez int neededWidth = result.getFirst(); 2716e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (neededWidth > measuredWidth) { 2726e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenWidth += neededWidth - measuredWidth; 2736e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2746e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (mMeasuredScreenWidth < measuredWidth) { 2756e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // If the screen width is less than the exact measured width, 2766e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // expand to match. 2776e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenWidth = measuredWidth; 2786e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2796e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2806e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2816e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (renderingMode.isVertExpand()) { 2826e1b7e3e383e12d36356841130647b846e4c8467Diego Perez int measuredHeight = exactMeasure.getSecond(); 2836e1b7e3e383e12d36356841130647b846e4c8467Diego Perez int neededHeight = result.getSecond(); 2846e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (neededHeight > measuredHeight) { 2856e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenHeight += neededHeight - measuredHeight; 2866e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2876e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (mMeasuredScreenHeight < measuredHeight) { 2886e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // If the screen height is less than the exact measured height, 2896e1b7e3e383e12d36356841130647b846e4c8467Diego Perez // expand to match. 2906e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenHeight = measuredHeight; 2916e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2926e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2936e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2946e1b7e3e383e12d36356841130647b846e4c8467Diego Perez } 2956e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 2966e1b7e3e383e12d36356841130647b846e4c8467Diego Perez /** 2973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Inflates the layout. 2983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 299ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 300ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 301ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 302ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 3033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 304ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result inflate() { 305ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 306ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 3073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet try { 3088b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mViewRoot = new Layout(mLayoutBuilder); 3098b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mLayoutBuilder = null; // Done with the builder. 3108b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mContentRoot = ((Layout) mViewRoot).getContentRoot(); 3110fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet SessionParams params = getParams(); 3120fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 3133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3145cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez if (Bridge.isLocaleRtl(params.getLocale())) { 3155cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez if (!params.isRtlSupported()) { 3165cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_ENABLED, 3175cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez "You are using a right-to-left " + 3185cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez "(RTL) locale but RTL is not enabled", null); 3195cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez } else if (params.getSimulatedPlatformVersion() < 17) { 3205cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez // This will render ok because we are using the latest layoutlib but at least 3215cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez // warn the user that this might fail in a real device. 3225cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_SUPPORTED, "You are using a " + 3235cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez "right-to-left " + 3245cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez "(RTL) locale but RTL is not supported for API level < 17", null); 3255cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez } 3265cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez } 3275cee4833e93b8f9aa9f38815eaa342fab9cc8658Diego Perez 3283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 3293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // it can instantiate the custom Fragment. 330b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); 3313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 332a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); 3338a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta boolean isPreference = "PreferenceScreen".equals(rootTag); 3348a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta View view; 3358a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta if (isPreference) { 336b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perez // First try to use the support library inflater. If something fails, fallback 337b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perez // to the system preference inflater. 338b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perez view = SupportPreferencesUtil.inflatePreference(getContext(), mBlockParser, 3398b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mContentRoot); 340b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perez if (view == null) { 341b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perez view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, 342b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perez mContentRoot); 343b321cbfeb00723a6d18746f0d5bbcfd6b6602f6eDiego Perez } 3448a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta } else { 3458a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta view = mInflater.inflate(mBlockParser, mContentRoot); 3468a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta } 3473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3487062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // done with the parser, pop it. 3497062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet context.popParser(); 3507062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 351b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(null); 3523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // set the AttachInfo on the root view. 354994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet AttachInfo_Accessor.setAttachInfo(mViewRoot); 3553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 356a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 357b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null); 3589028fa93da0f9c7dad2176de347cd6e705084c9fDeepanshu Gupta mInflater.onDoneInflation(); 359a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet 360c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen setActiveToolbar(view, context, params); 361c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 3627bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez measureLayout(params); 3636e1b7e3e383e12d36356841130647b846e4c8467Diego Perez measureView(mViewRoot, null /*measuredView*/, 3646e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenWidth, MeasureSpec.EXACTLY, 3656e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mMeasuredScreenHeight, MeasureSpec.EXACTLY); 3666e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 367e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez mSystemViewInfoList = 368e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(), 3696e1b7e3e383e12d36356841130647b846e4c8467Diego Perez false); 3706e1b7e3e383e12d36356841130647b846e4c8467Diego Perez 371ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 3723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (PostInflateException e) { 373ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 3743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (Throwable e) { 3753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the real cause of the exception. 3763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Throwable t = e; 3773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet while (t.getCause() != null) { 3783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet t = t.getCause(); 3793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 381ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 3823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 386344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta * Sets the time for which the next frame will be selected. The time is the elapsed time from 387344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta * the current system nanos time. You 388344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta */ 389344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta public void setElapsedFrameTimeNanos(long nanos) { 390344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta mElapsedFrameTimeNanos = nanos; 391344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta } 392344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta 393344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta /** 394f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez * Runs a layout pass for the given view root 3950685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez */ 396f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez private static void doLayout(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot, 397f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez int width, int height) { 3980685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez // measure again with the size we need 3990685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez // This must always be done before the call to layout 4000685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez measureView(viewRoot, null /*measuredView*/, 4010685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez width, MeasureSpec.EXACTLY, 4020685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez height, MeasureSpec.EXACTLY); 4030685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez 4040685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez // now do the layout. 4050685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez viewRoot.layout(0, 0, width, height); 4060685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez handleScrolling(context, viewRoot); 407f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez } 4080685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez 409f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez /** 410f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez * Renders the given view hierarchy to the passed canvas and returns the result of the render 411f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez * operation. 412f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez * @param canvas an optional canvas to render the views to. If null, only the measure and 413f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez * layout steps will be executed. 414f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez */ 415bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez private static Result renderAndBuildResult(@NonNull ViewGroup viewRoot, @Nullable Canvas canvas) { 4160685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez if (canvas == null) { 4170685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez return SUCCESS.createResult(); 4180685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez } 4190685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez 4200685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez AttachInfo_Accessor.dispatchOnPreDraw(viewRoot); 4210685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez viewRoot.draw(canvas); 4220685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez 4230685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez return SUCCESS.createResult(); 4240685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez } 4250685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez 4260685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez /** 4273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Renders the scene. 4283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 429ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 430ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 4314c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 4324c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 4334c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * animations.) 4344c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * 435ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 436ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 4371392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet * 4388d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * @see SessionParams#getRenderingMode() 439799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#render(long) 4403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 4414c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet public Result render(boolean freshRender) { 4427bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez return renderAndBuildResult(freshRender, false); 4437bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez } 4447bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez 4457bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez /** 4467bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * Measures the layout 4477bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * <p> 4487bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * {@link #acquire(long)} must have been called before this. 4497bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * 4507bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * @throws IllegalStateException if the current context is different than the one owned by 4517bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * the scene, or if {@link #acquire(long)} was not called. 4527bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * 4537bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * @see SessionParams#getRenderingMode() 4547bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * @see RenderSession#render(long) 4557bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez */ 4567bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez public Result measure() { 4577bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez return renderAndBuildResult(false, true); 4587bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez } 4597bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez 4607bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez /** 4617bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * Renders the scene. 4627bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * <p> 4637bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * {@link #acquire(long)} must have been called before this. 4647bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * 4657bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * @param freshRender whether the render is a new one and should erase the existing bitmap (in 4667bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * the case where bitmaps are reused). This is typically needed when not playing 4677bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * animations.) 4687bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * 4697bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * @throws IllegalStateException if the current context is different than the one owned by 4707bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * the scene, or if {@link #acquire(long)} was not called. 4717bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * 4727bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * @see SessionParams#getRenderingMode() 4737bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez * @see RenderSession#render(long) 4747bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez */ 4757bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez private Result renderAndBuildResult(boolean freshRender, boolean onlyMeasure) { 476ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 477ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 4780fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet SessionParams params = getParams(); 4790fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet 4803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet try { 4813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (mViewRoot == null) { 482ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 4833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 4843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4857bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez measureLayout(params); 4863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4876e1b7e3e383e12d36356841130647b846e4c8467Diego Perez HardwareConfig hardwareConfig = params.getHardwareConfig(); 4880685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez Result renderResult = SUCCESS.createResult(); 4897bb8850ed2076ebf8442a5fdb68ec9a8f53623e0Diego Perez if (onlyMeasure) { 490f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // delete the canvas and image to reset them on the next full rendering 491f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mImage = null; 492f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mCanvas = null; 493f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight); 494f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } else { 495f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // draw the views 496f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // create the BufferedImage into which the layout will be rendered. 497f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet boolean newImage = false; 498e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez 499e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // When disableBitmapCaching is true, we do not reuse mImage and 500e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // we create a new one in every render. 501e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // This is useful when mImage is just a wrapper of Graphics2D so 502e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // it doesn't get cached. 503e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( 504a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); 5056e1b7e3e383e12d36356841130647b846e4c8467Diego Perez if (mNewRenderSize || mCanvas == null || disableBitmapCaching) { 5066e1b7e3e383e12d36356841130647b846e4c8467Diego Perez mNewRenderSize = false; 507f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet if (params.getImageFactory() != null) { 508f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mImage = params.getImageFactory().getImage( 509f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenWidth, 510f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenHeight); 511f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } else { 512f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mImage = new BufferedImage( 513f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenWidth, 514f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenHeight, 515f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 516f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet newImage = true; 517f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } 518f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet 519f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet if (params.isBgColorOverridden()) { 520f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 521f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet newImage = true; 522f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 523f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 524f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 525f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 526f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.dispose(); 527f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } 528f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet 529f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // create an Android bitmap around the BufferedImage 530f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 53164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet true /*isMutable*/, hardwareConfig.getDensity()); 532f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet 533e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez if (mCanvas == null) { 534e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // create a Canvas around the Android bitmap 535e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez mCanvas = new Canvas(bitmap); 536e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez } else { 537e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez mCanvas.setBitmap(bitmap); 538e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez } 53964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 5401392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 5413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 542952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (freshRender && !newImage) { 5431392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 5444c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet gc.setComposite(AlphaComposite.Src); 5453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 546f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 547f4978e031c3ad565f02d5a4c65f87ae4477f3613Deepanshu Gupta gc.fillRect(0, 0, 548f4978e031c3ad565f02d5a4c65f87ae4477f3613Deepanshu Gupta mMeasuredScreenWidth, mMeasuredScreenHeight); 549a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 550f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // done 551f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.dispose(); 552f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } 553a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 554f1a0a823499fc0a464e18b8eba992b32d14b8bb1Diego Perez doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight); 555344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta if (mElapsedFrameTimeNanos >= 0) { 556344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta long initialTime = System_Delegate.nanoTime(); 557344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta if (!mFirstFrameExecuted) { 5580685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez // We need to run an initial draw call to initialize the animations 559bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez renderAndBuildResult(mViewRoot, NOP_CANVAS); 5600685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez 561344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta // The first frame will initialize the animations 562344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta Choreographer_Delegate.doFrame(initialTime); 563344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta mFirstFrameExecuted = true; 564344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta } 565344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta // Second frame will move the animations 566344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos); 567344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta } 568bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez renderResult = renderAndBuildResult(mViewRoot, mCanvas); 5694c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet } 5704c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet 571e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez mSystemViewInfoList = 572e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(), 57341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta false); 5743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 5753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // success! 5760685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez return renderResult; 5773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (Throwable e) { 5783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the real cause of the exception. 5793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Throwable t = e; 5803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet while (t.getCause() != null) { 5813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet t = t.getCause(); 5823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 5833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 584ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 5863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 5873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 5883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 5898ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * Executes {@link View#measure(int, int)} on a given view with the given parameters (used 5908ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. 5918ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * 5928ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) 5938ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). 5948ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * 5958ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param viewToMeasure the view on which to execute measure(). 5968ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param measuredView if non null, the view to query for its measured width/height. 5978ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param width the width to use in the MeasureSpec. 5988ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param widthMode the MeasureSpec mode to use for the width. 5998ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param height the height to use in the MeasureSpec. 6008ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param heightMode the MeasureSpec mode to use for the height. 6018ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @return the measured width/height if measuredView is non-null, null otherwise. 6028ae691c1148038995d1185716f629b82c582897fXavier Ducrohet */ 603952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 6040685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, 6058ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int width, int widthMode, int height, int heightMode) { 6068ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); 6078ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); 6088ae691c1148038995d1185716f629b82c582897fXavier Ducrohet viewToMeasure.measure(w_spec, h_spec); 6098ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 6108ae691c1148038995d1185716f629b82c582897fXavier Ducrohet if (measuredView != null) { 6118ae691c1148038995d1185716f629b82c582897fXavier Ducrohet return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); 6128ae691c1148038995d1185716f629b82c582897fXavier Ducrohet } 6138ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 6148ae691c1148038995d1185716f629b82c582897fXavier Ducrohet return null; 6158ae691c1148038995d1185716f629b82c582897fXavier Ducrohet } 6168ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 6178ae691c1148038995d1185716f629b82c582897fXavier Ducrohet /** 618ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Animate an object 619ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * <p> 620ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 621ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 622ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 623ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 62433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 625799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 626ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 627ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result animate(Object targetObject, String animationName, 628ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 629ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 630ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 6310fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 6320fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet 633ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // find the animation file. 634952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta ResourceValue animationResource; 635ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet int animationId = 0; 636ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (isFrameworkAnimation) { 6370fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 6381b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 639ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 640947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 641ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 642ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } else { 6430fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 6441b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 645ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 646b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta animationId = context.getLayoutlibCallback().getResourceId( 6471b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 648ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 649ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 650ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 651ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 652ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet try { 6530fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 654ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (anim != null) { 655ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet anim.setTarget(targetObject); 656ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 65733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 658ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 659ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 660ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 661ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } catch (Exception e) { 662b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // get the real cause of the exception. 663b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet Throwable t = e; 664b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet while (t.getCause() != null) { 665b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet t = t.getCause(); 666b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 667b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 668ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 669ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 670ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 671ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 672ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 673b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 674b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 67533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 67633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Insert a new child into an existing parent. 67733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 67833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 67933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 68033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 68133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 68233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 683799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 68433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 685ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 68633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final int index, IAnimationListener listener) { 687b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet checkLock(); 688b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 6890fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 6900fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet 691b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // create a block parser for the XML 692a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 693a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet childXml, context, false /* platformResourceFlag */); 694b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 695b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 696b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 697b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // be created correctly. 69833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 699a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet blockParser.ensurePopped(); 700b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 70133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet invalidateRenderingSize(); 70233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 70333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 70433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 70533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 70633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 707ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result preAnimation() { 70833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 70933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return addView(parentView, child, index); 71033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 71133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 71233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 71333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet public void postAnimation() { 71433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parentView.setLayoutTransition(null); 71533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 71633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet }.start(); 71733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 71833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 719ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(child); 7201392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 7211392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 72233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // add it to the parentView in the correct location 723ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = addView(parentView, child, index); 724952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 72533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 72633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 727b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 7284c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 7291766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet if (result.isSuccess()) { 73033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet result = result.getCopyWithData(child); 7311766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet } 7321766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet 7331766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet return result; 734b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 735b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 73633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 73733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Adds a given view to a given parent at a given index. 73833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 73933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param parent the parent to receive the view 74033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param view the view to add to the parent 74133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param index the index where to do the add. 74233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 743ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 744ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 74533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 74633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 747ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 74833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet try { 74933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.addView(view, index); 750ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 75133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } catch (UnsupportedOperationException e) { 75233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 753ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 75433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 75533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 75633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 75733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 75833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Moves a view to a new parent at a given location 75933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 76033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 76133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 76233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 76333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 76433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 765799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 76633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 76762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 76824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 769b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet checkLock(); 770b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 77133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet invalidateRenderingSize(); 77233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 773ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet LayoutParams layoutParams = null; 77433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (layoutParamsMap != null) { 77533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 77662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 77733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 77833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 7791392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 78062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // get the current parent of the view that needs to be moved. 78162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 78262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 78333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 78433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final LayoutParams params = layoutParams; 785ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 78624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 78724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // parent views are different we fake the animation through a no animation thread. 78824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (previousParent != newParentView) { 78924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet new Thread("not animated moveChild") { 79024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 79124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public void run() { 79224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 79324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet params); 794952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 79524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 79624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 79724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 79824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // ready to do the work, acquire the scene. 79924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet result = acquire(250); 800952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 80124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 80224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet return; 80324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 80424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 80524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet try { 8064c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 80724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (result.isSuccess()) { 80824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 80924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 81024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } finally { 81124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet release(); 81224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 81324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 81424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 81562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 81624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet }.start(); 81724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } else { 81824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 81962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 82024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 82124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public Result preAnimation() { 82224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // set up the transition for the parent. 82324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet LayoutTransition transition = new LayoutTransition(); 82424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.setLayoutTransition(transition); 8255562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet 82624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // tweak the animation durations and start delays (to match the duration of 82724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // animation playing just before). 82824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 82924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // on the LayoutTransition. 83024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 83124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 83224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 833ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 83424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 83524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 83624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 83724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 83824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 83924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 84024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 84124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 84224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 84324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 84424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 84524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 84624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public void postAnimation() { 84724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.setLayoutTransition(null); 84824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParentView.setLayoutTransition(null); 84924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 85024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet }.start(); 85124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 85233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 85333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 854ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(layoutParams); 855b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 856b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 85762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 858952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 85933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 86033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 861b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 8624c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 863ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet if (layoutParams != null && result.isSuccess()) { 86433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet result = result.getCopyWithData(layoutParams); 865ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet } 866ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 867ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet return result; 868b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 869b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 87033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 87133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 87233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * an optional new {@link LayoutParams} instance 87333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 87462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 87562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet * @param newParent the new parent 87624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet * @param movedView the view to move 87733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param index the new location in the new parent 87833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 87933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 880ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 881ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 88233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 88333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 88424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 88524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet final View movedView, final int index, final LayoutParams params) { 8861392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet try { 88762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // check if there is a transition on the previousParent. 88824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 88924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (previousTransition != null) { 8905562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 8915562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 8925562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 8935562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 8945562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // to handle). 8955562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 8965562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 8975562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // adding the child or the child will appear in its new location before the 8985562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // other children have made room for it. 89962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 90062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 90124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 90224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet private int mChangeDisappearingCount = 0; 90362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 904d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet @Override 90562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 90662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet View view, int transitionType) { 90724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 90824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount++; 90924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 91062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 91133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 912d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet @Override 91362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 91462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet View view, int transitionType) { 91524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 91624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount--; 91724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 91824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 91924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 92024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount == 0) { 92162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add it to the parentView in the correct location 92262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet if (params != null) { 92324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index, params); 92462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } else { 92524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index); 92662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 92762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 92862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 92962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet }); 93062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 93162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // remove the view from the current parent. 93224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.removeView(movedView); 93362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 93462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 93562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet return SUCCESS.createResult(); 93633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } else { 93762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // standard code with no animation. pretty simple. 93824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.removeView(movedView); 93933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 94062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add it to the parentView in the correct location 94162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet if (params != null) { 94224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index, params); 94362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } else { 94424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index); 94562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 94662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 94762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet return SUCCESS.createResult(); 94862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 9491392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } catch (UnsupportedOperationException e) { 9501392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 951ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 952b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 95333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 95433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 95533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 95633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Removes a child from its current parent. 95733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 95833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 95933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 96033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 96133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 96233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 963799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 96433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 965ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 96633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet checkLock(); 967b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 9681392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet invalidateRenderingSize(); 9691392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 97033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 97133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 97233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 97333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 97433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 97533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 976ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result preAnimation() { 97733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 97833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return removeView(parent, childView); 97933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 98033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 98133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 98233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet public void postAnimation() { 98333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.setLayoutTransition(null); 98433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 98533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet }.start(); 98633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 98733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 988ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 98933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 99033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 991ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = removeView(parent, childView); 992952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 99333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 99433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 99533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 9964c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet return render(false /*freshRender*/); 997ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 998ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 999ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 100033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Removes a given view from its current parent. 100133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 100233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param view the view to remove from its parent 100333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 1004ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 1005ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 100633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 100733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 1008ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 100933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet try { 101033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.removeView(view); 1011ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 101233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } catch (UnsupportedOperationException e) { 101333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 1014ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 101533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 101633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 101733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 10183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 1019952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * Post process on a view hierarchy that was just inflated. 1020952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * <p/> 1021952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the 10223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 10233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * based on the content of the {@link FrameLayout}. 10243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param view the root view to process. 1025b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta * @param layoutlibCallback callback to the project. 10268a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta * @param skip the view and it's children are not processed. 10273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 1028952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 1029b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip) 10303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throws PostInflateException { 10318a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta if (view == skip) { 10328a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta return; 10338a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta } 10343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (view instanceof TabHost) { 1035b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta setupTabHost((TabHost) view, layoutlibCallback); 103662c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 103762c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 103862c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet badge.setImageToDefault(); 10397062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } else if (view instanceof AdapterView<?>) { 10407062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // get the view ID. 10417062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet int id = view.getId(); 10427062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10437062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet BridgeContext context = getContext(); 10447062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10457062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // get a ResourceReference from the integer ID. 10467062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ResourceReference listRef = context.resolveId(id); 10477062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10487062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (listRef != null) { 10497062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet SessionParams params = getParams(); 10507062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet AdapterBinding binding = params.getAdapterBindings().get(listRef); 10517062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10527062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // if there was no adapter binding, trying to get it from the call back. 10537062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (binding == null) { 1054b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta binding = layoutlibCallback.getAdapterBinding( 1055b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta listRef, context.getViewKey(view), view); 10567062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 10577062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10587062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (binding != null) { 10597062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10607062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (view instanceof AbsListView) { 10617062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && 10627062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet view instanceof ListView) { 10637062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ListView list = (ListView) view; 10647062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10657062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet boolean skipCallbackParser = false; 10667062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10677062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet int count = binding.getHeaderCount(); 10688a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta for (int i = 0; i < count; i++) { 10697062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 10707062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet binding.getHeaderAt(i), 1071b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta list, false, skipCallbackParser); 10727062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (pair.getFirst() != null) { 10737062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet list.addHeaderView(pair.getFirst()); 10747062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 10757062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10767062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet skipCallbackParser |= pair.getSecond(); 10777062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 10787062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10797062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet count = binding.getFooterCount(); 10808a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta for (int i = 0; i < count; i++) { 10817062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 10827062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet binding.getFooterAt(i), 1083b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta list, false, skipCallbackParser); 10847062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (pair.getFirst() != null) { 10857062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet list.addFooterView(pair.getFirst()); 10867062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 10877062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10887062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet skipCallbackParser |= pair.getSecond(); 10897062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 10907062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 10917062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 10927062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (view instanceof ExpandableListView) { 10937062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ((ExpandableListView) view).setAdapter( 1094b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta new FakeExpandableAdapter(listRef, binding, layoutlibCallback)); 10957062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } else { 10967062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ((AbsListView) view).setAdapter( 1097b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 10987062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 10997062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } else if (view instanceof AbsSpinner) { 11007062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ((AbsSpinner) view).setAdapter( 1101b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 11027062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 11037062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 11047062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 11053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } else if (view instanceof ViewGroup) { 11069028fa93da0f9c7dad2176de347cd6e705084c9fDeepanshu Gupta mInflater.postInflateProcess(view); 11078a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta ViewGroup group = (ViewGroup) view; 11083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet final int count = group.getChildCount(); 11098a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta for (int c = 0; c < count; c++) { 11103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet View child = group.getChildAt(c); 1111b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta postInflateProcess(child, layoutlibCallback, skip); 11123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 1117c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen * If the root layout is a CoordinatorLayout with an AppBar: 1118c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen * Set the title of the AppBar to the title of the activity context. 1119c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen */ 1120c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen private void setActiveToolbar(View view, BridgeContext context, SessionParams params) { 1121c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT); 1122c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (coordinatorLayout == null) { 1123c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1124c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1125c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT); 1126c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (appBar == null) { 1127c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1128c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1129c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup collapsingToolbar = 1130c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT); 1131c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (collapsingToolbar == null) { 1132c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1133c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1134c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!hasToolbar(collapsingToolbar)) { 1135c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1136c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1137c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen RenderResources res = context.getRenderResources(); 1138c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen String title = params.getAppLabel(); 1139c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ResourceValue titleValue = res.findResValue(title, false); 1140c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (titleValue != null && titleValue.getValue() != null) { 1141c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen title = titleValue.getValue(); 1142c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1143c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen DesignLibUtil.setTitle(collapsingToolbar, title); 1144c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1145c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1146c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen private View findChildView(View view, String className) { 1147c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 1148c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return null; 1149c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1150c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 1151c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 1152c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), className)) { 1153c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return group.getChildAt(i); 1154c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1155c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1156c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return null; 1157c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1158c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1159c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen private boolean hasToolbar(View collapsingToolbar) { 1160c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!(collapsingToolbar instanceof ViewGroup)) { 1161c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return false; 1162c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1163c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup group = (ViewGroup) collapsingToolbar; 1164c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 1165c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) { 1166c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return true; 1167c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1168c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1169c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return false; 1170c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1171c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1172c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen /** 1173777163c3facaed668b43061d726a572fd58f6f60Diego Perez * Set the scroll position on all the components with the "scrollX" and "scrollY" attribute. If 1174777163c3facaed668b43061d726a572fd58f6f60Diego Perez * the component supports nested scrolling attempt that first, then use the unconsumed scroll 1175777163c3facaed668b43061d726a572fd58f6f60Diego Perez * part to scroll the content in the component. 1176c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen */ 11770685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez private static void handleScrolling(BridgeContext context, View view) { 1178777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollPosX = context.getScrollXPos(view); 1179777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollPosY = context.getScrollYPos(view); 1180777163c3facaed668b43061d726a572fd58f6f60Diego Perez if (scrollPosX != 0 || scrollPosY != 0) { 1181c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (view.isNestedScrollingEnabled()) { 1182c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen int[] consumed = new int[2]; 1183777163c3facaed668b43061d726a572fd58f6f60Diego Perez int axis = scrollPosX != 0 ? View.SCROLL_AXIS_HORIZONTAL : 0; 1184777163c3facaed668b43061d726a572fd58f6f60Diego Perez axis |= scrollPosY != 0 ? View.SCROLL_AXIS_VERTICAL : 0; 1185777163c3facaed668b43061d726a572fd58f6f60Diego Perez if (view.startNestedScroll(axis)) { 1186777163c3facaed668b43061d726a572fd58f6f60Diego Perez view.dispatchNestedPreScroll(scrollPosX, scrollPosY, consumed, null); 1187777163c3facaed668b43061d726a572fd58f6f60Diego Perez view.dispatchNestedScroll(consumed[0], consumed[1], scrollPosX, scrollPosY, 1188777163c3facaed668b43061d726a572fd58f6f60Diego Perez null); 1189c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen view.stopNestedScroll(); 1190777163c3facaed668b43061d726a572fd58f6f60Diego Perez scrollPosX -= consumed[0]; 1191777163c3facaed668b43061d726a572fd58f6f60Diego Perez scrollPosY -= consumed[1]; 1192c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1193c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1194777163c3facaed668b43061d726a572fd58f6f60Diego Perez if (scrollPosX != 0 || scrollPosY != 0) { 11950685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez view.scrollTo(scrollPosX, scrollPosY); 1196c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1197c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1198c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1199c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 1200c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1201c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1202c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 1203c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 1204c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen View child = group.getChildAt(i); 12050685ab35ad78094ceb2d9fb0583e2cadd1968c90Diego Perez handleScrolling(context, child); 1206c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1207c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1208c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1209c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen /** 12103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Sets up a {@link TabHost} object. 12113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param tabHost the TabHost to setup. 1212b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta * @param layoutlibCallback The project callback object to access the project R class. 1213bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez * @throws PostInflateException if TabHost is missing the required ids for TabHost 12143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 1215b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback) 12163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throws PostInflateException { 12173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 12183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 12193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (v == null) { 12213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException( 12223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 12233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1225952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!(v instanceof TabWidget)) { 12263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException(String.format( 12273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 12283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 12293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 12323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (v == null) { 1234952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty) 1235952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta //noinspection SpellCheckingInspection 12363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException( 12373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 12383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1240952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!(v instanceof FrameLayout)) { 1241952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta //noinspection SpellCheckingInspection 12423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException(String.format( 12433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 12443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 12453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet FrameLayout content = (FrameLayout)v; 12483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1249952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta // now process the content of the frameLayout and dynamically create tabs for it. 12503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet final int count = content.getChildCount(); 12513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 12533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // and FrameLayout. 12543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet tabHost.setup(); 12553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1256f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye if (count == 0) { 1257f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye // Create a dummy child to get a single tab 12586257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta TabSpec spec = tabHost.newTabSpec("tag") 12596257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta .setIndicator("Tab Label", tabHost.getResources() 12606257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta .getDrawable(android.R.drawable.ic_menu_info_details, null)) 1261bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez .setContent(tag -> new LinearLayout(getContext())); 1262f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye tabHost.addTab(spec); 1263f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } else { 1264952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta // for each child of the frameLayout, add a new TabSpec 1265f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye for (int i = 0 ; i < count ; i++) { 1266f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye View child = content.getChildAt(i); 1267f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 12688a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta @SuppressWarnings("ConstantConditions") // child cannot be null. 1269f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye int id = child.getId(); 1270952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") 1271b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id); 1272f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye String name; 1273f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye if (resource != null) { 1274947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet name = resource.getSecond(); 1275f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } else { 1276f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1277f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } 1278f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 12793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 128385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta /** 128485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the 128585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * bounds of all the views. 128685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 128785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param view the root View 1288e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * @param hOffset horizontal offset for the view bounds. 1289e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * @param vOffset vertical offset for the view bounds. 129085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 129185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 129285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * content frame. 129385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 129485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @return {@code ViewInfo} containing the bounds of the view and it children otherwise. 129585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta */ 1296e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez private ViewInfo visit(View view, int hOffset, int vOffset, boolean setExtendedInfo, 129785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta boolean isContentFrame) { 1298e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez ViewInfo result = createViewInfo(view, hOffset, vOffset, setExtendedInfo, isContentFrame); 1299799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 130085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (view instanceof ViewGroup) { 130185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewGroup group = ((ViewGroup) view); 1302e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez result.setChildren(visitAllChildren(group, isContentFrame ? 0 : hOffset, 1303e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez isContentFrame ? 0 : vOffset, 130485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta setExtendedInfo, isContentFrame)); 130585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 130685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return result; 130785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 1308799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 130985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta /** 131085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo} 13118d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with 131285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * the children of the {@code mContentRoot}. 131385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 131485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param viewGroup the root View 1315e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * @param hOffset horizontal offset from the top for the content view frame. 1316e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * @param vOffset vertical offset from the top for the content view frame. 131785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 131885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 131985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * content frame. {@code false} if the {@code ViewInfo} to be created is 132085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * part of the system decor. 132185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta */ 1322e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int hOffset, int vOffset, 132385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta boolean setExtendedInfo, boolean isContentFrame) { 132485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (viewGroup == null) { 132585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return null; 1326799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 1327799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 132885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (!isContentFrame) { 1329e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez vOffset += viewGroup.getTop(); 1330e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez hOffset += viewGroup.getLeft(); 133185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 1332799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 133385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta int childCount = viewGroup.getChildCount(); 133485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (viewGroup == mContentRoot) { 1335bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez List<ViewInfo> childrenWithoutOffset = new ArrayList<>(childCount); 1336bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez List<ViewInfo> childrenWithOffset = new ArrayList<>(childCount); 133785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta for (int i = 0; i < childCount; i++) { 1338e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez ViewInfo[] childViewInfo = 1339e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez visitContentRoot(viewGroup.getChildAt(i), hOffset, vOffset, 13406208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet setExtendedInfo); 134185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta childrenWithoutOffset.add(childViewInfo[0]); 134285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta childrenWithOffset.add(childViewInfo[1]); 1343799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 134485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta mViewInfoList = childrenWithOffset; 134585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return childrenWithoutOffset; 134685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } else { 1347bca9e5623c820c9aa1e959e3874442de9a9a6c32Diego Perez List<ViewInfo> children = new ArrayList<>(childCount); 134885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta for (int i = 0; i < childCount; i++) { 1349e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez children.add(visit(viewGroup.getChildAt(i), hOffset, vOffset, setExtendedInfo, 135085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta isContentFrame)); 135185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 135285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return children; 1353799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 135485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 1355799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 135685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta /** 135785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the 135885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * bounds of all the views. It returns two {@code ViewInfo} objects with the same children, 135985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * one with the {@code offset} and other without the {@code offset}. The offset is needed to 136085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * get the right bounds if the {@code ViewInfo} hierarchy is accessed from 136185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the 136285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * offset is not needed. 136385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 136485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at 136585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * index 1 is with the offset. 136685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta */ 1367432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta @NonNull 1368e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez private ViewInfo[] visitContentRoot(View view, int hOffset, int vOffset, 1369e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez boolean setExtendedInfo) { 137085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewInfo[] result = new ViewInfo[2]; 137185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (view == null) { 137285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return result; 137385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 137485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta 1375e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez result[0] = createViewInfo(view, 0, 0, setExtendedInfo, true); 1376e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez result[1] = createViewInfo(view, hOffset, vOffset, setExtendedInfo, true); 137785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (view instanceof ViewGroup) { 1378e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez List<ViewInfo> children = 1379e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez visitAllChildren((ViewGroup) view, 0, 0, setExtendedInfo, true); 138085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result[0].setChildren(children); 138185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result[1].setChildren(children); 138285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 138385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return result; 1384799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 13853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 13863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 138785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children 138885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not 138985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * set. 1390e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * @param hOffset horizontal offset for the view bounds. Used only if view is part of the 1391e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * content frame. 1392e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * @param vOffset vertial an offset for the view bounds. Used only if view is part of the 1393e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez * content frame. 13943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 1395e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez private ViewInfo createViewInfo(View view, int hOffset, int vOffset, boolean setExtendedInfo, 139685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta boolean isContentFrame) { 13973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (view == null) { 13983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return null; 13993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 14003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1401777163c3facaed668b43061d726a572fd58f6f60Diego Perez ViewParent parent = view.getParent(); 140285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewInfo result; 140385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (isContentFrame) { 1404777163c3facaed668b43061d726a572fd58f6f60Diego Perez // Account for parent scroll values when calculating the bounding box 1405777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollX = parent != null ? ((View)parent).getScrollX() : 0; 1406777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollY = parent != null ? ((View)parent).getScrollY() : 0; 1407777163c3facaed668b43061d726a572fd58f6f60Diego Perez 140870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // The view is part of the layout added by the user. Hence, 140970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // the ViewCookie may be obtained only through the Context. 141085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result = new ViewInfo(view.getClass().getName(), 1411e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez getContext().getViewKey(view), -scrollX + view.getLeft() + hOffset, 1412e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez -scrollY + view.getTop() + vOffset, -scrollX + view.getRight() + hOffset, 1413e48b02f441a8a90f0a1618ed2116c83441aae3bdDiego Perez -scrollY + view.getBottom() + vOffset, 1414777163c3facaed668b43061d726a572fd58f6f60Diego Perez view, view.getLayoutParams()); 141585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } else { 141670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // We are part of the system decor. 141770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), 141841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta getViewKey(view), 141985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta view.getLeft(), view.getTop(), view.getRight(), 142085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta view.getBottom(), view, view.getLayoutParams()); 142170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta result = r; 142270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // We currently mark three kinds of views: 142370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // 1. Menus in the Action Bar 142470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // 2. Menus in the Overflow popup. 142570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // 3. The overflow popup button. 142670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta if (view instanceof ListMenuItemView) { 142770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // Mark 2. 142870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // All menus in the popup are of type ListMenuItemView. 142970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU); 143070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } else { 143170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // Mark 3. 143270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta ViewGroup.LayoutParams lp = view.getLayoutParams(); 143370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta if (lp instanceof ActionMenuView.LayoutParams && 143470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta ((ActionMenuView.LayoutParams) lp).isOverflowButton) { 143570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW); 143670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } else { 143770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // Mark 1. 143870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // A view is a menu in the Action Bar is it is not the overflow button and of 143970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // its parent is of type ActionMenuView. We can also check if the view is 144070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // instanceof ActionMenuItemView but that will fail for menus using 144170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // actionProviderClass. 144270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta while (parent != mViewRoot && parent instanceof ViewGroup) { 144370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta if (parent instanceof ActionMenuView) { 144470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta r.setViewType(ViewType.ACTION_BAR_MENU); 144570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta break; 144670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 144770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta parent = parent.getParent(); 144870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 144970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 145070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 145185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 14523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 14536208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet if (setExtendedInfo) { 14546208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet MarginLayoutParams marginParams = null; 14556208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet LayoutParams params = view.getLayoutParams(); 14566208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet if (params instanceof MarginLayoutParams) { 14576208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams = (MarginLayoutParams) params; 14586208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet } 14596208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet result.setExtendedInfo(view.getBaseline(), 14606208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.leftMargin : 0, 14616208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.topMargin : 0, 14626208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.rightMargin : 0, 14636208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.bottomMargin : 0); 14646208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet } 14656208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet 14663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return result; 14673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 14683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 146970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta /* (non-Javadoc) 147041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta * The cookie for menu items are stored in menu item and not in the map from View stored in 147141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta * BridgeContext. 147241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta */ 1473432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta @Nullable 147441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta private Object getViewKey(View view) { 147541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta BridgeContext context = getContext(); 147641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta if (!(view instanceof MenuView.ItemView)) { 147741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta return context.getViewKey(view); 147841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 147941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta MenuItemImpl menuItem; 148041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta if (view instanceof ActionMenuItemView) { 148141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = ((ActionMenuItemView) view).getItemData(); 148241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } else if (view instanceof ListMenuItemView) { 148341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = ((ListMenuItemView) view).getItemData(); 148441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } else if (view instanceof IconMenuItemView) { 148541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = ((IconMenuItemView) view).getItemData(); 148641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } else { 148741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = null; 148841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 148941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta if (menuItem instanceof BridgeMenuItemImpl) { 149041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta return ((BridgeMenuItemImpl) menuItem).getViewCookie(); 149141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 149241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta 149341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta return null; 149441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 149541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta 1496620f80a7ee9796c2c41ec0a42d10d2913fc50c90Diego Perez public void invalidateRenderingSize() { 149785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 149885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 149985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta 15003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet public BufferedImage getImage() { 15013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return mImage; 15023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 15033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1504a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet public boolean isAlphaChannelImage() { 1505a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return mIsAlphaChannelImage; 1506a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1507a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1508e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet public List<ViewInfo> getViewInfos() { 1509e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet return mViewInfoList; 15103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 15112d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet 151285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta public List<ViewInfo> getSystemViewInfos() { 151385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return mSystemViewInfoList; 151485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 151585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta 151618be29a3d14f1b3e840e8ee88b5a1951a6f6e9c8Deepanshu Gupta public Map<Object, PropertiesMap> getDefaultProperties() { 151718be29a3d14f1b3e840e8ee88b5a1951a6f6e9c8Deepanshu Gupta return getContext().getDefaultProperties(); 151818be29a3d14f1b3e840e8ee88b5a1951a6f6e9c8Deepanshu Gupta } 151918be29a3d14f1b3e840e8ee88b5a1951a6f6e9c8Deepanshu Gupta 1520ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public void setScene(RenderSession session) { 1521ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet mScene = session; 1522b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 1523b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 1524ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public RenderSession getSession() { 1525b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet return mScene; 1526b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 152795eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez 152895eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez public void dispose() { 1529e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez boolean createdLooper = false; 1530e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez if (Looper.myLooper() == null) { 1531e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez // Detaching the root view from the window will try to stop any running animations. 1532e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez // The stop method checks that it can run in the looper so, if there is no current 1533e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez // looper, we create a temporary one to complete the shutdown. 1534e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez Bridge.prepareThread(); 1535e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez createdLooper = true; 1536e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez } 153795eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez AttachInfo_Accessor.detachFromWindow(mViewRoot); 153895eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez if (mCanvas != null) { 153995eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mCanvas.release(); 154095eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mCanvas = null; 154195eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 154295eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez if (mViewInfoList != null) { 154395eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mViewInfoList.clear(); 154495eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 154595eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez if (mSystemViewInfoList != null) { 154695eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mSystemViewInfoList.clear(); 154795eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 154895eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mImage = null; 154995eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mViewRoot = null; 155095eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mContentRoot = null; 1551e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez 1552e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez if (createdLooper) { 1553e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez Bridge.cleanupThread(); 1554405d10472d7b8ba7ff86f46e734195128709a829Deepanshu Gupta Choreographer_Delegate.dispose(); 1555e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez } 155695eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 15573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet} 1558