OnScreenHint.java revision d8bccef54d490ce562e61fc907201da0c666314e
1/* 2 * Copyright (C) 2009 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 17package com.android.camera; 18 19import android.app.INotificationManager; 20import android.app.ITransientNotification; 21import android.content.Context; 22import android.content.res.Resources; 23import android.graphics.PixelFormat; 24import android.os.RemoteException; 25import android.os.Handler; 26import android.os.ServiceManager; 27import android.util.Log; 28import android.view.Gravity; 29import android.view.LayoutInflater; 30import android.view.View; 31import android.view.WindowManager; 32import android.widget.TextView; 33 34/** 35 * A on-screen hint is a view containing a little message for the user and will 36 * be shown on the screen continuously. This class helps you create and show 37 * those. 38 * 39 * <p> 40 * When the view is shown to the user, appears as a floating view over the 41 * application. 42 * <p> 43 * The easiest way to use this class is to call one of the static methods that 44 * constructs everything you need and returns a new OnScreenHint object. 45 */ 46public class OnScreenHint { 47 static final String TAG = "OnScreenHint"; 48 static final boolean localLOGV = false; 49 50 final Context mContext; 51 int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 52 int mX, mY; 53 float mHorizontalMargin; 54 float mVerticalMargin; 55 View mView; 56 View mNextView; 57 58 private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); 59 private WindowManager mWM; 60 private final Handler mHandler = new Handler(); 61 62 /** 63 * Construct an empty OnScreenHint object. You must call {@link #setView} before you 64 * can call {@link #show}. 65 * 66 * @param context The context to use. Usually your {@link android.app.Application} 67 * or {@link android.app.Activity} object. 68 */ 69 public OnScreenHint(Context context) { 70 mContext = context; 71 mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 72 mY = context.getResources().getDimensionPixelSize(R.dimen.hint_y_offset); 73 74 mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 75 mParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 76 mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 77 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 78 mParams.format = PixelFormat.TRANSLUCENT; 79 mParams.windowAnimations = R.style.Animation_OnScreenHint; 80 mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; 81 mParams.setTitle("OnScreenHint"); 82 } 83 84 /** 85 * Show the view on the screen. 86 */ 87 public void show() { 88 if (mNextView == null) { 89 throw new RuntimeException("setView must have been called"); 90 } 91 if (localLOGV) Log.v(TAG, "SHOW: " + this); 92 mHandler.post(mShow); 93 } 94 95 /** 96 * Close the view if it's showing. 97 */ 98 public void cancel() { 99 if (localLOGV) Log.v(TAG, "HIDE: " + this); 100 mHandler.post(mHide); 101 } 102 103 /** 104 * Set the view to show. 105 * @see #getView 106 */ 107 public void setView(View view) { 108 mNextView = view; 109 } 110 111 /** 112 * Return the view. 113 * @see #setView 114 */ 115 public View getView() { 116 return mNextView; 117 } 118 119 /** 120 * Set the margins of the view. 121 * 122 * @param horizontalMargin The horizontal margin, in percentage of the 123 * container width, between the container's edges and the 124 * notification 125 * @param verticalMargin The vertical margin, in percentage of the 126 * container height, between the container's edges and the 127 * notification 128 */ 129 public void setMargin(float horizontalMargin, float verticalMargin) { 130 mHorizontalMargin = horizontalMargin; 131 mVerticalMargin = verticalMargin; 132 } 133 134 /** 135 * Return the horizontal margin. 136 */ 137 public float getHorizontalMargin() { 138 return mHorizontalMargin; 139 } 140 141 /** 142 * Return the vertical margin. 143 */ 144 public float getVerticalMargin() { 145 return mVerticalMargin; 146 } 147 148 /** 149 * Set the location at which the notification should appear on the screen. 150 * @see android.view.Gravity 151 * @see #getGravity 152 */ 153 public void setGravity(int gravity, int xOffset, int yOffset) { 154 mGravity = gravity; 155 mX = xOffset; 156 mY = yOffset; 157 } 158 159 /** 160 * Get the location at which the notification should appear on the screen. 161 * @see android.view.Gravity 162 * @see #getGravity 163 */ 164 public int getGravity() { 165 return mGravity; 166 } 167 168 /** 169 * Return the X offset in pixels to apply to the gravity's location. 170 */ 171 public int getXOffset() { 172 return mX; 173 } 174 175 /** 176 * Return the Y offset in pixels to apply to the gravity's location. 177 */ 178 public int getYOffset() { 179 return mY; 180 } 181 182 /** 183 * Make a standard hint that just contains a text view. 184 * 185 * @param context The context to use. Usually your {@link android.app.Application} 186 * or {@link android.app.Activity} object. 187 * @param text The text to show. Can be formatted text. 188 * 189 */ 190 public static OnScreenHint makeText(Context context, CharSequence text) { 191 OnScreenHint result = new OnScreenHint(context); 192 193 LayoutInflater inflate = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 194 View v = inflate.inflate(R.layout.on_screen_hint, null); 195 TextView tv = (TextView)v.findViewById(R.id.message); 196 tv.setText(text); 197 198 result.mNextView = v; 199 200 return result; 201 } 202 203 /** 204 * Make a standard hint that just contains a text view with the text from a resource. 205 * 206 * @param context The context to use. Usually your {@link android.app.Application} 207 * or {@link android.app.Activity} object. 208 * @param resId The resource id of the string resource to use. Can be formatted text. 209 * 210 * @throws Resources.NotFoundException if the resource can't be found. 211 */ 212 public static OnScreenHint makeText(Context context, int resId) 213 throws Resources.NotFoundException { 214 return makeText(context, context.getResources().getText(resId)); 215 } 216 217 /** 218 * Update the text in a OnScreenHint that was previously created using one of the makeText() methods. 219 * @param resId The new text for the OnScreenHint. 220 */ 221 public void setText(int resId) { 222 setText(mContext.getText(resId)); 223 } 224 225 /** 226 * Update the text in a OnScreenHint that was previously created using one of the makeText() methods. 227 * @param s The new text for the OnScreenHint. 228 */ 229 public void setText(CharSequence s) { 230 if (mNextView == null) { 231 throw new RuntimeException("This OnScreenHint was not created with OnScreenHint.makeText()"); 232 } 233 TextView tv = (TextView) mNextView.findViewById(R.id.message); 234 if (tv == null) { 235 throw new RuntimeException("This OnScreenHint was not created with OnScreenHint.makeText()"); 236 } 237 tv.setText(s); 238 } 239 240 private synchronized void handleShow() { 241 if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView 242 + " mNextView=" + mNextView); 243 if (mView != mNextView) { 244 // remove the old view if necessary 245 handleHide(); 246 mView = mNextView; 247 final int gravity = mGravity; 248 mParams.gravity = gravity; 249 if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { 250 mParams.horizontalWeight = 1.0f; 251 } 252 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { 253 mParams.verticalWeight = 1.0f; 254 } 255 mParams.x = mX; 256 mParams.y = mY; 257 mParams.verticalMargin = mVerticalMargin; 258 mParams.horizontalMargin = mHorizontalMargin; 259 if (mView.getParent() != null) { 260 if (localLOGV) Log.v( 261 TAG, "REMOVE! " + mView + " in " + this); 262 mWM.removeView(mView); 263 } 264 if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this); 265 mWM.addView(mView, mParams); 266 } 267 } 268 269 private synchronized void handleHide() { 270 if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView); 271 if (mView != null) { 272 // note: checking parent() just to make sure the view has 273 // been added... i have seen cases where we get here when 274 // the view isn't yet added, so let's try not to crash. 275 if (mView.getParent() != null) { 276 if (localLOGV) Log.v( 277 TAG, "REMOVE! " + mView + " in " + this); 278 mWM.removeView(mView); 279 } 280 mView = null; 281 } 282 } 283 284 private Runnable mShow = new Runnable() { 285 public void run() { 286 handleShow(); 287 } 288 }; 289 290 private Runnable mHide = new Runnable() { 291 public void run() { 292 handleHide(); 293 } 294 }; 295} 296 297