diff options
author | Xavier Ducrohet <xav@android.com> | 2010-11-04 17:15:54 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2010-11-08 18:38:12 -0800 |
commit | 7f7752439543db6e13c599bdd10cb10254c24528 (patch) | |
tree | 8161d572cce9194745972fc3fde670a6c6412614 /tools/layoutlib/bridge | |
parent | c9f32f23327cbeeb50f0d494d01c8d6784720bc6 (diff) | |
download | frameworks_base-7f7752439543db6e13c599bdd10cb10254c24528.zip frameworks_base-7f7752439543db6e13c599bdd10cb10254c24528.tar.gz frameworks_base-7f7752439543db6e13c599bdd10cb10254c24528.tar.bz2 |
Layoutlib: Load fragments
This change does the following:
- Make the bridge context extend Activity instead of Context
so that it can act as a view factory. This is needed because
the Activity is used as factory for Fragment objects.
- Override the default Fragment.instantiate(...) method
through a delegate. This is done to load the Fragment
classes located in the project (similar to custom views).
Change-Id: If62e7c9ff2b7585677077ad825aa1c3591d1b5e0
Diffstat (limited to 'tools/layoutlib/bridge')
3 files changed, 130 insertions, 7 deletions
diff --git a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java b/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java new file mode 100644 index 0000000..b46d95c --- /dev/null +++ b/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import com.android.layoutlib.api.IProjectCallback; + +import android.content.Context; +import android.os.Bundle; + +/** + * Delegate used to provide new implementation of a select few methods of {@link Fragment} + * + * Through the layoutlib_create tool, the original methods of Fragment have been replaced + * by calls to methods of the same name in this delegate class. + * + * The methods being re-implemented are the ones responsible for instantiating Fragment objects. + * Because the classes of these objects are found in the project, these methods need access to + * {@link IProjectCallback} object. They are however static methods, so the callback is set + * before the inflation through {@link #setProjectCallback(IProjectCallback)}. + */ +public class Fragment_Delegate { + + private static IProjectCallback sProjectCallback; + + /** + * Sets the current {@link IProjectCallback} to be used to instantiate classes coming + * from the project being rendered. + */ + public static void setProjectCallback(IProjectCallback projectCallback) { + sProjectCallback = projectCallback; + } + + /** + * Like {@link #instantiate(Context, String, Bundle)} but with a null + * argument Bundle. + */ + /*package*/ static Fragment instantiate(Context context, String fname) { + return instantiate(context, fname, null); + } + + /** + * Create a new instance of a Fragment with the given class name. This is + * the same as calling its empty constructor. + * + * @param context The calling context being used to instantiate the fragment. + * This is currently just used to get its ClassLoader. + * @param fname The class name of the fragment to instantiate. + * @param args Bundle of arguments to supply to the fragment, which it + * can retrieve with {@link #getArguments()}. May be null. + * @return Returns a new fragment instance. + * @throws InstantiationException If there is a failure in instantiating + * the given fragment class. This is a runtime exception; it is not + * normally expected to happen. + */ + /*package*/ static Fragment instantiate(Context context, String fname, Bundle args) { + try { + if (sProjectCallback != null) { + Fragment f = (Fragment) sProjectCallback.loadView(fname, + new Class[0], new Object[0]); + + if (args != null) { + args.setClassLoader(f.getClass().getClassLoader()); + f.mArguments = args; + } + return f; + } + + return null; + } catch (ClassNotFoundException e) { + throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } catch (java.lang.InstantiationException e) { + throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } catch (IllegalAccessException e) { + throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } catch (Exception e) { + throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index bd00b88..996a942 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -31,6 +31,7 @@ import com.android.ninepatch.NinePatch; import com.android.tools.layoutlib.create.MethodAdapter; import com.android.tools.layoutlib.create.OverrideMethod; +import android.app.Fragment_Delegate; import android.content.ClipData; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -366,6 +367,12 @@ public final class Bridge implements ILayoutBridge { BridgeContext context = null; try { + // we need to make sure the Looper has been initialized for this thread. + // this is required for View that creates Handler objects. + if (Looper.myLooper() == null) { + Looper.prepare(); + } + // setup the display Metrics. DisplayMetrics metrics = new DisplayMetrics(); metrics.densityDpi = density; @@ -380,6 +387,7 @@ public final class Bridge implements ILayoutBridge { frameworkResources, styleParentMap, customViewLoader, logger); BridgeInflater inflater = new BridgeInflater(context, customViewLoader); context.setBridgeInflater(inflater); + inflater.setFactory2(context); IResourceValue windowBackground = null; int screenOffset = 0; @@ -390,22 +398,22 @@ public final class Bridge implements ILayoutBridge { screenOffset = getScreenOffset(frameworkResources, currentTheme, context); } - // we need to make sure the Looper has been initialized for this thread. - // this is required for View that creates Handler objects. - if (Looper.myLooper() == null) { - Looper.prepare(); - } - BridgeXmlBlockParser parser = new BridgeXmlBlockParser(layoutDescription, context, false /* platformResourceFlag */); ViewGroup root = new FrameLayout(context); + // Sets the project callback (custom view loader) to the fragment delegate so that + // it can instantiate the custom Fragment. + Fragment_Delegate.setProjectCallback(customViewLoader); + View view = inflater.inflate(parser, root); // post-inflate process. For now this supports TabHost/TabWidget postInflateProcess(view, customViewLoader); + Fragment_Delegate.setProjectCallback(null); + // set the AttachInfo on the root view. AttachInfo info = new AttachInfo(new WindowSession(), new Window(), new Handler(), null); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java index 8592731..b9899b2 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java @@ -21,6 +21,8 @@ import com.android.layoutlib.api.IProjectCallback; import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IStyleResourceValue; +import android.app.Activity; +import android.app.Fragment; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -49,6 +51,7 @@ import android.os.Looper; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.BridgeInflater; +import android.view.LayoutInflater; import android.view.View; import java.io.File; @@ -65,7 +68,7 @@ import java.util.Map.Entry; /** * Custom implementation of Context to handle non compiled resources. */ -public final class BridgeContext extends Context { +public final class BridgeContext extends Activity { private final Resources mResources; private final Theme mTheme; @@ -129,6 +132,9 @@ public final class BridgeContext extends Context { mProjectResources = projectResources; mFrameworkResources = frameworkResources; mStyleInheritanceMap = styleInheritanceMap; + + mFragments.mCurState = Fragment.CREATED; + mFragments.mActivity = this; } public void setBridgeInflater(BridgeInflater inflater) { @@ -155,6 +161,14 @@ public final class BridgeContext extends Context { return mLogger; } + + // ------------- Activity Methods + + @Override + public LayoutInflater getLayoutInflater() { + return mInflater; + } + // ------------ Context methods @Override |