Take status bar height into account when computing scroll

When computing how much to scroll so that the bottom of the
edittext is visible (to maximize the amount of screen space
for displaying recipient dropdown), take status bar height
into account.

b/17441950

Change-Id: I51d96eebfc3cd75c918a42b6dc379ffb8336b3b7
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
index b4fe14b..1629360 100644
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -17,6 +17,7 @@
 
 package com.android.ex.chips;
 
+import android.app.Activity;
 import android.app.Dialog;
 import android.content.ClipData;
 import android.content.ClipDescription;
@@ -138,7 +139,7 @@
     private static final int MAX_CHIPS_PARSED = 50;
 
     private static int sSelectedTextColor = -1;
-    private static int sExcessTopPadding = -1;
+    private static int sVisibleDisplayFrameTop = -1;
 
     // Resources for displaying chips.
     private Drawable mChipBackground = null;
@@ -155,7 +156,6 @@
     private final int mTextHeight;
     private boolean mDisableDelete;
     private int mMaxLines;
-    private int mActionBarHeight;
 
     /**
      * Enumerator for avatar position. See attr.xml for more details.
@@ -471,11 +471,26 @@
         }
     }
 
-    private int getExcessTopPadding() {
-        if (sExcessTopPadding == -1) {
-            sExcessTopPadding = (int) (mChipHeight + mLineSpacingExtra);
+    // sVisibleDisplayFrameTop is computed on a on-demand basis because the view needs to be fully
+    // measured and created in order to calculate the visible display frame.
+    private int getVisibleDisplayFrameTop() {
+        if (sVisibleDisplayFrameTop == -1) {
+            final TypedValue tv = new TypedValue();
+            final Context context = getContext();
+            // Visible top is our visible display (due to status bar) plus the height of action bar.
+            if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
+                sVisibleDisplayFrameTop = TypedValue.complexToDimensionPixelSize(tv.data,
+                        getResources().getDisplayMetrics());
+            }
+            // Compute the status bar height, or rather where our visible display starts
+            if (context instanceof Activity) {
+                final Rect visibleRect = new Rect();
+                ((Activity) context).getWindow().getDecorView()
+                        .getWindowVisibleDisplayFrame(visibleRect);
+                sVisibleDisplayFrameTop += visibleRect.top;
+            }
         }
-        return sExcessTopPadding;
+        return sVisibleDisplayFrameTop;
     }
 
     @Override
@@ -497,14 +512,14 @@
 
     protected void scrollBottomIntoView() {
         if (mScrollView != null && mShouldShrink) {
-            int[] location = new int[2];
-            getLocationOnScreen(location);
-            int height = getHeight();
-            int currentPos = location[1] + height;
+            final int[] location = new int[2];
+            getLocationInWindow(location);
             // Desired position shows at least 1 line of chips below the action
             // bar. We add excess padding to make sure this is always below other
             // content.
-            int desiredPos = (int) mChipHeight + mActionBarHeight + getExcessTopPadding();
+            final int height = getHeight();
+            final int currentPos = location[1] + height;
+            final int desiredPos = getVisibleDisplayFrameTop() + height / getLineCount();
             if (currentPos > desiredPos) {
                 mScrollView.scrollBy(0, currentPos - desiredPos);
             }
@@ -950,11 +965,6 @@
 
         mMaxLines = r.getInteger(R.integer.chips_max_lines);
         mLineSpacingExtra = r.getDimensionPixelOffset(R.dimen.line_spacing_extra);
-        TypedValue tv = new TypedValue();
-        if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
-            mActionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources()
-                    .getDisplayMetrics());
-        }
 
         a.recycle();
     }