RenderSessionImpl.java revision 61ccc9198ab09363edbf500d7669dbcfafc5fa28
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; 51c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 527f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.animation.AnimationThread; 53e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator; 542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater; 55e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition; 562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 57476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.NonNull; 58476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable; 59c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate; 60c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap; 61c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 62c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas; 635d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perezimport android.os.Looper; 6410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Guptaimport android.preference.Preference_Delegate; 657f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor; 667f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.BridgeInflater; 6729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perezimport android.view.Choreographer_Delegate; 686dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.IWindowManager; 69891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport android.view.IWindowManagerImpl; 706dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.Surface; 71c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View; 72c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec; 7346d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.view.ViewGroup; 7401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams; 7505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams; 76bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.view.ViewParent; 776dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate; 782fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsListView; 792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsSpinner; 80bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.widget.ActionMenuView; 812fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView; 822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ExpandableListView; 83c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout; 84796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout; 852fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ListView; 8631fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge; 87c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost; 88796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec; 8946d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.widget.TabWidget; 90c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 915a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite; 92c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color; 93c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D; 94c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage; 95c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList; 96c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List; 97c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map; 98c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 9937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 10037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 10137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 10237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 10337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 10437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 10561f23e9bf7d784e7a52168196758c4f6c6853e77Deepanshu Guptaimport static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; 10637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta 107c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/** 10819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session. 1091ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 11019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 11119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 112c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout. 113c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 114b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> { 115c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // scene state 11719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private RenderSession mScene; 118c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 119c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeInflater mInflater; 120bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private ViewGroup mViewRoot; 121bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private FrameLayout mContentRoot; 1229eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private Canvas mCanvas; 1239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenWidth = -1; 1249eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenHeight = -1; 125bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private boolean mIsAlphaChannelImage; 12629ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** If >= 0, a frame will be executed */ 12729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez private long mElapsedFrameTimeNanos = -1; 12829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** True if one frame has been already executed to start the animations */ 12929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez private boolean mFirstFrameExecuted = false; 13016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 131c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // information being returned through the API 132c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BufferedImage mImage; 1337d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet private List<ViewInfo> mViewInfoList; 1344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> mSystemViewInfoList; 135b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta private Layout.Builder mLayoutBuilder; 136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 137c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final class PostInflateException extends Exception { 138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final long serialVersionUID = 1L; 139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public PostInflateException(String message) { 141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet super(message); 142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 1481b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)}, 1491b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * which act as a 15019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 1521b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see Bridge#createSession(SessionParams) 153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1541126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet public RenderSessionImpl(SessionParams params) { 155b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet super(new SessionParams(params)); 1562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 1572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 1582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 1592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 1602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * inflater, and parser. 1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 1632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return whether the scene was prepared 1652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #acquire(long) 1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #release() 1682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 169b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet @Override 17019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result init(long timeout) { 171b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Result result = super.init(timeout); 1721ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 1732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return result; 1742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 176b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 177b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 17916584225125acba18b74920b902c798dfead0328Xavier Ducrohet // use default of true in case it's not found to use alpha by default 180fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta mIsAlphaChannelImage = ResourceHelper.getBooleanThemeValue(params.getResources(), 181fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta "windowIsFloating", true, true); 1822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 183b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = new Layout.Builder(params, context); 184c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1856dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet // FIXME: find those out, and possibly add them to the render params 1866dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet boolean hasNavigationBar = true; 1871ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection ConstantConditions 1886dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), 189b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); 1906dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet WindowManagerGlobal_Delegate.setWindowManagerService(iwm); 1916dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet 192c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // build the inflater and parser. 19337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); 194b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet context.setBridgeInflater(mInflater); 1952eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 196b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); 1972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 198168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return SUCCESS.createResult(); 199c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 200c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Inflates the layout. 203c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 2042eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 2052eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2062eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 2072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 208c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 20919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result inflate() { 2102eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 2112eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 213b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mViewRoot = new Layout(mLayoutBuilder); 214b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = null; // Done with the builder. 215b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot = ((Layout) mViewRoot).getContentRoot(); 216b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 217b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 218c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 219c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 220c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // it can instantiate the custom Fragment. 22137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); 222c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 2231f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); 22410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta boolean isPreference = "PreferenceScreen".equals(rootTag); 22510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta View view; 22610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (isPreference) { 22710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, 228b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot); 22910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } else { 23010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = mInflater.inflate(mBlockParser, mContentRoot); 23110bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 232c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 2332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // done with the parser, pop it. 2342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet context.popParser(); 2352fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 23637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(null); 237c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 238c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // set the AttachInfo on the root view. 2397f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.setAttachInfo(mViewRoot); 240c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 24133758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 24237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null); 243ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.onDoneInflation(); 24433758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet 2454dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen setActiveToolbar(view, context, params); 2464dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 24719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 248c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (PostInflateException e) { 24919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 250c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 251c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 252c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 253c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 254c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 255c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 256c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 25719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 258c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 259c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 260c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 261c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 26229ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez * Sets the time for which the next frame will be selected. The time is the elapsed time from 26329ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez * the current system nanos time. You 26429ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez */ 26529ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez public void setElapsedFrameTimeNanos(long nanos) { 26629ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez mElapsedFrameTimeNanos = nanos; 26729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 26829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez 26929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez /** 270c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Renders the scene. 271c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 2722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 2732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2745a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 2755a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 2765a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * animations.) 2775a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * 2782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 2792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 2809eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 2811b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see SessionParams#getRenderingMode() 282bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#render(long) 283c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 2845a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet public Result render(boolean freshRender) { 2852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 2862eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 287b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 288b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 289c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 290c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mViewRoot == null) { 29119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 292c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 293c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 294b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet RenderingMode renderingMode = params.getRenderingMode(); 295891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet HardwareConfig hardwareConfig = params.getHardwareConfig(); 296fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet 2979eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // only do the screen measure when needed. 2989eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet boolean newRenderSize = false; 2999eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (mMeasuredScreenWidth == -1) { 3009eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet newRenderSize = true; 301891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); 302891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); 3039eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 3049eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode != RenderingMode.NORMAL) { 305c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int widthMeasureSpecMode = renderingMode.isHorizExpand() ? 306c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 307c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet : MeasureSpec.EXACTLY; 308c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int heightMeasureSpecMode = renderingMode.isVertExpand() ? 309c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 310c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet : MeasureSpec.EXACTLY; 311c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 312c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // We used to compare the measured size of the content to the screen size but 313c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // this does not work anymore due to the 2 following issues: 314c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // - If the content is in a decor (system bar, title/action bar), the root view 315c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // will not resize even with the UNSPECIFIED because of the embedded layout. 316c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // - If there is no decor, but a dialog frame, then the dialog padding prevents 317c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // comparing the size of the content to the screen frame (as it would not 318c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // take into account the dialog padding). 319c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 320c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // The solution is to first get the content size in a normal rendering, inside 321c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // the decor or the dialog padding. 322c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // Then measure only the content with UNSPECIFIED to see the size difference 323c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // and apply this to the screen size. 324c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 325c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // first measure the full layout, with EXACTLY to get the size of the 326c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // content as it is inside the decor/dialog 3271ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 328c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet Pair<Integer, Integer> exactMeasure = measureView( 329c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mViewRoot, mContentRoot.getChildAt(0), 330c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth, MeasureSpec.EXACTLY, 331c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight, MeasureSpec.EXACTLY); 332c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 333c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // now measure the content only using UNSPECIFIED (where applicable, based on 334c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // the rendering mode). This will give us the size the content needs. 3351ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 336c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet Pair<Integer, Integer> result = measureView( 337c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mContentRoot, mContentRoot.getChildAt(0), 338c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth, widthMeasureSpecMode, 339c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight, heightMeasureSpecMode); 340c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 341c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // now look at the difference and add what is needed. 3429eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isHorizExpand()) { 343c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int measuredWidth = exactMeasure.getFirst(); 344c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int neededWidth = result.getFirst(); 345c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (neededWidth > measuredWidth) { 346c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth += neededWidth - measuredWidth; 3479eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 3484362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez if (mMeasuredScreenWidth < measuredWidth) { 3494362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez // If the screen width is less than the exact measured width, 3504362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez // expand to match. 3514362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez mMeasuredScreenWidth = measuredWidth; 3524362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez } 353fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 354c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3559eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isVertExpand()) { 356c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int measuredHeight = exactMeasure.getSecond(); 357c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int neededHeight = result.getSecond(); 358c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (neededHeight > measuredHeight) { 359c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight += neededHeight - measuredHeight; 3609eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 3614362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez if (mMeasuredScreenHeight < measuredHeight) { 3624362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez // If the screen height is less than the exact measured height, 3634362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez // expand to match. 3644362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez mMeasuredScreenHeight = measuredHeight; 3654362443cd9a5df6c5cc012881a0aaf96c927b923Diego Perez } 366fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 367c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 368c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 369c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 370c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // measure again with the size we need 371c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // This must always be done before the call to layout 372c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet measureView(mViewRoot, null /*measuredView*/, 373c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth, MeasureSpec.EXACTLY, 374c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight, MeasureSpec.EXACTLY); 375c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 376c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now do the layout. 37716584225125acba18b74920b902c798dfead0328Xavier Ducrohet mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 378c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3794dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen handleScrolling(mViewRoot); 3804dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 38110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isLayoutOnly()) { 38210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // delete the canvas and image to reset them on the next full rendering 38310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = null; 38410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mCanvas = null; 38510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 3867f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot); 38710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 38810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // draw the views 38910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create the BufferedImage into which the layout will be rendered. 39010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet boolean newImage = false; 3912c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez 3922c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // When disableBitmapCaching is true, we do not reuse mImage and 3932c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // we create a new one in every render. 3942c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // This is useful when mImage is just a wrapper of Graphics2D so 3952c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // it doesn't get cached. 3962c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( 3971f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); 3982c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez if (newRenderSize || mCanvas == null || disableBitmapCaching) { 39910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.getImageFactory() != null) { 40010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = params.getImageFactory().getImage( 40110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 40210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight); 40310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 40410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = new BufferedImage( 40510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 40610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight, 40710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 40810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 40910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 41010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 41110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isBgColorOverridden()) { 41210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 41310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 41410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 41510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 41610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 41710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 41810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 41910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 42010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 42110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create an Android bitmap around the BufferedImage 42210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 423891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet true /*isMutable*/, hardwareConfig.getDensity()); 42410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 4252c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez if (mCanvas == null) { 4262c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // create a Canvas around the Android bitmap 4272c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas = new Canvas(bitmap); 4282c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } else { 4292c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas.setBitmap(bitmap); 4302c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } 431891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 4329eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 433c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4341ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (freshRender && !newImage) { 4359eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 4365a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 437c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 43810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 4394ea74d2960688db6aa13452765dd5f2d07a40189Deepanshu Gupta gc.fillRect(0, 0, 4404ea74d2960688db6aa13452765dd5f2d07a40189Deepanshu Gupta mMeasuredScreenWidth, mMeasuredScreenHeight); 44116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 44210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // done 44310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 44410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 44516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 44629ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez if (mElapsedFrameTimeNanos >= 0) { 44729ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez long initialTime = System_Delegate.nanoTime(); 44829ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez if (!mFirstFrameExecuted) { 44929ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez // The first frame will initialize the animations 45029ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez Choreographer_Delegate.doFrame(initialTime); 45129ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez mFirstFrameExecuted = true; 45229ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 45329ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez // Second frame will move the animations 45429ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos); 45529ed07524ce0fc2e5950f5340d306247145d0efaDiego Perez } 45610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mViewRoot.draw(mCanvas); 4575a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet } 4585a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet 4595ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), 4605ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta false); 461c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 462c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // success! 46319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 464c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 465c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 466c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 467c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 468c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 469c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 470c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 47119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 472c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 473c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 474c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 475c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 476c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * Executes {@link View#measure(int, int)} on a given view with the given parameters (used 477c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. 478c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 479c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) 480c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). 481c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 482c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param viewToMeasure the view on which to execute measure(). 483c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param measuredView if non null, the view to query for its measured width/height. 484c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param width the width to use in the MeasureSpec. 485c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param widthMode the MeasureSpec mode to use for the width. 486c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param height the height to use in the MeasureSpec. 487c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param heightMode the MeasureSpec mode to use for the height. 488c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @return the measured width/height if measuredView is non-null, null otherwise. 489c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet */ 4901ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 491c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, 492c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int width, int widthMode, int height, int heightMode) { 493c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); 494c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); 495c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet viewToMeasure.measure(w_spec, h_spec); 496c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 497c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (measuredView != null) { 498c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); 499c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 500c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 501c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return null; 502c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 503c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 504c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet /** 5052eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Animate an object 5062eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 5072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 5082eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 5092eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 5102eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 511e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 512bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 5132eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 51419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result animate(Object targetObject, String animationName, 5152eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 5162eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 5172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 518b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 519b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 5202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // find the animation file. 5211ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta ResourceValue animationResource; 5222eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet int animationId = 0; 5232eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (isFrameworkAnimation) { 524b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 52535ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5262eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 527b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 5282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5292eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 530b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 53135ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5322eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 53337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta animationId = context.getLayoutlibCallback().getResourceId( 53435ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5352eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5362eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5372eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5382eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 5392eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 540b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 5412eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (anim != null) { 5422eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet anim.setTarget(targetObject); 5432eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 544e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 5452eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 54619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 5472eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (Exception e) { 549c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 550c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t = e; 551c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t.getCause() != null) { 552c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t = t.getCause(); 553c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 554c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 55519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 55919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 560c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 561c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 562e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 563e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Insert a new child into an existing parent. 564e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 565e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 566e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 567e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 568e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 569e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 570bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 571e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 57219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 573e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final int index, IAnimationListener listener) { 574c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 575c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 576b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 577b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 578c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // create a block parser for the XML 57902d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 58002d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet childXml, context, false /* platformResourceFlag */); 581c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 582c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 583c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 584c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // be created correctly. 585e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 58602d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet blockParser.ensurePopped(); 587c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 588e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 589e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 590e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 591e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 592e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 593e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 59419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 595e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 596e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return addView(parentView, child, index); 597e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 598e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 599e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 600e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 601e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(null); 602e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 603e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 604e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 605e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 60619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(child); 6079eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 6089eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 609e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // add it to the parentView in the correct location 61019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = addView(parentView, child, index); 6111ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 612e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 613e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 614c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 6155a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 616c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (result.isSuccess()) { 617e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(child); 618c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet } 619c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet 620c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet return result; 621c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 622c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 623e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 624e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Adds a given view to a given parent at a given index. 625e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 626e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param parent the parent to receive the view 627e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to add to the parent 628e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the index where to do the add. 629e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 63019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 63119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 632e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 633e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 63419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 635e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 636e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.addView(view, index); 63719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 638e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 639e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 64019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 641e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 642e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 643e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 644e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 645e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a view to a new parent at a given location 646e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 647e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 648e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 649e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 650e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 651e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 652bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 653e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 6542b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 655479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 656c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 657c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 658e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 659e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 66001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet LayoutParams layoutParams = null; 661e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (layoutParamsMap != null) { 662e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 6632b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 664e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 665e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 6669eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 6672b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // get the current parent of the view that needs to be moved. 6682b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 6692b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 670e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 671e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final LayoutParams params = layoutParams; 67201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 673479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 674479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // parent views are different we fake the animation through a no animation thread. 675479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousParent != newParentView) { 676479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new Thread("not animated moveChild") { 677479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 678479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void run() { 679479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 680479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet params); 6811ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 682479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 683479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 684479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 685479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // ready to do the work, acquire the scene. 686479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet result = acquire(250); 6871ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 688479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 689479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return; 690479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 691479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 692479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet try { 6935a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 694479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess()) { 695479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 696479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 697479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } finally { 698479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet release(); 699479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 700479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 701479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 7022b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 703479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 704479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } else { 705479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new AnimationThread(this, "moveChild", listener) { 7062b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 707479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 708479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public Result preAnimation() { 709479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // set up the transition for the parent. 710479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition transition = new LayoutTransition(); 711479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(transition); 7127550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet 713479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // tweak the animation durations and start delays (to match the duration of 714479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // animation playing just before). 715479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 716479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // on the LayoutTransition. 717479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 718479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 719479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 72001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 721479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 722479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 723479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 724479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 725479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 726479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 727479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 728479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 729479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 730479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 731479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 732479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 733479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void postAnimation() { 734479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(null); 735479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParentView.setLayoutTransition(null); 736479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 737479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 738479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 739e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 740e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 74119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(layoutParams); 742c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 743c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7442b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 7451ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 746e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 747e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 748c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7495a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 75001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet if (layoutParams != null && result.isSuccess()) { 751e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(layoutParams); 75201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet } 75301811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 75401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet return result; 755c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 756c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 757e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 758e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 759e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * an optional new {@link LayoutParams} instance 760e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 7612b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 7622b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param newParent the new parent 763479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet * @param movedView the view to move 764e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the new location in the new parent 765e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 766e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 76719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 76819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 769e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 770e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 771479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 772479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet final View movedView, final int index, final LayoutParams params) { 7739eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet try { 7742b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // check if there is a transition on the previousParent. 775479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 776479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousTransition != null) { 7777550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 7787550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 7797550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 7807550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 7817550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // to handle). 7827550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 7837550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 7847550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // adding the child or the child will appear in its new location before the 7857550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // other children have made room for it. 7862b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7872b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 788479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 789479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private int mChangeDisappearingCount = 0; 7902b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 79146d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 7922b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 7932b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 794479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 795479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount++; 796479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 7972b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 798e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 79946d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 8002b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 8012b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 802479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 803479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount--; 804479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 805479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 806479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 807479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount == 0) { 8082b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8092b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 810479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8112b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 812479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8132b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8142b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8152b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8162b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet }); 8172b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8182b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // remove the view from the current parent. 819479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 8202b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8212b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 8222b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 823e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } else { 8242b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // standard code with no animation. pretty simple. 825479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 826e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8272b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8282b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 829479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8302b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 831479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8342b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 8352b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8369eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } catch (UnsupportedOperationException e) { 8379eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 83819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 839c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 840e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 841e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 842e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 843e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a child from its current parent. 844e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 845e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 846e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 847e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 848e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 849e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 850bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 851e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 85219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 853e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet checkLock(); 854c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 8559eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet invalidateRenderingSize(); 8569eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 857e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 858e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 859e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 860e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 861e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 862e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 86319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 864e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 865e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return removeView(parent, childView); 866e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 867e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 868e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 869e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 870e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(null); 871e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 872e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 873e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 874e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 87519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 876e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 877e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 87819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = removeView(parent, childView); 8791ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 880e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 881e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 882e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8835a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet return render(false /*freshRender*/); 8842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 8852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 8862eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 887e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a given view from its current parent. 888e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 889e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to remove from its parent 890e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 89119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 89219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 893e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 894e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 89519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 896e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 897e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.removeView(view); 89819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 899e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 900e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 90119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 902e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 903e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 904e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 905c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 9061ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * Post process on a view hierarchy that was just inflated. 9071ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 9081ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the 909c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 910c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * based on the content of the {@link FrameLayout}. 911c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root view to process. 91237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback callback to the project. 91310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta * @param skip the view and it's children are not processed. 914c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 9151ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 91637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip) 917c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 91810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (view == skip) { 91910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta return; 92010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 921c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof TabHost) { 92237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta setupTabHost((TabHost) view, layoutlibCallback); 92331fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 92431fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 92531fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet badge.setImageToDefault(); 9262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AdapterView<?>) { 9272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get the view ID. 9282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int id = view.getId(); 9292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet BridgeContext context = getContext(); 9312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9322fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get a ResourceReference from the integer ID. 9332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ResourceReference listRef = context.resolveId(id); 9342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9352fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (listRef != null) { 9362fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet SessionParams params = getParams(); 9372fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet AdapterBinding binding = params.getAdapterBindings().get(listRef); 9382fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9392fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // if there was no adapter binding, trying to get it from the call back. 9402fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding == null) { 94137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta binding = layoutlibCallback.getAdapterBinding( 94237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta listRef, context.getViewKey(view), view); 9432fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9442fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9452fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding != null) { 9462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof AbsListView) { 9482fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && 9492fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet view instanceof ListView) { 9502fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ListView list = (ListView) view; 9512fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9522fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet boolean skipCallbackParser = false; 9532fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9542fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int count = binding.getHeaderCount(); 95510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 9562fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 9572fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getHeaderAt(i), 95837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 9592fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 9602fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addHeaderView(pair.getFirst()); 9612fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9622fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9632fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 9642fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9652fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9662fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet count = binding.getFooterCount(); 96710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 9682fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 9692fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getFooterAt(i), 97037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 9712fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 9722fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addFooterView(pair.getFirst()); 9732fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9742fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9752fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 9762fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9772fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9782fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof ExpandableListView) { 9802fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((ExpandableListView) view).setAdapter( 98137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeExpandableAdapter(listRef, binding, layoutlibCallback)); 9822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else { 9832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsListView) view).setAdapter( 98437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 9852fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9862fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AbsSpinner) { 9872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsSpinner) view).setAdapter( 98837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 9892fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9902fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 992c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } else if (view instanceof ViewGroup) { 993ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.postInflateProcess(view); 99410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta ViewGroup group = (ViewGroup) view; 995c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = group.getChildCount(); 99610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int c = 0; c < count; c++) { 997c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View child = group.getChildAt(c); 99837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(child, layoutlibCallback, skip); 999c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1000c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1001c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1002c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1003c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 10044dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * If the root layout is a CoordinatorLayout with an AppBar: 10054dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * Set the title of the AppBar to the title of the activity context. 10064dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 10074dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private void setActiveToolbar(View view, BridgeContext context, SessionParams params) { 10084dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT); 10094dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (coordinatorLayout == null) { 10104dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10114dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10124dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT); 10134dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (appBar == null) { 10144dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10154dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10164dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup collapsingToolbar = 10174dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT); 10184dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (collapsingToolbar == null) { 10194dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10204dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10214dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!hasToolbar(collapsingToolbar)) { 10224dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10234dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10244dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen RenderResources res = context.getRenderResources(); 10254dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen String title = params.getAppLabel(); 10264dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ResourceValue titleValue = res.findResValue(title, false); 10274dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (titleValue != null && titleValue.getValue() != null) { 10284dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen title = titleValue.getValue(); 10294dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10304dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen DesignLibUtil.setTitle(collapsingToolbar, title); 10314dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10324dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10334dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private View findChildView(View view, String className) { 10344dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 10354dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10364dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10374dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 10384dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10394dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), className)) { 10404dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return group.getChildAt(i); 10414dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10424dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10434dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10444dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10454dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10464dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private boolean hasToolbar(View collapsingToolbar) { 10474dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(collapsingToolbar instanceof ViewGroup)) { 10484dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 10494dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10504dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) collapsingToolbar; 10514dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10524dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) { 10534dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return true; 10544dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10554dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10564dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 10574dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10584dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10594dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 1060d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * Set the scroll position on all the components with the "scrollX" and "scrollY" attribute. If 1061d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * the component supports nested scrolling attempt that first, then use the unconsumed scroll 1062d15459197f71f8cc940e2b057b399117df282f2cDiego Perez * part to scroll the content in the component. 10634dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 10644dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private void handleScrolling(View view) { 10654dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen BridgeContext context = getContext(); 1066d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollPosX = context.getScrollXPos(view); 1067d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollPosY = context.getScrollYPos(view); 1068d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (scrollPosX != 0 || scrollPosY != 0) { 10694dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (view.isNestedScrollingEnabled()) { 10704dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen int[] consumed = new int[2]; 1071d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int axis = scrollPosX != 0 ? View.SCROLL_AXIS_HORIZONTAL : 0; 1072d15459197f71f8cc940e2b057b399117df282f2cDiego Perez axis |= scrollPosY != 0 ? View.SCROLL_AXIS_VERTICAL : 0; 1073d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (view.startNestedScroll(axis)) { 1074d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view.dispatchNestedPreScroll(scrollPosX, scrollPosY, consumed, null); 1075d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view.dispatchNestedScroll(consumed[0], consumed[1], scrollPosX, scrollPosY, 1076d15459197f71f8cc940e2b057b399117df282f2cDiego Perez null); 10774dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.stopNestedScroll(); 1078d15459197f71f8cc940e2b057b399117df282f2cDiego Perez scrollPosX -= consumed[0]; 1079d15459197f71f8cc940e2b057b399117df282f2cDiego Perez scrollPosY -= consumed[1]; 10804dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10814dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 1082d15459197f71f8cc940e2b057b399117df282f2cDiego Perez if (scrollPosX != 0 || scrollPosY != 0) { 1083d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view.scrollBy(scrollPosX, scrollPosY); 10844dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10854dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10864dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10874dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 10884dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10894dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10904dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 10914dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10924dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View child = group.getChildAt(i); 10934dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen handleScrolling(child); 10944dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10954dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10964dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10974dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 1098c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Sets up a {@link TabHost} object. 1099c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param tabHost the TabHost to setup. 110037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback The project callback object to access the project R class. 1101c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @throws PostInflateException 1102c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 110337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback) 1104c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1105c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 1106c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 1107c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1108c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1109c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1110c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 1111c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1112c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11131ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof TabWidget)) { 1114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1115c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 1116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 1117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1118c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1119c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 1120c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1121c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 11221ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty) 11231ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1124c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1125c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 1126c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1127c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11281ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof FrameLayout)) { 11291ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1130c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1131c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 1132c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 1133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1135c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet FrameLayout content = (FrameLayout)v; 1136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11371ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // now process the content of the frameLayout and dynamically create tabs for it. 1138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = content.getChildCount(); 1139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 1141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // and FrameLayout. 1142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet tabHost.setup(); 1143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1144796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (count == 0) { 1145796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // Create a dummy child to get a single tab 114649ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta TabSpec spec = tabHost.newTabSpec("tag") 114749ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .setIndicator("Tab Label", tabHost.getResources() 114849ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .getDrawable(android.R.drawable.ic_menu_info_details, null)) 1149796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye .setContent(new TabHost.TabContentFactory() { 115046d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 1151796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye public View createTabContent(String tag) { 1152b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return new LinearLayout(getContext()); 1153796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1154796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye }); 1155796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(spec); 1156796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 11571ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // for each child of the frameLayout, add a new TabSpec 1158796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye for (int i = 0 ; i < count ; i++) { 1159796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye View child = content.getChildAt(i); 1160796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 116110bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta @SuppressWarnings("ConstantConditions") // child cannot be null. 1162796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye int id = child.getId(); 11631ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 116437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id); 1165796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String name; 1166796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (resource != null) { 1167b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet name = resource.getSecond(); 1168796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1169796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1170796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1171796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 1172c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1173c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1174c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 11774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the 11784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. 11794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 11804ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param view the root View 11814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. 11824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 11834ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 11844ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. 11854ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 11864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return {@code ViewInfo} containing the bounds of the view and it children otherwise. 11874ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 11884ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo visit(View view, int offset, boolean setExtendedInfo, 11894ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 11904ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame); 1191bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 11924ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 11934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewGroup group = ((ViewGroup) view); 11944ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset, 11954ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta setExtendedInfo, isContentFrame)); 11964ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 11974ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 11984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1199bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12014ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo} 12021b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with 12034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * the children of the {@code mContentRoot}. 12044ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12054ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param viewGroup the root View 12064ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset from the top for the content view frame. 12074ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 12084ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 12094ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. {@code false} if the {@code ViewInfo} to be created is 12104ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * part of the system decor. 12114ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 12124ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset, 12134ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean setExtendedInfo, boolean isContentFrame) { 12144ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == null) { 12154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return null; 1216bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1217bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (!isContentFrame) { 12194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta offset += viewGroup.getTop(); 12204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1221bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta int childCount = viewGroup.getChildCount(); 12234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == mContentRoot) { 12244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount); 12254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount); 12264ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 12274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset, 122805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet setExtendedInfo); 12294ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithoutOffset.add(childViewInfo[0]); 12304ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithOffset.add(childViewInfo[1]); 1231bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 12324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mViewInfoList = childrenWithOffset; 12334ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return childrenWithoutOffset; 12344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 12354ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = new ArrayList<ViewInfo>(childCount); 12364ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 12374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo, 12384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta isContentFrame)); 12394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return children; 1241bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 12424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1243bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the 12464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. It returns two {@code ViewInfo} objects with the same children, 12474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * one with the {@code offset} and other without the {@code offset}. The offset is needed to 12484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * get the right bounds if the {@code ViewInfo} hierarchy is accessed from 12494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the 12504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * offset is not needed. 12514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at 12534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * index 1 is with the offset. 12544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 1255d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @NonNull 12564ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) { 12574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] result = new ViewInfo[2]; 12584ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view == null) { 12594ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 12604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 12624ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0] = createViewInfo(view, 0, setExtendedInfo, true); 12634ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1] = createViewInfo(view, offset, setExtendedInfo, true); 12644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 12654ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true); 12664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0].setChildren(children); 12674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1].setChildren(children); 12684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 1270bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1271c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1272c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 12734ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children 12744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not 12754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * set. 12764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. Used only if view is part of the content frame. 1277c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 12784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo, 12794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 1280c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view == null) { 1281c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return null; 1282c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1283c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1284d15459197f71f8cc940e2b057b399117df282f2cDiego Perez ViewParent parent = view.getParent(); 12854ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result; 12864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (isContentFrame) { 1287d15459197f71f8cc940e2b057b399117df282f2cDiego Perez // Account for parent scroll values when calculating the bounding box 1288d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollX = parent != null ? ((View)parent).getScrollX() : 0; 1289d15459197f71f8cc940e2b057b399117df282f2cDiego Perez int scrollY = parent != null ? ((View)parent).getScrollY() : 0; 1290d15459197f71f8cc940e2b057b399117df282f2cDiego Perez 1291bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // The view is part of the layout added by the user. Hence, 1292bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // the ViewCookie may be obtained only through the Context. 12934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result = new ViewInfo(view.getClass().getName(), 1294bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta getContext().getViewKey(view), 1295d15459197f71f8cc940e2b057b399117df282f2cDiego Perez -scrollX + view.getLeft(), -scrollY + view.getTop() + offset, 1296d15459197f71f8cc940e2b057b399117df282f2cDiego Perez -scrollX + view.getRight(), -scrollY + view.getBottom() + offset, 1297d15459197f71f8cc940e2b057b399117df282f2cDiego Perez view, view.getLayoutParams()); 12984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 1299bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We are part of the system decor. 1300bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), 13015ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta getViewKey(view), 13024ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getLeft(), view.getTop(), view.getRight(), 13034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getBottom(), view, view.getLayoutParams()); 1304bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta result = r; 1305bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We currently mark three kinds of views: 1306bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 1. Menus in the Action Bar 1307bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 2. Menus in the Overflow popup. 1308bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 3. The overflow popup button. 1309bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (view instanceof ListMenuItemView) { 1310bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 2. 1311bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // All menus in the popup are of type ListMenuItemView. 1312bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU); 1313bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1314bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 3. 1315bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ViewGroup.LayoutParams lp = view.getLayoutParams(); 1316bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (lp instanceof ActionMenuView.LayoutParams && 1317bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ((ActionMenuView.LayoutParams) lp).isOverflowButton) { 1318bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW); 1319bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1320bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 1. 1321bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // A view is a menu in the Action Bar is it is not the overflow button and of 1322bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // its parent is of type ActionMenuView. We can also check if the view is 1323bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // instanceof ActionMenuItemView but that will fail for menus using 1324bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // actionProviderClass. 1325bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta while (parent != mViewRoot && parent instanceof ViewGroup) { 1326bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (parent instanceof ActionMenuView) { 1327bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_MENU); 1328bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta break; 1329bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1330bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta parent = parent.getParent(); 1331bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1332bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1333bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 13344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1335c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 133605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (setExtendedInfo) { 133705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet MarginLayoutParams marginParams = null; 133805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet LayoutParams params = view.getLayoutParams(); 133905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (params instanceof MarginLayoutParams) { 134005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams = (MarginLayoutParams) params; 134105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 134205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet result.setExtendedInfo(view.getBaseline(), 134305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.leftMargin : 0, 134405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.topMargin : 0, 134505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.rightMargin : 0, 134605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.bottomMargin : 0); 134705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 134805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet 1349c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return result; 1350c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1351c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1352bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta /* (non-Javadoc) 13535ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * The cookie for menu items are stored in menu item and not in the map from View stored in 13545ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * BridgeContext. 13555ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta */ 1356d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @Nullable 13575ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta private Object getViewKey(View view) { 13585ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta BridgeContext context = getContext(); 13595ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (!(view instanceof MenuView.ItemView)) { 13605ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return context.getViewKey(view); 13615ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13625ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta MenuItemImpl menuItem; 13635ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (view instanceof ActionMenuItemView) { 13645ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ActionMenuItemView) view).getItemData(); 13655ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof ListMenuItemView) { 13665ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ListMenuItemView) view).getItemData(); 13675ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof IconMenuItemView) { 13685ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((IconMenuItemView) view).getItemData(); 13695ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else { 13705ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = null; 13715ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13725ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (menuItem instanceof BridgeMenuItemImpl) { 13735ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return ((BridgeMenuItemImpl) menuItem).getViewCookie(); 13745ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13755ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 13765ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return null; 13775ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13785ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 1379c13aa0c035cd226d27323bc0e533632ba32f6a84Diego Perez public void invalidateRenderingSize() { 13804ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 13814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 1383c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public BufferedImage getImage() { 1384c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return mImage; 1385c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1386c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 138716584225125acba18b74920b902c798dfead0328Xavier Ducrohet public boolean isAlphaChannelImage() { 138816584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mIsAlphaChannelImage; 138916584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 139016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 13917d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public List<ViewInfo> getViewInfos() { 13927d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return mViewInfoList; 1393c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1394cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet 13954ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta public List<ViewInfo> getSystemViewInfos() { 13964ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return mSystemViewInfoList; 13974ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 139919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Map<String, String> getDefaultProperties(Object viewObject) { 1400b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return getContext().getDefaultPropMap(viewObject); 1401cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet } 1402c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 140319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public void setScene(RenderSession session) { 140419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mScene = session; 1405c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1406c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 140719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSession getSession() { 1408c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet return mScene; 1409c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1410f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez 1411f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez public void dispose() { 14125d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez boolean createdLooper = false; 14135d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez if (Looper.myLooper() == null) { 14145d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // Detaching the root view from the window will try to stop any running animations. 14155d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // The stop method checks that it can run in the looper so, if there is no current 14165d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez // looper, we create a temporary one to complete the shutdown. 14175d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez Bridge.prepareThread(); 14185d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez createdLooper = true; 14195d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez } 1420f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez AttachInfo_Accessor.detachFromWindow(mViewRoot); 1421f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mCanvas != null) { 1422f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mCanvas.release(); 1423f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mCanvas = null; 1424f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1425f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mViewInfoList != null) { 1426f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mViewInfoList.clear(); 1427f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1428f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez if (mSystemViewInfoList != null) { 1429f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mSystemViewInfoList.clear(); 1430f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1431f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mImage = null; 1432f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mViewRoot = null; 1433f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez mContentRoot = null; 14345d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez 14355d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez if (createdLooper) { 14365d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez Bridge.cleanupThread(); 143761ccc9198ab09363edbf500d7669dbcfafc5fa28Deepanshu Gupta Choreographer_Delegate.dispose(); 14385d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez } 1439f5650cf3a3a1a8d6ced9fc7b0f399689c9adc1b8Diego Perez } 1440c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet} 1441