1c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/* 2c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 3c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 4c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 5c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * you may not use this file except in compliance with the License. 6c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * You may obtain a copy of the License at 7c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 8c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 9c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 10c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software 11c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 12c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * See the License for the specific language governing permissions and 14c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * limitations under the License. 15c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 16c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 17c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetpackage com.android.layoutlib.bridge.impl; 18c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding; 20891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig; 2119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener; 2219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser; 2337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport com.android.ide.common.rendering.api.LayoutlibCallback; 2470552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 2519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference; 2719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 2819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 2919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 3046d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams; 311126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode; 3246d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo; 33bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport com.android.ide.common.rendering.api.ViewType; 345ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView; 355ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl; 365ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView; 375ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView; 385ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl; 395ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.MenuView; 402eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 41c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 4201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; 43c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 441f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaevimport com.android.layoutlib.bridge.android.RenderParamsFlags; 455ca21e4ceca42be633031809b8ee43fd8688389bDiego Perezimport com.android.layoutlib.bridge.android.graphics.NopCanvas; 464dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsenimport com.android.layoutlib.bridge.android.support.DesignLibUtil; 472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter; 482fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; 4935ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType; 5029ed07524ce0fc2e5950f5340d306247145d0efaDiego Perezimport com.android.tools.layoutlib.java.System_Delegate; 51b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair; 52eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Guptaimport com.android.util.PropertiesMap; 53c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 547f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.animation.AnimationThread; 55e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator; 562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater; 57e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition; 582b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 59476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.NonNull; 60476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable; 61c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate; 62c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap; 63c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 64c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas; 655d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perezimport android.os.Looper; 6610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Guptaimport android.preference.Preference_Delegate; 677f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor; 687f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.BridgeInflater; 6929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perezimport android.view.Choreographer_Delegate; 706dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.IWindowManager; 71891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport android.view.IWindowManagerImpl; 726dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.Surface; 73c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View; 74c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec; 7546d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.view.ViewGroup; 7601811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams; 7705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams; 78bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.view.ViewParent; 796dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate; 802fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsListView; 812fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsSpinner; 82bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.widget.ActionMenuView; 832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView; 842fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ExpandableListView; 85c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout; 86796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout; 872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ListView; 8831fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge; 89c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost; 90796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec; 9146d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.widget.TabWidget; 92c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 935a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite; 94c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color; 95c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D; 96c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage; 97c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList; 98c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List; 99c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map; 100c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 10137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 10237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 10337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 10437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 10537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 10637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 10761f23e9bf7d784e7a52168196758c4f6c6853e77Deepanshu Guptaimport static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; 10837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta 109c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/** 11019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session. 1111ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 11219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 11319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout. 115c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 116b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> { 117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1185ca21e4ceca42be633031809b8ee43fd8688389bDiego Perez private static final Canvas NOP_CANVAS = new NopCanvas(); 1195ca21e4ceca42be633031809b8ee43fd8688389bDiego Perez 120c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // scene state 12119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private RenderSession mScene; 122c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 123c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeInflater mInflater; 124bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private ViewGroup mViewRoot; 125bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private FrameLayout mContentRoot; 1269eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private Canvas mCanvas; 1279eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenWidth = -1; 1289eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenHeight = -1; 129bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private boolean mIsAlphaChannelImage; 13029ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** If >= 0, a frame will be executed */ 13129ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez private long mElapsedFrameTimeNanos = -1; 13229ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** True if one frame has been already executed to start the animations */ 13329ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez private boolean mFirstFrameExecuted = false; 13416584225125acba18b74920b902c798dfead0328Xavier Ducrohet 135c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // information being returned through the API 136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BufferedImage mImage; 1377d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet private List<ViewInfo> mViewInfoList; 1384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> mSystemViewInfoList; 139b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta private Layout.Builder mLayoutBuilder; 14039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez private boolean mNewRenderSize; 141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final class PostInflateException extends Exception { 143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final long serialVersionUID = 1L; 144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public PostInflateException(String message) { 146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet super(message); 147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 149c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 1531b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)}, 1541b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * which act as a 15519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 156c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 1571b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see Bridge#createSession(SessionParams) 158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1591126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet public RenderSessionImpl(SessionParams params) { 160b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet super(new SessionParams(params)); 1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 1622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 1632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 1642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 1652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * inflater, and parser. 1662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 1682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return whether the scene was prepared 1702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #acquire(long) 1722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #release() 1732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 174b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet @Override 17519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result init(long timeout) { 176b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Result result = super.init(timeout); 1771ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 1782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return result; 1792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 181b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 182b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 183c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 18416584225125acba18b74920b902c798dfead0328Xavier Ducrohet // use default of true in case it's not found to use alpha by default 185fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta mIsAlphaChannelImage = ResourceHelper.getBooleanThemeValue(params.getResources(), 186fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta "windowIsFloating", true, true); 1872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 188b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = new Layout.Builder(params, context); 189c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1906dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet // FIXME: find those out, and possibly add them to the render params 1916dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet boolean hasNavigationBar = true; 1921ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection ConstantConditions 1936dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), 194b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); 1956dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet WindowManagerGlobal_Delegate.setWindowManagerService(iwm); 1966dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet 197c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // build the inflater and parser. 19837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); 199b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet context.setBridgeInflater(mInflater); 2002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 201b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); 2022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 203168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return SUCCESS.createResult(); 204c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 205c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 206c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 20739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez * Measures the the current layout if needed (see {@link #invalidateRenderingSize}). 20839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez */ 20939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez private void measure(@NonNull SessionParams params) { 21039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // only do the screen measure when needed. 21139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mMeasuredScreenWidth != -1) { 21239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez return; 21339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 21439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 21539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez RenderingMode renderingMode = params.getRenderingMode(); 21639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez HardwareConfig hardwareConfig = params.getHardwareConfig(); 21739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 21839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mNewRenderSize = true; 21939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); 22039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); 22139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 22239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (renderingMode != RenderingMode.NORMAL) { 22339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int widthMeasureSpecMode = renderingMode.isHorizExpand() ? 22439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 22539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez : MeasureSpec.EXACTLY; 22639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int heightMeasureSpecMode = renderingMode.isVertExpand() ? 22739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 22839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez : MeasureSpec.EXACTLY; 22939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 23039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // We used to compare the measured size of the content to the screen size but 23139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // this does not work anymore due to the 2 following issues: 23239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // - If the content is in a decor (system bar, title/action bar), the root view 23339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // will not resize even with the UNSPECIFIED because of the embedded layout. 23439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // - If there is no decor, but a dialog frame, then the dialog padding prevents 23539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // comparing the size of the content to the screen frame (as it would not 23639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // take into account the dialog padding). 23739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 23839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // The solution is to first get the content size in a normal rendering, inside 23939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // the decor or the dialog padding. 24039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // Then measure only the content with UNSPECIFIED to see the size difference 24139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // and apply this to the screen size. 24239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 24339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // first measure the full layout, with EXACTLY to get the size of the 24439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // content as it is inside the decor/dialog 24539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez @SuppressWarnings("deprecation") 24639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez Pair<Integer, Integer> exactMeasure = measureView( 24739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mViewRoot, mContentRoot.getChildAt(0), 24839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth, MeasureSpec.EXACTLY, 24939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight, MeasureSpec.EXACTLY); 25039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 25139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // now measure the content only using UNSPECIFIED (where applicable, based on 25239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // the rendering mode). This will give us the size the content needs. 25339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez @SuppressWarnings("deprecation") 25439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez Pair<Integer, Integer> result = measureView( 25539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mContentRoot, mContentRoot.getChildAt(0), 25639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth, widthMeasureSpecMode, 25739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight, heightMeasureSpecMode); 25839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 25939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // now look at the difference and add what is needed. 26039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (renderingMode.isHorizExpand()) { 26139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int measuredWidth = exactMeasure.getFirst(); 26239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int neededWidth = result.getFirst(); 26339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (neededWidth > measuredWidth) { 26439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth += neededWidth - measuredWidth; 26539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 26639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mMeasuredScreenWidth < measuredWidth) { 26739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // If the screen width is less than the exact measured width, 26839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // expand to match. 26939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth = measuredWidth; 27039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 27139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 27239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 27339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (renderingMode.isVertExpand()) { 27439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int measuredHeight = exactMeasure.getSecond(); 27539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int neededHeight = result.getSecond(); 27639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (neededHeight > measuredHeight) { 27739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight += neededHeight - measuredHeight; 27839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 27939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mMeasuredScreenHeight < measuredHeight) { 28039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // If the screen height is less than the exact measured height, 28139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // expand to match. 28239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight = measuredHeight; 28339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 28839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez /** 289c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Inflates the layout. 290c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 2912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 2922eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 2942eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 295c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 29619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result inflate() { 2972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 2982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 299c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 300b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mViewRoot = new Layout(mLayoutBuilder); 301b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = null; // Done with the builder. 302b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot = ((Layout) mViewRoot).getContentRoot(); 303b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 304b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 305c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 306c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 307c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // it can instantiate the custom Fragment. 30837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); 309c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3101f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); 31110bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta boolean isPreference = "PreferenceScreen".equals(rootTag); 31210bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta View view; 31310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (isPreference) { 31410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, 315b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot); 31610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } else { 31710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = mInflater.inflate(mBlockParser, mContentRoot); 31810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 319c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // done with the parser, pop it. 3212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet context.popParser(); 3222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 32337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(null); 324c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 325c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // set the AttachInfo on the root view. 3267f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.setAttachInfo(mViewRoot); 327c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 32833758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 32937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null); 330ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.onDoneInflation(); 33133758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet 3324dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen setActiveToolbar(view, context, params); 3334dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 33439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez measure(params); 33539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez measureView(mViewRoot, null /*measuredView*/, 33639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth, MeasureSpec.EXACTLY, 33739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight, MeasureSpec.EXACTLY); 33839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 33939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), 34039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez false); 34139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 34219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 343c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (PostInflateException e) { 34419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 345c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 346c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 347c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 348c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 349c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 350c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 351c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 35219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 353c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 354c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 355c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 356c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 35729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez * Sets the time for which the next frame will be selected. The time is the elapsed time from 35829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez * the current system nanos time. You 35929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez */ 36029ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez public void setElapsedFrameTimeNanos(long nanos) { 36129ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez mElapsedFrameTimeNanos = nanos; 36229ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 36329ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez 36429ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** 3652605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * Renders the given view hierarchy to the passed canvas and returns the result of the render 3662605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * operation. 3672605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * @param canvas an optional canvas to render the views to. If null, only the measure and 3682605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * layout steps will be executed. 3692605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez */ 3702605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot, 3712605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez @Nullable Canvas canvas, int width, int height) { 3722605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // measure again with the size we need 3732605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // This must always be done before the call to layout 3742605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez measureView(viewRoot, null /*measuredView*/, 3752605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez width, MeasureSpec.EXACTLY, 3762605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez height, MeasureSpec.EXACTLY); 3772605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3782605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // now do the layout. 3792605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez viewRoot.layout(0, 0, width, height); 3802605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez handleScrolling(context, viewRoot); 3812605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3822605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez if (canvas == null) { 3832605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez return SUCCESS.createResult(); 3842605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez } 3852605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3862605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez AttachInfo_Accessor.dispatchOnPreDraw(viewRoot); 3872605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez viewRoot.draw(canvas); 3882605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3892605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez return SUCCESS.createResult(); 3902605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez } 3912605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3922605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez /** 393c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Renders the scene. 394c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 3952eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 3962eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 3975a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 3985a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 3995a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * animations.) 4005a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * 4012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 4022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 4039eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 4041b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see SessionParams#getRenderingMode() 405bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#render(long) 406c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 4075a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet public Result render(boolean freshRender) { 4082eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 4092eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 410b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 411b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 413c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mViewRoot == null) { 41419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 415c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 416c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 41739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez measure(params); 418c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 41939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez HardwareConfig hardwareConfig = params.getHardwareConfig(); 4202605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez Result renderResult = SUCCESS.createResult(); 42110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isLayoutOnly()) { 42210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // delete the canvas and image to reset them on the next full rendering 42310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = null; 42410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mCanvas = null; 42510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 42610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // draw the views 42710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create the BufferedImage into which the layout will be rendered. 42810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet boolean newImage = false; 4292c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez 4302c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // When disableBitmapCaching is true, we do not reuse mImage and 4312c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // we create a new one in every render. 4322c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // This is useful when mImage is just a wrapper of Graphics2D so 4332c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // it doesn't get cached. 4342c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( 4351f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); 43639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mNewRenderSize || mCanvas == null || disableBitmapCaching) { 43739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mNewRenderSize = false; 43810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.getImageFactory() != null) { 43910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = params.getImageFactory().getImage( 44010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 44110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight); 44210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 44310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = new BufferedImage( 44410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 44510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight, 44610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 44710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 44810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 44910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 45010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isBgColorOverridden()) { 45110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 45210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 45310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 45410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 45510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 45610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 45710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 45810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 45910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 46010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create an Android bitmap around the BufferedImage 46110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 462891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet true /*isMutable*/, hardwareConfig.getDensity()); 46310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 4642c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez if (mCanvas == null) { 4652c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // create a Canvas around the Android bitmap 4662c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas = new Canvas(bitmap); 4672c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } else { 4682c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas.setBitmap(bitmap); 4692c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } 470891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 4719eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 472c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4731ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (freshRender && !newImage) { 4749eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 4755a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 476c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 47710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 4784ea74d2960688db6aa13452765dd5f2d07a40189Deepanshu Gupta gc.fillRect(0, 0, 4794ea74d2960688db6aa13452765dd5f2d07a40189Deepanshu Gupta mMeasuredScreenWidth, mMeasuredScreenHeight); 48016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 48110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // done 48210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 48310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 48416584225125acba18b74920b902c798dfead0328Xavier Ducrohet 48529ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez if (mElapsedFrameTimeNanos >= 0) { 48629ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez long initialTime = System_Delegate.nanoTime(); 48729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez if (!mFirstFrameExecuted) { 4882605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // We need to run an initial draw call to initialize the animations 4895ca21e4ceca42be633031809b8ee43fd8688389bDiego Perez render(getContext(), mViewRoot, NOP_CANVAS, mMeasuredScreenWidth, mMeasuredScreenHeight); 4902605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 49129ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez // The first frame will initialize the animations 49229ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez Choreographer_Delegate.doFrame(initialTime); 49329ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez mFirstFrameExecuted = true; 49429ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 49529ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez // Second frame will move the animations 49629ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos); 49729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 4982605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth, 4992605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez mMeasuredScreenHeight); 5005a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet } 5015a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet 5025ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), 5035ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta false); 504c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 505c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // success! 5062605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez return renderResult; 507c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 508c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 509c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 510c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 511c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 512c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 513c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 51419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 515c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 516c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 517c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 518c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 519c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * Executes {@link View#measure(int, int)} on a given view with the given parameters (used 520c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. 521c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 522c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) 523c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). 524c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 525c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param viewToMeasure the view on which to execute measure(). 526c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param measuredView if non null, the view to query for its measured width/height. 527c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param width the width to use in the MeasureSpec. 528c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param widthMode the MeasureSpec mode to use for the width. 529c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param height the height to use in the MeasureSpec. 530c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param heightMode the MeasureSpec mode to use for the height. 531c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @return the measured width/height if measuredView is non-null, null otherwise. 532c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet */ 5331ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 5342605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, 535c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int width, int widthMode, int height, int heightMode) { 536c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); 537c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); 538c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet viewToMeasure.measure(w_spec, h_spec); 539c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 540c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (measuredView != null) { 541c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); 542c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 543c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 544c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return null; 545c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 546c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 547c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet /** 5482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Animate an object 5492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 5502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 5512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 5522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 5532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 554e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 555bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 5562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 55719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result animate(Object targetObject, String animationName, 5582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 5592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 5602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 561b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 562b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 5632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // find the animation file. 5641ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta ResourceValue animationResource; 5652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet int animationId = 0; 5662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (isFrameworkAnimation) { 567b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 56835ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 570b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 5712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 573b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 57435ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5752eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 57637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta animationId = context.getLayoutlibCallback().getResourceId( 57735ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 5822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 583b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 5842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (anim != null) { 5852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet anim.setTarget(targetObject); 5862eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 587e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 5882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 58919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 5902eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (Exception e) { 592c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 593c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t = e; 594c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t.getCause() != null) { 595c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t = t.getCause(); 596c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 597c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 59819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 6002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 6012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 60219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 603c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 604c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 605e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 606e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Insert a new child into an existing parent. 607e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 608e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 609e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 610e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 611e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 612e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 613bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 614e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 61519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 616e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final int index, IAnimationListener listener) { 617c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 618c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 619b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 620b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 621c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // create a block parser for the XML 62202d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 62302d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet childXml, context, false /* platformResourceFlag */); 624c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 625c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 626c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 627c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // be created correctly. 628e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 62902d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet blockParser.ensurePopped(); 630c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 631e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 632e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 633e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 634e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 635e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 636e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 63719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 638e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 639e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return addView(parentView, child, index); 640e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 641e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 642e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 643e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 644e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(null); 645e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 646e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 647e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 648e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 64919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(child); 6509eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 6519eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 652e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // add it to the parentView in the correct location 65319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = addView(parentView, child, index); 6541ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 655e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 656e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 657c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 6585a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 659c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (result.isSuccess()) { 660e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(child); 661c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet } 662c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet 663c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet return result; 664c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 665c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 666e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 667e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Adds a given view to a given parent at a given index. 668e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 669e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param parent the parent to receive the view 670e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to add to the parent 671e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the index where to do the add. 672e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 67319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 67419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 675e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 676e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 67719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 678e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 679e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.addView(view, index); 68019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 681e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 682e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 68319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 684e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 685e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 686e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 687e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 688e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a view to a new parent at a given location 689e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 690e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 691e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 692e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 693e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 694e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 695bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 696e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 6972b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 698479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 699c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 700c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 701e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 702e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 70301811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet LayoutParams layoutParams = null; 704e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (layoutParamsMap != null) { 705e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 7062b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 707e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 708e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 7099eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 7102b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // get the current parent of the view that needs to be moved. 7112b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 7122b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 713e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 714e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final LayoutParams params = layoutParams; 71501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 716479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 717479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // parent views are different we fake the animation through a no animation thread. 718479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousParent != newParentView) { 719479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new Thread("not animated moveChild") { 720479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 721479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void run() { 722479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 723479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet params); 7241ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 725479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 726479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 727479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 728479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // ready to do the work, acquire the scene. 729479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet result = acquire(250); 7301ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 731479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 732479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return; 733479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 734479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 735479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet try { 7365a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 737479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess()) { 738479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 739479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 740479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } finally { 741479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet release(); 742479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 743479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 744479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 7452b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 746479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 747479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } else { 748479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new AnimationThread(this, "moveChild", listener) { 7492b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 750479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 751479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public Result preAnimation() { 752479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // set up the transition for the parent. 753479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition transition = new LayoutTransition(); 754479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(transition); 7557550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet 756479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // tweak the animation durations and start delays (to match the duration of 757479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // animation playing just before). 758479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 759479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // on the LayoutTransition. 760479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 761479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 762479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 76301811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 764479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 765479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 766479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 767479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 768479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 769479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 770479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 771479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 772479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 773479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 774479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 775479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 776479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void postAnimation() { 777479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(null); 778479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParentView.setLayoutTransition(null); 779479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 780479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 781479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 782e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 783e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 78419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(layoutParams); 785c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 786c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7872b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 7881ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 789e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 790e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 791c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7925a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 79301811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet if (layoutParams != null && result.isSuccess()) { 794e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(layoutParams); 79501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet } 79601811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 79701811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet return result; 798c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 799c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 800e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 801e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 802e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * an optional new {@link LayoutParams} instance 803e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 8042b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 8052b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param newParent the new parent 806479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet * @param movedView the view to move 807e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the new location in the new parent 808e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 809e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 81019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 81119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 812e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 813e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 814479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 815479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet final View movedView, final int index, final LayoutParams params) { 8169eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet try { 8172b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // check if there is a transition on the previousParent. 818479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 819479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousTransition != null) { 8207550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 8217550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 8227550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 8237550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 8247550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // to handle). 8257550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 8267550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 8277550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // adding the child or the child will appear in its new location before the 8287550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // other children have made room for it. 8292b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8302b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 831479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 832479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private int mChangeDisappearingCount = 0; 8332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 83446d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 8352b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 8362b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 837479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 838479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount++; 839479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 8402b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 841e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 84246d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 8432b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 8442b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 845479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 846479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount--; 847479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 848479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 849479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 850479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount == 0) { 8512b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8522b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 853479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8542b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 855479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8572b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8582b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8592b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet }); 8602b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8612b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // remove the view from the current parent. 862479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 8632b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8642b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 8652b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 866e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } else { 8672b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // standard code with no animation. pretty simple. 868479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 869e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8702b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8712b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 872479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8732b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 874479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8752b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8762b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8772b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 8782b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8799eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } catch (UnsupportedOperationException e) { 8809eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 88119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 882c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 883e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 884e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 885e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 886e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a child from its current parent. 887e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 888e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 889e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 890e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 891e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 892e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 893bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 894e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 89519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 896e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet checkLock(); 897c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 8989eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet invalidateRenderingSize(); 8999eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 900e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 901e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 902e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 903e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 904e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 905e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 90619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 907e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 908e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return removeView(parent, childView); 909e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 910e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 911e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 912e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 913e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(null); 914e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 915e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 916e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 917e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 91819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 919e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 920e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 92119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = removeView(parent, childView); 9221ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 923e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 924e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 925e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 9265a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet return render(false /*freshRender*/); 9272eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 9282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 9292eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 930e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a given view from its current parent. 931e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 932e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to remove from its parent 933e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 93419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 93519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 936e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 937e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 93819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 939e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 940e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.removeView(view); 94119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 942e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 943e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 94419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 945e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 946e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 947e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 948c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 9491ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * Post process on a view hierarchy that was just inflated. 9501ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 9511ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the 952c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 953c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * based on the content of the {@link FrameLayout}. 954c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root view to process. 95537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback callback to the project. 95610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta * @param skip the view and it's children are not processed. 957c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 9581ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 95937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip) 960c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 96110bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (view == skip) { 96210bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta return; 96310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 964c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof TabHost) { 96537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta setupTabHost((TabHost) view, layoutlibCallback); 96631fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 96731fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 96831fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet badge.setImageToDefault(); 9692fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AdapterView<?>) { 9702fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get the view ID. 9712fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int id = view.getId(); 9722fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9732fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet BridgeContext context = getContext(); 9742fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9752fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get a ResourceReference from the integer ID. 9762fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ResourceReference listRef = context.resolveId(id); 9772fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9782fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (listRef != null) { 9792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet SessionParams params = getParams(); 9802fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet AdapterBinding binding = params.getAdapterBindings().get(listRef); 9812fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // if there was no adapter binding, trying to get it from the call back. 9832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding == null) { 98437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta binding = layoutlibCallback.getAdapterBinding( 98537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta listRef, context.getViewKey(view), view); 9862fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9882fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding != null) { 9892fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9902fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof AbsListView) { 9912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && 9922fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet view instanceof ListView) { 9932fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ListView list = (ListView) view; 9942fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9952fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet boolean skipCallbackParser = false; 9962fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9972fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int count = binding.getHeaderCount(); 99810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 9992fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 10002fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getHeaderAt(i), 100137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 10022fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 10032fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addHeaderView(pair.getFirst()); 10042fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10062fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 10072fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10082fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10092fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet count = binding.getFooterCount(); 101010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 10112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 10122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getFooterAt(i), 101337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 10142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 10152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addFooterView(pair.getFirst()); 10162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 10192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof ExpandableListView) { 10232fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((ExpandableListView) view).setAdapter( 102437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeExpandableAdapter(listRef, binding, layoutlibCallback)); 10252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else { 10262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsListView) view).setAdapter( 102737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 10282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AbsSpinner) { 10302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsSpinner) view).setAdapter( 103137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 10322fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 1035c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } else if (view instanceof ViewGroup) { 1036ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.postInflateProcess(view); 103710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta ViewGroup group = (ViewGroup) view; 1038c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = group.getChildCount(); 103910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int c = 0; c < count; c++) { 1040c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View child = group.getChildAt(c); 104137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(child, layoutlibCallback, skip); 1042c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1043c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1044c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1045c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1046c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 10474dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * If the root layout is a CoordinatorLayout with an AppBar: 10484dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * Set the title of the AppBar to the title of the activity context. 10494dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 10504dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private void setActiveToolbar(View view, BridgeContext context, SessionParams params) { 10514dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT); 10524dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (coordinatorLayout == null) { 10534dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10544dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10554dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT); 10564dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (appBar == null) { 10574dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10584dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10594dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup collapsingToolbar = 10604dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT); 10614dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (collapsingToolbar == null) { 10624dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10634dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10644dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!hasToolbar(collapsingToolbar)) { 10654dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10664dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10674dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen RenderResources res = context.getRenderResources(); 10684dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen String title = params.getAppLabel(); 10694dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ResourceValue titleValue = res.findResValue(title, false); 10704dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (titleValue != null && titleValue.getValue() != null) { 10714dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen title = titleValue.getValue(); 10724dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10734dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen DesignLibUtil.setTitle(collapsingToolbar, title); 10744dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10754dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10764dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private View findChildView(View view, String className) { 10774dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 10784dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10794dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10804dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 10814dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10824dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), className)) { 10834dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return group.getChildAt(i); 10844dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10854dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10864dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10874dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10884dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10894dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private boolean hasToolbar(View collapsingToolbar) { 10904dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(collapsingToolbar instanceof ViewGroup)) { 10914dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 10924dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10934dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) collapsingToolbar; 10944dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10954dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) { 10964dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return true; 10974dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10984dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10994dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 11004dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11014dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 11024dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 1103d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * Set the scroll position on all the components with the "scrollX" and "scrollY" attribute. If 1104d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * the component supports nested scrolling attempt that first, then use the unconsumed scroll 1105d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * part to scroll the content in the component. 11064dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 11072605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez private static void handleScrolling(BridgeContext context, View view) { 1108d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollPosX = context.getScrollXPos(view); 1109d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollPosY = context.getScrollYPos(view); 1110d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (scrollPosX != 0 || scrollPosY != 0) { 11114dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (view.isNestedScrollingEnabled()) { 11124dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen int[] consumed = new int[2]; 1113d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int axis = scrollPosX != 0 ? View.SCROLL_AXIS_HORIZONTAL : 0; 1114d15459197f71f8cc940e2b057b399117df282f2cDiego Perez axis |= scrollPosY != 0 ? View.SCROLL_AXIS_VERTICAL : 0; 1115d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (view.startNestedScroll(axis)) { 1116d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view.dispatchNestedPreScroll(scrollPosX, scrollPosY, consumed, null); 1117d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view.dispatchNestedScroll(consumed[0], consumed[1], scrollPosX, scrollPosY, 1118d15459197f71f8cc940e2b057b399117df282f2cDiego Perez null); 11194dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.stopNestedScroll(); 1120d15459197f71f8cc940e2b057b399117df282f2cDiego Perez scrollPosX -= consumed[0]; 1121d15459197f71f8cc940e2b057b399117df282f2cDiego Perez scrollPosY -= consumed[1]; 11224dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11234dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 1124d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (scrollPosX != 0 || scrollPosY != 0) { 11252605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez view.scrollTo(scrollPosX, scrollPosY); 11264dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11274dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11284dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 11294dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 11304dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 11314dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11324dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 11334dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 11344dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View child = group.getChildAt(i); 11352605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez handleScrolling(context, child); 11364dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11374dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11384dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 11394dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 1140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Sets up a {@link TabHost} object. 1141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param tabHost the TabHost to setup. 114237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback The project callback object to access the project R class. 1143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @throws PostInflateException 1144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 114537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback) 1146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 1148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 1149c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 1153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1154c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11551ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof TabWidget)) { 1156c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1157c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 1158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 1159c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1160c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1161c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 1162c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1163c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 11641ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty) 11651ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1166c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1167c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 1168c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1169c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11701ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof FrameLayout)) { 11711ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1172c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1173c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 1174c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 1175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1176c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1177c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet FrameLayout content = (FrameLayout)v; 1178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11791ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // now process the content of the frameLayout and dynamically create tabs for it. 1180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = content.getChildCount(); 1181c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1182c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 1183c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // and FrameLayout. 1184c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet tabHost.setup(); 1185c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1186796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (count == 0) { 1187796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // Create a dummy child to get a single tab 118849ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta TabSpec spec = tabHost.newTabSpec("tag") 118949ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .setIndicator("Tab Label", tabHost.getResources() 119049ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .getDrawable(android.R.drawable.ic_menu_info_details, null)) 1191796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye .setContent(new TabHost.TabContentFactory() { 119246d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 1193796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye public View createTabContent(String tag) { 1194b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return new LinearLayout(getContext()); 1195796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1196796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye }); 1197796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(spec); 1198796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 11991ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // for each child of the frameLayout, add a new TabSpec 1200796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye for (int i = 0 ; i < count ; i++) { 1201796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye View child = content.getChildAt(i); 1202796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 120310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta @SuppressWarnings("ConstantConditions") // child cannot be null. 1204796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye int id = child.getId(); 12051ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 120637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id); 1207796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String name; 1208796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (resource != null) { 1209b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet name = resource.getSecond(); 1210796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1211796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1212796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1213796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 1214c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1215c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1216c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1217c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 12184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the 12204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. 12214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param view the root View 12234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. 12244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 12254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 12264ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. 12274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12284ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return {@code ViewInfo} containing the bounds of the view and it children otherwise. 12294ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 12304ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo visit(View view, int offset, boolean setExtendedInfo, 12314ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 12324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame); 1233bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 12354ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewGroup group = ((ViewGroup) view); 12364ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset, 12374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta setExtendedInfo, isContentFrame)); 12384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 12404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1241bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12434ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo} 12441b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with 12454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * the children of the {@code mContentRoot}. 12464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param viewGroup the root View 12484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset from the top for the content view frame. 12494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 12504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 12514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. {@code false} if the {@code ViewInfo} to be created is 12524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * part of the system decor. 12534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 12544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset, 12554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean setExtendedInfo, boolean isContentFrame) { 12564ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == null) { 12574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return null; 1258bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1259bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (!isContentFrame) { 12614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta offset += viewGroup.getTop(); 12624ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1263bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta int childCount = viewGroup.getChildCount(); 12654ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == mContentRoot) { 12664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount); 12674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount); 12684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 12694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset, 127005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet setExtendedInfo); 12714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithoutOffset.add(childViewInfo[0]); 12724ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithOffset.add(childViewInfo[1]); 1273bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 12744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mViewInfoList = childrenWithOffset; 12754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return childrenWithoutOffset; 12764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 12774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = new ArrayList<ViewInfo>(childCount); 12784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 12794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo, 12804ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta isContentFrame)); 12814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return children; 1283bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 12844ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1285bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12874ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the 12884ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. It returns two {@code ViewInfo} objects with the same children, 12894ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * one with the {@code offset} and other without the {@code offset}. The offset is needed to 12904ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * get the right bounds if the {@code ViewInfo} hierarchy is accessed from 12914ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the 12924ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * offset is not needed. 12934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12944ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at 12954ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * index 1 is with the offset. 12964ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 1297d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @NonNull 12984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) { 12994ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] result = new ViewInfo[2]; 13004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view == null) { 13014ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 13024ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 13044ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0] = createViewInfo(view, 0, setExtendedInfo, true); 13054ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1] = createViewInfo(view, offset, setExtendedInfo, true); 13064ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 13074ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true); 13084ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0].setChildren(children); 13094ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1].setChildren(children); 13104ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13114ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 1312bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1313c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1314c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 13154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children 13164ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not 13174ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * set. 13184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. Used only if view is part of the content frame. 1319c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 13204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo, 13214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 1322c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view == null) { 1323c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return null; 1324c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1325c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1326d15459197f71f8cc940e2b057b399117df282f2cDiego Perez ViewParent parent = view.getParent(); 13274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result; 13284ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (isContentFrame) { 1329d15459197f71f8cc940e2b057b399117df282f2cDiego Perez // Account for parent scroll values when calculating the bounding box 1330d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollX = parent != null ? ((View)parent).getScrollX() : 0; 1331d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollY = parent != null ? ((View)parent).getScrollY() : 0; 1332d15459197f71f8cc940e2b057b399117df282f2cDiego Perez 1333bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // The view is part of the layout added by the user. Hence, 1334bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // the ViewCookie may be obtained only through the Context. 13354ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result = new ViewInfo(view.getClass().getName(), 1336bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta getContext().getViewKey(view), 1337d15459197f71f8cc940e2b057b399117df282f2cDiego Perez -scrollX + view.getLeft(), -scrollY + view.getTop() + offset, 1338d15459197f71f8cc940e2b057b399117df282f2cDiego Perez -scrollX + view.getRight(), -scrollY + view.getBottom() + offset, 1339d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view, view.getLayoutParams()); 13404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 1341bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We are part of the system decor. 1342bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), 13435ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta getViewKey(view), 13444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getLeft(), view.getTop(), view.getRight(), 13454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getBottom(), view, view.getLayoutParams()); 1346bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta result = r; 1347bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We currently mark three kinds of views: 1348bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 1. Menus in the Action Bar 1349bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 2. Menus in the Overflow popup. 1350bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 3. The overflow popup button. 1351bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (view instanceof ListMenuItemView) { 1352bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 2. 1353bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // All menus in the popup are of type ListMenuItemView. 1354bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU); 1355bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1356bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 3. 1357bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ViewGroup.LayoutParams lp = view.getLayoutParams(); 1358bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (lp instanceof ActionMenuView.LayoutParams && 1359bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ((ActionMenuView.LayoutParams) lp).isOverflowButton) { 1360bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW); 1361bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1362bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 1. 1363bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // A view is a menu in the Action Bar is it is not the overflow button and of 1364bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // its parent is of type ActionMenuView. We can also check if the view is 1365bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // instanceof ActionMenuItemView but that will fail for menus using 1366bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // actionProviderClass. 1367bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta while (parent != mViewRoot && parent instanceof ViewGroup) { 1368bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (parent instanceof ActionMenuView) { 1369bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_MENU); 1370bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta break; 1371bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1372bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta parent = parent.getParent(); 1373bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1374bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1375bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 13764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1377c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 137805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (setExtendedInfo) { 137905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet MarginLayoutParams marginParams = null; 138005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet LayoutParams params = view.getLayoutParams(); 138105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (params instanceof MarginLayoutParams) { 138205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams = (MarginLayoutParams) params; 138305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 138405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet result.setExtendedInfo(view.getBaseline(), 138505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.leftMargin : 0, 138605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.topMargin : 0, 138705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.rightMargin : 0, 138805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.bottomMargin : 0); 138905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 139005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet 1391c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return result; 1392c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1393c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1394bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta /* (non-Javadoc) 13955ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * The cookie for menu items are stored in menu item and not in the map from View stored in 13965ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * BridgeContext. 13975ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta */ 1398d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @Nullable 13995ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta private Object getViewKey(View view) { 14005ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta BridgeContext context = getContext(); 14015ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (!(view instanceof MenuView.ItemView)) { 14025ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return context.getViewKey(view); 14035ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14045ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta MenuItemImpl menuItem; 14055ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (view instanceof ActionMenuItemView) { 14065ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ActionMenuItemView) view).getItemData(); 14075ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof ListMenuItemView) { 14085ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ListMenuItemView) view).getItemData(); 14095ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof IconMenuItemView) { 14105ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((IconMenuItemView) view).getItemData(); 14115ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else { 14125ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = null; 14135ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14145ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (menuItem instanceof BridgeMenuItemImpl) { 14155ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return ((BridgeMenuItemImpl) menuItem).getViewCookie(); 14165ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14175ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 14185ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return null; 14195ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14205ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 1421c13aa0c035cd226d27323bc0e533632ba32f6a84Diego Perez public void invalidateRenderingSize() { 14224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 14234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 14244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 1425c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public BufferedImage getImage() { 1426c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return mImage; 1427c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1428c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 142916584225125acba18b74920b902c798dfead0328Xavier Ducrohet public boolean isAlphaChannelImage() { 143016584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mIsAlphaChannelImage; 143116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 143216584225125acba18b74920b902c798dfead0328Xavier Ducrohet 14337d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public List<ViewInfo> getViewInfos() { 14347d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return mViewInfoList; 1435c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1436cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet 14374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta public List<ViewInfo> getSystemViewInfos() { 14384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return mSystemViewInfoList; 14394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 14404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 1441eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta public Map<Object, PropertiesMap> getDefaultProperties() { 1442eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta return getContext().getDefaultProperties(); 1443eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta } 1444eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta 144519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public void setScene(RenderSession session) { 144619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mScene = session; 1447c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1448c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 144919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSession getSession() { 1450c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet return mScene; 1451c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1452f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez 1453f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez public void dispose() { 14545d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez boolean createdLooper = false; 14555d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez if (Looper.myLooper() == null) { 14565d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // Detaching the root view from the window will try to stop any running animations. 14575d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // The stop method checks that it can run in the looper so, if there is no current 14585d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // looper, we create a temporary one to complete the shutdown. 14595d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez Bridge.prepareThread(); 14605d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez createdLooper = true; 14615d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez } 1462f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez AttachInfo_Accessor.detachFromWindow(mViewRoot); 1463f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mCanvas != null) { 1464f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mCanvas.release(); 1465f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mCanvas = null; 1466f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1467f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mViewInfoList != null) { 1468f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mViewInfoList.clear(); 1469f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1470f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mSystemViewInfoList != null) { 1471f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mSystemViewInfoList.clear(); 1472f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1473f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mImage = null; 1474f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mViewRoot = null; 1475f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mContentRoot = null; 14765d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez 14775d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez if (createdLooper) { 14785d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez Bridge.cleanupThread(); 147961ccc9198ab09363edbf500d7669dbcfafc5fa28Deepanshu Gupta Choreographer_Delegate.dispose(); 14805d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez } 1481f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1482c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet} 1483