Migrated the onTouchListener of the header to its view

In order to ensure reusability and separate inflation,
the expand touch listener is now moved to its view.

Change-Id: I363fc4ae2c68833dc9f1258398ec9ad3bf44dc7f
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 659820f..46cd7ae 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,13 +17,14 @@
 package android.view;
 
 import android.annotation.Nullable;
+import android.app.Notification;
 import android.content.Context;
-import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.widget.LinearLayout;
 import android.widget.RemoteViews;
 
-import com.android.internal.R;
+import java.util.ArrayList;
 
 /**
  * A header of a notification view
@@ -35,6 +36,10 @@
     private final int mHeaderMinWidth;
     private View mAppName;
     private View mSubTextView;
+    private OnClickListener mExpandClickListener;
+    private HeaderTouchListener mTouchListener = new HeaderTouchListener();
+    private View mExpandButton;
+    private View mIcon;
 
     public NotificationHeaderView(Context context) {
         this(context, null);
@@ -59,6 +64,8 @@
         super.onFinishInflate();
         mAppName = findViewById(com.android.internal.R.id.app_name_text);
         mSubTextView = findViewById(com.android.internal.R.id.header_sub_text);
+        mExpandButton = findViewById(com.android.internal.R.id.expand_button);
+        mIcon = findViewById(com.android.internal.R.id.icon);
     }
 
     @Override
@@ -105,4 +112,125 @@
         }
         setMeasuredDimension(totalWidth, givenHeight);
     }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        updateTouchListener();
+    }
+
+    private void updateTouchListener() {
+        if (mExpandClickListener != null) {
+            mTouchListener.bindTouchRects();
+        }
+    }
+
+    @Override
+    public void setOnClickListener(@Nullable OnClickListener l) {
+        mExpandClickListener = l;
+        setOnTouchListener(mExpandClickListener != null ? mTouchListener : null);
+        updateTouchListener();
+    }
+
+    public class HeaderTouchListener implements View.OnTouchListener {
+
+        private final ArrayList<Rect> mTouchRects = new ArrayList<>();
+        private int mTouchSlop;
+        private boolean mTrackGesture;
+        private float mDownX;
+        private float mDownY;
+
+        public HeaderTouchListener() {
+        }
+
+        public void bindTouchRects() {
+            mTouchRects.clear();
+            addRectAroundViewView(mIcon);
+            addRectAroundViewView(mExpandButton);
+            addInBetweenRect();
+            mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+        }
+
+        private void addInBetweenRect() {
+            final Rect r = new Rect();
+            r.top = 0;
+            r.bottom = (int) (32 * getResources().getDisplayMetrics().density);
+            Rect leftRect = mTouchRects.get(0);
+            r.left = leftRect.right;
+            Rect rightRect = mTouchRects.get(1);
+            r.right = rightRect.left;
+            mTouchRects.add(r);
+        }
+
+        private void addRectAroundViewView(View view) {
+            final Rect r = getRectAroundView(view);
+            mTouchRects.add(r);
+        }
+
+        private Rect getRectAroundView(View view) {
+            float size = 48 * getResources().getDisplayMetrics().density;
+            final Rect r = new Rect();
+            if (view.getVisibility() == GONE) {
+                view = getFirstChildNotGone();
+                r.left = (int) (view.getLeft() - size / 2.0f);
+            } else {
+                r.left = (int) ((view.getLeft() + view.getRight()) / 2.0f - size / 2.0f);
+            }
+            r.top = (int) ((view.getTop() + view.getBottom()) / 2.0f - size / 2.0f);
+            r.bottom = (int) (r.top + size);
+            r.right = (int) (r.left + size);
+            return r;
+        }
+
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            float x = event.getX();
+            float y = event.getY();
+            switch (event.getActionMasked() & MotionEvent.ACTION_MASK) {
+                case MotionEvent.ACTION_DOWN:
+                    mTrackGesture = false;
+                    if (isInside(x, y)) {
+                        mTrackGesture = true;
+                        return true;
+                    }
+                    break;
+                case MotionEvent.ACTION_MOVE:
+                    if (mTrackGesture) {
+                        if (Math.abs(mDownX - x) > mTouchSlop
+                                || Math.abs(mDownY - y) > mTouchSlop) {
+                            mTrackGesture = false;
+                        }
+                    }
+                    break;
+                case MotionEvent.ACTION_UP:
+                    if (mTrackGesture) {
+                        mExpandClickListener.onClick(NotificationHeaderView.this);
+                    }
+                    break;
+            }
+            return mTrackGesture;
+        }
+
+        private boolean isInside(float x, float y) {
+            for (int i = 0; i < mTouchRects.size(); i++) {
+                Rect r = mTouchRects.get(i);
+                if (r.contains((int) x, (int) y)) {
+                    mDownX = x;
+                    mDownY = y;
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    private View getFirstChildNotGone() {
+        for (int i = 0; i < getChildCount(); i++) {
+            final View child = getChildAt(i);
+            if (child.getVisibility() != GONE) {
+                return child;
+            }
+        }
+        return this;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
index 9b52e04..f20ccd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
@@ -68,8 +68,6 @@
     private View mSubTextDivider;
     private ImageView mExpandButton;
     private ViewGroup mNotificationHeader;
-    private View.OnClickListener mExpandClickListener;
-    private HeaderTouchListener mHeaderTouchListener;
     private ProgressBar mProgressBar;
 
     protected NotificationTemplateViewWrapper(Context ctx, View view) {
@@ -98,15 +96,6 @@
         }
         mNotificationHeader = (ViewGroup) mView.findViewById(
                 com.android.internal.R.id.notification_header);
-        // Post to make sure the parent lays out its children before we get their bounds
-        mHeaderTouchListener = new HeaderTouchListener();
-        mExpandButton.post(new Runnable() {
-            @Override
-            public void run() {
-                // let's set up our touch regions
-                mHeaderTouchListener.bindTouchRects(mNotificationHeader, mIcon, mExpandButton);
-            }
-        });
         ArrayList<View> viewsToInvert = new ArrayList<>();
         if (mainColumn != null) {
             viewsToInvert.add(mainColumn);
@@ -299,8 +288,7 @@
     @Override
     public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {
         mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE);
-        mNotificationHeader.setOnTouchListener(expandable ? mHeaderTouchListener : null);
-        mExpandClickListener = onClickListener;
+        mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
     }
 
     private void updateGrayscaleMatrix(float intensity) {
@@ -322,91 +310,4 @@
                 (int) (gSource * (1f - t) + gTarget * t),
                 (int) (bSource * (1f - t) + bTarget * t));
     }
-
-    public class HeaderTouchListener implements View.OnTouchListener {
-
-        private final ArrayList<Rect> mTouchRects = new ArrayList<>();
-        private int mTouchSlop;
-        private boolean mTrackGesture;
-        private float mDownX;
-        private float mDownY;
-
-        public HeaderTouchListener() {
-        }
-
-        public void bindTouchRects(View parent, View icon, View expandButton) {
-            mTouchRects.clear();
-            addRectAroundViewView(icon);
-            addRectAroundViewView(expandButton);
-            addInBetweenRect(parent);
-            mTouchSlop = ViewConfiguration.get(parent.getContext()).getScaledTouchSlop();
-        }
-
-        private void addInBetweenRect(View parent) {
-            final Rect r = new Rect();
-            r.top = 0;
-            r.bottom = (int) (32 * parent.getResources().getDisplayMetrics().density);
-            Rect leftRect = mTouchRects.get(0);
-            r.left = leftRect.right;
-            Rect rightRect = mTouchRects.get(1);
-            r.right = rightRect.left;
-            mTouchRects.add(r);
-        }
-
-        private void addRectAroundViewView(View view) {
-            final Rect r = getRectAroundView(view);
-            mTouchRects.add(r);
-        }
-
-        private Rect getRectAroundView(View view) {
-            float size = 48 * view.getResources().getDisplayMetrics().density;
-            final Rect r = new Rect();
-            r.top = (int) ((view.getTop() + view.getBottom()) / 2.0f - size / 2.0f);
-            r.bottom = (int) (r.top + size);
-            r.left = (int) ((view.getLeft() + view.getRight()) / 2.0f - size / 2.0f);
-            r.right = (int) (r.left + size);
-            return r;
-        }
-
-        @Override
-        public boolean onTouch(View v, MotionEvent event) {
-            float x = event.getX();
-            float y = event.getY();
-            switch (event.getActionMasked() & MotionEvent.ACTION_MASK) {
-                case MotionEvent.ACTION_DOWN:
-                    mTrackGesture = false;
-                    if (isInside(x, y)) {
-                        mTrackGesture = true;
-                        return true;
-                    }
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                    if (mTrackGesture) {
-                        if (Math.abs(mDownX - x) > mTouchSlop
-                                || Math.abs(mDownY - y) > mTouchSlop) {
-                            mTrackGesture = false;
-                        }
-                    }
-                    break;
-                case MotionEvent.ACTION_UP:
-                    if (mTrackGesture) {
-                        mExpandClickListener.onClick(mNotificationHeader);
-                    }
-                    break;
-            }
-            return mTrackGesture;
-        }
-
-        private boolean isInside(float x, float y) {
-            for (int i = 0; i < mTouchRects.size(); i++) {
-                Rect r = mTouchRects.get(i);
-                if (r.contains((int) x, (int) y)) {
-                    mDownX = x;
-                    mDownY = y;
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
 }