diff options
26 files changed, 1038 insertions, 86 deletions
diff --git a/api/current.xml b/api/current.xml index 279744e..ccd1724 100644 --- a/api/current.xml +++ b/api/current.xml @@ -2792,6 +2792,28 @@ visibility="public" > </field> +<field name="breadCrumbShortTitle" + type="int" + transient="false" + volatile="false" + value="16843589" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="breadCrumbTitle" + type="int" + transient="false" + volatile="false" + value="16843588" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="bufferType" type="int" transient="false" @@ -17384,6 +17406,17 @@ visibility="public" > </field> +<field name="Widget_FragmentBreadCrumbs" + type="int" + transient="false" + volatile="false" + value="16973986" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="Widget_Gallery" type="int" transient="false" @@ -29343,6 +29376,113 @@ </parameter> </constructor> </class> +<class name="FragmentBreadCrumbs" + extends="android.view.ViewGroup" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<implements name="android.app.FragmentManager.OnBackStackChangedListener"> +</implements> +<constructor name="FragmentBreadCrumbs" + type="android.app.FragmentBreadCrumbs" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +</constructor> +<constructor name="FragmentBreadCrumbs" + type="android.app.FragmentBreadCrumbs" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="attrs" type="android.util.AttributeSet"> +</parameter> +</constructor> +<constructor name="FragmentBreadCrumbs" + type="android.app.FragmentBreadCrumbs" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="attrs" type="android.util.AttributeSet"> +</parameter> +<parameter name="defStyle" type="int"> +</parameter> +</constructor> +<method name="onBackStackChanged" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="onLayout" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="protected" +> +<parameter name="changed" type="boolean"> +</parameter> +<parameter name="l" type="int"> +</parameter> +<parameter name="t" type="int"> +</parameter> +<parameter name="r" type="int"> +</parameter> +<parameter name="b" type="int"> +</parameter> +</method> +<method name="setActivity" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="a" type="android.app.Activity"> +</parameter> +</method> +<method name="setTitle" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="title" type="java.lang.CharSequence"> +</parameter> +<parameter name="shortTitle" type="java.lang.CharSequence"> +</parameter> +</method> +</class> <interface name="FragmentManager" abstract="true" static="false" @@ -29350,6 +29490,30 @@ deprecated="not deprecated" visibility="public" > +<method name="addOnBackStackChangedListener" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener"> +</parameter> +</method> +<method name="countBackStackEntries" + return="int" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="findFragmentById" return="android.app.Fragment" abstract="true" @@ -29376,6 +29540,19 @@ <parameter name="tag" type="java.lang.String"> </parameter> </method> +<method name="getBackStackEntry" + return="android.app.FragmentManager.BackStackEntry" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="index" type="int"> +</parameter> +</method> <method name="getFragment" return="android.app.Fragment" abstract="true" @@ -29460,6 +29637,19 @@ <parameter name="fragment" type="android.app.Fragment"> </parameter> </method> +<method name="removeOnBackStackChangedListener" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener"> +</parameter> +</method> <field name="POP_BACK_STACK_INCLUSIVE" type="int" transient="false" @@ -29472,6 +29662,66 @@ > </field> </interface> +<interface name="FragmentManager.BackStackEntry" + abstract="true" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="getBreadCrumbShortTitle" + return="java.lang.CharSequence" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getBreadCrumbTitle" + return="java.lang.CharSequence" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getId" + return="int" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +</interface> +<interface name="FragmentManager.OnBackStackChangedListener" + abstract="true" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="onBackStackChanged" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +</interface> <interface name="FragmentTransaction" abstract="true" static="false" @@ -29619,6 +29869,58 @@ <parameter name="tag" type="java.lang.String"> </parameter> </method> +<method name="setBreadCrumbShortTitle" + return="android.app.FragmentTransaction" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="res" type="int"> +</parameter> +</method> +<method name="setBreadCrumbShortTitle" + return="android.app.FragmentTransaction" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="text" type="java.lang.CharSequence"> +</parameter> +</method> +<method name="setBreadCrumbTitle" + return="android.app.FragmentTransaction" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="res" type="int"> +</parameter> +</method> +<method name="setBreadCrumbTitle" + return="android.app.FragmentTransaction" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="text" type="java.lang.CharSequence"> +</parameter> +</method> <method name="setCustomAnimations" return="android.app.FragmentTransaction" abstract="true" @@ -142369,6 +142671,21 @@ <parameter name="preferenceScreen" type="android.preference.PreferenceScreen"> </parameter> </method> +<method name="showBreadCrumbs" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="title" type="java.lang.CharSequence"> +</parameter> +<parameter name="shortTitle" type="java.lang.CharSequence"> +</parameter> +</method> <method name="startPreferenceFragment" return="void" abstract="false" @@ -142384,6 +142701,21 @@ <parameter name="push" type="boolean"> </parameter> </method> +<method name="startPreferenceFragment" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="fragment" type="android.app.Fragment"> +</parameter> +<parameter name="ft" type="android.app.FragmentTransaction"> +</parameter> +</method> <method name="startWithFragment" return="void" abstract="false" @@ -142427,6 +142759,21 @@ <parameter name="header" type="android.preference.PreferenceActivity.Header"> </parameter> </method> +<method name="switchToHeaderInner" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="fragmentName" type="java.lang.String"> +</parameter> +<parameter name="args" type="android.os.Bundle"> +</parameter> +</method> <field name="EXTRA_NO_HEADERS" type="java.lang.String" transient="false" @@ -142539,6 +142886,26 @@ visibility="public" > </field> +<field name="breadCrumbShortTitle" + type="java.lang.CharSequence" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="breadCrumbTitle" + type="java.lang.CharSequence" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="extras" type="android.os.Bundle" transient="false" diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackRecord.java index 296b495..e6cc0f9 100644 --- a/core/java/android/app/BackStackEntry.java +++ b/core/java/android/app/BackStackRecord.java @@ -18,6 +18,7 @@ package android.app; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import android.util.Log; import java.util.ArrayList; @@ -28,16 +29,20 @@ final class BackStackState implements Parcelable { final int mTransitionStyle; final String mName; final int mIndex; - - public BackStackState(FragmentManagerImpl fm, BackStackEntry bse) { + final int mBreadCrumbTitleRes; + final CharSequence mBreadCrumbTitleText; + final int mBreadCrumbShortTitleRes; + final CharSequence mBreadCrumbShortTitleText; + + public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) { int numRemoved = 0; - BackStackEntry.Op op = bse.mHead; + BackStackRecord.Op op = bse.mHead; while (op != null) { if (op.removed != null) numRemoved += op.removed.size(); op = op.next; } mOps = new int[bse.mNumOp*5 + numRemoved]; - + if (!bse.mAddToBackStack) { throw new IllegalStateException("Not on back stack"); } @@ -64,21 +69,29 @@ final class BackStackState implements Parcelable { mTransitionStyle = bse.mTransitionStyle; mName = bse.mName; mIndex = bse.mIndex; + mBreadCrumbTitleRes = bse.mBreadCrumbTitleRes; + mBreadCrumbTitleText = bse.mBreadCrumbTitleText; + mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes; + mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText; } - + public BackStackState(Parcel in) { mOps = in.createIntArray(); mTransition = in.readInt(); mTransitionStyle = in.readInt(); mName = in.readString(); mIndex = in.readInt(); + mBreadCrumbTitleRes = in.readInt(); + mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + mBreadCrumbShortTitleRes = in.readInt(); + mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); } - - public BackStackEntry instantiate(FragmentManagerImpl fm) { - BackStackEntry bse = new BackStackEntry(fm); + + public BackStackRecord instantiate(FragmentManagerImpl fm) { + BackStackRecord bse = new BackStackRecord(fm); int pos = 0; while (pos < mOps.length) { - BackStackEntry.Op op = new BackStackEntry.Op(); + BackStackRecord.Op op = new BackStackRecord.Op(); op.cmd = mOps[pos++]; if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, "BSE " + bse + " set base fragment #" + mOps[pos]); @@ -103,10 +116,14 @@ final class BackStackState implements Parcelable { bse.mName = mName; bse.mIndex = mIndex; bse.mAddToBackStack = true; + bse.mBreadCrumbTitleRes = mBreadCrumbTitleRes; + bse.mBreadCrumbTitleText = mBreadCrumbTitleText; + bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes; + bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText; bse.bumpBackStackNesting(1); return bse; } - + public int describeContents() { return 0; } @@ -117,14 +134,18 @@ final class BackStackState implements Parcelable { dest.writeInt(mTransitionStyle); dest.writeString(mName); dest.writeInt(mIndex); + dest.writeInt(mBreadCrumbTitleRes); + TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0); + dest.writeInt(mBreadCrumbShortTitleRes); + TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0); } - + public static final Parcelable.Creator<BackStackState> CREATOR = new Parcelable.Creator<BackStackState>() { public BackStackState createFromParcel(Parcel in) { return new BackStackState(in); } - + public BackStackState[] newArray(int size) { return new BackStackState[size]; } @@ -134,18 +155,19 @@ final class BackStackState implements Parcelable { /** * @hide Entry of an operation on the fragment back stack. */ -final class BackStackEntry implements FragmentTransaction, Runnable { +final class BackStackRecord implements FragmentTransaction, + FragmentManager.BackStackEntry, Runnable { static final String TAG = "BackStackEntry"; - + final FragmentManagerImpl mManager; - + static final int OP_NULL = 0; static final int OP_ADD = 1; static final int OP_REPLACE = 2; static final int OP_REMOVE = 3; static final int OP_HIDE = 4; static final int OP_SHOW = 5; - + static final class Op { Op next; Op prev; @@ -155,7 +177,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { int exitAnim; ArrayList<Fragment> removed; } - + Op mHead; Op mTail; int mNumOp; @@ -167,11 +189,34 @@ final class BackStackEntry implements FragmentTransaction, Runnable { String mName; boolean mCommitted; int mIndex; - - public BackStackEntry(FragmentManagerImpl manager) { + + int mBreadCrumbTitleRes; + CharSequence mBreadCrumbTitleText; + int mBreadCrumbShortTitleRes; + CharSequence mBreadCrumbShortTitleText; + + public BackStackRecord(FragmentManagerImpl manager) { mManager = manager; } - + + public int getId() { + return mIndex; + } + + public CharSequence getBreadCrumbTitle() { + if (mBreadCrumbTitleRes != 0) { + return mManager.mActivity.getText(mBreadCrumbTitleRes); + } + return mBreadCrumbTitleText; + } + + public CharSequence getBreadCrumbShortTitle() { + if (mBreadCrumbShortTitleRes != 0) { + return mManager.mActivity.getText(mBreadCrumbShortTitleRes); + } + return mBreadCrumbShortTitleText; + } + void addOp(Op op) { if (mHead == null) { mHead = mTail = op; @@ -184,7 +229,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { op.exitAnim = mExitAnim; mNumOp++; } - + public FragmentTransaction add(Fragment fragment, String tag) { doAddOp(0, fragment, tag, OP_ADD); return this; @@ -206,7 +251,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } fragment.mImmediateActivity = mManager.mActivity; fragment.mFragmentManager = mManager; - + if (tag != null) { if (fragment.mTag != null && !tag.equals(fragment.mTag)) { throw new IllegalStateException("Can't change tag of fragment " @@ -215,7 +260,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } fragment.mTag = tag; } - + if (containerViewId != 0) { if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) { throw new IllegalStateException("Can't change container ID of fragment " @@ -224,7 +269,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } fragment.mContainerId = fragment.mFragmentId = containerViewId; } - + Op op = new Op(); op.cmd = opcmd; op.fragment = fragment; @@ -234,27 +279,27 @@ final class BackStackEntry implements FragmentTransaction, Runnable { public FragmentTransaction replace(int containerViewId, Fragment fragment) { return replace(containerViewId, fragment, null); } - + public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) { if (containerViewId == 0) { throw new IllegalArgumentException("Must use non-zero containerViewId"); } - + doAddOp(containerViewId, fragment, tag, OP_REPLACE); return this; } - + public FragmentTransaction remove(Fragment fragment) { if (fragment.mImmediateActivity == null) { throw new IllegalStateException("Fragment not added: " + fragment); } fragment.mImmediateActivity = null; - + Op op = new Op(); op.cmd = OP_REMOVE; op.fragment = fragment; addOp(op); - + return this; } @@ -262,50 +307,74 @@ final class BackStackEntry implements FragmentTransaction, Runnable { if (fragment.mImmediateActivity == null) { throw new IllegalStateException("Fragment not added: " + fragment); } - + Op op = new Op(); op.cmd = OP_HIDE; op.fragment = fragment; addOp(op); - + return this; } - + public FragmentTransaction show(Fragment fragment) { if (fragment.mImmediateActivity == null) { throw new IllegalStateException("Fragment not added: " + fragment); } - + Op op = new Op(); op.cmd = OP_SHOW; op.fragment = fragment; addOp(op); - + return this; } - + public FragmentTransaction setCustomAnimations(int enter, int exit) { mEnterAnim = enter; mExitAnim = exit; return this; } - + public FragmentTransaction setTransition(int transition) { mTransition = transition; return this; } - + public FragmentTransaction setTransitionStyle(int styleRes) { mTransitionStyle = styleRes; return this; } - + public FragmentTransaction addToBackStack(String name) { mAddToBackStack = true; mName = name; return this; } + public FragmentTransaction setBreadCrumbTitle(int res) { + mBreadCrumbTitleRes = res; + mBreadCrumbTitleText = null; + return this; + } + + public FragmentTransaction setBreadCrumbTitle(CharSequence text) { + mBreadCrumbTitleRes = 0; + mBreadCrumbTitleText = text; + return this; + } + + public FragmentTransaction setBreadCrumbShortTitle(int res) { + mBreadCrumbShortTitleRes = res; + mBreadCrumbShortTitleText = null; + return this; + } + + public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) { + mBreadCrumbShortTitleRes = 0; + mBreadCrumbShortTitleText = text; + return this; + } + void bumpBackStackNesting(int amt) { if (!mAddToBackStack) { return; @@ -341,10 +410,10 @@ final class BackStackEntry implements FragmentTransaction, Runnable { mManager.enqueueAction(this); return mIndex; } - + public void run() { if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this); - + if (mAddToBackStack) { if (mIndex < 0) { throw new IllegalStateException("addToBackStack() called after commit()"); @@ -405,23 +474,23 @@ final class BackStackEntry implements FragmentTransaction, Runnable { throw new IllegalArgumentException("Unknown cmd: " + op.cmd); } } - + op = op.next; } - + mManager.moveToState(mManager.mCurState, mTransition, mTransitionStyle, true); - + if (mAddToBackStack) { mManager.addBackStackState(this); } } - + public void popFromBackStack(boolean doStateMove) { if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this); bumpBackStackNesting(-1); - + Op op = mTail; while (op != null) { switch (op.cmd) { @@ -465,10 +534,10 @@ final class BackStackEntry implements FragmentTransaction, Runnable { throw new IllegalArgumentException("Unknown cmd: " + op.cmd); } } - + op = op.prev; } - + if (doStateMove) { mManager.moveToState(mManager.mCurState, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true); @@ -479,15 +548,15 @@ final class BackStackEntry implements FragmentTransaction, Runnable { mIndex = -1; } } - + public String getName() { return mName; } - + public int getTransition() { return mTransition; } - + public int getTransitionStyle() { return mTransitionStyle; } diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java new file mode 100644 index 0000000..0d39d0b --- /dev/null +++ b/core/java/android/app/FragmentBreadCrumbs.java @@ -0,0 +1,175 @@ +/* + * 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 android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +/** + * Helper class for showing "bread crumbs" representing the fragment + * stack in an activity. This is intended to be used with + * {@link ActionBar#setCustomNavigationMode(View) + * ActionBar.setCustomNavigationMode(View)} to place the bread crumbs in + * the navigation area of the action bar. + * + * <p>The default style for this view is + * {@link android.R.style#Widget_FragmentBreadCrumbs}. + */ +public class FragmentBreadCrumbs extends ViewGroup + implements FragmentManager.OnBackStackChangedListener { + Activity mActivity; + LayoutInflater mInflater; + LinearLayout mContainer; + + // Hahah + BackStackRecord mTopEntry; + + public FragmentBreadCrumbs(Context context) { + this(context, null); + } + + public FragmentBreadCrumbs(Context context, AttributeSet attrs) { + this(context, attrs, android.R.style.Widget_FragmentBreadCrumbs); + } + + public FragmentBreadCrumbs(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * Attach the bread crumbs to their activity. This must be called once + * when creating the bread crumbs. + */ + public void setActivity(Activity a) { + mActivity = a; + mInflater = (LayoutInflater)a.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mContainer = (LinearLayout)mInflater.inflate( + com.android.internal.R.layout.fragment_bread_crumbs, + this, false); + addView(mContainer); + a.getFragmentManager().addOnBackStackChangedListener(this); + updateCrumbs(); + } + + /** + * Set a custom title for the bread crumbs. This will be the first entry + * shown at the left, representing the root of the bread crumbs. If the + * title is null, it will not be shown. + */ + public void setTitle(CharSequence title, CharSequence shortTitle) { + if (title == null) { + mTopEntry = null; + } else { + mTopEntry = new BackStackRecord((FragmentManagerImpl) + mActivity.getFragmentManager()); + mTopEntry.setBreadCrumbTitle(title); + mTopEntry.setBreadCrumbShortTitle(shortTitle); + } + updateCrumbs(); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + // Eventually we should implement our own layout of the views, + // rather than relying on a linear layout. + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + int childRight = mPaddingLeft + child.getMeasuredWidth() - mPaddingRight; + int childBottom = mPaddingTop + child.getMeasuredHeight() - mPaddingBottom; + child.layout(mPaddingLeft, mPaddingTop, childRight, childBottom); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int count = getChildCount(); + + int maxHeight = 0; + int maxWidth = 0; + + // Find rightmost and bottom-most child + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + measureChild(child, widthMeasureSpec, heightMeasureSpec); + maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); + maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); + } + } + + // Account for padding too + maxWidth += mPaddingLeft + mPaddingRight; + maxHeight += mPaddingTop + mPaddingBottom; + + // Check against our minimum height and width + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), + resolveSize(maxHeight, heightMeasureSpec)); + } + + @Override + public void onBackStackChanged() { + updateCrumbs(); + } + + void updateCrumbs() { + FragmentManager fm = mActivity.getFragmentManager(); + int numEntries = fm.countBackStackEntries(); + int numViews = mContainer.getChildCount(); + for (int i=mTopEntry != null ? -1 : 0; i<numEntries; i++) { + FragmentManager.BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i); + int viewI = mTopEntry != null ? i+1 : i; + if (viewI < numViews) { + View v = mContainer.getChildAt(viewI); + Object tag = v.getTag(); + if (tag != bse) { + for (int j=viewI; j<numViews; j++) { + mContainer.removeViewAt(viewI); + } + numViews = viewI; + } + } + if (viewI >= numViews) { + View item = mInflater.inflate( + com.android.internal.R.layout.fragment_bread_crumb_item, + this, false); + TextView text = (TextView)item.findViewById(com.android.internal.R.id.title); + text.setText(bse.getBreadCrumbTitle()); + item.setTag(bse); + if (viewI == 0) { + text.setCompoundDrawables(null, null, null, null); + } + mContainer.addView(item); + } + } + int viewI = mTopEntry != null ? numEntries+1 : numEntries; + numViews = mContainer.getChildCount(); + while (numViews > viewI) { + mContainer.removeViewAt(numViews-1); + numViews--; + } + } +} diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index a704ec8..9f95824 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -40,6 +40,48 @@ import java.util.ArrayList; */ public interface FragmentManager { /** + * Representation of an entry on the fragment back stack, as created + * with {@link FragmentTransaction#addToBackStack(String) + * FragmentTransaction.addToBackStack()}. Entries can later be + * retrieved with {@link FragmentManager#getBackStackEntry(int) + * FragmentManager.getBackStackEntry()}. + * + * <p>Note that you should never hold on to a BackStackEntry object; + * the identifier as returned by {@link #getId} is the only thing that + * will be persisted across activity instances. + */ + public interface BackStackEntry { + /** + * Return the unique identifier for the entry. This is the only + * representation of the entry that will persist across activity + * instances. + */ + public int getId(); + + /** + * Return the full bread crumb title for the entry, or null if it + * does not have one. + */ + public CharSequence getBreadCrumbTitle(); + + /** + * Return the short bread crumb title for the entry, or null if it + * does not have one. + */ + public CharSequence getBreadCrumbShortTitle(); + } + + /** + * Interface to watch for changes to the back stack. + */ + public interface OnBackStackChangedListener { + /** + * Called whenever the contents of the back stack change. + */ + public void onBackStackChanged(); + } + + /** * Start a series of edit operations on the Fragments associated with * this FragmentManager. */ @@ -105,6 +147,28 @@ public interface FragmentManager { public boolean popBackStack(int id, int flags); /** + * Return the number of entries currently in the back stack. + */ + public int countBackStackEntries(); + + /** + * Return the BackStackEntry at index <var>index</var> in the back stack; + * entries start index 0 being the bottom of the stack. + */ + public BackStackEntry getBackStackEntry(int index); + + /** + * Add a new listener for changes to the fragment back stack. + */ + public void addOnBackStackChangedListener(OnBackStackChangedListener listener); + + /** + * Remove a listener that was previously added with + * {@link #addOnBackStackChangedListener(OnBackStackChangedListener)}. + */ + public void removeOnBackStackChangedListener(OnBackStackChangedListener listener); + + /** * Put a reference to a fragment in a Bundle. This Bundle can be * persisted as saved state, and when later restoring * {@link #getFragment(Bundle, String)} will return the current @@ -182,12 +246,14 @@ final class FragmentManagerImpl implements FragmentManager { ArrayList<Fragment> mActive; ArrayList<Fragment> mAdded; ArrayList<Integer> mAvailIndices; - ArrayList<BackStackEntry> mBackStack; + ArrayList<BackStackRecord> mBackStack; // Must be accessed while locked. - ArrayList<BackStackEntry> mBackStackIndices; + ArrayList<BackStackRecord> mBackStackIndices; ArrayList<Integer> mAvailBackStackIndices; + ArrayList<OnBackStackChangedListener> mBackStackChangeListeners; + int mCurState = Fragment.INITIALIZING; Activity mActivity; @@ -205,7 +271,7 @@ final class FragmentManagerImpl implements FragmentManager { } }; public FragmentTransaction openTransaction() { - return new BackStackEntry(this); + return new BackStackRecord(this); } public boolean popBackStack() { @@ -223,6 +289,27 @@ final class FragmentManagerImpl implements FragmentManager { return popBackStackState(mActivity.mHandler, null, id, flags); } + public int countBackStackEntries() { + return mBackStack != null ? mBackStack.size() : 0; + } + + public BackStackEntry getBackStackEntry(int index) { + return mBackStack.get(index); + } + + public void addOnBackStackChangedListener(OnBackStackChangedListener listener) { + if (mBackStackChangeListeners == null) { + mBackStackChangeListeners = new ArrayList<OnBackStackChangedListener>(); + } + mBackStackChangeListeners.add(listener); + } + + public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) { + if (mBackStackChangeListeners != null) { + mBackStackChangeListeners.remove(listener); + } + } + public void putFragment(Bundle bundle, String key, Fragment fragment) { if (fragment.mIndex < 0) { throw new IllegalStateException("Fragment " + fragment @@ -696,11 +783,11 @@ final class FragmentManagerImpl implements FragmentManager { } } - public int allocBackStackIndex(BackStackEntry bse) { + public int allocBackStackIndex(BackStackRecord bse) { synchronized (this) { if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) { if (mBackStackIndices == null) { - mBackStackIndices = new ArrayList<BackStackEntry>(); + mBackStackIndices = new ArrayList<BackStackRecord>(); } int index = mBackStackIndices.size(); if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse); @@ -716,10 +803,10 @@ final class FragmentManagerImpl implements FragmentManager { } } - public void setBackStackIndex(int index, BackStackEntry bse) { + public void setBackStackIndex(int index, BackStackRecord bse) { synchronized (this) { if (mBackStackIndices == null) { - mBackStackIndices = new ArrayList<BackStackEntry>(); + mBackStackIndices = new ArrayList<BackStackRecord>(); } int N = mBackStackIndices.size(); if (index < N) { @@ -785,11 +872,20 @@ final class FragmentManagerImpl implements FragmentManager { } } - public void addBackStackState(BackStackEntry state) { + void reportBackStackChanged() { + if (mBackStackChangeListeners != null) { + for (int i=0; i<mBackStackChangeListeners.size(); i++) { + mBackStackChangeListeners.get(i).onBackStackChanged(); + } + } + } + + void addBackStackState(BackStackRecord state) { if (mBackStack == null) { - mBackStack = new ArrayList<BackStackEntry>(); + mBackStack = new ArrayList<BackStackRecord>(); } mBackStack.add(state); + reportBackStackChanged(); } boolean popBackStackState(Handler handler, String name, int id, int flags) { @@ -801,11 +897,12 @@ final class FragmentManagerImpl implements FragmentManager { if (last < 0) { return false; } - final BackStackEntry bss = mBackStack.remove(last); + final BackStackRecord bss = mBackStack.remove(last); enqueueAction(new Runnable() { public void run() { if (DEBUG) Log.v(TAG, "Popping back stack state: " + bss); bss.popFromBackStack(true); + reportBackStackChanged(); } }); } else { @@ -815,7 +912,7 @@ final class FragmentManagerImpl implements FragmentManager { // the stack. index = mBackStack.size()-1; while (index >= 0) { - BackStackEntry bss = mBackStack.get(index); + BackStackRecord bss = mBackStack.get(index); if (name != null && name.equals(bss.getName())) { break; } @@ -831,7 +928,7 @@ final class FragmentManagerImpl implements FragmentManager { index--; // Consume all following entries that match. while (index >= 0) { - BackStackEntry bss = mBackStack.get(index); + BackStackRecord bss = mBackStack.get(index); if ((name != null && name.equals(bss.getName())) || (id >= 0 && id == bss.mIndex)) { index--; @@ -844,8 +941,8 @@ final class FragmentManagerImpl implements FragmentManager { if (index == mBackStack.size()-1) { return false; } - final ArrayList<BackStackEntry> states - = new ArrayList<BackStackEntry>(); + final ArrayList<BackStackRecord> states + = new ArrayList<BackStackRecord>(); for (int i=mBackStack.size()-1; i>index; i--) { states.add(mBackStack.remove(i)); } @@ -856,6 +953,7 @@ final class FragmentManagerImpl implements FragmentManager { if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i)); states.get(i).popFromBackStack(i == LAST); } + reportBackStackChanged(); } }); } @@ -1073,9 +1171,9 @@ final class FragmentManagerImpl implements FragmentManager { // Build the back stack. if (fms.mBackStack != null) { - mBackStack = new ArrayList<BackStackEntry>(fms.mBackStack.length); + mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length); for (int i=0; i<fms.mBackStack.length; i++) { - BackStackEntry bse = fms.mBackStack[i].instantiate(this); + BackStackRecord bse = fms.mBackStack[i].instantiate(this); if (DEBUG) Log.v(TAG, "restoreAllState: adding bse #" + i + " (index " + bse.mIndex + "): " + bse); mBackStack.add(bse); diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index 9d44106..09d8d26 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -88,7 +88,7 @@ public interface FragmentTransaction { /** * @return <code>true</code> if this transaction contains no operations, - * <code>false</code> otherwise. + * <code>false</code> otherwise. */ public boolean isEmpty(); @@ -111,14 +111,65 @@ public interface FragmentTransaction { /** Fragment is being removed */ public final int TRANSIT_FRAGMENT_CLOSE = 2 | TRANSIT_EXIT_MASK; + /** + * Set specific animation resources to run for the fragments that are + * entering and exiting in this transaction. + */ public FragmentTransaction setCustomAnimations(int enter, int exit); + /** + * Select a standard transition animation for this transaction. May be + * one of {@link #TRANSIT_NONE}, {@link #TRANSIT_FRAGMENT_OPEN}, + * or {@link #TRANSIT_FRAGMENT_CLOSE} + */ public FragmentTransaction setTransition(int transit); + + /** + * Set a custom style resource that will be used for resolving transit + * animations. + */ public FragmentTransaction setTransitionStyle(int styleRes); + /** + * Add this transaction to the back stack. This means that the transaction + * will be remembered after it is committed, and will reverse its operation + * when later popped off the stack. + * + * @param name An optional name for this back stack state, or null. + */ public FragmentTransaction addToBackStack(String name); /** + * Set the full title to show as a bread crumb when this transaction + * is on the back stack, as used by {@link FragmentBreadCrumbs}. + * + * @param res A string resource containing the title. + */ + public FragmentTransaction setBreadCrumbTitle(int res); + + /** + * Like {@link #setBreadCrumbTitle(int)} but taking a raw string; this + * method is <em>not</em> recommended, as the string can not be changed + * later if the locale changes. + */ + public FragmentTransaction setBreadCrumbTitle(CharSequence text); + + /** + * Set the short title to show as a bread crumb when this transaction + * is on the back stack, as used by {@link FragmentBreadCrumbs}. + * + * @param res A string resource containing the title. + */ + public FragmentTransaction setBreadCrumbShortTitle(int res); + + /** + * Like {@link #setBreadCrumbShortTitle(int)} but taking a raw string; this + * method is <em>not</em> recommended, as the string can not be changed + * later if the locale changes. + */ + public FragmentTransaction setBreadCrumbShortTitle(CharSequence text); + + /** * Schedules a commit of this transaction. Note that the commit does * not happen immediately; it will be scheduled as work on the main thread * to be done the next time that thread is ready. diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index 4247ae5..e78d2af 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -22,6 +22,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.app.Fragment; +import android.app.FragmentBreadCrumbs; import android.app.FragmentTransaction; import android.app.ListActivity; import android.content.Context; @@ -117,7 +118,6 @@ public abstract class PreferenceActivity extends ListActivity implements // Constants for state save/restore private static final String HEADERS_TAG = ":android:headers"; private static final String CUR_HEADER_TAG = ":android:cur_header"; - private static final String SINGLE_PANE_TAG = ":android:single_pane"; private static final String PREFERENCES_TAG = ":android:preferences"; /** @@ -169,6 +169,8 @@ public abstract class PreferenceActivity extends ListActivity implements private View mPrefsContainer; + private FragmentBreadCrumbs mFragmentBreadCrumbs; + private boolean mSinglePane; private Header mCurHeader; @@ -300,6 +302,18 @@ public abstract class PreferenceActivity extends ListActivity implements public CharSequence summary; /** + * Optional text to show as the title in the bread crumb. + * @attr ref android.R.styleable#PreferenceHeader_breadCrumbTitle + */ + public CharSequence breadCrumbTitle; + + /** + * Optional text to show as the short title in the bread crumb. + * @attr ref android.R.styleable#PreferenceHeader_breadCrumbShortTitle + */ + public CharSequence breadCrumbShortTitle; + + /** * Optional icon resource to show for this header. * @attr ref android.R.styleable#PreferenceHeader_icon */ @@ -341,6 +355,8 @@ public abstract class PreferenceActivity extends ListActivity implements dest.writeLong(id); TextUtils.writeToParcel(title, dest, flags); TextUtils.writeToParcel(summary, dest, flags); + TextUtils.writeToParcel(breadCrumbTitle, dest, flags); + TextUtils.writeToParcel(breadCrumbShortTitle, dest, flags); dest.writeInt(iconRes); dest.writeString(fragment); dest.writeBundle(fragmentArguments); @@ -357,6 +373,8 @@ public abstract class PreferenceActivity extends ListActivity implements id = in.readLong(); title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + breadCrumbTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + breadCrumbShortTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); iconRes = in.readInt(); fragment = in.readString(); fragmentArguments = in.readBundle(); @@ -405,7 +423,6 @@ public abstract class PreferenceActivity extends ListActivity implements setSelectedHeader(mHeaders.get(curHeader)); } } - mSinglePane = savedInstanceState.getBoolean(SINGLE_PANE_TAG); } else { if (initialFragment != null && mSinglePane) { @@ -537,7 +554,11 @@ public abstract class PreferenceActivity extends ListActivity implements public boolean onIsMultiPane() { Configuration config = getResources().getConfiguration(); if ((config.screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) - == Configuration.SCREENLAYOUT_SIZE_XLARGE + == Configuration.SCREENLAYOUT_SIZE_XLARGE) { + return true; + } + if ((config.screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) + == Configuration.SCREENLAYOUT_SIZE_LARGE && config.orientation == Configuration.ORIENTATION_LANDSCAPE) { return true; } @@ -649,6 +670,10 @@ public abstract class PreferenceActivity extends ListActivity implements com.android.internal.R.styleable.PreferenceHeader_title); header.summary = sa.getText( com.android.internal.R.styleable.PreferenceHeader_summary); + header.breadCrumbTitle = sa.getText( + com.android.internal.R.styleable.PreferenceHeader_breadCrumbTitle); + header.breadCrumbShortTitle = sa.getText( + com.android.internal.R.styleable.PreferenceHeader_breadCrumbShortTitle); header.iconRes = sa.getResourceId( com.android.internal.R.styleable.PreferenceHeader_icon, 0); header.fragment = sa.getString( @@ -741,7 +766,6 @@ public abstract class PreferenceActivity extends ListActivity implements } } } - outState.putBoolean(SINGLE_PANE_TAG, mSinglePane); if (mPreferenceManager != null) { final PreferenceScreen preferenceScreen = getPreferenceScreen(); @@ -837,6 +861,20 @@ public abstract class PreferenceActivity extends ListActivity implements startActivity(intent); } + /** + * Change the base title of the bread crumbs for the current preferences. + * This will normally be called for you. See + * {@link android.app.FragmentBreadCrumbs} for more information. + */ + public void showBreadCrumbs(CharSequence title, CharSequence shortTitle) { + if (mFragmentBreadCrumbs == null) { + mFragmentBreadCrumbs = new FragmentBreadCrumbs(this); + mFragmentBreadCrumbs.setActivity(this); + getActionBar().setCustomNavigationMode(mFragmentBreadCrumbs); + } + mFragmentBreadCrumbs.setTitle(title, shortTitle); + } + void setSelectedHeader(Header header) { mCurHeader = header; int index = mHeaders.indexOf(header); @@ -845,6 +883,21 @@ public abstract class PreferenceActivity extends ListActivity implements } else { getListView().clearChoices(); } + if (header != null) { + CharSequence title = header.breadCrumbTitle; + if (title == null) title = header.title; + if (title == null) title = getTitle(); + showBreadCrumbs(title, header.breadCrumbShortTitle); + } else { + showBreadCrumbs(getTitle(), null); + } + } + + public void switchToHeaderInner(String fragmentName, Bundle args) { + getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE); + Fragment f = Fragment.instantiate(this, fragmentName, args); + getFragmentManager().openTransaction().replace( + com.android.internal.R.id.prefs, f).commit(); } /** @@ -856,12 +909,7 @@ public abstract class PreferenceActivity extends ListActivity implements */ public void switchToHeader(String fragmentName, Bundle args) { setSelectedHeader(null); - - getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE); - - Fragment f = Fragment.instantiate(this, fragmentName, args); - getFragmentManager().openTransaction().replace( - com.android.internal.R.id.prefs, f).commit(); + switchToHeaderInner(fragmentName, args); } /** @@ -871,8 +919,7 @@ public abstract class PreferenceActivity extends ListActivity implements * @param header The new header to display. */ public void switchToHeader(Header header) { - switchToHeader(header.fragment, header.fragmentArguments); - mCurHeader = header; + switchToHeaderInner(header.fragment, header.fragmentArguments); setSelectedHeader(header); } @@ -930,17 +977,32 @@ public abstract class PreferenceActivity extends ListActivity implements */ public void startPreferenceFragment(Fragment fragment, boolean push) { FragmentTransaction transaction = getFragmentManager().openTransaction(); - transaction.replace(com.android.internal.R.id.prefs, fragment); + startPreferenceFragment(fragment, transaction); if (push) { transaction.addToBackStack(BACK_STACK_PREFS); } transaction.commit(); } + /** + * Start a new fragment. + * + * @param fragment The fragment to start + * @param ft The FragmentTransaction in which to perform this operation. + * Will not be added to the back stack or committed for you; you use do that. + */ + public void startPreferenceFragment(Fragment fragment, FragmentTransaction ft) { + ft.replace(com.android.internal.R.id.prefs, fragment); + } + @Override public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras()); - startPreferenceFragment(f, true); + FragmentTransaction transaction = getFragmentManager().openTransaction(); + startPreferenceFragment(f, transaction); + transaction.setBreadCrumbTitle(pref.getTitle()); + transaction.addToBackStack(BACK_STACK_PREFS); + transaction.commit(); return true; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 00efa90..ac65e09 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8745,7 +8745,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0); invalidate(); refreshDrawableState(); - dispatchSetSelected(activated); + dispatchSetActivated(activated); } } diff --git a/core/res/res/color/primary_text_dark.xml b/core/res/res/color/primary_text_dark.xml index 39c9e22..3dd73e7 100644 --- a/core/res/res/color/primary_text_dark.xml +++ b/core/res/res/color/primary_text_dark.xml @@ -19,7 +19,6 @@ <item android:state_window_focused="false" android:color="@android:color/bright_foreground_dark"/> <item android:state_pressed="true" android:color="@android:color/bright_foreground_dark_inverse"/> <item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/> <item android:color="@android:color/bright_foreground_dark"/> <!-- not selected --> - </selector> - diff --git a/core/res/res/color/primary_text_dark_focused.xml b/core/res/res/color/primary_text_dark_focused.xml index 7f3906a..c97c0bd 100644 --- a/core/res/res/color/primary_text_dark_focused.xml +++ b/core/res/res/color/primary_text_dark_focused.xml @@ -16,6 +16,7 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse" /> + <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse" /> <item android:state_focused="true" android:color="@android:color/bright_foreground_dark_inverse" /> <item android:state_pressed="true" android:color="@android:color/bright_foreground_dark_inverse" /> <item android:color="@android:color/bright_foreground_dark" /> diff --git a/core/res/res/color/primary_text_dark_nodisable.xml b/core/res/res/color/primary_text_dark_nodisable.xml index be1b9f9..443f7f4 100644 --- a/core/res/res/color/primary_text_dark_nodisable.xml +++ b/core/res/res/color/primary_text_dark_nodisable.xml @@ -16,6 +16,7 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/> <item android:color="@android:color/bright_foreground_dark"/> <!-- not selected --> </selector> diff --git a/core/res/res/color/primary_text_light.xml b/core/res/res/color/primary_text_light.xml index e112034..a12c6b4 100644 --- a/core/res/res/color/primary_text_light.xml +++ b/core/res/res/color/primary_text_light.xml @@ -19,6 +19,7 @@ <item android:state_window_focused="false" android:color="@android:color/bright_foreground_light"/> <item android:state_pressed="true" android:color="@android:color/bright_foreground_light"/> <item android:state_selected="true" android:color="@android:color/bright_foreground_light"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/> <item android:color="@android:color/bright_foreground_light"/> <!-- not selected --> </selector> diff --git a/core/res/res/color/primary_text_light_nodisable.xml b/core/res/res/color/primary_text_light_nodisable.xml index 2d35470..051cccf 100644 --- a/core/res/res/color/primary_text_light_nodisable.xml +++ b/core/res/res/color/primary_text_light_nodisable.xml @@ -16,6 +16,7 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="@android:color/bright_foreground_light"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/> <item android:color="@android:color/bright_foreground_light"/> <!-- not selected --> </selector> diff --git a/core/res/res/color/secondary_text_dark.xml b/core/res/res/color/secondary_text_dark.xml index c195ef0..1a38fa9 100644 --- a/core/res/res/color/secondary_text_dark.xml +++ b/core/res/res/color/secondary_text_dark.xml @@ -20,6 +20,7 @@ <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/> <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/> <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/> <item android:state_pressed="true" android:color="@android:color/dim_foreground_dark_inverse"/> <item android:state_enabled="false" android:color="@android:color/dim_foreground_dark_disabled"/> <item android:color="@android:color/dim_foreground_dark"/> <!-- not selected --> diff --git a/core/res/res/color/secondary_text_dark_nodisable.xml b/core/res/res/color/secondary_text_dark_nodisable.xml index 2c87a25..cbc7b02 100644 --- a/core/res/res/color/secondary_text_dark_nodisable.xml +++ b/core/res/res/color/secondary_text_dark_nodisable.xml @@ -16,5 +16,6 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/> <item android:color="@android:color/dim_foreground_dark"/> <!-- not selected --> </selector> diff --git a/core/res/res/color/secondary_text_light.xml b/core/res/res/color/secondary_text_light.xml index 99249a5..293f4aa 100644 --- a/core/res/res/color/secondary_text_light.xml +++ b/core/res/res/color/secondary_text_light.xml @@ -22,6 +22,7 @@ <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/> <item android:state_pressed="true" android:color="@android:color/dim_foreground_light"/> <item android:state_selected="true" android:color="@android:color/dim_foreground_light"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/> <item android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/> <item android:color="@android:color/dim_foreground_light"/> <!-- not selected --> </selector> diff --git a/core/res/res/color/secondary_text_light_nodisable.xml b/core/res/res/color/secondary_text_light_nodisable.xml index 2c87a25..cbc7b02 100644 --- a/core/res/res/color/secondary_text_light_nodisable.xml +++ b/core/res/res/color/secondary_text_light_nodisable.xml @@ -16,5 +16,6 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/> + <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/> <item android:color="@android:color/dim_foreground_dark"/> <!-- not selected --> </selector> diff --git a/core/res/res/drawable-hdpi/nav_divider.png b/core/res/res/drawable-hdpi/nav_divider.png Binary files differnew file mode 100644 index 0000000..7ca3e61 --- /dev/null +++ b/core/res/res/drawable-hdpi/nav_divider.png diff --git a/core/res/res/drawable-mdpi/nav_divider.png b/core/res/res/drawable-mdpi/nav_divider.png Binary files differnew file mode 100644 index 0000000..c9413d7 --- /dev/null +++ b/core/res/res/drawable-mdpi/nav_divider.png diff --git a/core/res/res/layout-port/preference_header_item.xml b/core/res/res/layout-port/preference_header_item.xml new file mode 100644 index 0000000..cc76c8e --- /dev/null +++ b/core/res/res/layout-port/preference_header_item.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2006 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. +--> + +<!-- Layout of a header item in PreferenceActivity. --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="96dp" + android:background="?android:attr/activatedBackgroundIndicator" + android:paddingRight="?android:attr/scrollbarSize"> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_gravity="center" + android:paddingLeft="4dip" + android:paddingRight="4dip" + android:paddingTop="4dip" + android:paddingBottom="4dip"> + + <ImageView + android:id="@+id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginBottom="2dip" /> + + <TextView android:id="@+android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginBottom="2dip" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceLarge" + android:ellipsize="marquee" + android:fadingEdge="horizontal" /> + + <TextView android:id="@+android:id/summary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:textAppearance="?android:attr/textAppearanceSmall" + android:ellipsize="end" + android:maxLines="2" /> + + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/fragment_bread_crumb_item.xml b/core/res/res/layout/fragment_bread_crumb_item.xml new file mode 100644 index 0000000..408f6e8 --- /dev/null +++ b/core/res/res/layout/fragment_bread_crumb_item.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:textAppearance="?android:attr/textAppearanceMediumInverse" + android:drawableLeft="@drawable/nav_divider" + android:paddingLeft="12dp" + android:drawablePadding="12dp" + /> diff --git a/core/res/res/layout/fragment_bread_crumbs.xml b/core/res/res/layout/fragment_bread_crumbs.xml new file mode 100644 index 0000000..f289e14 --- /dev/null +++ b/core/res/res/layout/fragment_bread_crumbs.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_width="wrap_content" + android:layout_height="match_parent"> +</LinearLayout> diff --git a/core/res/res/layout/preference_header_item.xml b/core/res/res/layout/preference_header_item.xml index 80a3ac2..aba7b2a 100644 --- a/core/res/res/layout/preference_header_item.xml +++ b/core/res/res/layout/preference_header_item.xml @@ -54,6 +54,7 @@ android:layout_below="@android:id/title" android:layout_alignLeft="@android:id/title" android:textAppearance="?android:attr/textAppearanceSmall" + android:ellipsize="end" android:maxLines="2" /> </RelativeLayout> diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml index fe950b2..9661c64 100644 --- a/core/res/res/layout/preference_list_content.xml +++ b/core/res/res/layout/preference_list_content.xml @@ -33,7 +33,7 @@ android:orientation="vertical" android:layout_width="0px" android:layout_height="match_parent" - android:layout_weight="1"> + android:layout_weight="10"> <ListView android:id="@android:id/list" android:layout_width="match_parent" @@ -52,7 +52,7 @@ <FrameLayout android:id="@+id/prefs" android:layout_width="0px" android:layout_height="match_parent" - android:layout_weight="3" + android:layout_weight="33" android:visibility="gone" /> </LinearLayout> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index b3d39f3..2dec5c5 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3561,6 +3561,10 @@ <attr name="title" /> <!-- The summary for the item. --> <attr name="summary" format="string" /> + <!-- The title for the bread crumb of this item. --> + <attr name="breadCrumbTitle" format="string" /> + <!-- The short title for the bread crumb of this item. --> + <attr name="breadCrumbShortTitle" format="string" /> <!-- An icon for the item. --> <attr name="icon" /> <!-- The fragment that is displayed when the user selects this item. --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 3b69acb..fbee438 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1352,6 +1352,8 @@ <public type="attr" name="popupMenuStyle" /> <public type="attr" name="textAppearanceLargePopupMenu" /> <public type="attr" name="textAppearanceSmallPopupMenu" /> + <public type="attr" name="breadCrumbTitle" /> + <public type="attr" name="breadCrumbShortTitle" /> <public type="anim" name="animator_fade_in" /> <public type="anim" name="animator_fade_out" /> @@ -1390,6 +1392,7 @@ <public type="style" name="Widget.ActionButton.CloseMode" /> <public type="style" name="TextAppearance.Widget.PopupMenu.Large" /> <public type="style" name="TextAppearance.Widget.PopupMenu.Small" /> + <public type="style" name="Widget.FragmentBreadCrumbs" /> <public type="string" name="selectTextMode" /> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 9ba0131..1db6f87 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -563,6 +563,11 @@ <item name="android:popupBackground">@android:drawable/editbox_dropdown_background_dark</item> </style> + <!-- Default style for {@link android.app.FragmentBreadCrumbs} view. --> + <style name="Widget.FragmentBreadCrumbs"> + <item name="android:padding">4dp</item> + </style> + <style name="Widget.KeyboardView" parent="android:Widget"> <item name="android:background">@android:drawable/keyboard_background</item> <item name="android:keyBackground">@android:drawable/btn_keyboard_key</item> |
