am 7081a114: Merge "Add preferences rendering." into lmp-dev
* commit '7081a114d4ee190c746f337057b0f84928c162dd': Add preferences rendering.
This commit is contained in:
@@ -215,7 +215,7 @@ public class Preference implements Comparable<Preference> {
|
||||
|
||||
final TypedArray a = context.obtainStyledAttributes(
|
||||
attrs, com.android.internal.R.styleable.Preference, defStyleAttr, defStyleRes);
|
||||
for (int i = a.getIndexCount(); i >= 0; i--) {
|
||||
for (int i = a.getIndexCount() - 1; i >= 0; i--) {
|
||||
int attr = a.getIndex(i);
|
||||
switch (attr) {
|
||||
case com.android.internal.R.styleable.Preference_icon:
|
||||
|
||||
@@ -156,7 +156,7 @@ public class PreferenceManager {
|
||||
* should be used ANY time a preference will be displayed, since some preference
|
||||
* types need an Activity for managed queries.
|
||||
*/
|
||||
private PreferenceManager(Context context) {
|
||||
/*package*/ PreferenceManager(Context context) {
|
||||
init(context);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.preference;
|
||||
|
||||
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BridgePreferenceInflater extends PreferenceInflater {
|
||||
|
||||
private final Map<Preference, Object> mViewCookieMap;
|
||||
|
||||
public BridgePreferenceInflater(Context context, PreferenceManager preferenceManager,
|
||||
Map<Preference, Object> viewCookieMap) {
|
||||
super(context, preferenceManager);
|
||||
mViewCookieMap = viewCookieMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Preference onCreateItem(String name, AttributeSet attrs)
|
||||
throws ClassNotFoundException {
|
||||
Object viewKey;
|
||||
if (attrs instanceof BridgeXmlBlockParser) {
|
||||
viewKey = ((BridgeXmlBlockParser) attrs).getViewCookie();
|
||||
} else {
|
||||
viewKey = null;
|
||||
}
|
||||
Preference preference = super.onCreateItem(name, attrs);
|
||||
if (viewKey != null) {
|
||||
mViewCookieMap.put(preference, viewKey);
|
||||
}
|
||||
return preference;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.preference;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.layoutlib.bridge.android.BridgeContext;
|
||||
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Delegate that provides implementation for native methods in {@link Preference}
|
||||
* <p/>
|
||||
* Through the layoutlib_create tool, selected methods of Preference have been replaced by calls to
|
||||
* methods of the same name in this delegate class.
|
||||
*/
|
||||
public class Preference_Delegate {
|
||||
|
||||
private static final Map<Preference, Object> sViewCookies = new HashMap<Preference, Object>();
|
||||
|
||||
@LayoutlibDelegate
|
||||
/*package*/ static void dispatchSetInitialValue(Preference preference) {
|
||||
// pass.
|
||||
}
|
||||
|
||||
@LayoutlibDelegate
|
||||
/*package*/ static View getView(Preference pref, View convertView, ViewGroup parent) {
|
||||
Context context = pref.getContext();
|
||||
BridgeContext bc = context instanceof BridgeContext ? ((BridgeContext) context) : null;
|
||||
convertView = pref.getView_Original(convertView, parent);
|
||||
Object cookie = sViewCookies.get(pref);
|
||||
if (bc != null && cookie != null) {
|
||||
bc.addViewKey(convertView, cookie);
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflates the parser and returns the ListView containing the Preferences. The caller must call
|
||||
* {@link #clearCookiesMap()} when the rendering is complete.
|
||||
*/
|
||||
public static View inflatePreference(Context context, XmlPullParser parser, ViewGroup root) {
|
||||
assert sViewCookies.isEmpty();
|
||||
PreferenceManager pm = new PreferenceManager(context);
|
||||
PreferenceScreen ps = pm.getPreferenceScreen();
|
||||
PreferenceInflater inflater = new BridgePreferenceInflater(context, pm, sViewCookies);
|
||||
ps = (PreferenceScreen) inflater.inflate(parser, ps, true);
|
||||
ListView preferenceView = createContainerView(context, root);
|
||||
ps.bind(preferenceView);
|
||||
return preferenceView;
|
||||
}
|
||||
|
||||
private static ListView createContainerView(Context context, ViewGroup root) {
|
||||
TypedArray a = context.obtainStyledAttributes(null, R.styleable.PreferenceFragment,
|
||||
R.attr.preferenceFragmentStyle, 0);
|
||||
int mLayoutResId = a.getResourceId(R.styleable.PreferenceFragment_layout,
|
||||
R.layout.preference_list_fragment);
|
||||
a.recycle();
|
||||
|
||||
LayoutInflater inflater =
|
||||
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
inflater.inflate(mLayoutResId, root, true);
|
||||
|
||||
return (ListView) root.findViewById(android.R.id.list);
|
||||
}
|
||||
|
||||
public static void clearCookiesMap() {
|
||||
sViewCookies.clear();
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ import javax.swing.text.Segment;
|
||||
|
||||
/**
|
||||
* Delegate that provides implementation for native methods in {@link android.text.StaticLayout}
|
||||
*
|
||||
* Through the layoutlib_create tool, selected methods of Handler have been replaced
|
||||
* <p/>
|
||||
* Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
|
||||
* by calls to methods of the same name in this delegate class.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
|
||||
import com.android.annotations.NonNull;
|
||||
import com.android.ide.common.rendering.api.Capability;
|
||||
import com.android.ide.common.rendering.api.DrawableParams;
|
||||
import com.android.ide.common.rendering.api.Features;
|
||||
import com.android.ide.common.rendering.api.LayoutLog;
|
||||
import com.android.ide.common.rendering.api.RenderSession;
|
||||
import com.android.ide.common.rendering.api.Result;
|
||||
@@ -180,7 +181,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
*/
|
||||
private static LayoutLog sCurrentLog = sDefaultLog;
|
||||
|
||||
private EnumSet<Capability> mCapabilities;
|
||||
private static final int LAST_SUPPORTED_FEATURE = Features.PREFERENCES_RENDERING;
|
||||
|
||||
@Override
|
||||
public int getApiLevel() {
|
||||
@@ -188,8 +189,16 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public EnumSet<Capability> getCapabilities() {
|
||||
return mCapabilities;
|
||||
// The Capability class is deprecated and frozen. All Capabilities enumerated there are
|
||||
// supported by this version of LayoutLibrary. So, it's safe to use EnumSet.allOf()
|
||||
return EnumSet.allOf(Capability.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(int feature) {
|
||||
return feature <= LAST_SUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,26 +209,6 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
sPlatformProperties = platformProperties;
|
||||
sEnumValueMap = enumValueMap;
|
||||
|
||||
// don't use EnumSet.allOf(), because the bridge doesn't come with its specific version
|
||||
// of layoutlib_api. It is provided by the client which could have a more recent version
|
||||
// with newer, unsupported capabilities.
|
||||
mCapabilities = EnumSet.of(
|
||||
Capability.UNBOUND_RENDERING,
|
||||
Capability.CUSTOM_BACKGROUND_COLOR,
|
||||
Capability.RENDER,
|
||||
Capability.LAYOUT_ONLY,
|
||||
Capability.EMBEDDED_LAYOUT,
|
||||
Capability.VIEW_MANIPULATION,
|
||||
Capability.PLAY_ANIMATION,
|
||||
Capability.ANIMATED_VIEW_MANIPULATION,
|
||||
Capability.ADAPTER_BINDING,
|
||||
Capability.EXTENDED_VIEWINFO,
|
||||
Capability.FIXED_SCALABLE_NINE_PATCH,
|
||||
Capability.RTL,
|
||||
Capability.ACTION_BAR,
|
||||
Capability.SIMULATE_PLATFORM);
|
||||
|
||||
|
||||
BridgeAssetManager.initSystem();
|
||||
|
||||
// When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 com.android.layoutlib.bridge.android;
|
||||
|
||||
import com.android.ide.common.rendering.api.SessionParams;
|
||||
|
||||
/**
|
||||
* This contains all known keys for the {@link SessionParams#getFlag(SessionParams.Key)}.
|
||||
* <p/>
|
||||
* The IDE has its own copy of this class which may be newer or older than this one.
|
||||
* <p/>
|
||||
* Constants should never be modified or removed from this class.
|
||||
*/
|
||||
public final class SessionParamsFlags {
|
||||
|
||||
public static final SessionParams.Key<String> FLAG_KEY_ROOT_TAG =
|
||||
new SessionParams.Key<String>("rootTag", String.class);
|
||||
|
||||
// Disallow instances.
|
||||
private SessionParamsFlags() {}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ import com.android.layoutlib.bridge.Bridge;
|
||||
import com.android.layoutlib.bridge.android.BridgeContext;
|
||||
import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
|
||||
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
|
||||
import com.android.layoutlib.bridge.android.SessionParamsFlags;
|
||||
import com.android.layoutlib.bridge.bars.Config;
|
||||
import com.android.layoutlib.bridge.bars.NavigationBar;
|
||||
import com.android.layoutlib.bridge.bars.StatusBar;
|
||||
@@ -73,6 +74,7 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap_Delegate;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.Preference_Delegate;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.AttachInfo_Accessor;
|
||||
@@ -87,7 +89,6 @@ import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewGroup.MarginLayoutParams;
|
||||
import android.view.ViewParent;
|
||||
import android.view.WindowManagerGlobal_Delegate;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AbsSpinner;
|
||||
import android.widget.ActionMenuView;
|
||||
@@ -397,7 +398,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
// it can instantiate the custom Fragment.
|
||||
Fragment_Delegate.setProjectCallback(params.getProjectCallback());
|
||||
|
||||
View view = mInflater.inflate(mBlockParser, mContentRoot);
|
||||
String rootTag = params.getFlag(SessionParamsFlags.FLAG_KEY_ROOT_TAG);
|
||||
boolean isPreference = "PreferenceScreen".equals(rootTag);
|
||||
View view;
|
||||
if (isPreference) {
|
||||
view = Preference_Delegate.inflatePreference(getContext(), mBlockParser,
|
||||
mContentRoot);
|
||||
} else {
|
||||
view = mInflater.inflate(mBlockParser, mContentRoot);
|
||||
}
|
||||
|
||||
// done with the parser, pop it.
|
||||
context.popParser();
|
||||
@@ -408,7 +417,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
AttachInfo_Accessor.setAttachInfo(mViewRoot);
|
||||
|
||||
// post-inflate process. For now this supports TabHost/TabWidget
|
||||
postInflateProcess(view, params.getProjectCallback());
|
||||
postInflateProcess(view, params.getProjectCallback(), isPreference ? view : null);
|
||||
|
||||
// get the background drawable
|
||||
if (mWindowBackground != null) {
|
||||
@@ -590,6 +599,9 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
|
||||
false);
|
||||
|
||||
// clear the preferences cookie map.
|
||||
Preference_Delegate.clearCookiesMap();
|
||||
|
||||
// success!
|
||||
return SUCCESS.createResult();
|
||||
} catch (Throwable e) {
|
||||
@@ -1210,12 +1222,16 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
* based on the content of the {@link FrameLayout}.
|
||||
* @param view the root view to process.
|
||||
* @param projectCallback callback to the project.
|
||||
* @param skip the view and it's children are not processed.
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // For the use of Pair
|
||||
private void postInflateProcess(View view, IProjectCallback projectCallback)
|
||||
private void postInflateProcess(View view, IProjectCallback projectCallback, View skip)
|
||||
throws PostInflateException {
|
||||
if (view == skip) {
|
||||
return;
|
||||
}
|
||||
if (view instanceof TabHost) {
|
||||
setupTabHost((TabHost)view, projectCallback);
|
||||
setupTabHost((TabHost) view, projectCallback);
|
||||
} else if (view instanceof QuickContactBadge) {
|
||||
QuickContactBadge badge = (QuickContactBadge) view;
|
||||
badge.setImageToDefault();
|
||||
@@ -1248,7 +1264,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
boolean skipCallbackParser = false;
|
||||
|
||||
int count = binding.getHeaderCount();
|
||||
for (int i = 0 ; i < count ; i++) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
Pair<View, Boolean> pair = context.inflateView(
|
||||
binding.getHeaderAt(i),
|
||||
list, false /*attachToRoot*/, skipCallbackParser);
|
||||
@@ -1260,7 +1276,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
}
|
||||
|
||||
count = binding.getFooterCount();
|
||||
for (int i = 0 ; i < count ; i++) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
Pair<View, Boolean> pair = context.inflateView(
|
||||
binding.getFooterAt(i),
|
||||
list, false /*attachToRoot*/, skipCallbackParser);
|
||||
@@ -1289,11 +1305,11 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
}
|
||||
}
|
||||
} else if (view instanceof ViewGroup) {
|
||||
ViewGroup group = (ViewGroup)view;
|
||||
ViewGroup group = (ViewGroup) view;
|
||||
final int count = group.getChildCount();
|
||||
for (int c = 0 ; c < count ; c++) {
|
||||
for (int c = 0; c < count; c++) {
|
||||
View child = group.getChildAt(c);
|
||||
postInflateProcess(child, projectCallback);
|
||||
postInflateProcess(child, projectCallback, skip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1361,6 +1377,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
for (int i = 0 ; i < count ; i++) {
|
||||
View child = content.getChildAt(i);
|
||||
String tabSpec = String.format("tab_spec%d", i+1);
|
||||
@SuppressWarnings("ConstantConditions") // child cannot be null.
|
||||
int id = child.getId();
|
||||
@SuppressWarnings("deprecation")
|
||||
Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
|
||||
|
||||
@@ -152,6 +152,8 @@ public final class CreateInfo implements ICreateInfo {
|
||||
"android.graphics.Typeface#getSystemFontConfigLocation",
|
||||
"android.os.Handler#sendMessageAtTime",
|
||||
"android.os.HandlerThread#run",
|
||||
"android.preference.Preference#dispatchSetInitialValue",
|
||||
"android.preference.Preference#getView",
|
||||
"android.text.format.DateFormat#is24HourFormat",
|
||||
"android.util.Xml#newPullParser",
|
||||
"android.view.Choreographer#getRefreshRate",
|
||||
@@ -273,6 +275,7 @@ public final class CreateInfo implements ICreateInfo {
|
||||
|
||||
private final static String[] EXCLUDED_CLASSES =
|
||||
new String[] {
|
||||
"android.preference.PreferenceActivity",
|
||||
"org.kxml2.io.KXmlParser"
|
||||
};
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ public class Main {
|
||||
"android.graphics.drawable.*",
|
||||
"android.content.*",
|
||||
"android.content.res.*",
|
||||
"android.preference.*",
|
||||
"org.apache.harmony.xml.*",
|
||||
"com.android.internal.R**",
|
||||
"android.pim.*", // for datepicker
|
||||
|
||||
Reference in New Issue
Block a user