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 17 package com.android.camera; 18 19 import android.content.Context; 20 import android.graphics.PixelFormat; 21 import android.os.Handler; 22 import android.view.Gravity; 23 import android.view.LayoutInflater; 24 import android.view.View; 25 import android.view.WindowManager; 26 import android.widget.TextView; 27 28 import com.android.camera.R; 29 30 /** 31 * A on-screen hint is a view containing a little message for the user and will 32 * be shown on the screen continuously. This class helps you create and show 33 * those. 34 * 35 * <p> 36 * When the view is shown to the user, appears as a floating view over the 37 * application. 38 * <p> 39 * The easiest way to use this class is to call one of the static methods that 40 * constructs everything you need and returns a new {@code OnScreenHint} object. 41 */ 42 public class OnScreenHint { 43 static final String TAG = "OnScreenHint"; 44 static final boolean LOCAL_LOGV = false; 45 46 int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 47 int mX, mY; 48 float mHorizontalMargin; 49 float mVerticalMargin; 50 View mView; 51 View mNextView; 52 53 private final WindowManager.LayoutParams mParams = 54 new WindowManager.LayoutParams(); 55 private final WindowManager mWM; 56 private final Handler mHandler = new Handler(); 57 58 /** 59 * Construct an empty OnScreenHint object. You must call {@link #setView} 60 * before you can call {@link #show}. 61 * 62 * @param context The context to use. Usually your 63 * {@link android.app.Application} or 64 * {@link android.app.Activity} object. 65 */ 66 public OnScreenHint(Context context) { 67 mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 68 mY = context.getResources().getDimensionPixelSize( 69 R.dimen.hint_y_offset); 70 71 mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 72 mParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 73 mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 74 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 75 mParams.format = PixelFormat.TRANSLUCENT; 76 mParams.windowAnimations = R.style.Animation_OnScreenHint; 77 mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; 78 mParams.setTitle("OnScreenHint"); 79 } 80 81 /** 82 * Show the view on the screen. 83 */ 84 public void show() { 85 if (mNextView == null) { 86 throw new RuntimeException("setView must have been called"); 87 } 88 mHandler.post(mShow); 89 } 90 91 /** 92 * Close the view if it's showing. 93 */ 94 public void cancel() { 95 mHandler.post(mHide); 96 } 97 98 /** 99 * Make a standard hint that just contains a text view. 100 * 101 * @param context The context to use. Usually your 102 * {@link android.app.Application} or 103 * {@link android.app.Activity} object. 104 * @param text The text to show. Can be formatted text. 105 * 106 */ 107 public static OnScreenHint makeText(Context context, CharSequence text) { 108 OnScreenHint result = new OnScreenHint(context); 109 110 LayoutInflater inflate = 111 (LayoutInflater) context.getSystemService( 112 Context.LAYOUT_INFLATER_SERVICE); 113 View v = inflate.inflate(R.layout.on_screen_hint, null); 114 TextView tv = (TextView) v.findViewById(R.id.message); 115 tv.setText(text); 116 117 result.mNextView = v; 118 119 return result; 120 } 121 122 /** 123 * Update the text in a OnScreenHint that was previously created using one 124 * of the makeText() methods. 125 * @param s The new text for the OnScreenHint. 126 */ 127 public void setText(CharSequence s) { 128 if (mNextView == null) { 129 throw new RuntimeException("This OnScreenHint was not " 130 + "created with OnScreenHint.makeText()"); 131 } 132 TextView tv = (TextView) mNextView.findViewById(R.id.message); 133 if (tv == null) { 134 throw new RuntimeException("This OnScreenHint was not " 135 + "created with OnScreenHint.makeText()"); 136 } 137 tv.setText(s); 138 } 139 140 private synchronized void handleShow() { 141 if (mView != mNextView) { 142 // remove the old view if necessary 143 handleHide(); 144 mView = mNextView; 145 final int gravity = mGravity; 146 mParams.gravity = gravity; 147 if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) 148 == Gravity.FILL_HORIZONTAL) { 149 mParams.horizontalWeight = 1.0f; 150 } 151 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) 152 == Gravity.FILL_VERTICAL) { 153 mParams.verticalWeight = 1.0f; 154 } 155 mParams.x = mX; 156 mParams.y = mY; 157 mParams.verticalMargin = mVerticalMargin; 158 mParams.horizontalMargin = mHorizontalMargin; 159 if (mView.getParent() != null) { 160 mWM.removeView(mView); 161 } 162 mWM.addView(mView, mParams); 163 } 164 } 165 166 private synchronized void handleHide() { 167 if (mView != null) { 168 // note: checking parent() just to make sure the view has 169 // been added... i have seen cases where we get here when 170 // the view isn't yet added, so let's try not to crash. 171 if (mView.getParent() != null) { 172 mWM.removeView(mView); 173 } 174 mView = null; 175 } 176 } 177 178 private final Runnable mShow = new Runnable() { 179 public void run() { 180 handleShow(); 181 } 182 }; 183 184 private final Runnable mHide = new Runnable() { 185 public void run() { 186 handleHide(); 187 } 188 }; 189 } 190 191