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