diff options
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 93 | ||||
| -rw-r--r-- | docs/html/develop/index.jd | 1 | ||||
| -rw-r--r-- | docs/html/guide/topics/ui/declaring-layout.jd | 26 | ||||
| -rw-r--r-- | docs/html/guide/topics/ui/layout/gridview.jd | 5 | ||||
| -rw-r--r-- | docs/html/guide/topics/ui/layout/listview.jd | 6 | ||||
| -rw-r--r-- | libs/hwui/FontRenderer.cpp | 11 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 1 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java | 46 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java | 20 |
9 files changed, 170 insertions, 39 deletions
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index c9e092c61352..c1e11bbec86c 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.AnimatorInflater; import android.animation.AnimatorListenerAdapter; import android.content.res.Configuration; +import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Handler; @@ -427,6 +428,94 @@ final class FragmentManagerImpl extends FragmentManager { } }; + private void logViewHierarchy(String prefix, View view) { + StringBuilder builder = new StringBuilder(128); + builder.append(prefix); + DebugUtils.buildShortClassTag(view, builder); + int id = view.getId(); + if (id != -1) { + builder.append(" #"); + builder.append(Integer.toHexString(id)); + if (id != 0 && id != -1) { + try { + String pkgname; + switch (id&0xff000000) { + case 0x7f000000: + pkgname="app"; + break; + case 0x01000000: + pkgname="android"; + break; + default: + pkgname = view.getResources().getResourcePackageName(id); + break; + } + String typename = view.getResources().getResourceTypeName(id); + String entryname = view.getResources().getResourceEntryName(id); + builder.append(" ("); + builder.append(pkgname); + builder.append(":"); + builder.append(typename); + builder.append("/"); + builder.append(entryname); + builder.append(")"); + } catch (Resources.NotFoundException e) { + } + } + } + Object tag = view.getTag(); + if (tag != null) { + builder.append(" "); + builder.append(tag); + } + builder.append("}"); + Log.e(TAG, builder.toString()); + + if (!(view instanceof ViewGroup)) { + return; + } + ViewGroup grp = (ViewGroup)view; + final int N = grp.getChildCount(); + if (N <= 0) { + return; + } + prefix = prefix + " "; + for (int i=0; i<N; i++) { + logViewHierarchy(prefix, grp.getChildAt(i)); + } + } + + private void throwNoViewFound(Fragment f) { + String msg = "No view found for id 0x" + + Integer.toHexString(f.mContainerId) + " (" + + f.getResources().getResourceName(f.mContainerId) + + ") for fragment " + f; + Log.e(TAG, msg); + Log.e(TAG, "Activity state:"); + if (f.getActivity() != null) { + try { + LogWriter logw = new LogWriter(Log.ERROR, TAG); + PrintWriter pw = new PrintWriter(logw); + f.getActivity().dump(" ", null, pw, new String[] { }); + } catch (Exception e) { + Log.e(TAG, "Failed dumping state", e); + } + } else { + Log.e(TAG, " NULL ACTIVITY!"); + } + Log.e(TAG, "View hierarchy:"); + if (f.getActivity() != null) { + try { + logViewHierarchy(" ", f.getActivity().getWindow().getDecorView()); + } catch (Exception e) { + Log.e(TAG, "Failed dumping view hierarchy", e); + } + } else { + Log.e(TAG, " NULL ACTIVITY!"); + } + throw new IllegalArgumentException(msg); + } + @Override public FragmentTransaction beginTransaction() { return new BackStackRecord(this); @@ -824,9 +913,7 @@ final class FragmentManagerImpl extends FragmentManager { if (f.mContainerId != 0) { container = (ViewGroup)mActivity.findViewById(f.mContainerId); if (container == null && !f.mRestored) { - throw new IllegalArgumentException("No view found for id 0x" - + Integer.toHexString(f.mContainerId) - + " for fragment " + f); + throwNoViewFound(f); } } f.mContainer = container; diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd index eaa70e21dcae..14ab5d587534 100644 --- a/docs/html/develop/index.jd +++ b/docs/html/develop/index.jd @@ -180,7 +180,6 @@ a').click();return false;">Watch the latest review</a></p> </div> <br class="clearfix"/> - </div> diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd index e971a752c4e4..e229f237936b 100644 --- a/docs/html/guide/topics/ui/declaring-layout.jd +++ b/docs/html/guide/topics/ui/declaring-layout.jd @@ -32,12 +32,17 @@ parent.link=index.html <li>{@link android.view.ViewGroup}</li> <li>{@link android.view.ViewGroup.LayoutParams}</li> </ol> -</div> + + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}training/basics/firstapp/building-ui.html">Building a Simple User +Interface</a></li> </div> </div> -<p>Your layout is the architecture for the user interface in an Activity. -It defines the layout structure and holds all the elements that appear to the user. -You can declare your layout in two ways:</p> +<p>A layout defines the visual structure for a user interface, such as the UI for an <a +href="{@docRoot}guide/components/activities.html">activity</a> or <a +href="{@docRoot}guide/topics/appwidgets/index.html">app widget</a>. +You can declare a layout in two ways:</p> <ul> <li><strong>Declare UI elements in XML</strong>. Android provides a straightforward XML vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts.</li> @@ -77,16 +82,6 @@ Layout Objects</a>. There are also a collection of tutorials on building various <h2 id="write">Write the XML</h2> -<div class="sidebox-wrapper"> -<div class="sidebox"> -<p>For your convenience, the API reference documentation for UI related classes -lists the available XML attributes that correspond to the class methods, including inherited -attributes.</p> -<p>To learn more about the available XML elements and attributes, as well as the format of the XML file, see <a -href="{@docRoot}guide/topics/resources/available-resources.html#layoutresources">Layout Resources</a>.</p> -</div> -</div> - <p>Using Android's XML vocabulary, you can quickly design UI layouts and the screen elements they contain, in the same way you create web pages in HTML — with a series of nested elements. </p> <p>Each layout file must contain exactly one root element, which must be a View or ViewGroup object. Once you've defined the root element, you can add additional layout objects or widgets as child elements to gradually build a View hierarchy that defines your layout. For example, here's an XML layout that uses a vertical {@link android.widget.LinearLayout} @@ -111,7 +106,8 @@ to hold a {@link android.widget.TextView} and a {@link android.widget.Button}:</ <p>After you've declared your layout in XML, save the file with the <code>.xml</code> extension, in your Android project's <code>res/layout/</code> directory, so it will properly compile. </p> -<p>We'll discuss each of the attributes shown here a little later.</p> +<p>More information about the syntax for a layout XML file is available in the <a +href="{@docRoot}guide/topics/resources/layout-resource.html">Layout Resources</a> document.</p> <h2 id="load">Load the XML Resource</h2> diff --git a/docs/html/guide/topics/ui/layout/gridview.jd b/docs/html/guide/topics/ui/layout/gridview.jd index 11c54740d631..67bdd0f080cf 100644 --- a/docs/html/guide/topics/ui/layout/gridview.jd +++ b/docs/html/guide/topics/ui/layout/gridview.jd @@ -22,10 +22,15 @@ two-dimensional, scrollable grid. The grid items are automatically inserted to the layout using a {@link android.widget.ListAdapter}.</p> +<p>For an introduction to how you can dynamically insert views using an adapter, read +<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts with + an Adapter</a>.</p> + <img src="{@docRoot}images/ui/gridview.png" alt="" /> <h2 id="example">Example</h2> + <p>In this tutorial, you'll create a grid of image thumbnails. When an item is selected, a toast message will display the position of the image.</p> diff --git a/docs/html/guide/topics/ui/layout/listview.jd b/docs/html/guide/topics/ui/layout/listview.jd index 26a75979988d..fee52927e846 100644 --- a/docs/html/guide/topics/ui/layout/listview.jd +++ b/docs/html/guide/topics/ui/layout/listview.jd @@ -28,6 +28,10 @@ scrollable items. The list items are automatically inserted to the list using an android.widget.Adapter} that pulls content from a source such as an array or database query and converts each item result into a view that's placed into the list.</p> +<p>For an introduction to how you can dynamically insert views using an adapter, read +<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts with + an Adapter</a>.</p> + <img src="{@docRoot}images/ui/listview.png" alt="" /> <h2 id="Loader">Using a Loader</h2> @@ -147,5 +151,5 @@ href="{@docRoot}guide/topics/providers/contacts-provider.html">Contacts Provider</a>, if you want to try this code, your app must request the {@link android.Manifest.permission#READ_CONTACTS} permission in the manifest file:<br/> -<code><uses-permission android:name="android.permission.READ_CONTACTS" /></p> +<code><uses-permission android:name="android.permission.READ_CONTACTS" /></code></p> diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index a596fa946467..b352ffc538ae 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -699,7 +699,6 @@ void FontRenderer::flushAllAndInvalidate() { } #if DEBUG_FONT_RENDERER - ALOGD("FontRenderer: flushAllAndInvalidatel"); // Erase caches, just as a debugging facility if (mCacheTextureSmall && mCacheTextureSmall->mTexture) { memset(mCacheTextureSmall->mTexture, 0, @@ -792,14 +791,12 @@ void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) { void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, uint32_t* retOriginX, uint32_t* retOriginY) { + checkInit(); cachedGlyph->mIsValid = false; // If the glyph is too tall, don't cache it - if (mCacheLines.size() == 0 || - glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) { - if (mCacheLines.size() != 0) { - ALOGE("Font size too large to fit in cache. width, height = %i, %i", - (int) glyph.fWidth, (int) glyph.fHeight); - } + if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) { + ALOGE("Font size too large to fit in cache. width, height = %i, %i", + (int) glyph.fWidth, (int) glyph.fHeight); return; } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 663923197f84..849c5563c4da 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -250,6 +250,7 @@ void OpenGLRenderer::resume() { glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST); mCaches.enableScissor(); mCaches.resetScissor(); dirtyClip(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index 83cabfb13d68..f44c5007425c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -19,6 +19,16 @@ public class PanelBar extends FrameLayout { private PanelHolder mPanelHolder; private ArrayList<PanelView> mPanels = new ArrayList<PanelView>(); protected PanelView mTouchingPanel; + private static final int STATE_CLOSED = 0; + private static final int STATE_TRANSITIONING = 1; + private static final int STATE_OPEN = 2; + private int mState = STATE_CLOSED; + private boolean mTracking; + + private void go(int state) { + LOG("go state: %d -> %d", mState, state); + mState = state; + } public PanelBar(Context context, AttributeSet attrs) { super(context, attrs); @@ -62,8 +72,11 @@ public class PanelBar extends FrameLayout { final int i = (int)(N * event.getX() / getMeasuredWidth()); mTouchingPanel = mPanels.get(i); mPanelHolder.setSelectedPanel(mTouchingPanel); - LOG("PanelBar.onTouch: ACTION_DOWN: panel %d", i); - onPanelPeeked(); + LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %d", mState, i); + if (mState == STATE_CLOSED || mState == STATE_OPEN) { + go(STATE_TRANSITIONING); + onPanelPeeked(); + } } final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event); return result; @@ -72,11 +85,13 @@ public class PanelBar extends FrameLayout { public void panelExpansionChanged(PanelView panel, float frac) { boolean fullyClosed = true; PanelView fullyOpenedPanel = null; + LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName()); for (PanelView pv : mPanels) { + // adjust any other panels that may be partially visible if (pv.getExpandedHeight() > 0f) { fullyClosed = false; final float thisFrac = pv.getExpandedFraction(); - LOG("panel %s: f=%.1f", pv, thisFrac); + LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); if (panel == pv) { if (thisFrac == 1f) fullyOpenedPanel = panel; } else { @@ -84,11 +99,15 @@ public class PanelBar extends FrameLayout { } } } - if (fullyOpenedPanel != null) onPanelFullyOpened(fullyOpenedPanel); - if (fullyClosed) onAllPanelsCollapsed(); - else onPanelPeeked(); + if (fullyOpenedPanel != null && !mTracking) { + go(STATE_OPEN); + onPanelFullyOpened(fullyOpenedPanel); + } else if (fullyClosed && !mTracking) { + go(STATE_CLOSED); + onAllPanelsCollapsed(); + } - LOG("panelExpansionChanged: [%s%s ]", + LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); } @@ -113,4 +132,17 @@ public class PanelBar extends FrameLayout { public void onPanelFullyOpened(PanelView openPanel) { LOG("onPanelFullyOpened"); } + + public void onTrackingStarted(PanelView panel) { + mTracking = true; + if (panel != mTouchingPanel) { + LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)", + panel, mTouchingPanel); + } + } + + public void onTrackingStopped(PanelView panel) { + mTracking = false; + panelExpansionChanged(panel, panel.getExpandedFraction()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index fa97299f1798..b5a50c68ae0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -16,9 +16,9 @@ import com.android.systemui.R; public class PanelView extends FrameLayout { public static final boolean DEBUG = false; public static final String TAG = PanelView.class.getSimpleName(); - public static final void LOG(String fmt, Object... args) { + public final void LOG(String fmt, Object... args) { if (!DEBUG) return; - Log.v(TAG, String.format(fmt, args)); + Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); } public static final boolean BRAKES = false; @@ -61,6 +61,7 @@ public class PanelView extends FrameLayout { private float mVel, mAccel; private int mFullHeight = 0; + private String mViewName; private void animationTick(long dtms) { if (!mTimeAnimator.isStarted()) { @@ -69,7 +70,7 @@ public class PanelView extends FrameLayout { mTimeAnimator.setTimeListener(mAnimationCallback); mTimeAnimator.start(); - } else { + } else if (dtms > 0) { final float dt = dtms * 0.001f; // ms -> s LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt); LOG("tick: before: h=%d", (int) mExpandedHeight); @@ -170,13 +171,16 @@ public class PanelView extends FrameLayout { public boolean onTouch(View v, MotionEvent event) { final float y = event.getY(); final float rawY = event.getRawY(); - LOG("handle.onTouch: y=%.1f rawY=%.1f off=%.1f", y, rawY, mTouchOffset); + LOG("handle.onTouch: a=%s y=%.1f rawY=%.1f off=%.1f", + MotionEvent.actionToString(event.getAction()), + y, rawY, mTouchOffset); PanelView.this.getLocationOnScreen(mAbsPos); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mVelocityTracker = VelocityTracker.obtain(); trackMovement(event); + mBar.onTrackingStarted(PanelView.this); mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight(); break; @@ -190,6 +194,7 @@ public class PanelView extends FrameLayout { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + mBar.onTrackingStopped(PanelView.this); trackMovement(event); mVelocityTracker.computeCurrentVelocity(1000); @@ -241,6 +246,11 @@ public class PanelView extends FrameLayout { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + mViewName = getResources().getResourceName(getId()); + } + + public String getName() { + return mViewName; } @Override @@ -278,7 +288,7 @@ public class PanelView extends FrameLayout { } LOG("setExpansion: height=%.1f fh=%.1f", h, fh); - + if (h < 0) h = 0; else if (h > fh) h = fh; |