1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/*
2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * you may not use this file except in compliance with the License.
6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * You may obtain a copy of the License at
7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * See the License for the specific language governing permissions and
14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * limitations under the License.
15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */
16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpackage com.android.camera;
18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
19b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context;
20b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.PixelFormat;
21b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler;
22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Gravity;
23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.LayoutInflater;
24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View;
25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager;
26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.TextView;
27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/**
29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * A on-screen hint is a view containing a little message for the user and will
30b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * be shown on the screen continuously.  This class helps you create and show
31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * those.
32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project *
33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * <p>
34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * When the view is shown to the user, appears as a floating view over the
35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * application.
36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * <p>
37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * The easiest way to use this class is to call one of the static methods that
38271b3095b9f763421c0547109da9de774795072dChih-Chung Chang * constructs everything you need and returns a new {@code OnScreenHint} object.
39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */
40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class OnScreenHint {
41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    static final String TAG = "OnScreenHint";
42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    int mX, mY;
45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    float mHorizontalMargin;
46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    float mVerticalMargin;
47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mView;
48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    View mNextView;
49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
50b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang    private final WindowManager.LayoutParams mParams =
51b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            new WindowManager.LayoutParams();
52bbc560b5216bbb2e3028020e426ce6a6e0e5df08Owen Lin    private final WindowManager mWM;
53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private final Handler mHandler = new Handler();
54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
56913f3784d368a5e11fee5d5db2c355ef832685daWu-cheng Li     * Construct an empty OnScreenHint object.
57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     *
58b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * @param context  The context to use.  Usually your
59b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Application} or
60b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Activity} object.
61b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
62913f3784d368a5e11fee5d5db2c355ef832685daWu-cheng Li    private OnScreenHint(Context context) {
63b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
64b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang        mY = context.getResources().getDimensionPixelSize(
65b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                R.dimen.hint_y_offset);
66b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
67b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
68b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
69b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
71b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.format = PixelFormat.TRANSLUCENT;
72b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.windowAnimations = R.style.Animation_OnScreenHint;
73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mParams.setTitle("OnScreenHint");
75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
76b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Show the view on the screen.
79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void show() {
81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mNextView == null) {
82913f3784d368a5e11fee5d5db2c355ef832685daWu-cheng Li            throw new RuntimeException("View is not initialized");
83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.post(mShow);
85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
86b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
87b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
88b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Close the view if it's showing.
89b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void cancel() {
91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        mHandler.post(mHide);
92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * Make a standard hint that just contains a text view.
96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     *
97b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * @param context  The context to use.  Usually your
98b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Application} or
99b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     *                 {@link android.app.Activity} object.
100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @param text     The text to show.  Can be formatted text.
101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     *
102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public static OnScreenHint makeText(Context context, CharSequence text) {
104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        OnScreenHint result = new OnScreenHint(context);
105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
106b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang        LayoutInflater inflate =
107b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                (LayoutInflater) context.getSystemService(
108b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                Context.LAYOUT_INFLATER_SERVICE);
109b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        View v = inflate.inflate(R.layout.on_screen_hint, null);
110b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang        TextView tv = (TextView) v.findViewById(R.id.message);
111b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        tv.setText(text);
112b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        result.mNextView = v;
114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        return result;
116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    /**
119b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * Update the text in a OnScreenHint that was previously created using one
120b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang     * of the makeText() methods.
121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     * @param s The new text for the OnScreenHint.
122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project     */
123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    public void setText(CharSequence s) {
124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mNextView == null) {
125b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            throw new RuntimeException("This OnScreenHint was not "
126b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    + "created with OnScreenHint.makeText()");
127b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
128b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        TextView tv = (TextView) mNextView.findViewById(R.id.message);
129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (tv == null) {
130b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            throw new RuntimeException("This OnScreenHint was not "
131b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    + "created with OnScreenHint.makeText()");
132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        tv.setText(s);
134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
135b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private synchronized void handleShow() {
137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mView != mNextView) {
138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // remove the old view if necessary
139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            handleHide();
140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mView = mNextView;
141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            final int gravity = mGravity;
142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.gravity = gravity;
143b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK)
144b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    == Gravity.FILL_HORIZONTAL) {
145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mParams.horizontalWeight = 1.0f;
146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
147b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK)
148b8af1c56debb56bad213e39245c79915c9dfece4Chih-Chung Chang                    == Gravity.FILL_VERTICAL) {
149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mParams.verticalWeight = 1.0f;
150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.x = mX;
152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.y = mY;
153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.verticalMargin = mVerticalMargin;
154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mParams.horizontalMargin = mHorizontalMargin;
155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mView.getParent() != null) {
156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mWM.removeView(mView);
157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mWM.addView(mView, mParams);
159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    private synchronized void handleHide() {
163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        if (mView != null) {
164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // note: checking parent() just to make sure the view has
165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // been added...  i have seen cases where we get here when
166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            // the view isn't yet added, so let's try not to crash.
167b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            if (mView.getParent() != null) {
168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project                mWM.removeView(mView);
169b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            }
170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            mView = null;
171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    }
173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
174bbc560b5216bbb2e3028020e426ce6a6e0e5df08Owen Lin    private final Runnable mShow = new Runnable() {
175913f3784d368a5e11fee5d5db2c355ef832685daWu-cheng Li        @Override
176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void run() {
177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            handleShow();
178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
181bbc560b5216bbb2e3028020e426ce6a6e0e5df08Owen Lin    private final Runnable mHide = new Runnable() {
182913f3784d368a5e11fee5d5db2c355ef832685daWu-cheng Li        @Override
183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        public void run() {
184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project            handleHide();
185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project        }
186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project    };
187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project}
188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project
189