/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java

https://github.com/aizuzi/platform_frameworks_base · Java · 285 lines · 207 code · 49 blank · 29 comment · 31 complexity · e6ec3f9a2f07d0ebb218f59389c9e9dc MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.android.systemui.statusbar.policy;
  17. import android.animation.LayoutTransition;
  18. import android.animation.ValueAnimator;
  19. import android.content.Context;
  20. import android.content.res.Configuration;
  21. import android.graphics.Rect;
  22. import android.util.AttributeSet;
  23. import android.util.Log;
  24. import android.view.MotionEvent;
  25. import android.view.View;
  26. import android.view.ViewConfiguration;
  27. import android.view.ViewGroup;
  28. import android.widget.LinearLayout;
  29. import com.android.systemui.ExpandHelper;
  30. import com.android.systemui.R;
  31. import com.android.systemui.SwipeHelper;
  32. import com.android.systemui.statusbar.ExpandableNotificationRow;
  33. import com.android.systemui.statusbar.NotificationData;
  34. import java.util.HashMap;
  35. public class NotificationRowLayout
  36. extends LinearLayout
  37. implements SwipeHelper.Callback, ExpandHelper.Callback
  38. {
  39. private static final String TAG = "NotificationRowLayout";
  40. private static final boolean DEBUG = false;
  41. private static final boolean SLOW_ANIMATIONS = DEBUG;
  42. private static final int APPEAR_ANIM_LEN = SLOW_ANIMATIONS ? 5000 : 250;
  43. private static final int DISAPPEAR_ANIM_LEN = APPEAR_ANIM_LEN;
  44. boolean mAnimateBounds = true;
  45. Rect mTmpRect = new Rect();
  46. HashMap<View, ValueAnimator> mAppearingViews = new HashMap<View, ValueAnimator>();
  47. HashMap<View, ValueAnimator> mDisappearingViews = new HashMap<View, ValueAnimator>();
  48. private SwipeHelper mSwipeHelper;
  49. private OnSizeChangedListener mOnSizeChangedListener;
  50. // Flag set during notification removal animation to avoid causing too much work until
  51. // animation is done
  52. boolean mRemoveViews = true;
  53. private LayoutTransition mRealLayoutTransition;
  54. public NotificationRowLayout(Context context, AttributeSet attrs) {
  55. this(context, attrs, 0);
  56. }
  57. public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
  58. super(context, attrs, defStyle);
  59. mRealLayoutTransition = new LayoutTransition();
  60. mRealLayoutTransition.setAnimateParentHierarchy(true);
  61. setLayoutTransitionsEnabled(true);
  62. setOrientation(LinearLayout.VERTICAL);
  63. if (DEBUG) {
  64. setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
  65. @Override
  66. public void onChildViewAdded(View parent, View child) {
  67. Log.d(TAG, "view added: " + child + "; new count: " + getChildCount());
  68. }
  69. @Override
  70. public void onChildViewRemoved(View parent, View child) {
  71. Log.d(TAG, "view removed: " + child + "; new count: " + (getChildCount() - 1));
  72. }
  73. });
  74. setBackgroundColor(0x80FF8000);
  75. }
  76. float densityScale = getResources().getDisplayMetrics().density;
  77. float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
  78. mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
  79. }
  80. public void setLongPressListener(View.OnLongClickListener listener) {
  81. mSwipeHelper.setLongPressListener(listener);
  82. }
  83. public void setOnSizeChangedListener(OnSizeChangedListener l) {
  84. mOnSizeChangedListener = l;
  85. }
  86. @Override
  87. public void onWindowFocusChanged(boolean hasWindowFocus) {
  88. super.onWindowFocusChanged(hasWindowFocus);
  89. if (!hasWindowFocus) {
  90. mSwipeHelper.removeLongPressCallback();
  91. }
  92. }
  93. public void setAnimateBounds(boolean anim) {
  94. mAnimateBounds = anim;
  95. }
  96. private void logLayoutTransition() {
  97. Log.v(TAG, "layout " +
  98. (mRealLayoutTransition.isChangingLayout() ? "is " : "is not ") +
  99. "in transition and animations " +
  100. (mRealLayoutTransition.isRunning() ? "are " : "are not ") +
  101. "running.");
  102. }
  103. @Override
  104. public boolean onInterceptTouchEvent(MotionEvent ev) {
  105. if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
  106. if (DEBUG) logLayoutTransition();
  107. return mSwipeHelper.onInterceptTouchEvent(ev) ||
  108. super.onInterceptTouchEvent(ev);
  109. }
  110. @Override
  111. public boolean onTouchEvent(MotionEvent ev) {
  112. if (DEBUG) Log.v(TAG, "onTouchEvent()");
  113. if (DEBUG) logLayoutTransition();
  114. return mSwipeHelper.onTouchEvent(ev) ||
  115. super.onTouchEvent(ev);
  116. }
  117. public boolean canChildBeDismissed(View v) {
  118. final View veto = v.findViewById(R.id.veto);
  119. return (veto != null && veto.getVisibility() != View.GONE);
  120. }
  121. public boolean canChildBeExpanded(View v) {
  122. return v instanceof ExpandableNotificationRow
  123. && ((ExpandableNotificationRow) v).isExpandable();
  124. }
  125. public void setUserExpandedChild(View v, boolean userExpanded) {
  126. if (v instanceof ExpandableNotificationRow) {
  127. ((ExpandableNotificationRow) v).setUserExpanded(userExpanded);
  128. }
  129. }
  130. public void setUserLockedChild(View v, boolean userLocked) {
  131. if (v instanceof ExpandableNotificationRow) {
  132. ((ExpandableNotificationRow) v).setUserLocked(userLocked);
  133. }
  134. }
  135. public void onChildDismissed(View v) {
  136. if (DEBUG) Log.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
  137. final View veto = v.findViewById(R.id.veto);
  138. if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
  139. veto.performClick();
  140. }
  141. }
  142. public void onBeginDrag(View v) {
  143. // We need to prevent the surrounding ScrollView from intercepting us now;
  144. // the scroll position will be locked while we swipe
  145. requestDisallowInterceptTouchEvent(true);
  146. }
  147. public void onDragCancelled(View v) {
  148. }
  149. public View getChildAtPosition(MotionEvent ev) {
  150. return getChildAtPosition(ev.getX(), ev.getY());
  151. }
  152. public View getChildAtRawPosition(float touchX, float touchY) {
  153. int[] location = new int[2];
  154. getLocationOnScreen(location);
  155. return getChildAtPosition((float) (touchX - location[0]), (float) (touchY - location[1]));
  156. }
  157. public View getChildAtPosition(float touchX, float touchY) {
  158. // find the view under the pointer, accounting for GONE views
  159. final int count = getChildCount();
  160. int y = 0;
  161. int childIdx = 0;
  162. View slidingChild;
  163. for (; childIdx < count; childIdx++) {
  164. slidingChild = getChildAt(childIdx);
  165. if (slidingChild.getVisibility() == GONE) {
  166. continue;
  167. }
  168. y += slidingChild.getMeasuredHeight();
  169. if (touchY < y) return slidingChild;
  170. }
  171. return null;
  172. }
  173. public View getChildContentView(View v) {
  174. return v;
  175. }
  176. @Override
  177. protected void onConfigurationChanged(Configuration newConfig) {
  178. super.onConfigurationChanged(newConfig);
  179. float densityScale = getResources().getDisplayMetrics().density;
  180. mSwipeHelper.setDensityScale(densityScale);
  181. float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
  182. mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
  183. }
  184. /**
  185. * Sets a flag to tell us whether to actually remove views. Removal is delayed by setting this
  186. * to false during some animations to smooth out performance. Callers should restore the
  187. * flag to true after the animation is done, and then they should make sure that the views
  188. * get removed properly.
  189. */
  190. public void setViewRemoval(boolean removeViews) {
  191. if (DEBUG) Log.v(TAG, "setViewRemoval: " + removeViews);
  192. mRemoveViews = removeViews;
  193. }
  194. // Suppress layout transitions for a little while.
  195. public void setLayoutTransitionsEnabled(boolean b) {
  196. if (b) {
  197. setLayoutTransition(mRealLayoutTransition);
  198. } else {
  199. if (mRealLayoutTransition.isRunning()) {
  200. mRealLayoutTransition.cancel();
  201. }
  202. setLayoutTransition(null);
  203. }
  204. }
  205. public void dismissRowAnimated(View child) {
  206. dismissRowAnimated(child, 0);
  207. }
  208. public void dismissRowAnimated(View child, int vel) {
  209. mSwipeHelper.dismissChild(child, vel);
  210. }
  211. @Override
  212. public void onFinishInflate() {
  213. super.onFinishInflate();
  214. if (DEBUG) setWillNotDraw(false);
  215. }
  216. @Override
  217. public void onDraw(android.graphics.Canvas c) {
  218. super.onDraw(c);
  219. if (DEBUG) logLayoutTransition();
  220. if (DEBUG) {
  221. //Log.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
  222. // + getMeasuredHeight() + "px");
  223. c.save();
  224. c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6,
  225. android.graphics.Region.Op.DIFFERENCE);
  226. c.drawColor(0xFFFF8000);
  227. c.restore();
  228. }
  229. }
  230. @Override
  231. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  232. if (mOnSizeChangedListener != null) {
  233. mOnSizeChangedListener.onSizeChanged(this, w, h, oldw, oldh);
  234. }
  235. }
  236. }