18872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/* 28872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Copyright (C) 2009 The Android Open Source Project 38872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * 48872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License"); 58872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * you may not use this file except in compliance with the License. 68872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * You may obtain a copy of the License at 78872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * 88872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * http://www.apache.org/licenses/LICENSE-2.0 98872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * 108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Unless required by applicable law or agreed to in writing, software 118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS, 128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * See the License for the specific language governing permissions and 148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * limitations under the License. 158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */ 168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpackage com.android.camera; 188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 19e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newbergerimport android.app.Activity; 208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.Context; 218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.graphics.PixelFormat; 228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.os.Handler; 238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.Gravity; 248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.LayoutInflater; 258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.View; 268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.WindowManager; 278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.widget.TextView; 288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 295596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 308e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport com.android.camera2.R; 3154987e8d3af88214ce4f3aed0b5c4e9ded5b1392John Reck 328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/** 338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * A on-screen hint is a view containing a little message for the user and will 348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * be shown on the screen continuously. This class helps you create and show 358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * those. 368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * 378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * <p> 388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * When the view is shown to the user, appears as a floating view over the 398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * application. 408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * <p> 418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * The easiest way to use this class is to call one of the static methods that 428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * constructs everything you need and returns a new {@code OnScreenHint} object. 438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */ 448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpublic class OnScreenHint { 455596b4c902dcb685928b43678f428746ca5ffd08Angus Kong static final Log.Tag TAG = new Log.Tag("OnScreenHint"); 468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb int mX, mY; 498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb float mHorizontalMargin; 508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb float mVerticalMargin; 518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb View mView; 528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb View mNextView; 538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb private final WindowManager.LayoutParams mParams = 558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb new WindowManager.LayoutParams(); 568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb private final WindowManager mWM; 578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb private final Handler mHandler = new Handler(); 588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb /** 608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Construct an empty OnScreenHint object. 618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * 628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * @param context The context to use. Usually your 638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * {@link android.app.Application} or 648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * {@link android.app.Activity} object. 658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */ 66e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger private OnScreenHint(Activity activity) { 67e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger mWM = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE); 68e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger mY = activity.getResources().getDimensionPixelSize( 698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb R.dimen.hint_y_offset); 708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.format = PixelFormat.TRANSLUCENT; 768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.windowAnimations = R.style.Animation_OnScreenHint; 778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; 788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.setTitle("OnScreenHint"); 798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb /** 828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Show the view on the screen. 838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */ 848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb public void show() { 858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if (mNextView == null) { 868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb throw new RuntimeException("View is not initialized"); 878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mHandler.post(mShow); 898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb /** 928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Close the view if it's showing. 938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */ 948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb public void cancel() { 958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mHandler.post(mHide); 968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb /** 998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Make a standard hint that just contains a text view. 1008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * 1018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * @param context The context to use. Usually your 1028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * {@link android.app.Application} or 1038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * {@link android.app.Activity} object. 1048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * @param text The text to show. Can be formatted text. 1058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * 1068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */ 107e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger public static OnScreenHint makeText(Activity activity, CharSequence text) { 108e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger OnScreenHint result = new OnScreenHint(activity); 1098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb LayoutInflater inflate = 111e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger (LayoutInflater) activity.getSystemService( 1128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb Context.LAYOUT_INFLATER_SERVICE); 1138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb View v = inflate.inflate(R.layout.on_screen_hint, null); 1148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb TextView tv = (TextView) v.findViewById(R.id.message); 1158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb tv.setText(text); 1168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb result.mNextView = v; 1188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb return result; 1208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb /** 1238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Update the text in a OnScreenHint that was previously created using one 1248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * of the makeText() methods. 1258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * @param s The new text for the OnScreenHint. 1268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */ 1278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb public void setText(CharSequence s) { 1288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if (mNextView == null) { 1298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb throw new RuntimeException("This OnScreenHint was not " 1308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb + "created with OnScreenHint.makeText()"); 1318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb TextView tv = (TextView) mNextView.findViewById(R.id.message); 1338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if (tv == null) { 1348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb throw new RuntimeException("This OnScreenHint was not " 1358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb + "created with OnScreenHint.makeText()"); 1368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb tv.setText(s); 1388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb private synchronized void handleShow() { 1418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if (mView != mNextView) { 1428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb // remove the old view if necessary 1438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb handleHide(); 1448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mView = mNextView; 1458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb final int gravity = mGravity; 1468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.gravity = gravity; 1478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) 1488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb == Gravity.FILL_HORIZONTAL) { 1498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.horizontalWeight = 1.0f; 1508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) 1528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb == Gravity.FILL_VERTICAL) { 1538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.verticalWeight = 1.0f; 1548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.x = mX; 1568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.y = mY; 1578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.verticalMargin = mVerticalMargin; 1588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mParams.horizontalMargin = mHorizontalMargin; 1598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if (mView.getParent() != null) { 1608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mWM.removeView(mView); 1618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mWM.addView(mView, mParams); 1638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb private synchronized void handleHide() { 1678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if (mView != null) { 1688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb // note: checking parent() just to make sure the view has 1698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb // been added... i have seen cases where we get here when 1708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb // the view isn't yet added, so let's try not to crash. 1718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb if (mView.getParent() != null) { 1728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mWM.removeView(mView); 1738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb mView = null; 1758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb private final Runnable mShow = new Runnable() { 1798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb @Override 1808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb public void run() { 1818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb handleShow(); 1828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb }; 1848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb 1858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb private final Runnable mHide = new Runnable() { 1868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb @Override 1878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb public void run() { 1888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb handleHide(); 1898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb } 1908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb }; 1918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb} 192