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.app.Activity; 20 import android.content.Context; 21 import android.graphics.PixelFormat; 22 import android.os.Handler; 23 import android.view.Gravity; 24 import android.view.LayoutInflater; 25 import android.view.View; 26 import android.view.WindowManager; 27 import android.widget.TextView; 28 29 import com.android.camera.debug.Log; 30 import com.android.camera2.R; 31 32 /** 33 * A on-screen hint is a view containing a little message for the user and will 34 * be shown on the screen continuously. This class helps you create and show 35 * those. 36 * 37 * <p> 38 * When the view is shown to the user, appears as a floating view over the 39 * application. 40 * <p> 41 * The easiest way to use this class is to call one of the static methods that 42 * constructs everything you need and returns a new {@code OnScreenHint} object. 43 */ 44 public class OnScreenHint { 45 static final Log.Tag TAG = new Log.Tag("OnScreenHint"); 46 47 int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 48 int mX, mY; 49 float mHorizontalMargin; 50 float mVerticalMargin; 51 View mView; 52 View mNextView; 53 54 private final WindowManager.LayoutParams mParams = 55 new WindowManager.LayoutParams(); 56 private final WindowManager mWM; 57 private final Handler mHandler = new Handler(); 58 59 /** 60 * Construct an empty OnScreenHint object. 61 * 62 * @param context The context to use. Usually your 63 * {@link android.app.Application} or 64 * {@link android.app.Activity} object. 65 */ 66 private OnScreenHint(Activity activity) { 67 mWM = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE); 68 mY = activity.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("View is not initialized"); 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(Activity activity, CharSequence text) { 108 OnScreenHint result = new OnScreenHint(activity); 109 110 LayoutInflater inflate = 111 (LayoutInflater) activity.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 @Override 180 public void run() { 181 handleShow(); 182 } 183 }; 184 185 private final Runnable mHide = new Runnable() { 186 @Override 187 public void run() { 188 handleHide(); 189 } 190 }; 191 } 192