RenderSessionImpl.java revision 39e540caffca2584aa6c4cb74ce42dceb24a93f7
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; 454dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsenimport com.android.layoutlib.bridge.android.support.DesignLibUtil; 462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter; 472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; 4835ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType; 4929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perezimport com.android.tools.layoutlib.java.System_Delegate; 50b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair; 51eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Guptaimport com.android.util.PropertiesMap; 52c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 537f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.animation.AnimationThread; 54e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator; 552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater; 56e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition; 572b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 58476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.NonNull; 59476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable; 60c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate; 61c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap; 62c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 63c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas; 645d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perezimport android.os.Looper; 6510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Guptaimport android.preference.Preference_Delegate; 667f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor; 677f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.BridgeInflater; 6829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perezimport android.view.Choreographer_Delegate; 696dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.IWindowManager; 70891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport android.view.IWindowManagerImpl; 716dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.Surface; 72c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View; 73c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec; 7446d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.view.ViewGroup; 7501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams; 7605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams; 77bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.view.ViewParent; 786dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate; 792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsListView; 802fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsSpinner; 81bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.widget.ActionMenuView; 822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView; 832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ExpandableListView; 84c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout; 85796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout; 862fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ListView; 8731fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge; 88c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost; 89796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec; 9046d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.widget.TabWidget; 91c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 925a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite; 93c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color; 94c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D; 95c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage; 96c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList; 97c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List; 98c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map; 99c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 10037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 10137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 10237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 10337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 10437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 10537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 10661f23e9bf7d784e7a52168196758c4f6c6853e77Deepanshu Guptaimport static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; 10737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta 108c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/** 10919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session. 1101ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 11119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 11219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 113c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout. 114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 115b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> { 116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // scene state 11819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private RenderSession mScene; 119c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 120c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeInflater mInflater; 121bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private ViewGroup mViewRoot; 122bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private FrameLayout mContentRoot; 1239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private Canvas mCanvas; 1249eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenWidth = -1; 1259eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenHeight = -1; 126bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private boolean mIsAlphaChannelImage; 12729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** If >= 0, a frame will be executed */ 12829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez private long mElapsedFrameTimeNanos = -1; 12929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** True if one frame has been already executed to start the animations */ 13029ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez private boolean mFirstFrameExecuted = false; 13116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 132c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // information being returned through the API 133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BufferedImage mImage; 1347d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet private List<ViewInfo> mViewInfoList; 1354ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> mSystemViewInfoList; 136b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta private Layout.Builder mLayoutBuilder; 13739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez private boolean mNewRenderSize; 138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final class PostInflateException extends Exception { 140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final long serialVersionUID = 1L; 141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public PostInflateException(String message) { 143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet super(message); 144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 149c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 1501b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)}, 1511b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * which act as a 15219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 1541b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see Bridge#createSession(SessionParams) 155c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1561126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet public RenderSessionImpl(SessionParams params) { 157b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet super(new SessionParams(params)); 1582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 1592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 1602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 1622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * inflater, and parser. 1632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 1652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return whether the scene was prepared 1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #acquire(long) 1692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #release() 1702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 171b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet @Override 17219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result init(long timeout) { 173b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Result result = super.init(timeout); 1741ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 1752eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return result; 1762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 177c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 178b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 179b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 18116584225125acba18b74920b902c798dfead0328Xavier Ducrohet // use default of true in case it's not found to use alpha by default 182fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta mIsAlphaChannelImage = ResourceHelper.getBooleanThemeValue(params.getResources(), 183fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta "windowIsFloating", true, true); 1842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 185b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = new Layout.Builder(params, context); 186c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1876dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet // FIXME: find those out, and possibly add them to the render params 1886dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet boolean hasNavigationBar = true; 1891ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection ConstantConditions 1906dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), 191b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); 1926dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet WindowManagerGlobal_Delegate.setWindowManagerService(iwm); 1936dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet 194c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // build the inflater and parser. 19537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); 196b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet context.setBridgeInflater(mInflater); 1972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 198b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); 1992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 200168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return SUCCESS.createResult(); 201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 203c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 20439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez * Measures the the current layout if needed (see {@link #invalidateRenderingSize}). 20539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez */ 20639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez private void measure(@NonNull SessionParams params) { 20739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // only do the screen measure when needed. 20839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mMeasuredScreenWidth != -1) { 20939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez return; 21039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 21139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 21239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez RenderingMode renderingMode = params.getRenderingMode(); 21339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez HardwareConfig hardwareConfig = params.getHardwareConfig(); 21439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 21539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mNewRenderSize = true; 21639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); 21739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); 21839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 21939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (renderingMode != RenderingMode.NORMAL) { 22039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int widthMeasureSpecMode = renderingMode.isHorizExpand() ? 22139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 22239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez : MeasureSpec.EXACTLY; 22339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int heightMeasureSpecMode = renderingMode.isVertExpand() ? 22439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 22539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez : MeasureSpec.EXACTLY; 22639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 22739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // We used to compare the measured size of the content to the screen size but 22839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // this does not work anymore due to the 2 following issues: 22939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // - If the content is in a decor (system bar, title/action bar), the root view 23039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // will not resize even with the UNSPECIFIED because of the embedded layout. 23139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // - If there is no decor, but a dialog frame, then the dialog padding prevents 23239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // comparing the size of the content to the screen frame (as it would not 23339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // take into account the dialog padding). 23439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 23539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // The solution is to first get the content size in a normal rendering, inside 23639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // the decor or the dialog padding. 23739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // Then measure only the content with UNSPECIFIED to see the size difference 23839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // and apply this to the screen size. 23939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 24039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // first measure the full layout, with EXACTLY to get the size of the 24139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // content as it is inside the decor/dialog 24239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez @SuppressWarnings("deprecation") 24339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez Pair<Integer, Integer> exactMeasure = measureView( 24439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mViewRoot, mContentRoot.getChildAt(0), 24539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth, MeasureSpec.EXACTLY, 24639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight, MeasureSpec.EXACTLY); 24739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 24839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // now measure the content only using UNSPECIFIED (where applicable, based on 24939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // the rendering mode). This will give us the size the content needs. 25039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez @SuppressWarnings("deprecation") 25139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez Pair<Integer, Integer> result = measureView( 25239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mContentRoot, mContentRoot.getChildAt(0), 25339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth, widthMeasureSpecMode, 25439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight, heightMeasureSpecMode); 25539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 25639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // now look at the difference and add what is needed. 25739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (renderingMode.isHorizExpand()) { 25839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int measuredWidth = exactMeasure.getFirst(); 25939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int neededWidth = result.getFirst(); 26039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (neededWidth > measuredWidth) { 26139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth += neededWidth - measuredWidth; 26239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 26339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mMeasuredScreenWidth < measuredWidth) { 26439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // If the screen width is less than the exact measured width, 26539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // expand to match. 26639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth = measuredWidth; 26739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 26839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 26939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 27039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (renderingMode.isVertExpand()) { 27139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int measuredHeight = exactMeasure.getSecond(); 27239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez int neededHeight = result.getSecond(); 27339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (neededHeight > measuredHeight) { 27439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight += neededHeight - measuredHeight; 27539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 27639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mMeasuredScreenHeight < measuredHeight) { 27739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // If the screen height is less than the exact measured height, 27839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez // expand to match. 27939e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight = measuredHeight; 28039e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez } 28439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 28539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez /** 286c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Inflates the layout. 287c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 2882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 2892eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2902eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 2912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 292c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 29319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result inflate() { 2942eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 2952eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 296c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 297b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mViewRoot = new Layout(mLayoutBuilder); 298b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = null; // Done with the builder. 299b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot = ((Layout) mViewRoot).getContentRoot(); 300b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 301b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 302c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 303c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 304c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // it can instantiate the custom Fragment. 30537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); 306c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3071f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); 30810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta boolean isPreference = "PreferenceScreen".equals(rootTag); 30910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta View view; 31010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (isPreference) { 31110bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, 312b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot); 31310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } else { 31410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = mInflater.inflate(mBlockParser, mContentRoot); 31510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 316c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // done with the parser, pop it. 3182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet context.popParser(); 3192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 32037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(null); 321c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 322c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // set the AttachInfo on the root view. 3237f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.setAttachInfo(mViewRoot); 324c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 32533758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 32637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null); 327ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.onDoneInflation(); 32833758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet 3294dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen setActiveToolbar(view, context, params); 3304dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 33139e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez measure(params); 33239e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez measureView(mViewRoot, null /*measuredView*/, 33339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenWidth, MeasureSpec.EXACTLY, 33439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mMeasuredScreenHeight, MeasureSpec.EXACTLY); 33539e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 33639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), 33739e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez false); 33839e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez 33919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 340c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (PostInflateException e) { 34119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 342c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 343c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 344c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 345c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 346c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 347c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 348c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 34919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 350c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 351c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 352c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 353c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 35429ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez * Sets the time for which the next frame will be selected. The time is the elapsed time from 35529ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez * the current system nanos time. You 35629ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez */ 35729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez public void setElapsedFrameTimeNanos(long nanos) { 35829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez mElapsedFrameTimeNanos = nanos; 35929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 36029ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez 36129ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** 3622605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * Renders the given view hierarchy to the passed canvas and returns the result of the render 3632605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * operation. 3642605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * @param canvas an optional canvas to render the views to. If null, only the measure and 3652605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez * layout steps will be executed. 3662605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez */ 3672605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot, 3682605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez @Nullable Canvas canvas, int width, int height) { 3692605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // measure again with the size we need 3702605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // This must always be done before the call to layout 3712605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez measureView(viewRoot, null /*measuredView*/, 3722605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez width, MeasureSpec.EXACTLY, 3732605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez height, MeasureSpec.EXACTLY); 3742605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3752605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // now do the layout. 3762605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez viewRoot.layout(0, 0, width, height); 3772605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez handleScrolling(context, viewRoot); 3782605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3792605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez if (canvas == null) { 3802605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez return SUCCESS.createResult(); 3812605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez } 3822605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3832605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez AttachInfo_Accessor.dispatchOnPreDraw(viewRoot); 3842605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez viewRoot.draw(canvas); 3852605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3862605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez return SUCCESS.createResult(); 3872605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez } 3882605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 3892605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez /** 390c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Renders the scene. 391c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 3922eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 3932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 3945a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 3955a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 3965a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * animations.) 3975a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * 3982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 3992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 4009eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 4011b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see SessionParams#getRenderingMode() 402bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#render(long) 403c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 4045a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet public Result render(boolean freshRender) { 4052eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 4062eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 407b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 408b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 409c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 410c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mViewRoot == null) { 41119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 413c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 41439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez measure(params); 415c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 41639e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez HardwareConfig hardwareConfig = params.getHardwareConfig(); 4172605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez Result renderResult = SUCCESS.createResult(); 41810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isLayoutOnly()) { 41910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // delete the canvas and image to reset them on the next full rendering 42010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = null; 42110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mCanvas = null; 42210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 42310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // draw the views 42410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create the BufferedImage into which the layout will be rendered. 42510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet boolean newImage = false; 4262c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez 4272c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // When disableBitmapCaching is true, we do not reuse mImage and 4282c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // we create a new one in every render. 4292c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // This is useful when mImage is just a wrapper of Graphics2D so 4302c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // it doesn't get cached. 4312c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( 4321f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); 43339e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez if (mNewRenderSize || mCanvas == null || disableBitmapCaching) { 43439e540caffca2584aa6c4cb74ce42dceb24a93f7Diego Perez mNewRenderSize = false; 43510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.getImageFactory() != null) { 43610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = params.getImageFactory().getImage( 43710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 43810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight); 43910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 44010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = new BufferedImage( 44110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 44210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight, 44310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 44410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 44510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 44610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 44710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isBgColorOverridden()) { 44810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 44910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 45010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 45110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 45210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 45310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 45410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 45510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 45610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 45710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create an Android bitmap around the BufferedImage 45810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 459891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet true /*isMutable*/, hardwareConfig.getDensity()); 46010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 4612c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez if (mCanvas == null) { 4622c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // create a Canvas around the Android bitmap 4632c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas = new Canvas(bitmap); 4642c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } else { 4652c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas.setBitmap(bitmap); 4662c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } 467891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 4689eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 469c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4701ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (freshRender && !newImage) { 4719eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 4725a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 473c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 47410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 4754ea74d2960688db6aa13452765dd5f2d07a40189Deepanshu Gupta gc.fillRect(0, 0, 4764ea74d2960688db6aa13452765dd5f2d07a40189Deepanshu Gupta mMeasuredScreenWidth, mMeasuredScreenHeight); 47716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 47810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // done 47910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 48010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 48116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 48229ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez if (mElapsedFrameTimeNanos >= 0) { 48329ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez long initialTime = System_Delegate.nanoTime(); 48429ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez if (!mFirstFrameExecuted) { 4852605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez // We need to run an initial draw call to initialize the animations 4862605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez render(getContext(), mViewRoot, mCanvas, 0, 0); 4872605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez 48829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez // The first frame will initialize the animations 48929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez Choreographer_Delegate.doFrame(initialTime); 49029ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez mFirstFrameExecuted = true; 49129ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 49229ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez // Second frame will move the animations 49329ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos); 49429ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 4952605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth, 4962605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez mMeasuredScreenHeight); 4975a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet } 4985a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet 4995ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), 5005ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta false); 501c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 502c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // success! 5032605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez return renderResult; 504c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 505c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 506c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 507c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 508c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 509c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 510c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 51119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 512c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 513c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 514c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 515c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 516c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * Executes {@link View#measure(int, int)} on a given view with the given parameters (used 517c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. 518c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 519c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) 520c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). 521c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 522c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param viewToMeasure the view on which to execute measure(). 523c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param measuredView if non null, the view to query for its measured width/height. 524c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param width the width to use in the MeasureSpec. 525c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param widthMode the MeasureSpec mode to use for the width. 526c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param height the height to use in the MeasureSpec. 527c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param heightMode the MeasureSpec mode to use for the height. 528c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @return the measured width/height if measuredView is non-null, null otherwise. 529c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet */ 5301ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 5312605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, 532c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int width, int widthMode, int height, int heightMode) { 533c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); 534c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); 535c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet viewToMeasure.measure(w_spec, h_spec); 536c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 537c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (measuredView != null) { 538c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); 539c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 540c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 541c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return null; 542c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 543c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 544c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet /** 5452eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Animate an object 5462eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 5472eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 5482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 5492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 5502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 551e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 552bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 5532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 55419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result animate(Object targetObject, String animationName, 5552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 5562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 5572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 558b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 559b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 5602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // find the animation file. 5611ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta ResourceValue animationResource; 5622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet int animationId = 0; 5632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (isFrameworkAnimation) { 564b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 56535ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 567b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 5682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 570b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 57135ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 57337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta animationId = context.getLayoutlibCallback().getResourceId( 57435ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5752eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 5792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 580b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 5812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (anim != null) { 5822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet anim.setTarget(targetObject); 5832eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 584e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 5852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 58619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 5872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (Exception e) { 589c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 590c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t = e; 591c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t.getCause() != null) { 592c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t = t.getCause(); 593c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 594c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 59519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5962eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 59919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 600c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 601c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 602e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 603e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Insert a new child into an existing parent. 604e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 605e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 606e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 607e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 608e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 609e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 610bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 611e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 61219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 613e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final int index, IAnimationListener listener) { 614c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 615c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 616b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 617b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 618c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // create a block parser for the XML 61902d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 62002d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet childXml, context, false /* platformResourceFlag */); 621c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 622c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 623c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 624c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // be created correctly. 625e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 62602d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet blockParser.ensurePopped(); 627c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 628e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 629e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 630e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 631e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 632e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 633e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 63419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 635e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 636e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return addView(parentView, child, index); 637e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 638e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 639e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 640e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 641e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(null); 642e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 643e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 644e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 645e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 64619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(child); 6479eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 6489eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 649e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // add it to the parentView in the correct location 65019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = addView(parentView, child, index); 6511ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 652e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 653e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 654c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 6555a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 656c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (result.isSuccess()) { 657e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(child); 658c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet } 659c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet 660c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet return result; 661c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 662c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 663e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 664e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Adds a given view to a given parent at a given index. 665e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 666e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param parent the parent to receive the view 667e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to add to the parent 668e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the index where to do the add. 669e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 67019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 67119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 672e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 673e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 67419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 675e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 676e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.addView(view, index); 67719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 678e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 679e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 68019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 681e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 682e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 683e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 684e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 685e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a view to a new parent at a given location 686e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 687e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 688e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 689e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 690e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 691e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 692bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 693e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 6942b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 695479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 696c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 697c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 698e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 699e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 70001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet LayoutParams layoutParams = null; 701e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (layoutParamsMap != null) { 702e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 7032b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 704e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 705e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 7069eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 7072b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // get the current parent of the view that needs to be moved. 7082b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 7092b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 710e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 711e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final LayoutParams params = layoutParams; 71201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 713479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 714479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // parent views are different we fake the animation through a no animation thread. 715479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousParent != newParentView) { 716479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new Thread("not animated moveChild") { 717479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 718479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void run() { 719479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 720479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet params); 7211ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 722479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 723479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 724479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 725479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // ready to do the work, acquire the scene. 726479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet result = acquire(250); 7271ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 728479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 729479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return; 730479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 731479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 732479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet try { 7335a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 734479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess()) { 735479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 736479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 737479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } finally { 738479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet release(); 739479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 740479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 741479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 7422b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 743479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 744479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } else { 745479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new AnimationThread(this, "moveChild", listener) { 7462b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 747479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 748479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public Result preAnimation() { 749479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // set up the transition for the parent. 750479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition transition = new LayoutTransition(); 751479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(transition); 7527550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet 753479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // tweak the animation durations and start delays (to match the duration of 754479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // animation playing just before). 755479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 756479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // on the LayoutTransition. 757479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 758479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 759479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 76001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 761479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 762479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 763479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 764479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 765479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 766479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 767479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 768479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 769479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 770479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 771479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 772479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 773479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void postAnimation() { 774479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(null); 775479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParentView.setLayoutTransition(null); 776479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 777479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 778479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 779e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 780e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 78119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(layoutParams); 782c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 783c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7842b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 7851ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 786e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 787e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 788c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7895a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 79001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet if (layoutParams != null && result.isSuccess()) { 791e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(layoutParams); 79201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet } 79301811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 79401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet return result; 795c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 796c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 797e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 798e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 799e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * an optional new {@link LayoutParams} instance 800e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 8012b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 8022b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param newParent the new parent 803479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet * @param movedView the view to move 804e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the new location in the new parent 805e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 806e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 80719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 80819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 809e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 810e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 811479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 812479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet final View movedView, final int index, final LayoutParams params) { 8139eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet try { 8142b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // check if there is a transition on the previousParent. 815479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 816479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousTransition != null) { 8177550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 8187550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 8197550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 8207550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 8217550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // to handle). 8227550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 8237550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 8247550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // adding the child or the child will appear in its new location before the 8257550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // other children have made room for it. 8262b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8272b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 828479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 829479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private int mChangeDisappearingCount = 0; 8302b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 83146d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 8322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 8332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 834479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 835479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount++; 836479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 8372b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 838e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 83946d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 8402b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 8412b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 842479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 843479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount--; 844479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 845479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 846479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 847479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount == 0) { 8482b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8492b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 850479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8512b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 852479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8532b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8542b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8552b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet }); 8572b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8582b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // remove the view from the current parent. 859479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 8602b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8612b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 8622b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 863e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } else { 8642b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // standard code with no animation. pretty simple. 865479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 866e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8672b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8682b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 869479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8702b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 871479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8722b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8732b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8742b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 8752b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8769eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } catch (UnsupportedOperationException e) { 8779eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 87819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 879c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 880e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 881e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 882e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 883e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a child from its current parent. 884e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 885e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 886e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 887e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 888e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 889e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 890bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 891e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 89219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 893e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet checkLock(); 894c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 8959eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet invalidateRenderingSize(); 8969eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 897e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 898e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 899e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 900e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 901e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 902e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 90319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 904e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 905e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return removeView(parent, childView); 906e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 907e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 908e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 909e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 910e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(null); 911e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 912e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 913e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 914e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 91519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 916e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 917e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 91819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = removeView(parent, childView); 9191ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 920e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 921e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 922e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 9235a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet return render(false /*freshRender*/); 9242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 9252eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 9262eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 927e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a given view from its current parent. 928e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 929e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to remove from its parent 930e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 93119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 93219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 933e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 934e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 93519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 936e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 937e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.removeView(view); 93819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 939e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 940e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 94119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 942e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 943e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 944e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 945c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 9461ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * Post process on a view hierarchy that was just inflated. 9471ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 9481ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the 949c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 950c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * based on the content of the {@link FrameLayout}. 951c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root view to process. 95237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback callback to the project. 95310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta * @param skip the view and it's children are not processed. 954c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 9551ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 95637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip) 957c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 95810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (view == skip) { 95910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta return; 96010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 961c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof TabHost) { 96237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta setupTabHost((TabHost) view, layoutlibCallback); 96331fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 96431fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 96531fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet badge.setImageToDefault(); 9662fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AdapterView<?>) { 9672fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get the view ID. 9682fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int id = view.getId(); 9692fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9702fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet BridgeContext context = getContext(); 9712fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9722fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get a ResourceReference from the integer ID. 9732fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ResourceReference listRef = context.resolveId(id); 9742fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9752fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (listRef != null) { 9762fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet SessionParams params = getParams(); 9772fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet AdapterBinding binding = params.getAdapterBindings().get(listRef); 9782fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // if there was no adapter binding, trying to get it from the call back. 9802fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding == null) { 98137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta binding = layoutlibCallback.getAdapterBinding( 98237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta listRef, context.getViewKey(view), view); 9832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9842fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9852fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding != null) { 9862fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof AbsListView) { 9882fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && 9892fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet view instanceof ListView) { 9902fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ListView list = (ListView) view; 9912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9922fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet boolean skipCallbackParser = false; 9932fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9942fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int count = binding.getHeaderCount(); 99510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 9962fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 9972fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getHeaderAt(i), 99837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 9992fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 10002fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addHeaderView(pair.getFirst()); 10012fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10022fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10032fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 10042fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10062fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet count = binding.getFooterCount(); 100710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 10082fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 10092fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getFooterAt(i), 101037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 10112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 10122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addFooterView(pair.getFirst()); 10132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 10162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 10192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof ExpandableListView) { 10202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((ExpandableListView) view).setAdapter( 102137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeExpandableAdapter(listRef, binding, layoutlibCallback)); 10222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else { 10232fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsListView) view).setAdapter( 102437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 10252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AbsSpinner) { 10272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsSpinner) view).setAdapter( 102837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 10292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 10312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 1032c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } else if (view instanceof ViewGroup) { 1033ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.postInflateProcess(view); 103410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta ViewGroup group = (ViewGroup) view; 1035c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = group.getChildCount(); 103610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int c = 0; c < count; c++) { 1037c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View child = group.getChildAt(c); 103837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(child, layoutlibCallback, skip); 1039c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1040c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1041c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1042c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1043c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 10444dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * If the root layout is a CoordinatorLayout with an AppBar: 10454dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * Set the title of the AppBar to the title of the activity context. 10464dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 10474dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private void setActiveToolbar(View view, BridgeContext context, SessionParams params) { 10484dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT); 10494dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (coordinatorLayout == null) { 10504dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10514dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10524dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT); 10534dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (appBar == null) { 10544dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10554dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10564dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup collapsingToolbar = 10574dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT); 10584dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (collapsingToolbar == null) { 10594dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10604dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10614dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!hasToolbar(collapsingToolbar)) { 10624dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10634dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10644dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen RenderResources res = context.getRenderResources(); 10654dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen String title = params.getAppLabel(); 10664dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ResourceValue titleValue = res.findResValue(title, false); 10674dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (titleValue != null && titleValue.getValue() != null) { 10684dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen title = titleValue.getValue(); 10694dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10704dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen DesignLibUtil.setTitle(collapsingToolbar, title); 10714dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10724dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10734dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private View findChildView(View view, String className) { 10744dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 10754dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10764dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10774dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 10784dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10794dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), className)) { 10804dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return group.getChildAt(i); 10814dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10824dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10834dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10844dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10854dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10864dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private boolean hasToolbar(View collapsingToolbar) { 10874dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(collapsingToolbar instanceof ViewGroup)) { 10884dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 10894dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10904dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) collapsingToolbar; 10914dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10924dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) { 10934dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return true; 10944dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10954dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10964dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 10974dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10984dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10994dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 1100d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * Set the scroll position on all the components with the "scrollX" and "scrollY" attribute. If 1101d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * the component supports nested scrolling attempt that first, then use the unconsumed scroll 1102d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * part to scroll the content in the component. 11034dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 11042605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez private static void handleScrolling(BridgeContext context, View view) { 1105d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollPosX = context.getScrollXPos(view); 1106d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollPosY = context.getScrollYPos(view); 1107d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (scrollPosX != 0 || scrollPosY != 0) { 11084dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (view.isNestedScrollingEnabled()) { 11094dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen int[] consumed = new int[2]; 1110d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int axis = scrollPosX != 0 ? View.SCROLL_AXIS_HORIZONTAL : 0; 1111d15459197f71f8cc940e2b057b399117df282f2cDiego Perez axis |= scrollPosY != 0 ? View.SCROLL_AXIS_VERTICAL : 0; 1112d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (view.startNestedScroll(axis)) { 1113d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view.dispatchNestedPreScroll(scrollPosX, scrollPosY, consumed, null); 1114d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view.dispatchNestedScroll(consumed[0], consumed[1], scrollPosX, scrollPosY, 1115d15459197f71f8cc940e2b057b399117df282f2cDiego Perez null); 11164dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.stopNestedScroll(); 1117d15459197f71f8cc940e2b057b399117df282f2cDiego Perez scrollPosX -= consumed[0]; 1118d15459197f71f8cc940e2b057b399117df282f2cDiego Perez scrollPosY -= consumed[1]; 11194dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11204dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 1121d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (scrollPosX != 0 || scrollPosY != 0) { 11222605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez view.scrollTo(scrollPosX, scrollPosY); 11234dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11244dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11254dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 11264dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 11274dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 11284dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11294dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 11304dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 11314dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View child = group.getChildAt(i); 11322605f91f705fbf51800c6fde8ee8cd5f199447b4Diego Perez handleScrolling(context, child); 11334dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11344dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 11354dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 11364dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 1137c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Sets up a {@link TabHost} object. 1138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param tabHost the TabHost to setup. 113937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback The project callback object to access the project R class. 1140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @throws PostInflateException 1141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 114237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback) 1143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 1145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 1146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1149c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 1150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11521ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof TabWidget)) { 1153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1154c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 1155c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 1156c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1157c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 1159c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1160c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 11611ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty) 11621ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1163c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1164c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 1165c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1166c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11671ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof FrameLayout)) { 11681ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1169c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1170c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 1171c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 1172c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1173c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1174c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet FrameLayout content = (FrameLayout)v; 1175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11761ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // now process the content of the frameLayout and dynamically create tabs for it. 1177c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = content.getChildCount(); 1178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1179c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 1180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // and FrameLayout. 1181c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet tabHost.setup(); 1182c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1183796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (count == 0) { 1184796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // Create a dummy child to get a single tab 118549ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta TabSpec spec = tabHost.newTabSpec("tag") 118649ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .setIndicator("Tab Label", tabHost.getResources() 118749ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .getDrawable(android.R.drawable.ic_menu_info_details, null)) 1188796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye .setContent(new TabHost.TabContentFactory() { 118946d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 1190796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye public View createTabContent(String tag) { 1191b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return new LinearLayout(getContext()); 1192796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1193796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye }); 1194796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(spec); 1195796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 11961ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // for each child of the frameLayout, add a new TabSpec 1197796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye for (int i = 0 ; i < count ; i++) { 1198796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye View child = content.getChildAt(i); 1199796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 120010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta @SuppressWarnings("ConstantConditions") // child cannot be null. 1201796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye int id = child.getId(); 12021ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 120337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id); 1204796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String name; 1205796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (resource != null) { 1206b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet name = resource.getSecond(); 1207796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1208796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1209796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1210796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 1211c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1213c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1214c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 12154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12164ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the 12174ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. 12184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param view the root View 12204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. 12214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 12224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 12234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. 12244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return {@code ViewInfo} containing the bounds of the view and it children otherwise. 12264ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 12274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo visit(View view, int offset, boolean setExtendedInfo, 12284ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 12294ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame); 1230bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12314ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 12324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewGroup group = ((ViewGroup) view); 12334ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset, 12344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta setExtendedInfo, isContentFrame)); 12354ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12364ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 12374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1238bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo} 12411b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with 12424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * the children of the {@code mContentRoot}. 12434ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param viewGroup the root View 12454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset from the top for the content view frame. 12464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 12474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 12484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. {@code false} if the {@code ViewInfo} to be created is 12494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * part of the system decor. 12504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 12514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset, 12524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean setExtendedInfo, boolean isContentFrame) { 12534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == null) { 12544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return null; 1255bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1256bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (!isContentFrame) { 12584ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta offset += viewGroup.getTop(); 12594ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1260bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta int childCount = viewGroup.getChildCount(); 12624ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == mContentRoot) { 12634ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount); 12644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount); 12654ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 12664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset, 126705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet setExtendedInfo); 12684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithoutOffset.add(childViewInfo[0]); 12694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithOffset.add(childViewInfo[1]); 1270bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 12714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mViewInfoList = childrenWithOffset; 12724ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return childrenWithoutOffset; 12734ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 12744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = new ArrayList<ViewInfo>(childCount); 12754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 12764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo, 12774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta isContentFrame)); 12784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return children; 1280bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 12814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1282bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12834ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12844ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the 12854ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. It returns two {@code ViewInfo} objects with the same children, 12864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * one with the {@code offset} and other without the {@code offset}. The offset is needed to 12874ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * get the right bounds if the {@code ViewInfo} hierarchy is accessed from 12884ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the 12894ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * offset is not needed. 12904ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12914ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at 12924ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * index 1 is with the offset. 12934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 1294d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @NonNull 12954ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) { 12964ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] result = new ViewInfo[2]; 12974ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view == null) { 12984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 12994ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 13014ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0] = createViewInfo(view, 0, setExtendedInfo, true); 13024ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1] = createViewInfo(view, offset, setExtendedInfo, true); 13034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 13044ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true); 13054ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0].setChildren(children); 13064ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1].setChildren(children); 13074ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13084ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 1309bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1310c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1311c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 13124ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children 13134ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not 13144ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * set. 13154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. Used only if view is part of the content frame. 1316c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 13174ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo, 13184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 1319c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view == null) { 1320c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return null; 1321c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1322c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1323d15459197f71f8cc940e2b057b399117df282f2cDiego Perez ViewParent parent = view.getParent(); 13244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result; 13254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (isContentFrame) { 1326d15459197f71f8cc940e2b057b399117df282f2cDiego Perez // Account for parent scroll values when calculating the bounding box 1327d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollX = parent != null ? ((View)parent).getScrollX() : 0; 1328d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollY = parent != null ? ((View)parent).getScrollY() : 0; 1329d15459197f71f8cc940e2b057b399117df282f2cDiego Perez 1330bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // The view is part of the layout added by the user. Hence, 1331bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // the ViewCookie may be obtained only through the Context. 13324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result = new ViewInfo(view.getClass().getName(), 1333bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta getContext().getViewKey(view), 1334d15459197f71f8cc940e2b057b399117df282f2cDiego Perez -scrollX + view.getLeft(), -scrollY + view.getTop() + offset, 1335d15459197f71f8cc940e2b057b399117df282f2cDiego Perez -scrollX + view.getRight(), -scrollY + view.getBottom() + offset, 1336d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view, view.getLayoutParams()); 13374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 1338bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We are part of the system decor. 1339bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), 13405ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta getViewKey(view), 13414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getLeft(), view.getTop(), view.getRight(), 13424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getBottom(), view, view.getLayoutParams()); 1343bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta result = r; 1344bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We currently mark three kinds of views: 1345bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 1. Menus in the Action Bar 1346bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 2. Menus in the Overflow popup. 1347bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 3. The overflow popup button. 1348bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (view instanceof ListMenuItemView) { 1349bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 2. 1350bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // All menus in the popup are of type ListMenuItemView. 1351bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU); 1352bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1353bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 3. 1354bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ViewGroup.LayoutParams lp = view.getLayoutParams(); 1355bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (lp instanceof ActionMenuView.LayoutParams && 1356bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ((ActionMenuView.LayoutParams) lp).isOverflowButton) { 1357bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW); 1358bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1359bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 1. 1360bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // A view is a menu in the Action Bar is it is not the overflow button and of 1361bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // its parent is of type ActionMenuView. We can also check if the view is 1362bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // instanceof ActionMenuItemView but that will fail for menus using 1363bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // actionProviderClass. 1364bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta while (parent != mViewRoot && parent instanceof ViewGroup) { 1365bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (parent instanceof ActionMenuView) { 1366bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_MENU); 1367bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta break; 1368bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1369bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta parent = parent.getParent(); 1370bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1371bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1372bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 13734ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1374c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 137505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (setExtendedInfo) { 137605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet MarginLayoutParams marginParams = null; 137705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet LayoutParams params = view.getLayoutParams(); 137805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (params instanceof MarginLayoutParams) { 137905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams = (MarginLayoutParams) params; 138005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 138105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet result.setExtendedInfo(view.getBaseline(), 138205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.leftMargin : 0, 138305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.topMargin : 0, 138405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.rightMargin : 0, 138505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.bottomMargin : 0); 138605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 138705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet 1388c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return result; 1389c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1390c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1391bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta /* (non-Javadoc) 13925ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * The cookie for menu items are stored in menu item and not in the map from View stored in 13935ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * BridgeContext. 13945ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta */ 1395d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @Nullable 13965ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta private Object getViewKey(View view) { 13975ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta BridgeContext context = getContext(); 13985ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (!(view instanceof MenuView.ItemView)) { 13995ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return context.getViewKey(view); 14005ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14015ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta MenuItemImpl menuItem; 14025ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (view instanceof ActionMenuItemView) { 14035ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ActionMenuItemView) view).getItemData(); 14045ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof ListMenuItemView) { 14055ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ListMenuItemView) view).getItemData(); 14065ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof IconMenuItemView) { 14075ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((IconMenuItemView) view).getItemData(); 14085ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else { 14095ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = null; 14105ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14115ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (menuItem instanceof BridgeMenuItemImpl) { 14125ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return ((BridgeMenuItemImpl) menuItem).getViewCookie(); 14135ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14145ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 14155ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return null; 14165ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 14175ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 1418c13aa0c035cd226d27323bc0e533632ba32f6a84Diego Perez public void invalidateRenderingSize() { 14194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 14204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 14214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 1422c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public BufferedImage getImage() { 1423c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return mImage; 1424c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1425c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 142616584225125acba18b74920b902c798dfead0328Xavier Ducrohet public boolean isAlphaChannelImage() { 142716584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mIsAlphaChannelImage; 142816584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 142916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 14307d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public List<ViewInfo> getViewInfos() { 14317d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return mViewInfoList; 1432c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1433cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet 14344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta public List<ViewInfo> getSystemViewInfos() { 14354ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return mSystemViewInfoList; 14364ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 14374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 1438eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta public Map<Object, PropertiesMap> getDefaultProperties() { 1439eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta return getContext().getDefaultProperties(); 1440eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta } 1441eaf1853b98d7bf2c3d693ad702050968ef0a404cDeepanshu Gupta 144219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public void setScene(RenderSession session) { 144319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mScene = session; 1444c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1445c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 144619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSession getSession() { 1447c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet return mScene; 1448c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1449f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez 1450f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez public void dispose() { 14515d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez boolean createdLooper = false; 14525d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez if (Looper.myLooper() == null) { 14535d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // Detaching the root view from the window will try to stop any running animations. 14545d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // The stop method checks that it can run in the looper so, if there is no current 14555d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // looper, we create a temporary one to complete the shutdown. 14565d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez Bridge.prepareThread(); 14575d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez createdLooper = true; 14585d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez } 1459f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez AttachInfo_Accessor.detachFromWindow(mViewRoot); 1460f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mCanvas != null) { 1461f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mCanvas.release(); 1462f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mCanvas = null; 1463f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1464f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mViewInfoList != null) { 1465f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mViewInfoList.clear(); 1466f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1467f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mSystemViewInfoList != null) { 1468f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mSystemViewInfoList.clear(); 1469f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1470f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mImage = null; 1471f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mViewRoot = null; 1472f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mContentRoot = null; 14735d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez 14745d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez if (createdLooper) { 14755d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez Bridge.cleanupThread(); 147661ccc9198ab09363edbf500d7669dbcfafc5fa28Deepanshu Gupta Choreographer_Delegate.dispose(); 14775d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez } 1478f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1479c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet} 1480