RenderSessionImpl.java revision 777163c3facaed668b43061d726a572fd58f6f60
13bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/* 23bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 33bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 43bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 53bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * you may not use this file except in compliance with the License. 63bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * You may obtain a copy of the License at 73bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 83bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 93bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software 113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * See the License for the specific language governing permissions and 143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * limitations under the License. 153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetpackage com.android.layoutlib.bridge.impl; 183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 197062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding; 2064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig; 21ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener; 22ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser; 23b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport com.android.ide.common.rendering.api.LayoutlibCallback; 240d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 25ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference; 27ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 28ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 29ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 30d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams; 31b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode; 32d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo; 3370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport com.android.ide.common.rendering.api.ViewType; 3441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView; 3541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl; 3641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView; 3741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView; 3841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl; 3941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuView; 40ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 42ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; 433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 44a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaevimport com.android.layoutlib.bridge.android.RenderParamsFlags; 45c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsenimport com.android.layoutlib.bridge.android.support.DesignLibUtil; 467062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter; 477062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; 481b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohetimport com.android.resources.ResourceType; 49344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Guptaimport com.android.tools.layoutlib.java.System_Delegate; 50947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohetimport com.android.util.Pair; 513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 52994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.animation.AnimationThread; 5333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.Animator; 54ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport android.animation.AnimatorInflater; 5533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.LayoutTransition; 5662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 57442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.NonNull; 58442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.Nullable; 593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.app.Fragment_Delegate; 603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap; 613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Canvas; 63e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perezimport android.os.Looper; 648a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Guptaimport android.preference.Preference_Delegate; 65994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.AttachInfo_Accessor; 66994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.BridgeInflater; 67344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Guptaimport android.view.Choreographer_Delegate; 6876f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.IWindowManager; 6964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport android.view.IWindowManagerImpl; 7076f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.Surface; 713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View; 723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View.MeasureSpec; 73d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.view.ViewGroup; 74ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport android.view.ViewGroup.LayoutParams; 756208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams; 7670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.view.ViewParent; 7776f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate; 787062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsListView; 797062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsSpinner; 8070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.widget.ActionMenuView; 817062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AdapterView; 827062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ExpandableListView; 833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.FrameLayout; 84f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.LinearLayout; 857062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ListView; 8662c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohetimport android.widget.QuickContactBadge; 873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.TabHost; 88f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.TabHost.TabSpec; 89d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.widget.TabWidget; 903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 914c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohetimport java.awt.AlphaComposite; 923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Color; 933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Graphics2D; 943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.image.BufferedImage; 953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.ArrayList; 963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.List; 973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.Map; 983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 99b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 100b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 101b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 102b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 103b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 104b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 105baf88de1f5c435a788f6c38720354b2dbaa19e60Deepanshu Guptaimport static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; 106b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta 1073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/** 108ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * Class implementing the render session. 109952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * <p/> 110ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 111ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 1123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * be done on the layout. 1133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 1140fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> { 1153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // scene state 117ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private RenderSession mScene; 1183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 1193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BridgeInflater mInflater; 120799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet private ViewGroup mViewRoot; 121799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet private FrameLayout mContentRoot; 1221392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private Canvas mCanvas; 1231392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private int mMeasuredScreenWidth = -1; 1241392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private int mMeasuredScreenHeight = -1; 125799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet private boolean mIsAlphaChannelImage; 126344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta /** If >= 0, a frame will be executed */ 127344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta private long mElapsedFrameTimeNanos = -1; 128344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta /** True if one frame has been already executed to start the animations */ 129344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta private boolean mFirstFrameExecuted = false; 130a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // information being returned through the API 1323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BufferedImage mImage; 133e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet private List<ViewInfo> mViewInfoList; 13485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta private List<ViewInfo> mSystemViewInfoList; 1358b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta private Layout.Builder mLayoutBuilder; 1363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final class PostInflateException extends Exception { 1383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final long serialVersionUID = 1L; 1393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet public PostInflateException(String message) { 1413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet super(message); 1423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 1463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 1473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 1488d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)}, 1498d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * which act as a 150ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 1513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 1528d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * @see Bridge#createSession(SessionParams) 1533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 154b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohet public RenderSessionImpl(SessionParams params) { 1550fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet super(new SessionParams(params)); 156ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 157ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 158ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 159ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 160ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * inflater, and parser. 161ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 162ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 163ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 164ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @return whether the scene was prepared 165ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 166ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @see #acquire(long) 167ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @see #release() 168ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 1690fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet @Override 170ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result init(long timeout) { 1710fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet Result result = super.init(timeout); 172952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 173ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet return result; 174ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 1753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1760fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet SessionParams params = getParams(); 1770fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 1783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 179a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // use default of true in case it's not found to use alpha by default 180300f4893351a9974fa3380c513b29d4a7883cd74Deepanshu Gupta mIsAlphaChannelImage = ResourceHelper.getBooleanThemeValue(params.getResources(), 181300f4893351a9974fa3380c513b29d4a7883cd74Deepanshu Gupta "windowIsFloating", true, true); 182ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 1838b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mLayoutBuilder = new Layout.Builder(params, context); 1843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 18576f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet // FIXME: find those out, and possibly add them to the render params 18676f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet boolean hasNavigationBar = true; 187952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta //noinspection ConstantConditions 18876f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), 1898b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); 19076f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet WindowManagerGlobal_Delegate.setWindowManagerService(iwm); 19176f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet 1923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // build the inflater and parser. 193b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); 1940fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet context.setBridgeInflater(mInflater); 195ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 1968b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); 197ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 1983054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet return SUCCESS.createResult(); 1993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 2023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Inflates the layout. 2033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 204ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 205ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 206ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 207ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 2083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 209ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result inflate() { 210ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 211ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 2123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet try { 2138b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mViewRoot = new Layout(mLayoutBuilder); 2148b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mLayoutBuilder = null; // Done with the builder. 2158b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mContentRoot = ((Layout) mViewRoot).getContentRoot(); 2160fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet SessionParams params = getParams(); 2170fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 2183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 2203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // it can instantiate the custom Fragment. 221b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); 2223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 223a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); 2248a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta boolean isPreference = "PreferenceScreen".equals(rootTag); 2258a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta View view; 2268a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta if (isPreference) { 2278a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, 2288b4b0ce31acc9f57c7df5b1c70183a6655c1edfbDeepanshu Gupta mContentRoot); 2298a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta } else { 2308a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta view = mInflater.inflate(mBlockParser, mContentRoot); 2318a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta } 2323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2337062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // done with the parser, pop it. 2347062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet context.popParser(); 2357062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 236b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(null); 2373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // set the AttachInfo on the root view. 239994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet AttachInfo_Accessor.setAttachInfo(mViewRoot); 2403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 241a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 242b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null); 2439028fa93da0f9c7dad2176de347cd6e705084c9fDeepanshu Gupta mInflater.onDoneInflation(); 244a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet 245c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen setActiveToolbar(view, context, params); 246c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 247ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 2483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (PostInflateException e) { 249ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 2503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (Throwable e) { 2513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the real cause of the exception. 2523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Throwable t = e; 2533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet while (t.getCause() != null) { 2543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet t = t.getCause(); 2553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 257ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 2583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 262344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta * Sets the time for which the next frame will be selected. The time is the elapsed time from 263344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta * the current system nanos time. You 264344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta */ 265344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta public void setElapsedFrameTimeNanos(long nanos) { 266344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta mElapsedFrameTimeNanos = nanos; 267344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta } 268344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta 269344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta /** 2703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Renders the scene. 2713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 272ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 273ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 2744c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 2754c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 2764c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * animations.) 2774c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * 278ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 279ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 2801392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet * 2818d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * @see SessionParams#getRenderingMode() 282799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#render(long) 2833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 2844c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet public Result render(boolean freshRender) { 285ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 286ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 2870fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet SessionParams params = getParams(); 2880fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet 2893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet try { 2903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (mViewRoot == null) { 291ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 2923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2940fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet RenderingMode renderingMode = params.getRenderingMode(); 29564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet HardwareConfig hardwareConfig = params.getHardwareConfig(); 296e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet 2971392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // only do the screen measure when needed. 2981392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet boolean newRenderSize = false; 2991392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (mMeasuredScreenWidth == -1) { 3001392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet newRenderSize = true; 30164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); 30264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); 3031392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 3041392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (renderingMode != RenderingMode.NORMAL) { 3058ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int widthMeasureSpecMode = renderingMode.isHorizExpand() ? 3068ae691c1148038995d1185716f629b82c582897fXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 3078ae691c1148038995d1185716f629b82c582897fXavier Ducrohet : MeasureSpec.EXACTLY; 3088ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int heightMeasureSpecMode = renderingMode.isVertExpand() ? 3098ae691c1148038995d1185716f629b82c582897fXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 3108ae691c1148038995d1185716f629b82c582897fXavier Ducrohet : MeasureSpec.EXACTLY; 3118ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 3128ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // We used to compare the measured size of the content to the screen size but 3138ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // this does not work anymore due to the 2 following issues: 3148ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // - If the content is in a decor (system bar, title/action bar), the root view 3158ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // will not resize even with the UNSPECIFIED because of the embedded layout. 3168ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // - If there is no decor, but a dialog frame, then the dialog padding prevents 3178ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // comparing the size of the content to the screen frame (as it would not 3188ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // take into account the dialog padding). 3198ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 3208ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // The solution is to first get the content size in a normal rendering, inside 3218ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // the decor or the dialog padding. 3228ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // Then measure only the content with UNSPECIFIED to see the size difference 3238ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // and apply this to the screen size. 3248ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 3258ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // first measure the full layout, with EXACTLY to get the size of the 3268ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // content as it is inside the decor/dialog 327952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") 3288ae691c1148038995d1185716f629b82c582897fXavier Ducrohet Pair<Integer, Integer> exactMeasure = measureView( 3298ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mViewRoot, mContentRoot.getChildAt(0), 3308ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenWidth, MeasureSpec.EXACTLY, 3318ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenHeight, MeasureSpec.EXACTLY); 3328ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 3338ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // now measure the content only using UNSPECIFIED (where applicable, based on 3348ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // the rendering mode). This will give us the size the content needs. 335952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") 3368ae691c1148038995d1185716f629b82c582897fXavier Ducrohet Pair<Integer, Integer> result = measureView( 3378ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mContentRoot, mContentRoot.getChildAt(0), 3388ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenWidth, widthMeasureSpecMode, 3398ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenHeight, heightMeasureSpecMode); 3408ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 3418ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // now look at the difference and add what is needed. 3421392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (renderingMode.isHorizExpand()) { 3438ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int measuredWidth = exactMeasure.getFirst(); 3448ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int neededWidth = result.getFirst(); 3458ae691c1148038995d1185716f629b82c582897fXavier Ducrohet if (neededWidth > measuredWidth) { 3468ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenWidth += neededWidth - measuredWidth; 3471392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 34892d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez if (mMeasuredScreenWidth < measuredWidth) { 34992d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez // If the screen width is less than the exact measured width, 35092d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez // expand to match. 35192d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez mMeasuredScreenWidth = measuredWidth; 35292d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez } 353e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet } 3543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3551392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (renderingMode.isVertExpand()) { 3568ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int measuredHeight = exactMeasure.getSecond(); 3578ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int neededHeight = result.getSecond(); 3588ae691c1148038995d1185716f629b82c582897fXavier Ducrohet if (neededHeight > measuredHeight) { 3598ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenHeight += neededHeight - measuredHeight; 3601392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 36192d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez if (mMeasuredScreenHeight < measuredHeight) { 36292d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez // If the screen height is less than the exact measured height, 36392d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez // expand to match. 36492d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez mMeasuredScreenHeight = measuredHeight; 36592d9c3fa220868d6641b5831b24a0a72af7c6751Diego Perez } 366e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet } 3673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3708ae691c1148038995d1185716f629b82c582897fXavier Ducrohet // measure again with the size we need 3713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // This must always be done before the call to layout 3728ae691c1148038995d1185716f629b82c582897fXavier Ducrohet measureView(mViewRoot, null /*measuredView*/, 3738ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenWidth, MeasureSpec.EXACTLY, 3748ae691c1148038995d1185716f629b82c582897fXavier Ducrohet mMeasuredScreenHeight, MeasureSpec.EXACTLY); 3753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // now do the layout. 377a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 3783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 379c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen handleScrolling(mViewRoot); 380c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 381f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet if (params.isLayoutOnly()) { 382f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // delete the canvas and image to reset them on the next full rendering 383f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mImage = null; 384f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mCanvas = null; 385f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } else { 386994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot); 387f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet 388f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // draw the views 389f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // create the BufferedImage into which the layout will be rendered. 390f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet boolean newImage = false; 391e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez 392e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // When disableBitmapCaching is true, we do not reuse mImage and 393e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // we create a new one in every render. 394e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // This is useful when mImage is just a wrapper of Graphics2D so 395e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // it doesn't get cached. 396e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( 397a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); 398e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez if (newRenderSize || mCanvas == null || disableBitmapCaching) { 399f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet if (params.getImageFactory() != null) { 400f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mImage = params.getImageFactory().getImage( 401f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenWidth, 402f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenHeight); 403f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } else { 404f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mImage = new BufferedImage( 405f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenWidth, 406f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mMeasuredScreenHeight, 407f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 408f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet newImage = true; 409f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } 410f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet 411f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet if (params.isBgColorOverridden()) { 412f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 413f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet newImage = true; 414f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 415f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 416f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 417f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 418f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.dispose(); 419f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } 420f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet 421f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // create an Android bitmap around the BufferedImage 422f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 42364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet true /*isMutable*/, hardwareConfig.getDensity()); 424f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet 425e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez if (mCanvas == null) { 426e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez // create a Canvas around the Android bitmap 427e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez mCanvas = new Canvas(bitmap); 428e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez } else { 429e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez mCanvas.setBitmap(bitmap); 430e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez } 43164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 4321392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 4333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 434952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (freshRender && !newImage) { 4351392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 4364c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet gc.setComposite(AlphaComposite.Src); 4373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 438f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 439f4978e031c3ad565f02d5a4c65f87ae4477f3613Deepanshu Gupta gc.fillRect(0, 0, 440f4978e031c3ad565f02d5a4c65f87ae4477f3613Deepanshu Gupta mMeasuredScreenWidth, mMeasuredScreenHeight); 441a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 442f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet // done 443f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet gc.dispose(); 444f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet } 445a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 446344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta if (mElapsedFrameTimeNanos >= 0) { 447344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta long initialTime = System_Delegate.nanoTime(); 448344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta if (!mFirstFrameExecuted) { 449344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta // The first frame will initialize the animations 450344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta Choreographer_Delegate.doFrame(initialTime); 451344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta mFirstFrameExecuted = true; 452344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta } 453344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta // Second frame will move the animations 454344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos); 455344cbc9b8ed3ae06a5b183d684df0399fef59879Deepanshu Gupta } 456f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet mViewRoot.draw(mCanvas); 4574c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet } 4584c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet 45941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), 46041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta false); 4613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // success! 463ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 4643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (Throwable e) { 4653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the real cause of the exception. 4663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Throwable t = e; 4673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet while (t.getCause() != null) { 4683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet t = t.getCause(); 4693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 4703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 471ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 4723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 4733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 4743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 4768ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * Executes {@link View#measure(int, int)} on a given view with the given parameters (used 4778ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. 4788ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * 4798ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) 4808ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). 4818ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * 4828ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param viewToMeasure the view on which to execute measure(). 4838ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param measuredView if non null, the view to query for its measured width/height. 4848ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param width the width to use in the MeasureSpec. 4858ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param widthMode the MeasureSpec mode to use for the width. 4868ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param height the height to use in the MeasureSpec. 4878ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @param heightMode the MeasureSpec mode to use for the height. 4888ae691c1148038995d1185716f629b82c582897fXavier Ducrohet * @return the measured width/height if measuredView is non-null, null otherwise. 4898ae691c1148038995d1185716f629b82c582897fXavier Ducrohet */ 490952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 4918ae691c1148038995d1185716f629b82c582897fXavier Ducrohet private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, 4928ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int width, int widthMode, int height, int heightMode) { 4938ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); 4948ae691c1148038995d1185716f629b82c582897fXavier Ducrohet int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); 4958ae691c1148038995d1185716f629b82c582897fXavier Ducrohet viewToMeasure.measure(w_spec, h_spec); 4968ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 4978ae691c1148038995d1185716f629b82c582897fXavier Ducrohet if (measuredView != null) { 4988ae691c1148038995d1185716f629b82c582897fXavier Ducrohet return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); 4998ae691c1148038995d1185716f629b82c582897fXavier Ducrohet } 5008ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 5018ae691c1148038995d1185716f629b82c582897fXavier Ducrohet return null; 5028ae691c1148038995d1185716f629b82c582897fXavier Ducrohet } 5038ae691c1148038995d1185716f629b82c582897fXavier Ducrohet 5048ae691c1148038995d1185716f629b82c582897fXavier Ducrohet /** 505ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Animate an object 506ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * <p> 507ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 508ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 509ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 510ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 51133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 512799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 513ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 514ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result animate(Object targetObject, String animationName, 515ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 516ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 517ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 5180fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 5190fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet 520ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // find the animation file. 521952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta ResourceValue animationResource; 522ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet int animationId = 0; 523ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (isFrameworkAnimation) { 5240fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 5251b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 526ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 527947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 528ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 529ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } else { 5300fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 5311b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 532ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 533b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta animationId = context.getLayoutlibCallback().getResourceId( 5341b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 535ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 536ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 537ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 538ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 539ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet try { 5400fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 541ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (anim != null) { 542ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet anim.setTarget(targetObject); 543ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 54433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 545ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 546ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 547ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 548ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } catch (Exception e) { 549b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // get the real cause of the exception. 550b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet Throwable t = e; 551b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet while (t.getCause() != null) { 552b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet t = t.getCause(); 553b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 554b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 555ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 556ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 557ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 558ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 559ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 560b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 561b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 56233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 56333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Insert a new child into an existing parent. 56433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 56533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 56633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 56733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 56833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 56933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 570799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 57133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 572ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 57333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final int index, IAnimationListener listener) { 574b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet checkLock(); 575b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 5760fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet BridgeContext context = getContext(); 5770fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet 578b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // create a block parser for the XML 579a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 580a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet childXml, context, false /* platformResourceFlag */); 581b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 582b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 583b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 584b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // be created correctly. 58533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 586a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet blockParser.ensurePopped(); 587b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 58833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet invalidateRenderingSize(); 58933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 59033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 59133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 59233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 59333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 594ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result preAnimation() { 59533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 59633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return addView(parentView, child, index); 59733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 59833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 59933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 60033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet public void postAnimation() { 60133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parentView.setLayoutTransition(null); 60233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 60333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet }.start(); 60433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 60533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 606ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(child); 6071392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 6081392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 60933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // add it to the parentView in the correct location 610ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = addView(parentView, child, index); 611952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 61233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 61333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 614b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 6154c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 6161766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet if (result.isSuccess()) { 61733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet result = result.getCopyWithData(child); 6181766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet } 6191766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet 6201766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet return result; 621b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 622b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 62333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 62433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Adds a given view to a given parent at a given index. 62533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 62633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param parent the parent to receive the view 62733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param view the view to add to the parent 62833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param index the index where to do the add. 62933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 630ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 631ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 63233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 63333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 634ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 63533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet try { 63633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.addView(view, index); 637ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 63833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } catch (UnsupportedOperationException e) { 63933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 640ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 64133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 64233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 64333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 64433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 64533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Moves a view to a new parent at a given location 64633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 64733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 64833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 64933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 65033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 65133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 652799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 65333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 65462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 65524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 656b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet checkLock(); 657b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 65833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet invalidateRenderingSize(); 65933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 660ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet LayoutParams layoutParams = null; 66133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (layoutParamsMap != null) { 66233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 66362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 66433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 66533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 6661392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 66762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // get the current parent of the view that needs to be moved. 66862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 66962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 67033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 67133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final LayoutParams params = layoutParams; 672ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 67324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 67424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // parent views are different we fake the animation through a no animation thread. 67524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (previousParent != newParentView) { 67624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet new Thread("not animated moveChild") { 67724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 67824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public void run() { 67924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 68024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet params); 681952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 68224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 68324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 68424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 68524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // ready to do the work, acquire the scene. 68624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet result = acquire(250); 687952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 68824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 68924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet return; 69024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 69124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 69224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet try { 6934c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 69424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (result.isSuccess()) { 69524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 69624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 69724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } finally { 69824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet release(); 69924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 70024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 70124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 70262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 70324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet }.start(); 70424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } else { 70524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 70662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 70724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 70824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public Result preAnimation() { 70924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // set up the transition for the parent. 71024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet LayoutTransition transition = new LayoutTransition(); 71124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.setLayoutTransition(transition); 7125562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet 71324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // tweak the animation durations and start delays (to match the duration of 71424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // animation playing just before). 71524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 71624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // on the LayoutTransition. 71724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 71824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 71924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 720ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 72124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 72224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 72324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 72424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 72524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 72624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 72724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 72824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 72924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 73024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 73124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 73224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 73324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public void postAnimation() { 73424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.setLayoutTransition(null); 73524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParentView.setLayoutTransition(null); 73624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 73724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet }.start(); 73824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 73933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 74033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 741ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(layoutParams); 742b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 743b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 74462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 745952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 74633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 74733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 748b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 7494c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 750ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet if (layoutParams != null && result.isSuccess()) { 75133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet result = result.getCopyWithData(layoutParams); 752ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet } 753ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 754ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet return result; 755b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 756b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 75733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 75833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 75933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * an optional new {@link LayoutParams} instance 76033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 76162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 76262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet * @param newParent the new parent 76324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet * @param movedView the view to move 76433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param index the new location in the new parent 76533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 76633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 767ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 768ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 76933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 77033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 77124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 77224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet final View movedView, final int index, final LayoutParams params) { 7731392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet try { 77462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // check if there is a transition on the previousParent. 77524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 77624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (previousTransition != null) { 7775562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 7785562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 7795562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 7805562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 7815562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // to handle). 7825562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 7835562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 7845562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // adding the child or the child will appear in its new location before the 7855562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // other children have made room for it. 78662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 78762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 78824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 78924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet private int mChangeDisappearingCount = 0; 79062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 791d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet @Override 79262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 79362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet View view, int transitionType) { 79424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 79524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount++; 79624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 79762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 79833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 799d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet @Override 80062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 80162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet View view, int transitionType) { 80224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 80324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount--; 80424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 80524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 80624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 80724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount == 0) { 80862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add it to the parentView in the correct location 80962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet if (params != null) { 81024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index, params); 81162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } else { 81224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index); 81362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 81462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 81562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 81662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet }); 81762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 81862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // remove the view from the current parent. 81924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.removeView(movedView); 82062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 82162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 82262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet return SUCCESS.createResult(); 82333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } else { 82462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // standard code with no animation. pretty simple. 82524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.removeView(movedView); 82633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 82762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add it to the parentView in the correct location 82862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet if (params != null) { 82924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index, params); 83062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } else { 83124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index); 83262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 83362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 83462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet return SUCCESS.createResult(); 83562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 8361392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } catch (UnsupportedOperationException e) { 8371392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 838ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 839b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 84033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 84133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 84233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 84333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Removes a child from its current parent. 84433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 84533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 84633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 84733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 84833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 84933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 850799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 85133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 852ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 85333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet checkLock(); 854b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 8551392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet invalidateRenderingSize(); 8561392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 85733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 85833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 85933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 86033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 86133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 86233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 863ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result preAnimation() { 86433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 86533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return removeView(parent, childView); 86633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 86733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 86833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 86933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet public void postAnimation() { 87033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.setLayoutTransition(null); 87133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 87233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet }.start(); 87333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 87433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 875ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 87633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 87733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 878ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = removeView(parent, childView); 879952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!result.isSuccess()) { 88033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 88133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 88233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 8834c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet return render(false /*freshRender*/); 884ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 885ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 886ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 88733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Removes a given view from its current parent. 88833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 88933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param view the view to remove from its parent 89033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 891ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 892ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 89333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 89433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 895ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 89633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet try { 89733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.removeView(view); 898ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 89933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } catch (UnsupportedOperationException e) { 90033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 901ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 90233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 90333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 90433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 9053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 906952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * Post process on a view hierarchy that was just inflated. 907952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * <p/> 908952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the 9093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 9103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * based on the content of the {@link FrameLayout}. 9113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param view the root view to process. 912b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta * @param layoutlibCallback callback to the project. 9138a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta * @param skip the view and it's children are not processed. 9143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 915952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 916b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip) 9173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throws PostInflateException { 9188a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta if (view == skip) { 9198a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta return; 9208a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta } 9213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (view instanceof TabHost) { 922b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta setupTabHost((TabHost) view, layoutlibCallback); 92362c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 92462c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 92562c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet badge.setImageToDefault(); 9267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } else if (view instanceof AdapterView<?>) { 9277062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // get the view ID. 9287062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet int id = view.getId(); 9297062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9307062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet BridgeContext context = getContext(); 9317062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9327062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // get a ResourceReference from the integer ID. 9337062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ResourceReference listRef = context.resolveId(id); 9347062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9357062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (listRef != null) { 9367062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet SessionParams params = getParams(); 9377062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet AdapterBinding binding = params.getAdapterBindings().get(listRef); 9387062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9397062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet // if there was no adapter binding, trying to get it from the call back. 9407062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (binding == null) { 941b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta binding = layoutlibCallback.getAdapterBinding( 942b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta listRef, context.getViewKey(view), view); 9437062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9447062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9457062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (binding != null) { 9467062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9477062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (view instanceof AbsListView) { 9487062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && 9497062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet view instanceof ListView) { 9507062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ListView list = (ListView) view; 9517062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9527062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet boolean skipCallbackParser = false; 9537062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9547062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet int count = binding.getHeaderCount(); 9558a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta for (int i = 0; i < count; i++) { 9567062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 9577062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet binding.getHeaderAt(i), 958b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta list, false, skipCallbackParser); 9597062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (pair.getFirst() != null) { 9607062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet list.addHeaderView(pair.getFirst()); 9617062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9627062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9637062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet skipCallbackParser |= pair.getSecond(); 9647062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9657062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9667062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet count = binding.getFooterCount(); 9678a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta for (int i = 0; i < count; i++) { 9687062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 9697062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet binding.getFooterAt(i), 970b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta list, false, skipCallbackParser); 9717062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (pair.getFirst() != null) { 9727062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet list.addFooterView(pair.getFirst()); 9737062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9747062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9757062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet skipCallbackParser |= pair.getSecond(); 9767062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9777062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9787062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet 9797062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet if (view instanceof ExpandableListView) { 9807062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ((ExpandableListView) view).setAdapter( 981b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta new FakeExpandableAdapter(listRef, binding, layoutlibCallback)); 9827062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } else { 9837062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ((AbsListView) view).setAdapter( 984b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 9857062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9867062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } else if (view instanceof AbsSpinner) { 9877062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet ((AbsSpinner) view).setAdapter( 988b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 9897062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9907062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9917062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet } 9923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } else if (view instanceof ViewGroup) { 9939028fa93da0f9c7dad2176de347cd6e705084c9fDeepanshu Gupta mInflater.postInflateProcess(view); 9948a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta ViewGroup group = (ViewGroup) view; 9953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet final int count = group.getChildCount(); 9968a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta for (int c = 0; c < count; c++) { 9973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet View child = group.getChildAt(c); 998b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta postInflateProcess(child, layoutlibCallback, skip); 9993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 10003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 10013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 10023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 10033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 1004c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen * If the root layout is a CoordinatorLayout with an AppBar: 1005c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen * Set the title of the AppBar to the title of the activity context. 1006c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen */ 1007c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen private void setActiveToolbar(View view, BridgeContext context, SessionParams params) { 1008c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT); 1009c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (coordinatorLayout == null) { 1010c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1011c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1012c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT); 1013c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (appBar == null) { 1014c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1015c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1016c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup collapsingToolbar = 1017c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT); 1018c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (collapsingToolbar == null) { 1019c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1020c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1021c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!hasToolbar(collapsingToolbar)) { 1022c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1023c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1024c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen RenderResources res = context.getRenderResources(); 1025c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen String title = params.getAppLabel(); 1026c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ResourceValue titleValue = res.findResValue(title, false); 1027c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (titleValue != null && titleValue.getValue() != null) { 1028c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen title = titleValue.getValue(); 1029c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1030c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen DesignLibUtil.setTitle(collapsingToolbar, title); 1031c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1032c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1033c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen private View findChildView(View view, String className) { 1034c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 1035c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return null; 1036c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1037c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 1038c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 1039c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), className)) { 1040c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return group.getChildAt(i); 1041c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1042c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1043c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return null; 1044c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1045c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1046c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen private boolean hasToolbar(View collapsingToolbar) { 1047c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!(collapsingToolbar instanceof ViewGroup)) { 1048c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return false; 1049c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1050c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup group = (ViewGroup) collapsingToolbar; 1051c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 1052c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) { 1053c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return true; 1054c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1055c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1056c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return false; 1057c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1058c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1059c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen /** 1060777163c3facaed668b43061d726a572fd58f6f60Diego Perez * Set the scroll position on all the components with the "scrollX" and "scrollY" attribute. If 1061777163c3facaed668b43061d726a572fd58f6f60Diego Perez * the component supports nested scrolling attempt that first, then use the unconsumed scroll 1062777163c3facaed668b43061d726a572fd58f6f60Diego Perez * part to scroll the content in the component. 1063c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen */ 1064c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen private void handleScrolling(View view) { 1065c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen BridgeContext context = getContext(); 1066777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollPosX = context.getScrollXPos(view); 1067777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollPosY = context.getScrollYPos(view); 1068777163c3facaed668b43061d726a572fd58f6f60Diego Perez if (scrollPosX != 0 || scrollPosY != 0) { 1069c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (view.isNestedScrollingEnabled()) { 1070c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen int[] consumed = new int[2]; 1071777163c3facaed668b43061d726a572fd58f6f60Diego Perez int axis = scrollPosX != 0 ? View.SCROLL_AXIS_HORIZONTAL : 0; 1072777163c3facaed668b43061d726a572fd58f6f60Diego Perez axis |= scrollPosY != 0 ? View.SCROLL_AXIS_VERTICAL : 0; 1073777163c3facaed668b43061d726a572fd58f6f60Diego Perez if (view.startNestedScroll(axis)) { 1074777163c3facaed668b43061d726a572fd58f6f60Diego Perez view.dispatchNestedPreScroll(scrollPosX, scrollPosY, consumed, null); 1075777163c3facaed668b43061d726a572fd58f6f60Diego Perez view.dispatchNestedScroll(consumed[0], consumed[1], scrollPosX, scrollPosY, 1076777163c3facaed668b43061d726a572fd58f6f60Diego Perez null); 1077c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen view.stopNestedScroll(); 1078777163c3facaed668b43061d726a572fd58f6f60Diego Perez scrollPosX -= consumed[0]; 1079777163c3facaed668b43061d726a572fd58f6f60Diego Perez scrollPosY -= consumed[1]; 1080c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1081c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1082777163c3facaed668b43061d726a572fd58f6f60Diego Perez if (scrollPosX != 0 || scrollPosY != 0) { 1083777163c3facaed668b43061d726a572fd58f6f60Diego Perez view.scrollBy(scrollPosX, scrollPosY); 1084c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1085c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1086c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1087c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 1088c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen return; 1089c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1090c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 1091c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 1092c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen View child = group.getChildAt(i); 1093c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen handleScrolling(child); 1094c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1095c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen } 1096c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen 1097c46c84ee673934f340b27b40366a5a61669a4a1eJens Ole Lauridsen /** 10983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Sets up a {@link TabHost} object. 10993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param tabHost the TabHost to setup. 1100b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta * @param layoutlibCallback The project callback object to access the project R class. 11013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @throws PostInflateException 11023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 1103b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback) 11043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throws PostInflateException { 11053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 11063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 11073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (v == null) { 11093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException( 11103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 11113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1113952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!(v instanceof TabWidget)) { 11143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException(String.format( 11153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 11163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 11173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 11203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (v == null) { 1122952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty) 1123952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta //noinspection SpellCheckingInspection 11243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException( 11253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 11263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1128952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta if (!(v instanceof FrameLayout)) { 1129952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta //noinspection SpellCheckingInspection 11303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException(String.format( 11313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 11323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 11333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet FrameLayout content = (FrameLayout)v; 11363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1137952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta // now process the content of the frameLayout and dynamically create tabs for it. 11383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet final int count = content.getChildCount(); 11393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 11413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // and FrameLayout. 11423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet tabHost.setup(); 11433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1144f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye if (count == 0) { 1145f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye // Create a dummy child to get a single tab 11466257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta TabSpec spec = tabHost.newTabSpec("tag") 11476257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta .setIndicator("Tab Label", tabHost.getResources() 11486257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta .getDrawable(android.R.drawable.ic_menu_info_details, null)) 1149f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye .setContent(new TabHost.TabContentFactory() { 1150d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet @Override 1151f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye public View createTabContent(String tag) { 11520fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet return new LinearLayout(getContext()); 1153f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } 1154f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye }); 1155f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye tabHost.addTab(spec); 1156f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } else { 1157952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta // for each child of the frameLayout, add a new TabSpec 1158f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye for (int i = 0 ; i < count ; i++) { 1159f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye View child = content.getChildAt(i); 1160f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 11618a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta @SuppressWarnings("ConstantConditions") // child cannot be null. 1162f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye int id = child.getId(); 1163952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta @SuppressWarnings("deprecation") 1164b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id); 1165f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye String name; 1166f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye if (resource != null) { 1167947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet name = resource.getSecond(); 1168f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } else { 1169f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1170f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } 1171f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 11723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 117685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta /** 117785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the 117885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * bounds of all the views. 117985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 118085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param view the root View 118185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param offset an offset for the view bounds. 118285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 118385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 118485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * content frame. 118585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 118685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @return {@code ViewInfo} containing the bounds of the view and it children otherwise. 118785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta */ 118885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta private ViewInfo visit(View view, int offset, boolean setExtendedInfo, 118985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta boolean isContentFrame) { 119085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame); 1191799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 119285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (view instanceof ViewGroup) { 119385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewGroup group = ((ViewGroup) view); 119485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset, 119585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta setExtendedInfo, isContentFrame)); 119685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 119785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return result; 119885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 1199799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 120085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta /** 120185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo} 12028d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with 120385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * the children of the {@code mContentRoot}. 120485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 120585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param viewGroup the root View 120685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param offset an offset from the top for the content view frame. 120785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 120885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 120985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * content frame. {@code false} if the {@code ViewInfo} to be created is 121085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * part of the system decor. 121185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta */ 121285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset, 121385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta boolean setExtendedInfo, boolean isContentFrame) { 121485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (viewGroup == null) { 121585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return null; 1216799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 1217799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 121885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (!isContentFrame) { 121985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta offset += viewGroup.getTop(); 122085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 1221799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 122285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta int childCount = viewGroup.getChildCount(); 122385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (viewGroup == mContentRoot) { 122485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount); 122585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount); 122685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta for (int i = 0; i < childCount; i++) { 122785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset, 12286208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet setExtendedInfo); 122985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta childrenWithoutOffset.add(childViewInfo[0]); 123085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta childrenWithOffset.add(childViewInfo[1]); 1231799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 123285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta mViewInfoList = childrenWithOffset; 123385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return childrenWithoutOffset; 123485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } else { 123585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta List<ViewInfo> children = new ArrayList<ViewInfo>(childCount); 123685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta for (int i = 0; i < childCount; i++) { 123785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo, 123885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta isContentFrame)); 123985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 124085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return children; 1241799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 124285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 1243799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet 124485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta /** 124585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the 124685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * bounds of all the views. It returns two {@code ViewInfo} objects with the same children, 124785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * one with the {@code offset} and other without the {@code offset}. The offset is needed to 124885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * get the right bounds if the {@code ViewInfo} hierarchy is accessed from 124985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the 125085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * offset is not needed. 125185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * 125285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at 125385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * index 1 is with the offset. 125485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta */ 1255432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta @NonNull 125685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) { 125785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewInfo[] result = new ViewInfo[2]; 125885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (view == null) { 125985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return result; 126085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 126185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta 126285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result[0] = createViewInfo(view, 0, setExtendedInfo, true); 126385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result[1] = createViewInfo(view, offset, setExtendedInfo, true); 126485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (view instanceof ViewGroup) { 126585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true); 126685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result[0].setChildren(children); 126785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result[1].setChildren(children); 126885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 126985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return result; 1270799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet } 12713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 127385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children 127485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not 127585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * set. 127685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta * @param offset an offset for the view bounds. Used only if view is part of the content frame. 12773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 127885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo, 127985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta boolean isContentFrame) { 12803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (view == null) { 12813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return null; 12823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1284777163c3facaed668b43061d726a572fd58f6f60Diego Perez ViewParent parent = view.getParent(); 128585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta ViewInfo result; 128685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta if (isContentFrame) { 1287777163c3facaed668b43061d726a572fd58f6f60Diego Perez // Account for parent scroll values when calculating the bounding box 1288777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollX = parent != null ? ((View)parent).getScrollX() : 0; 1289777163c3facaed668b43061d726a572fd58f6f60Diego Perez int scrollY = parent != null ? ((View)parent).getScrollY() : 0; 1290777163c3facaed668b43061d726a572fd58f6f60Diego Perez 129170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // The view is part of the layout added by the user. Hence, 129270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // the ViewCookie may be obtained only through the Context. 129385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta result = new ViewInfo(view.getClass().getName(), 129470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta getContext().getViewKey(view), 1295777163c3facaed668b43061d726a572fd58f6f60Diego Perez -scrollX + view.getLeft(), -scrollY + view.getTop() + offset, 1296777163c3facaed668b43061d726a572fd58f6f60Diego Perez -scrollX + view.getRight(), -scrollY + view.getBottom() + offset, 1297777163c3facaed668b43061d726a572fd58f6f60Diego Perez view, view.getLayoutParams()); 129885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } else { 129970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // We are part of the system decor. 130070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), 130141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta getViewKey(view), 130285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta view.getLeft(), view.getTop(), view.getRight(), 130385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta view.getBottom(), view, view.getLayoutParams()); 130470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta result = r; 130570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // We currently mark three kinds of views: 130670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // 1. Menus in the Action Bar 130770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // 2. Menus in the Overflow popup. 130870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // 3. The overflow popup button. 130970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta if (view instanceof ListMenuItemView) { 131070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // Mark 2. 131170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // All menus in the popup are of type ListMenuItemView. 131270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU); 131370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } else { 131470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // Mark 3. 131570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta ViewGroup.LayoutParams lp = view.getLayoutParams(); 131670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta if (lp instanceof ActionMenuView.LayoutParams && 131770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta ((ActionMenuView.LayoutParams) lp).isOverflowButton) { 131870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW); 131970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } else { 132070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // Mark 1. 132170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // A view is a menu in the Action Bar is it is not the overflow button and of 132270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // its parent is of type ActionMenuView. We can also check if the view is 132370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // instanceof ActionMenuItemView but that will fail for menus using 132470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta // actionProviderClass. 132570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta while (parent != mViewRoot && parent instanceof ViewGroup) { 132670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta if (parent instanceof ActionMenuView) { 132770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta r.setViewType(ViewType.ACTION_BAR_MENU); 132870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta break; 132970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 133070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta parent = parent.getParent(); 133170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 133270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 133370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta } 133485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 13353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 13366208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet if (setExtendedInfo) { 13376208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet MarginLayoutParams marginParams = null; 13386208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet LayoutParams params = view.getLayoutParams(); 13396208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet if (params instanceof MarginLayoutParams) { 13406208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams = (MarginLayoutParams) params; 13416208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet } 13426208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet result.setExtendedInfo(view.getBaseline(), 13436208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.leftMargin : 0, 13446208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.topMargin : 0, 13456208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.rightMargin : 0, 13466208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet marginParams != null ? marginParams.bottomMargin : 0); 13476208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet } 13486208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet 13493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return result; 13503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 13513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 135270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta /* (non-Javadoc) 135341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta * The cookie for menu items are stored in menu item and not in the map from View stored in 135441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta * BridgeContext. 135541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta */ 1356432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta @Nullable 135741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta private Object getViewKey(View view) { 135841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta BridgeContext context = getContext(); 135941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta if (!(view instanceof MenuView.ItemView)) { 136041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta return context.getViewKey(view); 136141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 136241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta MenuItemImpl menuItem; 136341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta if (view instanceof ActionMenuItemView) { 136441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = ((ActionMenuItemView) view).getItemData(); 136541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } else if (view instanceof ListMenuItemView) { 136641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = ((ListMenuItemView) view).getItemData(); 136741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } else if (view instanceof IconMenuItemView) { 136841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = ((IconMenuItemView) view).getItemData(); 136941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } else { 137041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta menuItem = null; 137141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 137241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta if (menuItem instanceof BridgeMenuItemImpl) { 137341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta return ((BridgeMenuItemImpl) menuItem).getViewCookie(); 137441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 137541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta 137641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta return null; 137741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta } 137841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta 1379620f80a7ee9796c2c41ec0a42d10d2913fc50c90Diego Perez public void invalidateRenderingSize() { 138085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 138185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 138285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta 13833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet public BufferedImage getImage() { 13843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return mImage; 13853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 13863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1387a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet public boolean isAlphaChannelImage() { 1388a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return mIsAlphaChannelImage; 1389a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1390a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1391e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet public List<ViewInfo> getViewInfos() { 1392e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet return mViewInfoList; 13933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 13942d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet 139585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta public List<ViewInfo> getSystemViewInfos() { 139685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta return mSystemViewInfoList; 139785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta } 139885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta 1399ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Map<String, String> getDefaultProperties(Object viewObject) { 14000fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet return getContext().getDefaultPropMap(viewObject); 14012d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet } 1402b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 1403ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public void setScene(RenderSession session) { 1404ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet mScene = session; 1405b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 1406b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 1407ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public RenderSession getSession() { 1408b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet return mScene; 1409b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 141095eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez 141195eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez public void dispose() { 1412e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez boolean createdLooper = false; 1413e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez if (Looper.myLooper() == null) { 1414e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez // Detaching the root view from the window will try to stop any running animations. 1415e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez // The stop method checks that it can run in the looper so, if there is no current 1416e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez // looper, we create a temporary one to complete the shutdown. 1417e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez Bridge.prepareThread(); 1418e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez createdLooper = true; 1419e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez } 142095eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez AttachInfo_Accessor.detachFromWindow(mViewRoot); 142195eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez if (mCanvas != null) { 142295eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mCanvas.release(); 142395eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mCanvas = null; 142495eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 142595eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez if (mViewInfoList != null) { 142695eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mViewInfoList.clear(); 142795eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 142895eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez if (mSystemViewInfoList != null) { 142995eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mSystemViewInfoList.clear(); 143095eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 143195eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mImage = null; 143295eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mViewRoot = null; 143395eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez mContentRoot = null; 1434e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez 1435e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez if (createdLooper) { 1436e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez Bridge.cleanupThread(); 1437e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez } 143895eceea4f12c4f0e5170b1a14658f23e87e343d5Diego Perez } 14393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet} 1440