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