RenderSessionImpl.java revision b1484862e2367d87d3ccbd0fd0a6d2598ed5918a
1c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/* 2c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 3c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 4c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 5c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * you may not use this file except in compliance with the License. 6c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * You may obtain a copy of the License at 7c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 8c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 9c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 10c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software 11c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 12c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * See the License for the specific language governing permissions and 14c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * limitations under the License. 15c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 16c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 17c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetpackage com.android.layoutlib.bridge.impl; 18c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding; 20891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig; 2119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener; 2219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser; 2337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport com.android.ide.common.rendering.api.LayoutlibCallback; 2470552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 2519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference; 2719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 2819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 2919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 3046d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams; 311126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode; 3246d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo; 33bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport com.android.ide.common.rendering.api.ViewType; 345ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView; 355ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl; 365ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView; 375ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView; 385ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl; 395ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.MenuView; 402eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 41c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 4201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; 43c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 441f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaevimport com.android.layoutlib.bridge.android.RenderParamsFlags; 454dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsenimport com.android.layoutlib.bridge.android.support.DesignLibUtil; 462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter; 472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; 4835ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType; 49b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair; 50c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 517f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.animation.AnimationThread; 52e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator; 532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater; 54e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition; 552b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 56476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.NonNull; 57476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable; 58c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate; 59c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap; 60c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 61c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas; 6210bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Guptaimport android.preference.Preference_Delegate; 637f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor; 647f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.BridgeInflater; 656dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.IWindowManager; 66891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport android.view.IWindowManagerImpl; 676dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.Surface; 68c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View; 69c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec; 7046d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.view.ViewGroup; 7101811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams; 7205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams; 73bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.view.ViewParent; 746dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate; 752fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsListView; 762fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsSpinner; 77bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.widget.ActionMenuView; 782fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView; 792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ExpandableListView; 80c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout; 81796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout; 822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ListView; 8331fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge; 84c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost; 85796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec; 8646d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.widget.TabWidget; 87c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 885a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite; 89c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color; 90c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D; 91c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage; 92c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList; 93c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List; 94c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map; 95c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 9637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 9737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 9837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 9937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 10037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 10137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 10261f23e9bf7d784e7a52168196758c4f6c6853e77Deepanshu Guptaimport static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; 10337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta 104c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/** 10519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session. 1061ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 10719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 10819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 109c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout. 110c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 111b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> { 112c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 113c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // scene state 11419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private RenderSession mScene; 115c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeInflater mInflater; 117bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private ViewGroup mViewRoot; 118bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private FrameLayout mContentRoot; 1199eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private Canvas mCanvas; 1209eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenWidth = -1; 1219eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenHeight = -1; 122bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private boolean mIsAlphaChannelImage; 12316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 124c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // information being returned through the API 125c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BufferedImage mImage; 1267d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet private List<ViewInfo> mViewInfoList; 1274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> mSystemViewInfoList; 128b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta private Layout.Builder mLayoutBuilder; 129c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 130c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final class PostInflateException extends Exception { 131c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final long serialVersionUID = 1L; 132c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public PostInflateException(String message) { 134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet super(message); 135c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 137c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 1411b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)}, 1421b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * which act as a 14319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 1451b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see Bridge#createSession(SessionParams) 146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1471126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet public RenderSessionImpl(SessionParams params) { 148b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet super(new SessionParams(params)); 1492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 1502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 1512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 1522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 1532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * inflater, and parser. 1542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 1562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return whether the scene was prepared 1582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #acquire(long) 1602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #release() 1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 162b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet @Override 16319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result init(long timeout) { 164b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Result result = super.init(timeout); 1651ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 1662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return result; 1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 168c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 169b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 170b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 171c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 17216584225125acba18b74920b902c798dfead0328Xavier Ducrohet // use default of true in case it's not found to use alpha by default 173b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mIsAlphaChannelImage = Layout.Builder.getBooleanThemeValue(params.getResources(), 174b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta "windowIsFloating", true, true); 1752eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 176b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = new Layout.Builder(params, context); 177c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1786dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet // FIXME: find those out, and possibly add them to the render params 1796dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet boolean hasNavigationBar = true; 1801ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection ConstantConditions 1816dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), 182b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); 1836dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet WindowManagerGlobal_Delegate.setWindowManagerService(iwm); 1846dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet 185c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // build the inflater and parser. 18637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); 187b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet context.setBridgeInflater(mInflater); 1882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 189b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); 1902eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 191168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return SUCCESS.createResult(); 192c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 193c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 194c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 195c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Inflates the layout. 196c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 1972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 1982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 2002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 20219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result inflate() { 2032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 2042eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 205c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 206b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mViewRoot = new Layout(mLayoutBuilder); 207b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mLayoutBuilder = null; // Done with the builder. 208b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot = ((Layout) mViewRoot).getContentRoot(); 209b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 210b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 211c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 213c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // it can instantiate the custom Fragment. 21437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback()); 215c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 2161f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); 21710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta boolean isPreference = "PreferenceScreen".equals(rootTag); 21810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta View view; 21910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (isPreference) { 22010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, 221b1484862e2367d87d3ccbd0fd0a6d2598ed5918aDeepanshu Gupta mContentRoot); 22210bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } else { 22310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta view = mInflater.inflate(mBlockParser, mContentRoot); 22410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 225c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 2262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // done with the parser, pop it. 2272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet context.popParser(); 2282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 22937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Fragment_Delegate.setLayoutlibCallback(null); 230c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 231c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // set the AttachInfo on the root view. 2327f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.setAttachInfo(mViewRoot); 233c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 23433758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 23537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null); 236ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.onDoneInflation(); 23733758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet 2384dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen setActiveToolbar(view, context, params); 2394dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 24019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 241c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (PostInflateException e) { 24219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 243c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 244c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 245c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 246c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 247c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 248c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 249c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 25019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 251c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 252c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 253c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 254c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 255c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Renders the scene. 256c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 2572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 2582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2595a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 2605a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 2615a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * animations.) 2625a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * 2632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 2642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 2659eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 2661b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * @see SessionParams#getRenderingMode() 267bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#render(long) 268c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 2695a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet public Result render(boolean freshRender) { 2702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 2712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 272b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 273b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 274c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 275c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mViewRoot == null) { 27619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 277c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 278c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 279b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet RenderingMode renderingMode = params.getRenderingMode(); 280891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet HardwareConfig hardwareConfig = params.getHardwareConfig(); 281fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet 2829eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // only do the screen measure when needed. 2839eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet boolean newRenderSize = false; 2849eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (mMeasuredScreenWidth == -1) { 2859eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet newRenderSize = true; 286891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); 287891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); 2889eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 2899eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode != RenderingMode.NORMAL) { 290c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int widthMeasureSpecMode = renderingMode.isHorizExpand() ? 291c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 292c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet : MeasureSpec.EXACTLY; 293c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int heightMeasureSpecMode = renderingMode.isVertExpand() ? 294c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 295c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet : MeasureSpec.EXACTLY; 296c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 297c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // We used to compare the measured size of the content to the screen size but 298c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // this does not work anymore due to the 2 following issues: 299c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // - If the content is in a decor (system bar, title/action bar), the root view 300c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // will not resize even with the UNSPECIFIED because of the embedded layout. 301c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // - If there is no decor, but a dialog frame, then the dialog padding prevents 302c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // comparing the size of the content to the screen frame (as it would not 303c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // take into account the dialog padding). 304c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 305c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // The solution is to first get the content size in a normal rendering, inside 306c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // the decor or the dialog padding. 307c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // Then measure only the content with UNSPECIFIED to see the size difference 308c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // and apply this to the screen size. 309c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 310c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // first measure the full layout, with EXACTLY to get the size of the 311c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // content as it is inside the decor/dialog 3121ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 313c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet Pair<Integer, Integer> exactMeasure = measureView( 314c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mViewRoot, mContentRoot.getChildAt(0), 315c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth, MeasureSpec.EXACTLY, 316c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight, MeasureSpec.EXACTLY); 317c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 318c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // now measure the content only using UNSPECIFIED (where applicable, based on 319c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // the rendering mode). This will give us the size the content needs. 3201ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 321c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet Pair<Integer, Integer> result = measureView( 322c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mContentRoot, mContentRoot.getChildAt(0), 323c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth, widthMeasureSpecMode, 324c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight, heightMeasureSpecMode); 325c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 326c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // now look at the difference and add what is needed. 3279eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isHorizExpand()) { 328c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int measuredWidth = exactMeasure.getFirst(); 329c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int neededWidth = result.getFirst(); 330c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (neededWidth > measuredWidth) { 331c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth += neededWidth - measuredWidth; 3329eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 333fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 334c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3359eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isVertExpand()) { 336c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int measuredHeight = exactMeasure.getSecond(); 337c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int neededHeight = result.getSecond(); 338c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (neededHeight > measuredHeight) { 339c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight += neededHeight - measuredHeight; 3409eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 341fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 342c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 343c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 344c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 345c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet // measure again with the size we need 346c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // This must always be done before the call to layout 347c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet measureView(mViewRoot, null /*measuredView*/, 348c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenWidth, MeasureSpec.EXACTLY, 349c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet mMeasuredScreenHeight, MeasureSpec.EXACTLY); 350c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 351c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now do the layout. 35216584225125acba18b74920b902c798dfead0328Xavier Ducrohet mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 353c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3544dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen handleScrolling(mViewRoot); 3554dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 35610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isLayoutOnly()) { 35710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // delete the canvas and image to reset them on the next full rendering 35810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = null; 35910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mCanvas = null; 36010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 3617f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot); 36210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 36310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // draw the views 36410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create the BufferedImage into which the layout will be rendered. 36510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet boolean newImage = false; 3662c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez 3672c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // When disableBitmapCaching is true, we do not reuse mImage and 3682c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // we create a new one in every render. 3692c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // This is useful when mImage is just a wrapper of Graphics2D so 3702c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // it doesn't get cached. 3712c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( 3721f158819bc7cf58f97e47fabfaf23b2fb838f2ebAndrew Shulaev RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); 3732c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez if (newRenderSize || mCanvas == null || disableBitmapCaching) { 37410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.getImageFactory() != null) { 37510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = params.getImageFactory().getImage( 37610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 37710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight); 37810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 37910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = new BufferedImage( 38010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 38110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight, 38210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 38310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 38410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 38510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 38610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isBgColorOverridden()) { 38710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 38810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 38910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 39010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 39110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 39210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 39310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 39410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 39510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 39610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create an Android bitmap around the BufferedImage 39710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 398891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet true /*isMutable*/, hardwareConfig.getDensity()); 39910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 4002c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez if (mCanvas == null) { 4012c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez // create a Canvas around the Android bitmap 4022c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas = new Canvas(bitmap); 4032c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } else { 4042c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez mCanvas.setBitmap(bitmap); 4052c5e85b303077d2120b428bd4c7e6ecb6970935bDiego Perez } 406891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); 4079eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 408c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4091ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (freshRender && !newImage) { 4109eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 4115a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 41310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 41410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.fillRect(0, 0, 41510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, mMeasuredScreenHeight); 41616584225125acba18b74920b902c798dfead0328Xavier Ducrohet 41710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // done 41810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 41910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 42016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 42110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mViewRoot.draw(mCanvas); 4225a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet } 4235a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet 4245ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), 4255ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta false); 426c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 427c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // success! 42819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 429c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 430c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 431c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 432c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 433c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 434c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 435c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 43619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 437c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 438c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 439c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 440c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 441c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * Executes {@link View#measure(int, int)} on a given view with the given parameters (used 442c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. 443c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 444c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) 445c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). 446c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * 447c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param viewToMeasure the view on which to execute measure(). 448c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param measuredView if non null, the view to query for its measured width/height. 449c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param width the width to use in the MeasureSpec. 450c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param widthMode the MeasureSpec mode to use for the width. 451c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param height the height to use in the MeasureSpec. 452c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @param heightMode the MeasureSpec mode to use for the height. 453c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet * @return the measured width/height if measuredView is non-null, null otherwise. 454c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet */ 4551ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 456c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, 457c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int width, int widthMode, int height, int heightMode) { 458c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); 459c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); 460c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet viewToMeasure.measure(w_spec, h_spec); 461c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 462c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet if (measuredView != null) { 463c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); 464c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 465c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 466c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet return null; 467c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet } 468c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet 469c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet /** 4702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Animate an object 4712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 4722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 4732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 4742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 4752eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 476e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 477bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 4782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 47919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result animate(Object targetObject, String animationName, 4802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 4812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 4822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 483b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 484b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 4852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // find the animation file. 4861ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta ResourceValue animationResource; 4872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet int animationId = 0; 4882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (isFrameworkAnimation) { 489b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 49035ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 4912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 492b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 4932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 4942eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 495b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 49635ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 4972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 49837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta animationId = context.getLayoutlibCallback().getResourceId( 49935ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 5042eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 505b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 5062eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (anim != null) { 5072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet anim.setTarget(targetObject); 5082eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 509e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 5102eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 51119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 5122eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5132eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (Exception e) { 514c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 515c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t = e; 516c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t.getCause() != null) { 517c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t = t.getCause(); 518c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 519c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 52019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5222eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5232eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 52419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 525c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 526c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 527e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 528e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Insert a new child into an existing parent. 529e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 530e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 531e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 532e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 533e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 534e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 535bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 536e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 53719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 538e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final int index, IAnimationListener listener) { 539c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 540c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 541b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 542b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 543c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // create a block parser for the XML 54402d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 54502d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet childXml, context, false /* platformResourceFlag */); 546c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 547c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 548c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 549c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // be created correctly. 550e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 55102d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet blockParser.ensurePopped(); 552c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 553e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 554e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 555e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 556e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 557e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 558e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 55919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 560e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 561e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return addView(parentView, child, index); 562e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 563e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 564e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 565e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 566e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(null); 567e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 568e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 569e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 570e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 57119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(child); 5729eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 5739eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 574e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // add it to the parentView in the correct location 57519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = addView(parentView, child, index); 5761ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 577e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 578e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 579c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 5805a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 581c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (result.isSuccess()) { 582e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(child); 583c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet } 584c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet 585c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet return result; 586c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 587c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 588e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 589e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Adds a given view to a given parent at a given index. 590e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 591e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param parent the parent to receive the view 592e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to add to the parent 593e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the index where to do the add. 594e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 59519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 59619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 597e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 598e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 59919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 600e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 601e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.addView(view, index); 60219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 603e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 604e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 60519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 606e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 607e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 608e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 609e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 610e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a view to a new parent at a given location 611e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 612e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 613e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 614e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 615e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 616e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 617bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 618e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 6192b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 620479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 621c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 622c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 623e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 624e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 62501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet LayoutParams layoutParams = null; 626e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (layoutParamsMap != null) { 627e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 6282b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 629e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 630e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 6319eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 6322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // get the current parent of the view that needs to be moved. 6332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 6342b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 635e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 636e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final LayoutParams params = layoutParams; 63701811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 638479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 639479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // parent views are different we fake the animation through a no animation thread. 640479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousParent != newParentView) { 641479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new Thread("not animated moveChild") { 642479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 643479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void run() { 644479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 645479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet params); 6461ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 647479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 648479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 649479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 650479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // ready to do the work, acquire the scene. 651479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet result = acquire(250); 6521ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 653479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 654479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return; 655479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 656479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 657479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet try { 6585a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 659479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess()) { 660479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 661479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 662479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } finally { 663479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet release(); 664479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 665479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 666479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 6672b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 668479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 669479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } else { 670479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new AnimationThread(this, "moveChild", listener) { 6712b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 672479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 673479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public Result preAnimation() { 674479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // set up the transition for the parent. 675479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition transition = new LayoutTransition(); 676479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(transition); 6777550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet 678479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // tweak the animation durations and start delays (to match the duration of 679479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // animation playing just before). 680479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 681479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // on the LayoutTransition. 682479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 683479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 684479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 68501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 686479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 687479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 688479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 689479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 690479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 691479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 692479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 693479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 694479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 695479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 696479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 697479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 698479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void postAnimation() { 699479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(null); 700479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParentView.setLayoutTransition(null); 701479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 702479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 703479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 704e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 705e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 70619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(layoutParams); 707c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 708c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7092b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 7101ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 711e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 712e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 713c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7145a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 71501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet if (layoutParams != null && result.isSuccess()) { 716e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(layoutParams); 71701811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet } 71801811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 71901811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet return result; 720c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 721c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 722e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 723e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 724e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * an optional new {@link LayoutParams} instance 725e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 7262b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 7272b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param newParent the new parent 728479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet * @param movedView the view to move 729e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the new location in the new parent 730e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 731e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 73219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 73319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 734e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 735e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 736479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 737479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet final View movedView, final int index, final LayoutParams params) { 7389eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet try { 7392b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // check if there is a transition on the previousParent. 740479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 741479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousTransition != null) { 7427550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 7437550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 7447550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 7457550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 7467550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // to handle). 7477550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 7487550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 7497550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // adding the child or the child will appear in its new location before the 7507550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // other children have made room for it. 7512b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7522b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 753479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 754479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private int mChangeDisappearingCount = 0; 7552b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 75646d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 7572b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 7582b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 759479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 760479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount++; 761479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 7622b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 763e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 76446d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 7652b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 7662b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 767479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 768479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount--; 769479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 770479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 771479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 772479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount == 0) { 7732b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 7742b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 775479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 7762b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 777479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 7782b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 7792b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 7802b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 7812b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet }); 7822b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7832b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // remove the view from the current parent. 784479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 7852b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7862b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 7872b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 788e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } else { 7892b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // standard code with no animation. pretty simple. 790479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 791e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 7922b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 7932b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 794479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 7952b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 796479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 7972b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 7982b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7992b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 8002b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8019eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } catch (UnsupportedOperationException e) { 8029eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 80319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 804c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 805e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 806e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 807e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 808e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a child from its current parent. 809e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 810e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 811e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 812e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 813e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 814e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 815bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 816e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 81719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 818e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet checkLock(); 819c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 8209eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet invalidateRenderingSize(); 8219eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 822e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 823e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 824e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 825e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 826e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 827e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 82819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 829e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 830e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return removeView(parent, childView); 831e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 832e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 833e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 834e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 835e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(null); 836e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 837e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 838e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 839e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 84019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 841e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 842e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 84319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = removeView(parent, childView); 8441ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!result.isSuccess()) { 845e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 846e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 847e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8485a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet return render(false /*freshRender*/); 8492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 8502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 8512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 852e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a given view from its current parent. 853e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 854e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to remove from its parent 855e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 85619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 85719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 858e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 859e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 86019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 861e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 862e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.removeView(view); 86319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 864e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 865e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 86619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 867e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 868e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 869e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 870c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 8711ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * Post process on a view hierarchy that was just inflated. 8721ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/> 8731ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the 874c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 875c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * based on the content of the {@link FrameLayout}. 876c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root view to process. 87737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback callback to the project. 87810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta * @param skip the view and it's children are not processed. 879c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 8801ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") // For the use of Pair 88137dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip) 882c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 88310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta if (view == skip) { 88410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta return; 88510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta } 886c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof TabHost) { 88737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta setupTabHost((TabHost) view, layoutlibCallback); 88831fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 88931fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 89031fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet badge.setImageToDefault(); 8912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AdapterView<?>) { 8922fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get the view ID. 8932fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int id = view.getId(); 8942fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 8952fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet BridgeContext context = getContext(); 8962fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 8972fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // get a ResourceReference from the integer ID. 8982fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ResourceReference listRef = context.resolveId(id); 8992fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9002fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (listRef != null) { 9012fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet SessionParams params = getParams(); 9022fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet AdapterBinding binding = params.getAdapterBindings().get(listRef); 9032fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9042fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet // if there was no adapter binding, trying to get it from the call back. 9052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding == null) { 90637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta binding = layoutlibCallback.getAdapterBinding( 90737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta listRef, context.getViewKey(view), view); 9082fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9092fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9102fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (binding != null) { 9112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof AbsListView) { 9132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && 9142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet view instanceof ListView) { 9152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ListView list = (ListView) view; 9162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet boolean skipCallbackParser = false; 9182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet int count = binding.getHeaderCount(); 92010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 9212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 9222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getHeaderAt(i), 92337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 9242fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 9252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addHeaderView(pair.getFirst()); 9262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 9292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet count = binding.getFooterCount(); 93210bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int i = 0; i < count; i++) { 9332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet Pair<View, Boolean> pair = context.inflateView( 9342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet binding.getFooterAt(i), 93537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta list, false, skipCallbackParser); 9362fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (pair.getFirst() != null) { 9372fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet list.addFooterView(pair.getFirst()); 9382fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9392fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9402fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet skipCallbackParser |= pair.getSecond(); 9412fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9422fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9432fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet 9442fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (view instanceof ExpandableListView) { 9452fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((ExpandableListView) view).setAdapter( 94637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeExpandableAdapter(listRef, binding, layoutlibCallback)); 9472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else { 9482fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsListView) view).setAdapter( 94937dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 9502fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9512fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } else if (view instanceof AbsSpinner) { 9522fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet ((AbsSpinner) view).setAdapter( 95337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta new FakeAdapter(listRef, binding, layoutlibCallback)); 9542fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9552fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 9562fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet } 957c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } else if (view instanceof ViewGroup) { 958ccbc11770397888cf7780925bb4c7cf1d2f2f80eDeepanshu Gupta mInflater.postInflateProcess(view); 95910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta ViewGroup group = (ViewGroup) view; 960c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = group.getChildCount(); 96110bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta for (int c = 0; c < count; c++) { 962c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View child = group.getChildAt(c); 96337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta postInflateProcess(child, layoutlibCallback, skip); 964c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 965c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 966c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 967c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 968c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 9694dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * If the root layout is a CoordinatorLayout with an AppBar: 9704dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * Set the title of the AppBar to the title of the activity context. 9714dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 9724dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private void setActiveToolbar(View view, BridgeContext context, SessionParams params) { 9734dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT); 9744dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (coordinatorLayout == null) { 9754dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 9764dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 9774dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT); 9784dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (appBar == null) { 9794dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 9804dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 9814dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup collapsingToolbar = 9824dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT); 9834dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (collapsingToolbar == null) { 9844dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 9854dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 9864dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!hasToolbar(collapsingToolbar)) { 9874dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 9884dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 9894dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen RenderResources res = context.getRenderResources(); 9904dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen String title = params.getAppLabel(); 9914dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ResourceValue titleValue = res.findResValue(title, false); 9924dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (titleValue != null && titleValue.getValue() != null) { 9934dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen title = titleValue.getValue(); 9944dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 9954dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen DesignLibUtil.setTitle(collapsingToolbar, title); 9964dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 9974dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 9984dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private View findChildView(View view, String className) { 9994dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 10004dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10014dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10024dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 10034dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10044dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), className)) { 10054dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return group.getChildAt(i); 10064dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10074dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10084dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return null; 10094dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10104dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10114dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private boolean hasToolbar(View collapsingToolbar) { 10124dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(collapsingToolbar instanceof ViewGroup)) { 10134dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 10144dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10154dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) collapsingToolbar; 10164dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10174dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) { 10184dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return true; 10194dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10204dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10214dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return false; 10224dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10234dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10244dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 10254dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * Set the vertical scroll position on all the components with the "scrollY" attribute. If the 10264dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * component supports nested scrolling attempt that first, then use the unconsumed scroll part 10274dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen * to scroll the content in the component. 10284dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen */ 10294dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen private void handleScrolling(View view) { 10304dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen BridgeContext context = getContext(); 10314dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen int scrollPos = context.getScrollYPos(view); 10324dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (scrollPos != 0) { 10334dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (view.isNestedScrollingEnabled()) { 10344dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen int[] consumed = new int[2]; 10354dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (view.startNestedScroll(DesignLibUtil.SCROLL_AXIS_VERTICAL)) { 10364dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.dispatchNestedPreScroll(0, scrollPos, consumed, null); 10374dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.dispatchNestedScroll(consumed[0], consumed[1], 0, scrollPos, null); 10384dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.stopNestedScroll(); 10394dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen scrollPos -= consumed[1]; 10404dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10414dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10424dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (scrollPos != 0) { 10434dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.scrollBy(0, scrollPos); 10444dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } else { 10454dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.scrollBy(0, scrollPos); 10464dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10474dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } else { 10484dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen view.scrollBy(0, scrollPos); 10494dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10504dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10514dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen if (!(view instanceof ViewGroup)) { 10524dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen return; 10534dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10544dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen ViewGroup group = (ViewGroup) view; 10554dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen for (int i = 0; i < group.getChildCount(); i++) { 10564dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen View child = group.getChildAt(i); 10574dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen handleScrolling(child); 10584dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10594dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen } 10604dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen 10614dfe4d43ce5634f059a3ba669e3cac4551c3a3eeJens Ole Lauridsen /** 1062c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Sets up a {@link TabHost} object. 1063c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param tabHost the TabHost to setup. 106437dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta * @param layoutlibCallback The project callback object to access the project R class. 1065c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @throws PostInflateException 1066c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 106737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback) 1068c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1069c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 1070c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 1071c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1072c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1073c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1074c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 1075c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1076c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 10771ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof TabWidget)) { 1078c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1079c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 1080c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 1081c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1082c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1083c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 1084c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1085c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 10861ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty) 10871ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1088c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1089c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 1090c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1091c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 10921ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta if (!(v instanceof FrameLayout)) { 10931ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta //noinspection SpellCheckingInspection 1094c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1095c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 1096c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 1097c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1098c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1099c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet FrameLayout content = (FrameLayout)v; 1100c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11011ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // now process the content of the frameLayout and dynamically create tabs for it. 1102c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = content.getChildCount(); 1103c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1104c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 1105c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // and FrameLayout. 1106c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet tabHost.setup(); 1107c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1108796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (count == 0) { 1109796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // Create a dummy child to get a single tab 111049ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta TabSpec spec = tabHost.newTabSpec("tag") 111149ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .setIndicator("Tab Label", tabHost.getResources() 111249ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta .getDrawable(android.R.drawable.ic_menu_info_details, null)) 1113796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye .setContent(new TabHost.TabContentFactory() { 111446d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 1115796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye public View createTabContent(String tag) { 1116b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return new LinearLayout(getContext()); 1117796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1118796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye }); 1119796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(spec); 1120796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 11211ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta // for each child of the frameLayout, add a new TabSpec 1122796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye for (int i = 0 ; i < count ; i++) { 1123796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye View child = content.getChildAt(i); 1124796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 112510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta @SuppressWarnings("ConstantConditions") // child cannot be null. 1126796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye int id = child.getId(); 11271ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta @SuppressWarnings("deprecation") 112837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id); 1129796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String name; 1130796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (resource != null) { 1131b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet name = resource.getSecond(); 1132796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1133796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1134796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1135796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 1136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1137c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 11404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 11414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the 11424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. 11434ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 11444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param view the root View 11454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. 11464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 11474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 11484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. 11494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 11504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return {@code ViewInfo} containing the bounds of the view and it children otherwise. 11514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 11524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo visit(View view, int offset, boolean setExtendedInfo, 11534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 11544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame); 1155bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 11564ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 11574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewGroup group = ((ViewGroup) view); 11584ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset, 11594ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta setExtendedInfo, isContentFrame)); 11604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 11614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 11624ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1163bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 11644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 11654ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo} 11661b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with 11674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * the children of the {@code mContentRoot}. 11684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 11694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param viewGroup the root View 11704ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset from the top for the content view frame. 11714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. 11724ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the 11734ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * content frame. {@code false} if the {@code ViewInfo} to be created is 11744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * part of the system decor. 11754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 11764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset, 11774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean setExtendedInfo, boolean isContentFrame) { 11784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == null) { 11794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return null; 1180bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1181bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 11824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (!isContentFrame) { 11834ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta offset += viewGroup.getTop(); 11844ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1185bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 11864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta int childCount = viewGroup.getChildCount(); 11874ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (viewGroup == mContentRoot) { 11884ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount); 11894ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount); 11904ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 11914ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset, 119205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet setExtendedInfo); 11934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithoutOffset.add(childViewInfo[0]); 11944ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta childrenWithOffset.add(childViewInfo[1]); 1195bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 11964ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mViewInfoList = childrenWithOffset; 11974ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return childrenWithoutOffset; 11984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 11994ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = new ArrayList<ViewInfo>(childCount); 12004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta for (int i = 0; i < childCount; i++) { 12014ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo, 12024ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta isContentFrame)); 12034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12044ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return children; 1205bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 12064ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1207bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12084ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta /** 12094ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the 12104ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * bounds of all the views. It returns two {@code ViewInfo} objects with the same children, 12114ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * one with the {@code offset} and other without the {@code offset}. The offset is needed to 12124ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * get the right bounds if the {@code ViewInfo} hierarchy is accessed from 12134ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the 12144ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * offset is not needed. 12154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * 12164ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at 12174ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * index 1 is with the offset. 12184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta */ 1219d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @NonNull 12204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) { 12214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo[] result = new ViewInfo[2]; 12224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view == null) { 12234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 12244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 12264ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0] = createViewInfo(view, 0, setExtendedInfo, true); 12274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1] = createViewInfo(view, offset, setExtendedInfo, true); 12284ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (view instanceof ViewGroup) { 12294ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true); 12304ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[0].setChildren(children); 12314ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result[1].setChildren(children); 12324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 12334ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return result; 1234bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1235c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1236c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 12374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children 12384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not 12394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * set. 12404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta * @param offset an offset for the view bounds. Used only if view is part of the content frame. 1241c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 12424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo, 12434ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta boolean isContentFrame) { 1244c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view == null) { 1245c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return null; 1246c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1247c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 12484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta ViewInfo result; 12494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta if (isContentFrame) { 1250bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // The view is part of the layout added by the user. Hence, 1251bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // the ViewCookie may be obtained only through the Context. 12524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta result = new ViewInfo(view.getClass().getName(), 1253bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta getContext().getViewKey(view), 12544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getLeft(), view.getTop() + offset, view.getRight(), 12554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getBottom() + offset, view, view.getLayoutParams()); 12564ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } else { 1257bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We are part of the system decor. 1258bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), 12595ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta getViewKey(view), 12604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getLeft(), view.getTop(), view.getRight(), 12614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta view.getBottom(), view, view.getLayoutParams()); 1262bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta result = r; 1263bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // We currently mark three kinds of views: 1264bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 1. Menus in the Action Bar 1265bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 2. Menus in the Overflow popup. 1266bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // 3. The overflow popup button. 1267bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (view instanceof ListMenuItemView) { 1268bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 2. 1269bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // All menus in the popup are of type ListMenuItemView. 1270bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU); 1271bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1272bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 3. 1273bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ViewGroup.LayoutParams lp = view.getLayoutParams(); 1274bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (lp instanceof ActionMenuView.LayoutParams && 1275bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ((ActionMenuView.LayoutParams) lp).isOverflowButton) { 1276bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_OVERFLOW); 1277bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } else { 1278bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // Mark 1. 1279bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // A view is a menu in the Action Bar is it is not the overflow button and of 1280bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // its parent is of type ActionMenuView. We can also check if the view is 1281bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // instanceof ActionMenuItemView but that will fail for menus using 1282bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta // actionProviderClass. 1283bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta ViewParent parent = view.getParent(); 1284bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta while (parent != mViewRoot && parent instanceof ViewGroup) { 1285bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta if (parent instanceof ActionMenuView) { 1286bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta r.setViewType(ViewType.ACTION_BAR_MENU); 1287bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta break; 1288bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1289bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta parent = parent.getParent(); 1290bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1291bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 1292bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta } 12934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 1294c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 129505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (setExtendedInfo) { 129605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet MarginLayoutParams marginParams = null; 129705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet LayoutParams params = view.getLayoutParams(); 129805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet if (params instanceof MarginLayoutParams) { 129905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams = (MarginLayoutParams) params; 130005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 130105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet result.setExtendedInfo(view.getBaseline(), 130205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.leftMargin : 0, 130305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.topMargin : 0, 130405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.rightMargin : 0, 130505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet marginParams != null ? marginParams.bottomMargin : 0); 130605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet } 130705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet 1308c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return result; 1309c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1310c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1311bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta /* (non-Javadoc) 13125ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * The cookie for menu items are stored in menu item and not in the map from View stored in 13135ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta * BridgeContext. 13145ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta */ 1315d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta @Nullable 13165ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta private Object getViewKey(View view) { 13175ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta BridgeContext context = getContext(); 13185ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (!(view instanceof MenuView.ItemView)) { 13195ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return context.getViewKey(view); 13205ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13215ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta MenuItemImpl menuItem; 13225ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (view instanceof ActionMenuItemView) { 13235ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ActionMenuItemView) view).getItemData(); 13245ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof ListMenuItemView) { 13255ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((ListMenuItemView) view).getItemData(); 13265ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else if (view instanceof IconMenuItemView) { 13275ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = ((IconMenuItemView) view).getItemData(); 13285ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } else { 13295ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta menuItem = null; 13305ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13315ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta if (menuItem instanceof BridgeMenuItemImpl) { 13325ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return ((BridgeMenuItemImpl) menuItem).getViewCookie(); 13335ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13345ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 13355ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta return null; 13365ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta } 13375ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta 1338c13aa0c035cd226d27323bc0e533632ba32f6a84Diego Perez public void invalidateRenderingSize() { 13394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 13404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 1342c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public BufferedImage getImage() { 1343c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return mImage; 1344c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1345c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 134616584225125acba18b74920b902c798dfead0328Xavier Ducrohet public boolean isAlphaChannelImage() { 134716584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mIsAlphaChannelImage; 134816584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 134916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 13507d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public List<ViewInfo> getViewInfos() { 13517d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return mViewInfoList; 1352c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1353cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet 13544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta public List<ViewInfo> getSystemViewInfos() { 13554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta return mSystemViewInfoList; 13564ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta } 13574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta 135819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Map<String, String> getDefaultProperties(Object viewObject) { 1359b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return getContext().getDefaultPropMap(viewObject); 1360cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet } 1361c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 136219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public void setScene(RenderSession session) { 136319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mScene = session; 1364c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1365c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 136619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSession getSession() { 1367c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet return mScene; 1368c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1369c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet} 1370