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