blob: 2f2c906f7c1306f3e69c6e442dad1da126f461c0 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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 android.view;
18
Christopher Tatea53146c2010-09-07 11:57:52 -070019import android.content.ClipData;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.Context;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080021import android.content.res.Configuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.res.Resources;
23import android.content.res.TypedArray;
24import android.graphics.Bitmap;
Adam Powell2b342f02010-08-18 18:14:13 -070025import android.graphics.Camera;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.graphics.Canvas;
Philip Milne1557fd72012-04-04 23:41:34 -070027import android.graphics.Insets;
Mike Cleronf116bf82009-09-27 19:14:12 -070028import android.graphics.Interpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.graphics.LinearGradient;
30import android.graphics.Matrix;
31import android.graphics.Paint;
32import android.graphics.PixelFormat;
svetoslavganov75986cf2009-05-14 22:28:01 -070033import android.graphics.Point;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.graphics.PorterDuff;
35import android.graphics.PorterDuffXfermode;
36import android.graphics.Rect;
Adam Powell6e346362010-07-23 10:18:23 -070037import android.graphics.RectF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.graphics.Region;
39import android.graphics.Shader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.graphics.drawable.ColorDrawable;
41import android.graphics.drawable.Drawable;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070042import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.Handler;
44import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.os.Parcel;
46import android.os.Parcelable;
47import android.os.RemoteException;
48import android.os.SystemClock;
Philip Milne10ca24a2012-04-23 15:38:27 -070049import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.util.AttributeSet;
Doug Feltcb3791202011-07-07 11:57:48 -070051import android.util.FloatProperty;
52import android.util.LocaleUtil;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import android.util.Log;
Romain Guyd928d682009-03-31 17:52:16 -070054import android.util.Pool;
svetoslavganov75986cf2009-05-14 22:28:01 -070055import android.util.Poolable;
Romain Guyd928d682009-03-31 17:52:16 -070056import android.util.PoolableManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070057import android.util.Pools;
Doug Feltcb3791202011-07-07 11:57:48 -070058import android.util.Property;
svetoslavganov75986cf2009-05-14 22:28:01 -070059import android.util.SparseArray;
Jeff Brown33bbfd22011-02-24 20:55:35 -080060import android.util.TypedValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.view.ContextMenu.ContextMenuInfo;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -070062import android.view.AccessibilityIterators.TextSegmentIterator;
63import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
64import android.view.AccessibilityIterators.WordTextSegmentIterator;
65import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
svetoslavganov75986cf2009-05-14 22:28:01 -070066import android.view.accessibility.AccessibilityEvent;
67import android.view.accessibility.AccessibilityEventSource;
68import android.view.accessibility.AccessibilityManager;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070069import android.view.accessibility.AccessibilityNodeInfo;
Svetoslav Ganov02107852011-10-03 17:06:56 -070070import android.view.accessibility.AccessibilityNodeProvider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.view.animation.Animation;
Mike Cleron3ecd58c2009-09-28 11:39:02 -070072import android.view.animation.AnimationUtils;
Chet Haase64a48c12012-02-13 16:33:29 -080073import android.view.animation.Transformation;
svetoslavganov75986cf2009-05-14 22:28:01 -070074import android.view.inputmethod.EditorInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.view.inputmethod.InputConnection;
76import android.view.inputmethod.InputMethodManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.widget.ScrollBarDrawable;
78
Romain Guy1ef3fdb2011-09-09 15:30:30 -070079import static android.os.Build.VERSION_CODES.*;
Philip Milne6c8ea062012-04-03 17:38:43 -070080import static java.lang.Math.max;
Romain Guy1ef3fdb2011-09-09 15:30:30 -070081
Doug Feltcb3791202011-07-07 11:57:48 -070082import com.android.internal.R;
83import com.android.internal.util.Predicate;
84import com.android.internal.view.menu.MenuBuilder;
85
Christopher Tatea0374192010-10-05 13:06:41 -070086import java.lang.ref.WeakReference;
svetoslavganov75986cf2009-05-14 22:28:01 -070087import java.lang.reflect.InvocationTargetException;
88import java.lang.reflect.Method;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import java.util.ArrayList;
90import java.util.Arrays;
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070091import java.util.Locale;
Adam Powell4afd62b2011-02-18 15:02:18 -080092import java.util.concurrent.CopyOnWriteArrayList;
Adam Powella9108a22012-07-18 11:18:09 -070093import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094
95/**
96 * <p>
97 * This class represents the basic building block for user interface components. A View
98 * occupies a rectangular area on the screen and is responsible for drawing and
99 * event handling. View is the base class for <em>widgets</em>, which are
Romain Guy8506ab42009-06-11 17:35:47 -0700100 * used to create interactive UI components (buttons, text fields, etc.). The
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
102 * are invisible containers that hold other Views (or other ViewGroups) and define
103 * their layout properties.
104 * </p>
105 *
Joe Fernandezb54e7a32011-10-03 15:09:50 -0700106 * <div class="special reference">
107 * <h3>Developer Guides</h3>
108 * <p>For information about using this class to develop your application's user interface,
109 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 * </div>
Romain Guy8506ab42009-06-11 17:35:47 -0700111 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 * <a name="Using"></a>
113 * <h3>Using Views</h3>
114 * <p>
115 * All of the views in a window are arranged in a single tree. You can add views
116 * either from code or by specifying a tree of views in one or more XML layout
117 * files. There are many specialized subclasses of views that act as controls or
118 * are capable of displaying text, images, or other content.
119 * </p>
120 * <p>
121 * Once you have created a tree of views, there are typically a few types of
122 * common operations you may wish to perform:
123 * <ul>
124 * <li><strong>Set properties:</strong> for example setting the text of a
125 * {@link android.widget.TextView}. The available properties and the methods
126 * that set them will vary among the different subclasses of views. Note that
127 * properties that are known at build time can be set in the XML layout
128 * files.</li>
129 * <li><strong>Set focus:</strong> The framework will handled moving focus in
130 * response to user input. To force focus to a specific view, call
131 * {@link #requestFocus}.</li>
132 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
133 * that will be notified when something interesting happens to the view. For
134 * example, all views will let you set a listener to be notified when the view
135 * gains or loses focus. You can register such a listener using
Romain Guy5c22a8c2011-05-13 11:48:45 -0700136 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
Philip Milne6c8ea062012-04-03 17:38:43 -0700137 * Other view subclasses offer more specialized listeners. For example, a Button
Romain Guy5c22a8c2011-05-13 11:48:45 -0700138 * exposes a listener to notify clients when the button is clicked.</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 * <li><strong>Set visibility:</strong> You can hide or show views using
Romain Guy5c22a8c2011-05-13 11:48:45 -0700140 * {@link #setVisibility(int)}.</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 * </ul>
142 * </p>
143 * <p><em>
144 * Note: The Android framework is responsible for measuring, laying out and
145 * drawing views. You should not call methods that perform these actions on
146 * views yourself unless you are actually implementing a
147 * {@link android.view.ViewGroup}.
148 * </em></p>
149 *
150 * <a name="Lifecycle"></a>
151 * <h3>Implementing a Custom View</h3>
152 *
153 * <p>
154 * To implement a custom view, you will usually begin by providing overrides for
155 * some of the standard methods that the framework calls on all views. You do
156 * not need to override all of these methods. In fact, you can start by just
157 * overriding {@link #onDraw(android.graphics.Canvas)}.
158 * <table border="2" width="85%" align="center" cellpadding="5">
159 * <thead>
160 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
161 * </thead>
162 *
163 * <tbody>
164 * <tr>
165 * <td rowspan="2">Creation</td>
166 * <td>Constructors</td>
167 * <td>There is a form of the constructor that are called when the view
168 * is created from code and a form that is called when the view is
169 * inflated from a layout file. The second form should parse and apply
170 * any attributes defined in the layout file.
171 * </td>
172 * </tr>
173 * <tr>
174 * <td><code>{@link #onFinishInflate()}</code></td>
175 * <td>Called after a view and all of its children has been inflated
176 * from XML.</td>
177 * </tr>
178 *
179 * <tr>
180 * <td rowspan="3">Layout</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700181 * <td><code>{@link #onMeasure(int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 * <td>Called to determine the size requirements for this view and all
183 * of its children.
184 * </td>
185 * </tr>
186 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700187 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 * <td>Called when this view should assign a size and position to all
189 * of its children.
190 * </td>
191 * </tr>
192 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700193 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 * <td>Called when the size of this view has changed.
195 * </td>
196 * </tr>
197 *
198 * <tr>
199 * <td>Drawing</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700200 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 * <td>Called when the view should render its content.
202 * </td>
203 * </tr>
204 *
205 * <tr>
206 * <td rowspan="4">Event processing</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700207 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
Jean Chalard405bc512012-05-29 19:12:34 +0900208 * <td>Called when a new hardware key event occurs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 * </td>
210 * </tr>
211 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700212 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
Jean Chalard405bc512012-05-29 19:12:34 +0900213 * <td>Called when a hardware key up event occurs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 * </td>
215 * </tr>
216 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700217 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 * <td>Called when a trackball motion event occurs.
219 * </td>
220 * </tr>
221 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700222 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 * <td>Called when a touch screen motion event occurs.
224 * </td>
225 * </tr>
226 *
227 * <tr>
228 * <td rowspan="2">Focus</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700229 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 * <td>Called when the view gains or loses focus.
231 * </td>
232 * </tr>
233 *
234 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700235 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 * <td>Called when the window containing the view gains or loses focus.
237 * </td>
238 * </tr>
239 *
240 * <tr>
241 * <td rowspan="3">Attaching</td>
242 * <td><code>{@link #onAttachedToWindow()}</code></td>
243 * <td>Called when the view is attached to a window.
244 * </td>
245 * </tr>
246 *
247 * <tr>
248 * <td><code>{@link #onDetachedFromWindow}</code></td>
249 * <td>Called when the view is detached from its window.
250 * </td>
251 * </tr>
252 *
253 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700254 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 * <td>Called when the visibility of the window containing the view
256 * has changed.
257 * </td>
258 * </tr>
259 * </tbody>
260 *
261 * </table>
262 * </p>
263 *
264 * <a name="IDs"></a>
265 * <h3>IDs</h3>
266 * Views may have an integer id associated with them. These ids are typically
267 * assigned in the layout XML files, and are used to find specific views within
268 * the view tree. A common pattern is to:
269 * <ul>
270 * <li>Define a Button in the layout file and assign it a unique ID.
271 * <pre>
Gilles Debunne0243caf2010-08-24 23:06:35 -0700272 * &lt;Button
273 * android:id="@+id/my_button"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 * android:layout_width="wrap_content"
275 * android:layout_height="wrap_content"
276 * android:text="@string/my_button_text"/&gt;
277 * </pre></li>
278 * <li>From the onCreate method of an Activity, find the Button
279 * <pre class="prettyprint">
280 * Button myButton = (Button) findViewById(R.id.my_button);
281 * </pre></li>
282 * </ul>
283 * <p>
284 * View IDs need not be unique throughout the tree, but it is good practice to
285 * ensure that they are at least unique within the part of the tree you are
286 * searching.
287 * </p>
288 *
289 * <a name="Position"></a>
290 * <h3>Position</h3>
291 * <p>
292 * The geometry of a view is that of a rectangle. A view has a location,
293 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
294 * two dimensions, expressed as a width and a height. The unit for location
295 * and dimensions is the pixel.
296 * </p>
297 *
298 * <p>
299 * It is possible to retrieve the location of a view by invoking the methods
300 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
301 * coordinate of the rectangle representing the view. The latter returns the
302 * top, or Y, coordinate of the rectangle representing the view. These methods
303 * both return the location of the view relative to its parent. For instance,
304 * when getLeft() returns 20, that means the view is located 20 pixels to the
305 * right of the left edge of its direct parent.
306 * </p>
307 *
308 * <p>
309 * In addition, several convenience methods are offered to avoid unnecessary
310 * computations, namely {@link #getRight()} and {@link #getBottom()}.
311 * These methods return the coordinates of the right and bottom edges of the
312 * rectangle representing the view. For instance, calling {@link #getRight()}
313 * is similar to the following computation: <code>getLeft() + getWidth()</code>
314 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
315 * </p>
316 *
317 * <a name="SizePaddingMargins"></a>
318 * <h3>Size, padding and margins</h3>
319 * <p>
320 * The size of a view is expressed with a width and a height. A view actually
321 * possess two pairs of width and height values.
322 * </p>
323 *
324 * <p>
325 * The first pair is known as <em>measured width</em> and
326 * <em>measured height</em>. These dimensions define how big a view wants to be
327 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
328 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
329 * and {@link #getMeasuredHeight()}.
330 * </p>
331 *
332 * <p>
333 * The second pair is simply known as <em>width</em> and <em>height</em>, or
334 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
335 * dimensions define the actual size of the view on screen, at drawing time and
336 * after layout. These values may, but do not have to, be different from the
337 * measured width and height. The width and height can be obtained by calling
338 * {@link #getWidth()} and {@link #getHeight()}.
339 * </p>
340 *
341 * <p>
342 * To measure its dimensions, a view takes into account its padding. The padding
343 * is expressed in pixels for the left, top, right and bottom parts of the view.
344 * Padding can be used to offset the content of the view by a specific amount of
345 * pixels. For instance, a left padding of 2 will push the view's content by
346 * 2 pixels to the right of the left edge. Padding can be set using the
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -0700347 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
348 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
349 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
350 * {@link #getPaddingEnd()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 * </p>
352 *
353 * <p>
354 * Even though a view can define a padding, it does not provide any support for
355 * margins. However, view groups provide such a support. Refer to
356 * {@link android.view.ViewGroup} and
357 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
358 * </p>
359 *
360 * <a name="Layout"></a>
361 * <h3>Layout</h3>
362 * <p>
363 * Layout is a two pass process: a measure pass and a layout pass. The measuring
364 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
365 * of the view tree. Each view pushes dimension specifications down the tree
366 * during the recursion. At the end of the measure pass, every view has stored
367 * its measurements. The second pass happens in
368 * {@link #layout(int,int,int,int)} and is also top-down. During
369 * this pass each parent is responsible for positioning all of its children
370 * using the sizes computed in the measure pass.
371 * </p>
372 *
373 * <p>
374 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
375 * {@link #getMeasuredHeight()} values must be set, along with those for all of
376 * that view's descendants. A view's measured width and measured height values
377 * must respect the constraints imposed by the view's parents. This guarantees
378 * that at the end of the measure pass, all parents accept all of their
379 * children's measurements. A parent view may call measure() more than once on
380 * its children. For example, the parent may measure each child once with
381 * unspecified dimensions to find out how big they want to be, then call
382 * measure() on them again with actual numbers if the sum of all the children's
383 * unconstrained sizes is too big or too small.
384 * </p>
385 *
386 * <p>
387 * The measure pass uses two classes to communicate dimensions. The
388 * {@link MeasureSpec} class is used by views to tell their parents how they
389 * want to be measured and positioned. The base LayoutParams class just
390 * describes how big the view wants to be for both width and height. For each
391 * dimension, it can specify one of:
392 * <ul>
393 * <li> an exact number
Romain Guy980a9382010-01-08 15:06:28 -0800394 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 * (minus padding)
396 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
397 * enclose its content (plus padding).
398 * </ul>
399 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
400 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
401 * an X and Y value.
402 * </p>
403 *
404 * <p>
405 * MeasureSpecs are used to push requirements down the tree from parent to
406 * child. A MeasureSpec can be in one of three modes:
407 * <ul>
408 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
409 * of a child view. For example, a LinearLayout may call measure() on its child
410 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
411 * tall the child view wants to be given a width of 240 pixels.
412 * <li>EXACTLY: This is used by the parent to impose an exact size on the
413 * child. The child must use this size, and guarantee that all of its
414 * descendants will fit within this size.
415 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
416 * child. The child must gurantee that it and all of its descendants will fit
417 * within this size.
418 * </ul>
419 * </p>
420 *
421 * <p>
422 * To intiate a layout, call {@link #requestLayout}. This method is typically
423 * called by a view on itself when it believes that is can no longer fit within
424 * its current bounds.
425 * </p>
426 *
427 * <a name="Drawing"></a>
428 * <h3>Drawing</h3>
429 * <p>
430 * Drawing is handled by walking the tree and rendering each view that
Joe Fernandez558459f2011-10-13 16:47:36 -0700431 * intersects the invalid region. Because the tree is traversed in-order,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * this means that parents will draw before (i.e., behind) their children, with
433 * siblings drawn in the order they appear in the tree.
434 * If you set a background drawable for a View, then the View will draw it for you
435 * before calling back to its <code>onDraw()</code> method.
436 * </p>
437 *
438 * <p>
Romain Guy8506ab42009-06-11 17:35:47 -0700439 * Note that the framework will not draw views that are not in the invalid region.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * </p>
441 *
442 * <p>
443 * To force a view to draw, call {@link #invalidate()}.
444 * </p>
445 *
446 * <a name="EventHandlingThreading"></a>
447 * <h3>Event Handling and Threading</h3>
448 * <p>
449 * The basic cycle of a view is as follows:
450 * <ol>
451 * <li>An event comes in and is dispatched to the appropriate view. The view
452 * handles the event and notifies any listeners.</li>
453 * <li>If in the course of processing the event, the view's bounds may need
454 * to be changed, the view will call {@link #requestLayout()}.</li>
455 * <li>Similarly, if in the course of processing the event the view's appearance
456 * may need to be changed, the view will call {@link #invalidate()}.</li>
457 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
458 * the framework will take care of measuring, laying out, and drawing the tree
459 * as appropriate.</li>
460 * </ol>
461 * </p>
462 *
463 * <p><em>Note: The entire view tree is single threaded. You must always be on
464 * the UI thread when calling any method on any view.</em>
465 * If you are doing work on other threads and want to update the state of a view
466 * from that thread, you should use a {@link Handler}.
467 * </p>
468 *
469 * <a name="FocusHandling"></a>
470 * <h3>Focus Handling</h3>
471 * <p>
472 * The framework will handle routine focus movement in response to user input.
473 * This includes changing the focus as views are removed or hidden, or as new
474 * views become available. Views indicate their willingness to take focus
475 * through the {@link #isFocusable} method. To change whether a view can take
476 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
477 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
478 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
479 * </p>
480 * <p>
481 * Focus movement is based on an algorithm which finds the nearest neighbor in a
482 * given direction. In rare cases, the default algorithm may not match the
483 * intended behavior of the developer. In these situations, you can provide
484 * explicit overrides by using these XML attributes in the layout file:
485 * <pre>
486 * nextFocusDown
487 * nextFocusLeft
488 * nextFocusRight
489 * nextFocusUp
490 * </pre>
491 * </p>
492 *
493 *
494 * <p>
495 * To get a particular view to take focus, call {@link #requestFocus()}.
496 * </p>
497 *
498 * <a name="TouchMode"></a>
499 * <h3>Touch Mode</h3>
500 * <p>
501 * When a user is navigating a user interface via directional keys such as a D-pad, it is
502 * necessary to give focus to actionable items such as buttons so the user can see
503 * what will take input. If the device has touch capabilities, however, and the user
504 * begins interacting with the interface by touching it, it is no longer necessary to
505 * always highlight, or give focus to, a particular view. This motivates a mode
506 * for interaction named 'touch mode'.
507 * </p>
508 * <p>
509 * For a touch capable device, once the user touches the screen, the device
510 * will enter touch mode. From this point onward, only views for which
511 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
512 * Other views that are touchable, like buttons, will not take focus when touched; they will
513 * only fire the on click listeners.
514 * </p>
515 * <p>
516 * Any time a user hits a directional key, such as a D-pad direction, the view device will
517 * exit touch mode, and find a view to take focus, so that the user may resume interacting
518 * with the user interface without touching the screen again.
519 * </p>
520 * <p>
521 * The touch mode state is maintained across {@link android.app.Activity}s. Call
522 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
523 * </p>
524 *
525 * <a name="Scrolling"></a>
526 * <h3>Scrolling</h3>
527 * <p>
528 * The framework provides basic support for views that wish to internally
529 * scroll their content. This includes keeping track of the X and Y scroll
530 * offset as well as mechanisms for drawing scrollbars. See
Joe Malin32736f02011-01-19 16:14:20 -0800531 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
Mike Cleronf116bf82009-09-27 19:14:12 -0700532 * {@link #awakenScrollBars()} for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 * </p>
534 *
535 * <a name="Tags"></a>
536 * <h3>Tags</h3>
537 * <p>
538 * Unlike IDs, tags are not used to identify views. Tags are essentially an
539 * extra piece of information that can be associated with a view. They are most
540 * often used as a convenience to store data related to views in the views
541 * themselves rather than by putting them in a separate structure.
542 * </p>
543 *
Chet Haasecb150fe2012-05-03 15:15:05 -0700544 * <a name="Properties"></a>
545 * <h3>Properties</h3>
546 * <p>
547 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
548 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
549 * available both in the {@link Property} form as well as in similarly-named setter/getter
550 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
551 * be used to set persistent state associated with these rendering-related properties on the view.
552 * The properties and methods can also be used in conjunction with
553 * {@link android.animation.Animator Animator}-based animations, described more in the
554 * <a href="#Animation">Animation</a> section.
555 * </p>
556 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 * <a name="Animation"></a>
558 * <h3>Animation</h3>
559 * <p>
Chet Haasecb150fe2012-05-03 15:15:05 -0700560 * Starting with Android 3.0, the preferred way of animating views is to use the
561 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
562 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
563 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
564 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
565 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
566 * makes animating these View properties particularly easy and efficient.
567 * </p>
568 * <p>
569 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 * You can attach an {@link Animation} object to a view using
571 * {@link #setAnimation(Animation)} or
572 * {@link #startAnimation(Animation)}. The animation can alter the scale,
573 * rotation, translation and alpha of a view over time. If the animation is
574 * attached to a view that has children, the animation will affect the entire
575 * subtree rooted by that node. When an animation is started, the framework will
576 * take care of redrawing the appropriate views until the animation completes.
577 * </p>
578 *
Jeff Brown85a31762010-09-01 17:01:00 -0700579 * <a name="Security"></a>
580 * <h3>Security</h3>
581 * <p>
582 * Sometimes it is essential that an application be able to verify that an action
583 * is being performed with the full knowledge and consent of the user, such as
584 * granting a permission request, making a purchase or clicking on an advertisement.
585 * Unfortunately, a malicious application could try to spoof the user into
586 * performing these actions, unaware, by concealing the intended purpose of the view.
587 * As a remedy, the framework offers a touch filtering mechanism that can be used to
588 * improve the security of views that provide access to sensitive functionality.
589 * </p><p>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700590 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
Jeff Brown49ed71d2010-12-06 17:13:33 -0800591 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework
Jeff Brown85a31762010-09-01 17:01:00 -0700592 * will discard touches that are received whenever the view's window is obscured by
593 * another visible window. As a result, the view will not receive touches whenever a
594 * toast, dialog or other window appears above the view's window.
595 * </p><p>
596 * For more fine-grained control over security, consider overriding the
Romain Guy5c22a8c2011-05-13 11:48:45 -0700597 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
598 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
Jeff Brown85a31762010-09-01 17:01:00 -0700599 * </p>
600 *
Romain Guy171c5922011-01-06 10:04:23 -0800601 * @attr ref android.R.styleable#View_alpha
Romain Guyd6a463a2009-05-21 23:10:10 -0700602 * @attr ref android.R.styleable#View_background
603 * @attr ref android.R.styleable#View_clickable
604 * @attr ref android.R.styleable#View_contentDescription
605 * @attr ref android.R.styleable#View_drawingCacheQuality
606 * @attr ref android.R.styleable#View_duplicateParentState
607 * @attr ref android.R.styleable#View_id
Romain Guy1ef3fdb2011-09-09 15:30:30 -0700608 * @attr ref android.R.styleable#View_requiresFadingEdge
Philip Milne6c8ea062012-04-03 17:38:43 -0700609 * @attr ref android.R.styleable#View_fadeScrollbars
Romain Guyd6a463a2009-05-21 23:10:10 -0700610 * @attr ref android.R.styleable#View_fadingEdgeLength
Jeff Brown85a31762010-09-01 17:01:00 -0700611 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 * @attr ref android.R.styleable#View_fitsSystemWindows
Romain Guyd6a463a2009-05-21 23:10:10 -0700613 * @attr ref android.R.styleable#View_isScrollContainer
614 * @attr ref android.R.styleable#View_focusable
615 * @attr ref android.R.styleable#View_focusableInTouchMode
616 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
617 * @attr ref android.R.styleable#View_keepScreenOn
Romain Guy171c5922011-01-06 10:04:23 -0800618 * @attr ref android.R.styleable#View_layerType
Romain Guyd6a463a2009-05-21 23:10:10 -0700619 * @attr ref android.R.styleable#View_longClickable
620 * @attr ref android.R.styleable#View_minHeight
621 * @attr ref android.R.styleable#View_minWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 * @attr ref android.R.styleable#View_nextFocusDown
623 * @attr ref android.R.styleable#View_nextFocusLeft
624 * @attr ref android.R.styleable#View_nextFocusRight
625 * @attr ref android.R.styleable#View_nextFocusUp
Romain Guyd6a463a2009-05-21 23:10:10 -0700626 * @attr ref android.R.styleable#View_onClick
627 * @attr ref android.R.styleable#View_padding
628 * @attr ref android.R.styleable#View_paddingBottom
629 * @attr ref android.R.styleable#View_paddingLeft
630 * @attr ref android.R.styleable#View_paddingRight
631 * @attr ref android.R.styleable#View_paddingTop
Fabrice Di Meglio101d5aa2012-02-16 18:36:06 -0800632 * @attr ref android.R.styleable#View_paddingStart
633 * @attr ref android.R.styleable#View_paddingEnd
Romain Guyd6a463a2009-05-21 23:10:10 -0700634 * @attr ref android.R.styleable#View_saveEnabled
Chet Haase73066682010-11-29 15:55:32 -0800635 * @attr ref android.R.styleable#View_rotation
636 * @attr ref android.R.styleable#View_rotationX
637 * @attr ref android.R.styleable#View_rotationY
638 * @attr ref android.R.styleable#View_scaleX
639 * @attr ref android.R.styleable#View_scaleY
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 * @attr ref android.R.styleable#View_scrollX
641 * @attr ref android.R.styleable#View_scrollY
Romain Guyd6a463a2009-05-21 23:10:10 -0700642 * @attr ref android.R.styleable#View_scrollbarSize
643 * @attr ref android.R.styleable#View_scrollbarStyle
644 * @attr ref android.R.styleable#View_scrollbars
Mike Cleronf116bf82009-09-27 19:14:12 -0700645 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
646 * @attr ref android.R.styleable#View_scrollbarFadeDuration
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
648 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 * @attr ref android.R.styleable#View_scrollbarThumbVertical
650 * @attr ref android.R.styleable#View_scrollbarTrackVertical
651 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
652 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
Romain Guyd6a463a2009-05-21 23:10:10 -0700653 * @attr ref android.R.styleable#View_soundEffectsEnabled
654 * @attr ref android.R.styleable#View_tag
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -0700655 * @attr ref android.R.styleable#View_textAlignment
Chet Haase73066682010-11-29 15:55:32 -0800656 * @attr ref android.R.styleable#View_transformPivotX
657 * @attr ref android.R.styleable#View_transformPivotY
658 * @attr ref android.R.styleable#View_translationX
659 * @attr ref android.R.styleable#View_translationY
Romain Guyd6a463a2009-05-21 23:10:10 -0700660 * @attr ref android.R.styleable#View_visibility
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 *
662 * @see android.view.ViewGroup
663 */
Fabrice Di Megliob03b4342012-06-04 12:55:30 -0700664public class View implements Drawable.Callback, KeyEvent.Callback,
Adam Powell8fc54f92011-09-07 16:40:45 -0700665 AccessibilityEventSource {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 private static final boolean DBG = false;
667
668 /**
669 * The logging tag used by this class with android.util.Log.
670 */
671 protected static final String VIEW_LOG_TAG = "View";
672
673 /**
Guang Zhu0d607fb2012-05-11 19:34:56 -0700674 * When set to true, apps will draw debugging information about their layouts.
Romain Guy4b8c4f82012-04-27 15:48:35 -0700675 *
676 * @hide
677 */
678 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
679
680 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 * Used to mark a View that has no ID.
682 */
683 public static final int NO_ID = -1;
684
685 /**
686 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
687 * calling setFlags.
688 */
689 private static final int NOT_FOCUSABLE = 0x00000000;
690
691 /**
692 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
693 * setFlags.
694 */
695 private static final int FOCUSABLE = 0x00000001;
696
697 /**
698 * Mask for use with setFlags indicating bits used for focus.
699 */
700 private static final int FOCUSABLE_MASK = 0x00000001;
701
702 /**
703 * This view will adjust its padding to fit sytem windows (e.g. status bar)
704 */
705 private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
706
707 /**
Scott Main812634c22011-07-27 13:22:35 -0700708 * This view is visible.
709 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
710 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 */
712 public static final int VISIBLE = 0x00000000;
713
714 /**
715 * This view is invisible, but it still takes up space for layout purposes.
Scott Main812634c22011-07-27 13:22:35 -0700716 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
717 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 */
719 public static final int INVISIBLE = 0x00000004;
720
721 /**
722 * This view is invisible, and it doesn't take any space for layout
Scott Main812634c22011-07-27 13:22:35 -0700723 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
724 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725 */
726 public static final int GONE = 0x00000008;
727
728 /**
729 * Mask for use with setFlags indicating bits used for visibility.
730 * {@hide}
731 */
732 static final int VISIBILITY_MASK = 0x0000000C;
733
734 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
735
736 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -0700737 * This view is enabled. Interpretation varies by subclass.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 * Use with ENABLED_MASK when calling setFlags.
739 * {@hide}
740 */
741 static final int ENABLED = 0x00000000;
742
743 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -0700744 * This view is disabled. Interpretation varies by subclass.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 * Use with ENABLED_MASK when calling setFlags.
746 * {@hide}
747 */
748 static final int DISABLED = 0x00000020;
749
750 /**
751 * Mask for use with setFlags indicating bits used for indicating whether
752 * this view is enabled
753 * {@hide}
754 */
755 static final int ENABLED_MASK = 0x00000020;
756
757 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -0700758 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
759 * called and further optimizations will be performed. It is okay to have
760 * this flag set and a background. Use with DRAW_MASK when calling setFlags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 * {@hide}
762 */
763 static final int WILL_NOT_DRAW = 0x00000080;
764
765 /**
766 * Mask for use with setFlags indicating bits used for indicating whether
767 * this view is will draw
768 * {@hide}
769 */
770 static final int DRAW_MASK = 0x00000080;
771
772 /**
773 * <p>This view doesn't show scrollbars.</p>
774 * {@hide}
775 */
776 static final int SCROLLBARS_NONE = 0x00000000;
777
778 /**
779 * <p>This view shows horizontal scrollbars.</p>
780 * {@hide}
781 */
782 static final int SCROLLBARS_HORIZONTAL = 0x00000100;
783
784 /**
785 * <p>This view shows vertical scrollbars.</p>
786 * {@hide}
787 */
788 static final int SCROLLBARS_VERTICAL = 0x00000200;
789
790 /**
791 * <p>Mask for use with setFlags indicating bits used for indicating which
792 * scrollbars are enabled.</p>
793 * {@hide}
794 */
795 static final int SCROLLBARS_MASK = 0x00000300;
796
Jeff Brown85a31762010-09-01 17:01:00 -0700797 /**
798 * Indicates that the view should filter touches when its window is obscured.
799 * Refer to the class comments for more information about this security feature.
800 * {@hide}
801 */
802 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
803
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700804 /**
805 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
806 * that they are optional and should be skipped if the window has
807 * requested system UI flags that ignore those insets for layout.
808 */
809 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810
811 /**
812 * <p>This view doesn't show fading edges.</p>
813 * {@hide}
814 */
815 static final int FADING_EDGE_NONE = 0x00000000;
816
817 /**
818 * <p>This view shows horizontal fading edges.</p>
819 * {@hide}
820 */
821 static final int FADING_EDGE_HORIZONTAL = 0x00001000;
822
823 /**
824 * <p>This view shows vertical fading edges.</p>
825 * {@hide}
826 */
827 static final int FADING_EDGE_VERTICAL = 0x00002000;
828
829 /**
830 * <p>Mask for use with setFlags indicating bits used for indicating which
831 * fading edges are enabled.</p>
832 * {@hide}
833 */
834 static final int FADING_EDGE_MASK = 0x00003000;
835
836 /**
837 * <p>Indicates this view can be clicked. When clickable, a View reacts
838 * to clicks by notifying the OnClickListener.<p>
839 * {@hide}
840 */
841 static final int CLICKABLE = 0x00004000;
842
843 /**
844 * <p>Indicates this view is caching its drawing into a bitmap.</p>
845 * {@hide}
846 */
847 static final int DRAWING_CACHE_ENABLED = 0x00008000;
848
849 /**
850 * <p>Indicates that no icicle should be saved for this view.<p>
851 * {@hide}
852 */
853 static final int SAVE_DISABLED = 0x000010000;
854
855 /**
856 * <p>Mask for use with setFlags indicating bits used for the saveEnabled
857 * property.</p>
858 * {@hide}
859 */
860 static final int SAVE_DISABLED_MASK = 0x000010000;
861
862 /**
863 * <p>Indicates that no drawing cache should ever be created for this view.<p>
864 * {@hide}
865 */
866 static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
867
868 /**
869 * <p>Indicates this view can take / keep focus when int touch mode.</p>
870 * {@hide}
871 */
872 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
873
874 /**
875 * <p>Enables low quality mode for the drawing cache.</p>
876 */
877 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
878
879 /**
880 * <p>Enables high quality mode for the drawing cache.</p>
881 */
882 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
883
884 /**
885 * <p>Enables automatic quality mode for the drawing cache.</p>
886 */
887 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
888
889 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
890 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
891 };
892
893 /**
894 * <p>Mask for use with setFlags indicating bits used for the cache
895 * quality property.</p>
896 * {@hide}
897 */
898 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
899
900 /**
901 * <p>
902 * Indicates this view can be long clicked. When long clickable, a View
903 * reacts to long clicks by notifying the OnLongClickListener or showing a
904 * context menu.
905 * </p>
906 * {@hide}
907 */
908 static final int LONG_CLICKABLE = 0x00200000;
909
910 /**
911 * <p>Indicates that this view gets its drawable states from its direct parent
912 * and ignores its original internal states.</p>
913 *
914 * @hide
915 */
916 static final int DUPLICATE_PARENT_STATE = 0x00400000;
917
918 /**
919 * The scrollbar style to display the scrollbars inside the content area,
920 * without increasing the padding. The scrollbars will be overlaid with
921 * translucency on the view's content.
922 */
923 public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
924
925 /**
926 * The scrollbar style to display the scrollbars inside the padded area,
927 * increasing the padding of the view. The scrollbars will not overlap the
928 * content area of the view.
929 */
930 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
931
932 /**
933 * The scrollbar style to display the scrollbars at the edge of the view,
934 * without increasing the padding. The scrollbars will be overlaid with
935 * translucency.
936 */
937 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
938
939 /**
940 * The scrollbar style to display the scrollbars at the edge of the view,
941 * increasing the padding of the view. The scrollbars will only overlap the
942 * background, if any.
943 */
944 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
945
946 /**
947 * Mask to check if the scrollbar style is overlay or inset.
948 * {@hide}
949 */
950 static final int SCROLLBARS_INSET_MASK = 0x01000000;
951
952 /**
953 * Mask to check if the scrollbar style is inside or outside.
954 * {@hide}
955 */
956 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
957
958 /**
959 * Mask for scrollbar style.
960 * {@hide}
961 */
962 static final int SCROLLBARS_STYLE_MASK = 0x03000000;
963
964 /**
965 * View flag indicating that the screen should remain on while the
966 * window containing this view is visible to the user. This effectively
967 * takes care of automatically setting the WindowManager's
968 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
969 */
970 public static final int KEEP_SCREEN_ON = 0x04000000;
971
972 /**
973 * View flag indicating whether this view should have sound effects enabled
974 * for events such as clicking and touching.
975 */
976 public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
977
978 /**
979 * View flag indicating whether this view should have haptic feedback
980 * enabled for events such as long presses.
981 */
982 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
983
984 /**
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700985 * <p>Indicates that the view hierarchy should stop saving state when
986 * it reaches this view. If state saving is initiated immediately at
987 * the view, it will be allowed.
988 * {@hide}
989 */
990 static final int PARENT_SAVE_DISABLED = 0x20000000;
991
992 /**
993 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
994 * {@hide}
995 */
996 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
997
998 /**
svetoslavganov75986cf2009-05-14 22:28:01 -0700999 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1000 * should add all focusable Views regardless if they are focusable in touch mode.
1001 */
1002 public static final int FOCUSABLES_ALL = 0x00000000;
1003
1004 /**
1005 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1006 * should add only Views focusable in touch mode.
1007 */
1008 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1009
1010 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001011 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 * item.
1013 */
1014 public static final int FOCUS_BACKWARD = 0x00000001;
1015
1016 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001017 * Use with {@link #focusSearch(int)}. Move focus to the next selectable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 * item.
1019 */
1020 public static final int FOCUS_FORWARD = 0x00000002;
1021
1022 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001023 * Use with {@link #focusSearch(int)}. Move focus to the left.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 */
1025 public static final int FOCUS_LEFT = 0x00000011;
1026
1027 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001028 * Use with {@link #focusSearch(int)}. Move focus up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 */
1030 public static final int FOCUS_UP = 0x00000021;
1031
1032 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001033 * Use with {@link #focusSearch(int)}. Move focus to the right.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 */
1035 public static final int FOCUS_RIGHT = 0x00000042;
1036
1037 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001038 * Use with {@link #focusSearch(int)}. Move focus down.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 */
1040 public static final int FOCUS_DOWN = 0x00000082;
1041
Svetoslav Ganov42138042012-03-20 11:51:39 -07001042 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08001043 * Bits of {@link #getMeasuredWidthAndState()} and
1044 * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1045 */
1046 public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1047
1048 /**
1049 * Bits of {@link #getMeasuredWidthAndState()} and
1050 * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1051 */
1052 public static final int MEASURED_STATE_MASK = 0xff000000;
1053
1054 /**
1055 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1056 * for functions that combine both width and height into a single int,
1057 * such as {@link #getMeasuredState()} and the childState argument of
1058 * {@link #resolveSizeAndState(int, int, int)}.
1059 */
1060 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1061
1062 /**
1063 * Bit of {@link #getMeasuredWidthAndState()} and
1064 * {@link #getMeasuredWidthAndState()} that indicates the measured size
1065 * is smaller that the space the view would like to have.
1066 */
1067 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1068
1069 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 * Base View state sets
1071 */
1072 // Singles
1073 /**
1074 * Indicates the view has no states set. States are used with
1075 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1076 * view depending on its state.
1077 *
1078 * @see android.graphics.drawable.Drawable
1079 * @see #getDrawableState()
1080 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001081 protected static final int[] EMPTY_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 /**
1083 * Indicates the view is enabled. States are used with
1084 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1085 * view depending on its state.
1086 *
1087 * @see android.graphics.drawable.Drawable
1088 * @see #getDrawableState()
1089 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001090 protected static final int[] ENABLED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 /**
1092 * Indicates the view is focused. States are used with
1093 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1094 * view depending on its state.
1095 *
1096 * @see android.graphics.drawable.Drawable
1097 * @see #getDrawableState()
1098 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001099 protected static final int[] FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 /**
1101 * Indicates the view is selected. States are used with
1102 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1103 * view depending on its state.
1104 *
1105 * @see android.graphics.drawable.Drawable
1106 * @see #getDrawableState()
1107 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001108 protected static final int[] SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 /**
1110 * Indicates the view is pressed. States are used with
1111 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1112 * view depending on its state.
1113 *
1114 * @see android.graphics.drawable.Drawable
1115 * @see #getDrawableState()
1116 * @hide
1117 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001118 protected static final int[] PRESSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 /**
1120 * Indicates the view's window has focus. States are used with
1121 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1122 * view depending on its state.
1123 *
1124 * @see android.graphics.drawable.Drawable
1125 * @see #getDrawableState()
1126 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001127 protected static final int[] WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 // Doubles
1129 /**
1130 * Indicates the view is enabled and has the focus.
1131 *
1132 * @see #ENABLED_STATE_SET
1133 * @see #FOCUSED_STATE_SET
1134 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001135 protected static final int[] ENABLED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 /**
1137 * Indicates the view is enabled and selected.
1138 *
1139 * @see #ENABLED_STATE_SET
1140 * @see #SELECTED_STATE_SET
1141 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001142 protected static final int[] ENABLED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 /**
1144 * Indicates the view is enabled and that its window has focus.
1145 *
1146 * @see #ENABLED_STATE_SET
1147 * @see #WINDOW_FOCUSED_STATE_SET
1148 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001149 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 /**
1151 * Indicates the view is focused and selected.
1152 *
1153 * @see #FOCUSED_STATE_SET
1154 * @see #SELECTED_STATE_SET
1155 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001156 protected static final int[] FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 /**
1158 * Indicates the view has the focus and that its window has the focus.
1159 *
1160 * @see #FOCUSED_STATE_SET
1161 * @see #WINDOW_FOCUSED_STATE_SET
1162 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001163 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 /**
1165 * Indicates the view is selected and that its window has the focus.
1166 *
1167 * @see #SELECTED_STATE_SET
1168 * @see #WINDOW_FOCUSED_STATE_SET
1169 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001170 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 // Triples
1172 /**
1173 * Indicates the view is enabled, focused and selected.
1174 *
1175 * @see #ENABLED_STATE_SET
1176 * @see #FOCUSED_STATE_SET
1177 * @see #SELECTED_STATE_SET
1178 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001179 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 /**
1181 * Indicates the view is enabled, focused and its window has the focus.
1182 *
1183 * @see #ENABLED_STATE_SET
1184 * @see #FOCUSED_STATE_SET
1185 * @see #WINDOW_FOCUSED_STATE_SET
1186 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001187 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 /**
1189 * Indicates the view is enabled, selected and its window has the focus.
1190 *
1191 * @see #ENABLED_STATE_SET
1192 * @see #SELECTED_STATE_SET
1193 * @see #WINDOW_FOCUSED_STATE_SET
1194 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001195 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 /**
1197 * Indicates the view is focused, selected and its window has the focus.
1198 *
1199 * @see #FOCUSED_STATE_SET
1200 * @see #SELECTED_STATE_SET
1201 * @see #WINDOW_FOCUSED_STATE_SET
1202 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001203 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 /**
1205 * Indicates the view is enabled, focused, selected and its window
1206 * has the focus.
1207 *
1208 * @see #ENABLED_STATE_SET
1209 * @see #FOCUSED_STATE_SET
1210 * @see #SELECTED_STATE_SET
1211 * @see #WINDOW_FOCUSED_STATE_SET
1212 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001213 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 /**
1215 * Indicates the view is pressed and its window has the focus.
1216 *
1217 * @see #PRESSED_STATE_SET
1218 * @see #WINDOW_FOCUSED_STATE_SET
1219 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001220 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 /**
1222 * Indicates the view is pressed and selected.
1223 *
1224 * @see #PRESSED_STATE_SET
1225 * @see #SELECTED_STATE_SET
1226 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001227 protected static final int[] PRESSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 /**
1229 * Indicates the view is pressed, selected and its window has the focus.
1230 *
1231 * @see #PRESSED_STATE_SET
1232 * @see #SELECTED_STATE_SET
1233 * @see #WINDOW_FOCUSED_STATE_SET
1234 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001235 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 /**
1237 * Indicates the view is pressed and focused.
1238 *
1239 * @see #PRESSED_STATE_SET
1240 * @see #FOCUSED_STATE_SET
1241 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001242 protected static final int[] PRESSED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 /**
1244 * Indicates the view is pressed, focused and its window has the focus.
1245 *
1246 * @see #PRESSED_STATE_SET
1247 * @see #FOCUSED_STATE_SET
1248 * @see #WINDOW_FOCUSED_STATE_SET
1249 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001250 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 /**
1252 * Indicates the view is pressed, focused and selected.
1253 *
1254 * @see #PRESSED_STATE_SET
1255 * @see #SELECTED_STATE_SET
1256 * @see #FOCUSED_STATE_SET
1257 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001258 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 /**
1260 * Indicates the view is pressed, focused, selected and its window has the focus.
1261 *
1262 * @see #PRESSED_STATE_SET
1263 * @see #FOCUSED_STATE_SET
1264 * @see #SELECTED_STATE_SET
1265 * @see #WINDOW_FOCUSED_STATE_SET
1266 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001267 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268 /**
1269 * Indicates the view is pressed and enabled.
1270 *
1271 * @see #PRESSED_STATE_SET
1272 * @see #ENABLED_STATE_SET
1273 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001274 protected static final int[] PRESSED_ENABLED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 /**
1276 * Indicates the view is pressed, enabled and its window has the focus.
1277 *
1278 * @see #PRESSED_STATE_SET
1279 * @see #ENABLED_STATE_SET
1280 * @see #WINDOW_FOCUSED_STATE_SET
1281 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001282 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 /**
1284 * Indicates the view is pressed, enabled and selected.
1285 *
1286 * @see #PRESSED_STATE_SET
1287 * @see #ENABLED_STATE_SET
1288 * @see #SELECTED_STATE_SET
1289 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001290 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 /**
1292 * Indicates the view is pressed, enabled, selected and its window has the
1293 * focus.
1294 *
1295 * @see #PRESSED_STATE_SET
1296 * @see #ENABLED_STATE_SET
1297 * @see #SELECTED_STATE_SET
1298 * @see #WINDOW_FOCUSED_STATE_SET
1299 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001300 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 /**
1302 * Indicates the view is pressed, enabled and focused.
1303 *
1304 * @see #PRESSED_STATE_SET
1305 * @see #ENABLED_STATE_SET
1306 * @see #FOCUSED_STATE_SET
1307 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001308 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 /**
1310 * Indicates the view is pressed, enabled, focused and its window has the
1311 * focus.
1312 *
1313 * @see #PRESSED_STATE_SET
1314 * @see #ENABLED_STATE_SET
1315 * @see #FOCUSED_STATE_SET
1316 * @see #WINDOW_FOCUSED_STATE_SET
1317 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001318 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 /**
1320 * Indicates the view is pressed, enabled, focused and selected.
1321 *
1322 * @see #PRESSED_STATE_SET
1323 * @see #ENABLED_STATE_SET
1324 * @see #SELECTED_STATE_SET
1325 * @see #FOCUSED_STATE_SET
1326 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001327 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 /**
1329 * Indicates the view is pressed, enabled, focused, selected and its window
1330 * has the focus.
1331 *
1332 * @see #PRESSED_STATE_SET
1333 * @see #ENABLED_STATE_SET
1334 * @see #SELECTED_STATE_SET
1335 * @see #FOCUSED_STATE_SET
1336 * @see #WINDOW_FOCUSED_STATE_SET
1337 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001338 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339
1340 /**
1341 * The order here is very important to {@link #getDrawableState()}
1342 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001343 private static final int[][] VIEW_STATE_SETS;
1344
Romain Guyb051e892010-09-28 19:09:36 -07001345 static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1346 static final int VIEW_STATE_SELECTED = 1 << 1;
1347 static final int VIEW_STATE_FOCUSED = 1 << 2;
1348 static final int VIEW_STATE_ENABLED = 1 << 3;
1349 static final int VIEW_STATE_PRESSED = 1 << 4;
1350 static final int VIEW_STATE_ACTIVATED = 1 << 5;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001351 static final int VIEW_STATE_ACCELERATED = 1 << 6;
PY Laligandc33d8d49e2011-03-14 18:22:53 -07001352 static final int VIEW_STATE_HOVERED = 1 << 7;
Christopher Tate3d4bf172011-03-28 16:16:46 -07001353 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1354 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001355
1356 static final int[] VIEW_STATE_IDS = new int[] {
1357 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED,
1358 R.attr.state_selected, VIEW_STATE_SELECTED,
1359 R.attr.state_focused, VIEW_STATE_FOCUSED,
1360 R.attr.state_enabled, VIEW_STATE_ENABLED,
1361 R.attr.state_pressed, VIEW_STATE_PRESSED,
1362 R.attr.state_activated, VIEW_STATE_ACTIVATED,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001363 R.attr.state_accelerated, VIEW_STATE_ACCELERATED,
PY Laligandc33d8d49e2011-03-14 18:22:53 -07001364 R.attr.state_hovered, VIEW_STATE_HOVERED,
Christopher Tate3d4bf172011-03-28 16:16:46 -07001365 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT,
Svetoslav Ganov42138042012-03-20 11:51:39 -07001366 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 };
1368
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001369 static {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001370 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1371 throw new IllegalStateException(
1372 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1373 }
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001374 int[] orderedIds = new int[VIEW_STATE_IDS.length];
Romain Guyb051e892010-09-28 19:09:36 -07001375 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001376 int viewState = R.styleable.ViewDrawableStates[i];
Romain Guyb051e892010-09-28 19:09:36 -07001377 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001378 if (VIEW_STATE_IDS[j] == viewState) {
Romain Guyb051e892010-09-28 19:09:36 -07001379 orderedIds[i * 2] = viewState;
1380 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001381 }
1382 }
1383 }
Romain Guyb051e892010-09-28 19:09:36 -07001384 final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1385 VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1386 for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001387 int numBits = Integer.bitCount(i);
1388 int[] set = new int[numBits];
1389 int pos = 0;
Romain Guyb051e892010-09-28 19:09:36 -07001390 for (int j = 0; j < orderedIds.length; j += 2) {
1391 if ((i & orderedIds[j+1]) != 0) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001392 set[pos++] = orderedIds[j];
1393 }
1394 }
1395 VIEW_STATE_SETS[i] = set;
1396 }
1397
1398 EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1399 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1400 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1401 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1402 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1403 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1404 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1405 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1406 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1407 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1408 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1409 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1410 | VIEW_STATE_FOCUSED];
1411 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1412 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1413 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1414 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1415 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1416 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1417 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1418 | VIEW_STATE_ENABLED];
1419 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1420 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1421 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1422 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1423 | VIEW_STATE_ENABLED];
1424 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1425 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1426 | VIEW_STATE_ENABLED];
1427 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1428 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1429 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1430
1431 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1432 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1433 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1434 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1435 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1436 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1437 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1438 | VIEW_STATE_PRESSED];
1439 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1440 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1441 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1442 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1443 | VIEW_STATE_PRESSED];
1444 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1445 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1446 | VIEW_STATE_PRESSED];
1447 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1448 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1449 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1450 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1451 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1452 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1453 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1454 | VIEW_STATE_PRESSED];
1455 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1456 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1457 | VIEW_STATE_PRESSED];
1458 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1459 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1460 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1461 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1462 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1463 | VIEW_STATE_PRESSED];
1464 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1465 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1466 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1467 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1468 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1469 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1470 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1471 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1472 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1473 | VIEW_STATE_PRESSED];
1474 }
1475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 /**
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07001477 * Accessibility event types that are dispatched for text population.
1478 */
1479 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1480 AccessibilityEvent.TYPE_VIEW_CLICKED
1481 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1482 | AccessibilityEvent.TYPE_VIEW_SELECTED
1483 | AccessibilityEvent.TYPE_VIEW_FOCUSED
1484 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1485 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
Svetoslav Ganov9920f4f2011-10-07 18:39:11 -07001486 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
Svetoslav Ganov84dd52e2011-11-18 10:24:00 -08001487 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
Svetoslav Ganov42138042012-03-20 11:51:39 -07001488 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001489 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1490 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07001491
1492 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 * Temporary Rect currently for use in setBackground(). This will probably
1494 * be extended in the future to hold our own class with more than just
1495 * a Rect. :)
1496 */
1497 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
Romain Guyd90a3312009-05-06 14:54:28 -07001498
1499 /**
1500 * Map used to store views' tags.
1501 */
Adam Powell7db82ac2011-09-22 19:44:04 -07001502 private SparseArray<Object> mKeyedTags;
Romain Guyd90a3312009-05-06 14:54:28 -07001503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001505 * The next available accessiiblity id.
1506 */
1507 private static int sNextAccessibilityViewId;
1508
1509 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 * The animation currently associated with this view.
1511 * @hide
1512 */
1513 protected Animation mCurrentAnimation = null;
1514
1515 /**
1516 * Width as measured during measure pass.
1517 * {@hide}
1518 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001519 @ViewDebug.ExportedProperty(category = "measurement")
Romain Guy676b1732011-02-14 14:45:33 -08001520 int mMeasuredWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521
1522 /**
1523 * Height as measured during measure pass.
1524 * {@hide}
1525 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001526 @ViewDebug.ExportedProperty(category = "measurement")
Romain Guy676b1732011-02-14 14:45:33 -08001527 int mMeasuredHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528
1529 /**
Chet Haasedaf98e92011-01-10 14:10:36 -08001530 * Flag to indicate that this view was marked INVALIDATED, or had its display list
1531 * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1532 * its display list. This flag, used only when hw accelerated, allows us to clear the
1533 * flag while retaining this information until it's needed (at getDisplayList() time and
1534 * in drawChild(), when we decide to draw a view's children's display lists into our own).
1535 *
1536 * {@hide}
1537 */
1538 boolean mRecreateDisplayList = false;
1539
1540 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 * The view's identifier.
1542 * {@hide}
1543 *
1544 * @see #setId(int)
1545 * @see #getId()
1546 */
1547 @ViewDebug.ExportedProperty(resolveId = true)
1548 int mID = NO_ID;
1549
1550 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07001551 * The stable ID of this view for accessibility purposes.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001552 */
1553 int mAccessibilityViewId = NO_ID;
1554
1555 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001556 * @hide
1557 */
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07001558 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001559
1560 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 * The view's tag.
1562 * {@hide}
1563 *
1564 * @see #setTag(Object)
1565 * @see #getTag()
1566 */
1567 protected Object mTag;
1568
1569 // for mPrivateFlags:
1570 /** {@hide} */
1571 static final int WANTS_FOCUS = 0x00000001;
1572 /** {@hide} */
1573 static final int FOCUSED = 0x00000002;
1574 /** {@hide} */
1575 static final int SELECTED = 0x00000004;
1576 /** {@hide} */
1577 static final int IS_ROOT_NAMESPACE = 0x00000008;
1578 /** {@hide} */
1579 static final int HAS_BOUNDS = 0x00000010;
1580 /** {@hide} */
1581 static final int DRAWN = 0x00000020;
1582 /**
1583 * When this flag is set, this view is running an animation on behalf of its
1584 * children and should therefore not cancel invalidate requests, even if they
1585 * lie outside of this view's bounds.
1586 *
1587 * {@hide}
1588 */
1589 static final int DRAW_ANIMATION = 0x00000040;
1590 /** {@hide} */
1591 static final int SKIP_DRAW = 0x00000080;
1592 /** {@hide} */
1593 static final int ONLY_DRAWS_BACKGROUND = 0x00000100;
1594 /** {@hide} */
1595 static final int REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1596 /** {@hide} */
1597 static final int DRAWABLE_STATE_DIRTY = 0x00000400;
1598 /** {@hide} */
1599 static final int MEASURED_DIMENSION_SET = 0x00000800;
1600 /** {@hide} */
1601 static final int FORCE_LAYOUT = 0x00001000;
Konstantin Lopyrevc6dc4572010-08-06 15:01:52 -07001602 /** {@hide} */
1603 static final int LAYOUT_REQUIRED = 0x00002000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604
1605 private static final int PRESSED = 0x00004000;
1606
1607 /** {@hide} */
1608 static final int DRAWING_CACHE_VALID = 0x00008000;
1609 /**
1610 * Flag used to indicate that this view should be drawn once more (and only once
1611 * more) after its animation has completed.
1612 * {@hide}
1613 */
1614 static final int ANIMATION_STARTED = 0x00010000;
1615
1616 private static final int SAVE_STATE_CALLED = 0x00020000;
1617
1618 /**
1619 * Indicates that the View returned true when onSetAlpha() was called and that
1620 * the alpha must be restored.
1621 * {@hide}
1622 */
1623 static final int ALPHA_SET = 0x00040000;
1624
1625 /**
1626 * Set by {@link #setScrollContainer(boolean)}.
1627 */
1628 static final int SCROLL_CONTAINER = 0x00080000;
1629
1630 /**
1631 * Set by {@link #setScrollContainer(boolean)}.
1632 */
1633 static final int SCROLL_CONTAINER_ADDED = 0x00100000;
1634
1635 /**
Romain Guy809a7f62009-05-14 15:44:42 -07001636 * View flag indicating whether this view was invalidated (fully or partially.)
1637 *
1638 * @hide
1639 */
1640 static final int DIRTY = 0x00200000;
1641
1642 /**
1643 * View flag indicating whether this view was invalidated by an opaque
1644 * invalidate request.
1645 *
1646 * @hide
1647 */
1648 static final int DIRTY_OPAQUE = 0x00400000;
1649
1650 /**
1651 * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
1652 *
1653 * @hide
1654 */
1655 static final int DIRTY_MASK = 0x00600000;
1656
1657 /**
Romain Guy8f1344f52009-05-15 16:03:59 -07001658 * Indicates whether the background is opaque.
1659 *
1660 * @hide
1661 */
1662 static final int OPAQUE_BACKGROUND = 0x00800000;
1663
1664 /**
1665 * Indicates whether the scrollbars are opaque.
1666 *
1667 * @hide
1668 */
1669 static final int OPAQUE_SCROLLBARS = 0x01000000;
1670
1671 /**
1672 * Indicates whether the view is opaque.
1673 *
1674 * @hide
1675 */
1676 static final int OPAQUE_MASK = 0x01800000;
Joe Malin32736f02011-01-19 16:14:20 -08001677
Adam Powelle14579b2009-12-16 18:39:52 -08001678 /**
1679 * Indicates a prepressed state;
1680 * the short time between ACTION_DOWN and recognizing
1681 * a 'real' press. Prepressed is used to recognize quick taps
1682 * even when they are shorter than ViewConfiguration.getTapTimeout().
Joe Malin32736f02011-01-19 16:14:20 -08001683 *
Adam Powelle14579b2009-12-16 18:39:52 -08001684 * @hide
1685 */
1686 private static final int PREPRESSED = 0x02000000;
Joe Malin32736f02011-01-19 16:14:20 -08001687
Adam Powellc9fbaab2010-02-16 17:16:19 -08001688 /**
Romain Guy8afa5152010-02-26 11:56:30 -08001689 * Indicates whether the view is temporarily detached.
1690 *
1691 * @hide
1692 */
1693 static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
Joe Malin32736f02011-01-19 16:14:20 -08001694
Adam Powell8568c3a2010-04-19 14:26:11 -07001695 /**
1696 * Indicates that we should awaken scroll bars once attached
Joe Malin32736f02011-01-19 16:14:20 -08001697 *
Adam Powell8568c3a2010-04-19 14:26:11 -07001698 * @hide
1699 */
1700 private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
Romain Guy8f1344f52009-05-15 16:03:59 -07001701
1702 /**
Jeff Browna032cc02011-03-07 16:56:21 -08001703 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
1704 * @hide
1705 */
1706 private static final int HOVERED = 0x10000000;
1707
1708 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07001709 * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1710 * for transform operations
1711 *
1712 * @hide
1713 */
Adam Powellf37df072010-09-17 16:22:49 -07001714 private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
Chet Haasefd2b0022010-08-06 13:08:56 -07001715
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001716 /** {@hide} */
Adam Powellf37df072010-09-17 16:22:49 -07001717 static final int ACTIVATED = 0x40000000;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001718
Chet Haasefd2b0022010-08-06 13:08:56 -07001719 /**
Chet Haasedaf98e92011-01-10 14:10:36 -08001720 * Indicates that this view was specifically invalidated, not just dirtied because some
1721 * child view was invalidated. The flag is used to determine when we need to recreate
1722 * a view's display list (as opposed to just returning a reference to its existing
1723 * display list).
1724 *
1725 * @hide
1726 */
1727 static final int INVALIDATED = 0x80000000;
1728
Christopher Tate3d4bf172011-03-28 16:16:46 -07001729 /* Masks for mPrivateFlags2 */
1730
1731 /**
1732 * Indicates that this view has reported that it can accept the current drag's content.
1733 * Cleared when the drag operation concludes.
1734 * @hide
1735 */
1736 static final int DRAG_CAN_ACCEPT = 0x00000001;
1737
1738 /**
1739 * Indicates that this view is currently directly under the drag location in a
1740 * drag-and-drop operation involving content that it can accept. Cleared when
1741 * the drag exits the view, or when the drag operation concludes.
1742 * @hide
1743 */
1744 static final int DRAG_HOVERED = 0x00000002;
1745
Cibu Johny86666632010-02-22 13:01:02 -08001746 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001747 * Horizontal layout direction of this view is from Left to Right.
1748 * Use with {@link #setLayoutDirection}.
Cibu Johny86666632010-02-22 13:01:02 -08001749 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001750 public static final int LAYOUT_DIRECTION_LTR = 0;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001751
1752 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001753 * Horizontal layout direction of this view is from Right to Left.
1754 * Use with {@link #setLayoutDirection}.
1755 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001756 public static final int LAYOUT_DIRECTION_RTL = 1;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001757
1758 /**
1759 * Horizontal layout direction of this view is inherited from its parent.
1760 * Use with {@link #setLayoutDirection}.
1761 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001762 public static final int LAYOUT_DIRECTION_INHERIT = 2;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001763
1764 /**
1765 * Horizontal layout direction of this view is from deduced from the default language
1766 * script for the locale. Use with {@link #setLayoutDirection}.
1767 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001768 public static final int LAYOUT_DIRECTION_LOCALE = 3;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001769
1770 /**
1771 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001772 * @hide
1773 */
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001774 static final int LAYOUT_DIRECTION_MASK_SHIFT = 2;
1775
1776 /**
1777 * Mask for use with private flags indicating bits used for horizontal layout direction.
1778 * @hide
1779 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001780 static final int LAYOUT_DIRECTION_MASK = 0x00000003 << LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001781
1782 /**
1783 * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1784 * right-to-left direction.
1785 * @hide
1786 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001787 static final int LAYOUT_DIRECTION_RESOLVED_RTL = 4 << LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001788
1789 /**
1790 * Indicates whether the view horizontal layout direction has been resolved.
1791 * @hide
1792 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001793 static final int LAYOUT_DIRECTION_RESOLVED = 8 << LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001794
1795 /**
1796 * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1797 * @hide
1798 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001799 static final int LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C << LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001800
1801 /*
1802 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1803 * flag value.
1804 * @hide
1805 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001806 private static final int[] LAYOUT_DIRECTION_FLAGS = {
1807 LAYOUT_DIRECTION_LTR,
1808 LAYOUT_DIRECTION_RTL,
1809 LAYOUT_DIRECTION_INHERIT,
1810 LAYOUT_DIRECTION_LOCALE
1811 };
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001812
1813 /**
1814 * Default horizontal layout direction.
1815 * @hide
1816 */
1817 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001818
Adam Powell539ee872012-02-03 19:00:49 -08001819 /**
1820 * Indicates that the view is tracking some sort of transient state
1821 * that the app should not need to be aware of, but that the framework
1822 * should take special care to preserve.
1823 *
1824 * @hide
1825 */
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001826 static final int HAS_TRANSIENT_STATE = 0x00000100;
Adam Powell539ee872012-02-03 19:00:49 -08001827
1828
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001829 /**
1830 * Text direction is inherited thru {@link ViewGroup}
1831 */
1832 public static final int TEXT_DIRECTION_INHERIT = 0;
1833
1834 /**
1835 * Text direction is using "first strong algorithm". The first strong directional character
1836 * determines the paragraph direction. If there is no strong directional character, the
1837 * paragraph direction is the view's resolved layout direction.
1838 */
1839 public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1840
1841 /**
1842 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1843 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1844 * If there are neither, the paragraph direction is the view's resolved layout direction.
1845 */
1846 public static final int TEXT_DIRECTION_ANY_RTL = 2;
1847
1848 /**
1849 * Text direction is forced to LTR.
1850 */
1851 public static final int TEXT_DIRECTION_LTR = 3;
1852
1853 /**
1854 * Text direction is forced to RTL.
1855 */
1856 public static final int TEXT_DIRECTION_RTL = 4;
1857
1858 /**
1859 * Text direction is coming from the system Locale.
1860 */
1861 public static final int TEXT_DIRECTION_LOCALE = 5;
1862
1863 /**
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001864 * Default text direction is inherited
1865 */
1866 protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1867
1868 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001869 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1870 * @hide
1871 */
1872 static final int TEXT_DIRECTION_MASK_SHIFT = 6;
1873
1874 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001875 * Mask for use with private flags indicating bits used for text direction.
1876 * @hide
1877 */
1878 static final int TEXT_DIRECTION_MASK = 0x00000007 << TEXT_DIRECTION_MASK_SHIFT;
1879
1880 /**
1881 * Array of text direction flags for mapping attribute "textDirection" to correct
1882 * flag value.
1883 * @hide
1884 */
1885 private static final int[] TEXT_DIRECTION_FLAGS = {
1886 TEXT_DIRECTION_INHERIT << TEXT_DIRECTION_MASK_SHIFT,
1887 TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_MASK_SHIFT,
1888 TEXT_DIRECTION_ANY_RTL << TEXT_DIRECTION_MASK_SHIFT,
1889 TEXT_DIRECTION_LTR << TEXT_DIRECTION_MASK_SHIFT,
1890 TEXT_DIRECTION_RTL << TEXT_DIRECTION_MASK_SHIFT,
1891 TEXT_DIRECTION_LOCALE << TEXT_DIRECTION_MASK_SHIFT
1892 };
1893
1894 /**
1895 * Indicates whether the view text direction has been resolved.
1896 * @hide
1897 */
1898 static final int TEXT_DIRECTION_RESOLVED = 0x00000008 << TEXT_DIRECTION_MASK_SHIFT;
1899
1900 /**
1901 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1902 * @hide
1903 */
1904 static final int TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
1905
1906 /**
1907 * Mask for use with private flags indicating bits used for resolved text direction.
1908 * @hide
1909 */
1910 static final int TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1911
1912 /**
1913 * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
1914 * @hide
1915 */
1916 static final int TEXT_DIRECTION_RESOLVED_DEFAULT =
1917 TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1918
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001919 /*
1920 * Default text alignment. The text alignment of this View is inherited from its parent.
1921 * Use with {@link #setTextAlignment(int)}
1922 */
1923 public static final int TEXT_ALIGNMENT_INHERIT = 0;
1924
1925 /**
1926 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
1927 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
1928 *
1929 * Use with {@link #setTextAlignment(int)}
1930 */
1931 public static final int TEXT_ALIGNMENT_GRAVITY = 1;
1932
1933 /**
1934 * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
1935 *
1936 * Use with {@link #setTextAlignment(int)}
1937 */
1938 public static final int TEXT_ALIGNMENT_TEXT_START = 2;
1939
1940 /**
1941 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
1942 *
1943 * Use with {@link #setTextAlignment(int)}
1944 */
1945 public static final int TEXT_ALIGNMENT_TEXT_END = 3;
1946
1947 /**
1948 * Center the paragraph, e.g. ALIGN_CENTER.
1949 *
1950 * Use with {@link #setTextAlignment(int)}
1951 */
1952 public static final int TEXT_ALIGNMENT_CENTER = 4;
1953
1954 /**
1955 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
1956 * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
1957 *
1958 * Use with {@link #setTextAlignment(int)}
1959 */
1960 public static final int TEXT_ALIGNMENT_VIEW_START = 5;
1961
1962 /**
1963 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
1964 * layoutDirection is LTR, and ALIGN_LEFT otherwise.
1965 *
1966 * Use with {@link #setTextAlignment(int)}
1967 */
1968 public static final int TEXT_ALIGNMENT_VIEW_END = 6;
1969
1970 /**
1971 * Default text alignment is inherited
1972 */
1973 protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
1974
1975 /**
1976 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1977 * @hide
1978 */
1979 static final int TEXT_ALIGNMENT_MASK_SHIFT = 13;
1980
1981 /**
1982 * Mask for use with private flags indicating bits used for text alignment.
1983 * @hide
1984 */
1985 static final int TEXT_ALIGNMENT_MASK = 0x00000007 << TEXT_ALIGNMENT_MASK_SHIFT;
1986
1987 /**
1988 * Array of text direction flags for mapping attribute "textAlignment" to correct
1989 * flag value.
1990 * @hide
1991 */
1992 private static final int[] TEXT_ALIGNMENT_FLAGS = {
1993 TEXT_ALIGNMENT_INHERIT << TEXT_ALIGNMENT_MASK_SHIFT,
1994 TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_MASK_SHIFT,
1995 TEXT_ALIGNMENT_TEXT_START << TEXT_ALIGNMENT_MASK_SHIFT,
1996 TEXT_ALIGNMENT_TEXT_END << TEXT_ALIGNMENT_MASK_SHIFT,
1997 TEXT_ALIGNMENT_CENTER << TEXT_ALIGNMENT_MASK_SHIFT,
1998 TEXT_ALIGNMENT_VIEW_START << TEXT_ALIGNMENT_MASK_SHIFT,
1999 TEXT_ALIGNMENT_VIEW_END << TEXT_ALIGNMENT_MASK_SHIFT
2000 };
2001
2002 /**
2003 * Indicates whether the view text alignment has been resolved.
2004 * @hide
2005 */
2006 static final int TEXT_ALIGNMENT_RESOLVED = 0x00000008 << TEXT_ALIGNMENT_MASK_SHIFT;
2007
2008 /**
2009 * Bit shift to get the resolved text alignment.
2010 * @hide
2011 */
2012 static final int TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2013
2014 /**
2015 * Mask for use with private flags indicating bits used for text alignment.
2016 * @hide
2017 */
2018 static final int TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2019
2020 /**
2021 * Indicates whether if the view text alignment has been resolved to gravity
2022 */
2023 public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2024 TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2025
Svetoslav Ganov42138042012-03-20 11:51:39 -07002026 // Accessiblity constants for mPrivateFlags2
2027
2028 /**
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07002029 * Shift for the bits in {@link #mPrivateFlags2} related to the
2030 * "importantForAccessibility" attribute.
Svetoslav Ganov42138042012-03-20 11:51:39 -07002031 */
2032 static final int IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2033
2034 /**
2035 * Automatically determine whether a view is important for accessibility.
2036 */
2037 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2038
2039 /**
2040 * The view is important for accessibility.
2041 */
2042 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2043
2044 /**
2045 * The view is not important for accessibility.
2046 */
2047 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2048
2049 /**
2050 * The default whether the view is important for accessiblity.
2051 */
2052 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2053
2054 /**
2055 * Mask for obtainig the bits which specify how to determine
2056 * whether a view is important for accessibility.
2057 */
2058 static final int IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2059 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
2060 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2061
2062 /**
2063 * Flag indicating whether a view has accessibility focus.
2064 */
2065 static final int ACCESSIBILITY_FOCUSED = 0x00000040 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2066
2067 /**
2068 * Flag indicating whether a view state for accessibility has changed.
2069 */
2070 static final int ACCESSIBILITY_STATE_CHANGED = 0x00000080 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07002071
Chet Haaseafd5c3e2012-05-10 13:21:10 -07002072 /**
Chet Haase1a3ab172012-05-11 08:41:20 -07002073 * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2074 * is used to check whether later changes to the view's transform should invalidate the
2075 * view to force the quickReject test to run again.
2076 */
Chet Haase21433372012-06-05 07:54:09 -07002077 static final int VIEW_QUICK_REJECTED = 0x10000000;
Chet Haase1a3ab172012-05-11 08:41:20 -07002078
Adam Powell0090f202012-08-07 17:15:30 -07002079 /**
2080 * Flag indicating that start/end padding has been resolved into left/right padding
2081 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2082 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2083 * during measurement. In some special cases this is required such as when an adapter-based
2084 * view measures prospective children without attaching them to a window.
2085 */
2086 static final int PADDING_RESOLVED = 0x20000000;
2087
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07002088 // There are a couple of flags left in mPrivateFlags2
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07002089
Christopher Tate3d4bf172011-03-28 16:16:46 -07002090 /* End of masks for mPrivateFlags2 */
2091
Chet Haase21433372012-06-05 07:54:09 -07002092 /* Masks for mPrivateFlags3 */
2093
2094 /**
2095 * Flag indicating that view has a transform animation set on it. This is used to track whether
2096 * an animation is cleared between successive frames, in order to tell the associated
2097 * DisplayList to clear its animation matrix.
2098 */
2099 static final int VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2100
2101 /**
2102 * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2103 * animation is cleared between successive frames, in order to tell the associated
2104 * DisplayList to restore its alpha value.
2105 */
2106 static final int VIEW_IS_ANIMATING_ALPHA = 0x2;
2107
2108
2109 /* End of masks for mPrivateFlags3 */
2110
Christopher Tate3d4bf172011-03-28 16:16:46 -07002111 static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
2112
Chet Haasedaf98e92011-01-10 14:10:36 -08002113 /**
Adam Powell637d3372010-08-25 14:37:03 -07002114 * Always allow a user to over-scroll this view, provided it is a
2115 * view that can scroll.
2116 *
2117 * @see #getOverScrollMode()
2118 * @see #setOverScrollMode(int)
2119 */
2120 public static final int OVER_SCROLL_ALWAYS = 0;
2121
2122 /**
2123 * Allow a user to over-scroll this view only if the content is large
2124 * enough to meaningfully scroll, provided it is a view that can scroll.
2125 *
2126 * @see #getOverScrollMode()
2127 * @see #setOverScrollMode(int)
2128 */
2129 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2130
2131 /**
2132 * Never allow a user to over-scroll this view.
2133 *
2134 * @see #getOverScrollMode()
2135 * @see #setOverScrollMode(int)
2136 */
2137 public static final int OVER_SCROLL_NEVER = 2;
2138
2139 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002140 * Special constant for {@link #setSystemUiVisibility(int)}: View has
2141 * requested the system UI (status bar) to be visible (the default).
Joe Onorato664644d2011-01-23 17:53:23 -08002142 *
Joe Malin32736f02011-01-19 16:14:20 -08002143 * @see #setSystemUiVisibility(int)
Joe Onorato664644d2011-01-23 17:53:23 -08002144 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002145 public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
Joe Onorato664644d2011-01-23 17:53:23 -08002146
2147 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002148 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2149 * system UI to enter an unobtrusive "low profile" mode.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002150 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002151 * <p>This is for use in games, book readers, video players, or any other
Philip Milne6c8ea062012-04-03 17:38:43 -07002152 * "immersive" application where the usual system chrome is deemed too distracting.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002153 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002154 * <p>In low profile mode, the status bar and/or navigation icons may dim.
Joe Onorato664644d2011-01-23 17:53:23 -08002155 *
Joe Malin32736f02011-01-19 16:14:20 -08002156 * @see #setSystemUiVisibility(int)
Joe Onorato664644d2011-01-23 17:53:23 -08002157 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002158 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2159
2160 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002161 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2162 * system navigation be temporarily hidden.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002163 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002164 * <p>This is an even less obtrusive state than that called for by
Daniel Sandler60ee2562011-07-22 12:34:33 -04002165 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2166 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2167 * those to disappear. This is useful (in conjunction with the
Philip Milne6c8ea062012-04-03 17:38:43 -07002168 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
Daniel Sandler60ee2562011-07-22 12:34:33 -04002169 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2170 * window flags) for displaying content using every last pixel on the display.
2171 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002172 * <p>There is a limitation: because navigation controls are so important, the least user
2173 * interaction will cause them to reappear immediately. When this happens, both
2174 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2175 * so that both elements reappear at the same time.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002176 *
2177 * @see #setSystemUiVisibility(int)
2178 */
2179 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2180
2181 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002182 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2183 * into the normal fullscreen mode so that its content can take over the screen
2184 * while still allowing the user to interact with the application.
2185 *
2186 * <p>This has the same visual effect as
2187 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2188 * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2189 * meaning that non-critical screen decorations (such as the status bar) will be
2190 * hidden while the user is in the View's window, focusing the experience on
2191 * that content. Unlike the window flag, if you are using ActionBar in
2192 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2193 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2194 * hide the action bar.
2195 *
2196 * <p>This approach to going fullscreen is best used over the window flag when
2197 * it is a transient state -- that is, the application does this at certain
2198 * points in its user interaction where it wants to allow the user to focus
2199 * on content, but not as a continuous state. For situations where the application
2200 * would like to simply stay full screen the entire time (such as a game that
2201 * wants to take over the screen), the
2202 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2203 * is usually a better approach. The state set here will be removed by the system
2204 * in various situations (such as the user moving to another application) like
2205 * the other system UI states.
2206 *
2207 * <p>When using this flag, the application should provide some easy facility
2208 * for the user to go out of it. A common example would be in an e-book
2209 * reader, where tapping on the screen brings back whatever screen and UI
2210 * decorations that had been hidden while the user was immersed in reading
2211 * the book.
2212 *
2213 * @see #setSystemUiVisibility(int)
2214 */
2215 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2216
2217 /**
2218 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2219 * flags, we would like a stable view of the content insets given to
2220 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
2221 * will always represent the worst case that the application can expect
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002222 * as a continuous state. In the stock Android UI this is the space for
2223 * the system bar, nav bar, and status bar, but not more transient elements
2224 * such as an input method.
2225 *
2226 * The stable layout your UI sees is based on the system UI modes you can
2227 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2228 * then you will get a stable layout for changes of the
2229 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2230 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2231 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2232 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2233 * with a stable layout. (Note that you should avoid using
2234 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2235 *
Jeff Smitha45746e2012-07-19 14:19:24 -05002236 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002237 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2238 * then a hidden status bar will be considered a "stable" state for purposes
2239 * here. This allows your UI to continually hide the status bar, while still
2240 * using the system UI flags to hide the action bar while still retaining
2241 * a stable layout. Note that changing the window fullscreen flag will never
2242 * provide a stable layout for a clean transition.
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002243 *
2244 * <p>If you are using ActionBar in
2245 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2246 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2247 * insets it adds to those given to the application.
2248 */
2249 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2250
2251 /**
2252 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2253 * to be layed out as if it has requested
2254 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
2255 * allows it to avoid artifacts when switching in and out of that mode, at
2256 * the expense that some of its user interface may be covered by screen
2257 * decorations when they are shown. You can perform layout of your inner
2258 * UI elements to account for the navagation system UI through the
2259 * {@link #fitSystemWindows(Rect)} method.
2260 */
2261 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2262
2263 /**
2264 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2265 * to be layed out as if it has requested
2266 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This
2267 * allows it to avoid artifacts when switching in and out of that mode, at
2268 * the expense that some of its user interface may be covered by screen
2269 * decorations when they are shown. You can perform layout of your inner
2270 * UI elements to account for non-fullscreen system UI through the
2271 * {@link #fitSystemWindows(Rect)} method.
2272 */
2273 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2274
2275 /**
Daniel Sandler60ee2562011-07-22 12:34:33 -04002276 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2277 */
2278 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2279
2280 /**
2281 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2282 */
2283 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
Joe Onorato664644d2011-01-23 17:53:23 -08002284
2285 /**
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002286 * @hide
2287 *
2288 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2289 * out of the public fields to keep the undefined bits out of the developer's way.
2290 *
2291 * Flag to make the status bar not expandable. Unless you also
2292 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2293 */
2294 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2295
2296 /**
2297 * @hide
2298 *
2299 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2300 * out of the public fields to keep the undefined bits out of the developer's way.
2301 *
2302 * Flag to hide notification icons and scrolling ticker text.
2303 */
2304 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2305
2306 /**
2307 * @hide
2308 *
2309 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2310 * out of the public fields to keep the undefined bits out of the developer's way.
2311 *
2312 * Flag to disable incoming notification alerts. This will not block
2313 * icons, but it will block sound, vibrating and other visual or aural notifications.
2314 */
2315 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2316
2317 /**
2318 * @hide
2319 *
2320 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2321 * out of the public fields to keep the undefined bits out of the developer's way.
2322 *
2323 * Flag to hide only the scrolling ticker. Note that
2324 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2325 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2326 */
2327 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2328
2329 /**
2330 * @hide
2331 *
2332 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2333 * out of the public fields to keep the undefined bits out of the developer's way.
2334 *
2335 * Flag to hide the center system info area.
2336 */
2337 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2338
2339 /**
2340 * @hide
2341 *
2342 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2343 * out of the public fields to keep the undefined bits out of the developer's way.
2344 *
Daniel Sandlerdba93562011-10-06 16:39:58 -04002345 * Flag to hide only the home button. Don't use this
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002346 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2347 */
Daniel Sandlerdba93562011-10-06 16:39:58 -04002348 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002349
2350 /**
2351 * @hide
2352 *
2353 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2354 * out of the public fields to keep the undefined bits out of the developer's way.
2355 *
Daniel Sandlerdba93562011-10-06 16:39:58 -04002356 * Flag to hide only the back button. Don't use this
Joe Onorato6478adc2011-01-27 21:15:01 -08002357 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2358 */
2359 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2360
2361 /**
2362 * @hide
2363 *
2364 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2365 * out of the public fields to keep the undefined bits out of the developer's way.
2366 *
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002367 * Flag to hide only the clock. You might use this if your activity has
2368 * its own clock making the status bar's clock redundant.
2369 */
Joe Onorato6478adc2011-01-27 21:15:01 -08002370 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2371
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002372 /**
2373 * @hide
Daniel Sandlerdba93562011-10-06 16:39:58 -04002374 *
2375 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2376 * out of the public fields to keep the undefined bits out of the developer's way.
2377 *
2378 * Flag to hide only the recent apps button. Don't use this
2379 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2380 */
2381 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2382
2383 /**
2384 * @hide
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002385 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002386 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002387
2388 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -07002389 * These are the system UI flags that can be cleared by events outside
2390 * of an application. Currently this is just the ability to tap on the
2391 * screen while hiding the navigation bar to have it return.
2392 * @hide
2393 */
2394 public static final int SYSTEM_UI_CLEARABLE_FLAGS =
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002395 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2396 | SYSTEM_UI_FLAG_FULLSCREEN;
2397
2398 /**
2399 * Flags that can impact the layout in relation to system UI.
2400 */
2401 public static final int SYSTEM_UI_LAYOUT_FLAGS =
2402 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2403 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
Dianne Hackborn9a230e02011-10-06 11:51:27 -07002404
2405 /**
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07002406 * Find views that render the specified text.
2407 *
2408 * @see #findViewsWithText(ArrayList, CharSequence, int)
2409 */
2410 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2411
2412 /**
2413 * Find find views that contain the specified content description.
2414 *
2415 * @see #findViewsWithText(ArrayList, CharSequence, int)
2416 */
2417 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2418
2419 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002420 * Find views that contain {@link AccessibilityNodeProvider}. Such
2421 * a View is a root of virtual view hierarchy and may contain the searched
2422 * text. If this flag is set Views with providers are automatically
2423 * added and it is a responsibility of the client to call the APIs of
2424 * the provider to determine whether the virtual tree rooted at this View
2425 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2426 * represeting the virtual views with this text.
2427 *
2428 * @see #findViewsWithText(ArrayList, CharSequence, int)
2429 *
2430 * @hide
2431 */
2432 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2433
2434 /**
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07002435 * The undefined cursor position.
2436 */
2437 private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2438
2439 /**
Romain Guybb9908b2012-03-08 11:14:07 -08002440 * Indicates that the screen has changed state and is now off.
2441 *
2442 * @see #onScreenStateChanged(int)
2443 */
2444 public static final int SCREEN_STATE_OFF = 0x0;
2445
2446 /**
2447 * Indicates that the screen has changed state and is now on.
2448 *
Romain Guy1e3d3132012-03-08 15:55:56 -08002449 * @see #onScreenStateChanged(int)
Romain Guybb9908b2012-03-08 11:14:07 -08002450 */
2451 public static final int SCREEN_STATE_ON = 0x1;
2452
2453 /**
Adam Powell637d3372010-08-25 14:37:03 -07002454 * Controls the over-scroll mode for this view.
2455 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2456 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2457 * and {@link #OVER_SCROLL_NEVER}.
2458 */
2459 private int mOverScrollMode;
2460
2461 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002462 * The parent this view is attached to.
2463 * {@hide}
2464 *
2465 * @see #getParent()
2466 */
2467 protected ViewParent mParent;
2468
2469 /**
2470 * {@hide}
2471 */
2472 AttachInfo mAttachInfo;
2473
2474 /**
2475 * {@hide}
2476 */
Romain Guy809a7f62009-05-14 15:44:42 -07002477 @ViewDebug.ExportedProperty(flagMapping = {
2478 @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
2479 name = "FORCE_LAYOUT"),
2480 @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
2481 name = "LAYOUT_REQUIRED"),
2482 @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
Romain Guy5bcdff42009-05-14 21:27:18 -07002483 name = "DRAWING_CACHE_INVALID", outputIf = false),
Romain Guy809a7f62009-05-14 15:44:42 -07002484 @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
2485 @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
2486 @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2487 @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
2488 })
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 int mPrivateFlags;
Christopher Tate3d4bf172011-03-28 16:16:46 -07002490 int mPrivateFlags2;
Chet Haase21433372012-06-05 07:54:09 -07002491 int mPrivateFlags3;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492
2493 /**
Joe Onorato664644d2011-01-23 17:53:23 -08002494 * This view's request for the visibility of the status bar.
2495 * @hide
2496 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002497 @ViewDebug.ExportedProperty(flagMapping = {
2498 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2499 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2500 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2501 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2502 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2503 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2504 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2505 equals = SYSTEM_UI_FLAG_VISIBLE,
2506 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2507 })
Joe Onorato664644d2011-01-23 17:53:23 -08002508 int mSystemUiVisibility;
2509
2510 /**
Chet Haase563d4f22012-04-18 16:20:08 -07002511 * Reference count for transient state.
2512 * @see #setHasTransientState(boolean)
2513 */
2514 int mTransientStateCount = 0;
2515
2516 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 * Count of how many windows this view has been attached to.
2518 */
2519 int mWindowAttachCount;
2520
2521 /**
2522 * The layout parameters associated with this view and used by the parent
2523 * {@link android.view.ViewGroup} to determine how this view should be
2524 * laid out.
2525 * {@hide}
2526 */
2527 protected ViewGroup.LayoutParams mLayoutParams;
2528
2529 /**
2530 * The view flags hold various views states.
2531 * {@hide}
2532 */
2533 @ViewDebug.ExportedProperty
2534 int mViewFlags;
2535
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002536 static class TransformationInfo {
2537 /**
2538 * The transform matrix for the View. This transform is calculated internally
2539 * based on the rotation, scaleX, and scaleY properties. The identity matrix
2540 * is used by default. Do *not* use this variable directly; instead call
2541 * getMatrix(), which will automatically recalculate the matrix if necessary
2542 * to get the correct matrix based on the latest rotation and scale properties.
2543 */
2544 private final Matrix mMatrix = new Matrix();
Chet Haasec3aa3612010-06-17 08:50:37 -07002545
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002546 /**
2547 * The transform matrix for the View. This transform is calculated internally
2548 * based on the rotation, scaleX, and scaleY properties. The identity matrix
2549 * is used by default. Do *not* use this variable directly; instead call
2550 * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2551 * to get the correct matrix based on the latest rotation and scale properties.
2552 */
2553 private Matrix mInverseMatrix;
Chet Haasec3aa3612010-06-17 08:50:37 -07002554
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002555 /**
2556 * An internal variable that tracks whether we need to recalculate the
2557 * transform matrix, based on whether the rotation or scaleX/Y properties
2558 * have changed since the matrix was last calculated.
2559 */
2560 boolean mMatrixDirty = false;
Chet Haasec3aa3612010-06-17 08:50:37 -07002561
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002562 /**
2563 * An internal variable that tracks whether we need to recalculate the
2564 * transform matrix, based on whether the rotation or scaleX/Y properties
2565 * have changed since the matrix was last calculated.
2566 */
2567 private boolean mInverseMatrixDirty = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07002568
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002569 /**
2570 * A variable that tracks whether we need to recalculate the
2571 * transform matrix, based on whether the rotation or scaleX/Y properties
2572 * have changed since the matrix was last calculated. This variable
2573 * is only valid after a call to updateMatrix() or to a function that
2574 * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2575 */
2576 private boolean mMatrixIsIdentity = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07002577
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002578 /**
2579 * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2580 */
2581 private Camera mCamera = null;
Chet Haasefd2b0022010-08-06 13:08:56 -07002582
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002583 /**
2584 * This matrix is used when computing the matrix for 3D rotations.
2585 */
2586 private Matrix matrix3D = null;
Chet Haasefd2b0022010-08-06 13:08:56 -07002587
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002588 /**
2589 * These prev values are used to recalculate a centered pivot point when necessary. The
2590 * pivot point is only used in matrix operations (when rotation, scale, or translation are
2591 * set), so thes values are only used then as well.
2592 */
2593 private int mPrevWidth = -1;
2594 private int mPrevHeight = -1;
Philip Milne6c8ea062012-04-03 17:38:43 -07002595
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002596 /**
2597 * The degrees rotation around the vertical axis through the pivot point.
2598 */
2599 @ViewDebug.ExportedProperty
2600 float mRotationY = 0f;
2601
2602 /**
2603 * The degrees rotation around the horizontal axis through the pivot point.
2604 */
2605 @ViewDebug.ExportedProperty
2606 float mRotationX = 0f;
2607
2608 /**
2609 * The degrees rotation around the pivot point.
2610 */
2611 @ViewDebug.ExportedProperty
2612 float mRotation = 0f;
2613
2614 /**
2615 * The amount of translation of the object away from its left property (post-layout).
2616 */
2617 @ViewDebug.ExportedProperty
2618 float mTranslationX = 0f;
2619
2620 /**
2621 * The amount of translation of the object away from its top property (post-layout).
2622 */
2623 @ViewDebug.ExportedProperty
2624 float mTranslationY = 0f;
2625
2626 /**
2627 * The amount of scale in the x direction around the pivot point. A
2628 * value of 1 means no scaling is applied.
2629 */
2630 @ViewDebug.ExportedProperty
2631 float mScaleX = 1f;
2632
2633 /**
2634 * The amount of scale in the y direction around the pivot point. A
2635 * value of 1 means no scaling is applied.
2636 */
2637 @ViewDebug.ExportedProperty
2638 float mScaleY = 1f;
2639
2640 /**
Chet Haasea33de552012-02-03 16:28:24 -08002641 * The x location of the point around which the view is rotated and scaled.
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002642 */
2643 @ViewDebug.ExportedProperty
2644 float mPivotX = 0f;
2645
2646 /**
Chet Haasea33de552012-02-03 16:28:24 -08002647 * The y location of the point around which the view is rotated and scaled.
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002648 */
2649 @ViewDebug.ExportedProperty
2650 float mPivotY = 0f;
2651
2652 /**
2653 * The opacity of the View. This is a value from 0 to 1, where 0 means
2654 * completely transparent and 1 means completely opaque.
2655 */
2656 @ViewDebug.ExportedProperty
2657 float mAlpha = 1f;
2658 }
2659
2660 TransformationInfo mTransformationInfo;
Chet Haasefd2b0022010-08-06 13:08:56 -07002661
Joe Malin32736f02011-01-19 16:14:20 -08002662 private boolean mLastIsOpaque;
2663
Chet Haasefd2b0022010-08-06 13:08:56 -07002664 /**
2665 * Convenience value to check for float values that are close enough to zero to be considered
2666 * zero.
2667 */
Romain Guy2542d192010-08-18 11:47:12 -07002668 private static final float NONZERO_EPSILON = .001f;
Chet Haasefd2b0022010-08-06 13:08:56 -07002669
2670 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 * The distance in pixels from the left edge of this view's parent
2672 * to the left edge of this view.
2673 * {@hide}
2674 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002675 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 protected int mLeft;
2677 /**
2678 * The distance in pixels from the left edge of this view's parent
2679 * to the right edge of this view.
2680 * {@hide}
2681 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002682 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 protected int mRight;
2684 /**
2685 * The distance in pixels from the top edge of this view's parent
2686 * to the top edge of this view.
2687 * {@hide}
2688 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002689 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 protected int mTop;
2691 /**
2692 * The distance in pixels from the top edge of this view's parent
2693 * to the bottom edge of this view.
2694 * {@hide}
2695 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002696 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 protected int mBottom;
2698
2699 /**
2700 * The offset, in pixels, by which the content of this view is scrolled
2701 * horizontally.
2702 * {@hide}
2703 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002704 @ViewDebug.ExportedProperty(category = "scrolling")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 protected int mScrollX;
2706 /**
2707 * The offset, in pixels, by which the content of this view is scrolled
2708 * vertically.
2709 * {@hide}
2710 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002711 @ViewDebug.ExportedProperty(category = "scrolling")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 protected int mScrollY;
2713
2714 /**
2715 * The left padding in pixels, that is the distance in pixels between the
2716 * left edge of this view and the left edge of its content.
2717 * {@hide}
2718 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002719 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 protected int mPaddingLeft;
2721 /**
2722 * The right padding in pixels, that is the distance in pixels between the
2723 * right edge of this view and the right edge of its content.
2724 * {@hide}
2725 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002726 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 protected int mPaddingRight;
2728 /**
2729 * The top padding in pixels, that is the distance in pixels between the
2730 * top edge of this view and the top edge of its content.
2731 * {@hide}
2732 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002733 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 protected int mPaddingTop;
2735 /**
2736 * The bottom padding in pixels, that is the distance in pixels between the
2737 * bottom edge of this view and the bottom edge of its content.
2738 * {@hide}
2739 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002740 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 protected int mPaddingBottom;
2742
2743 /**
Philip Milne1557fd72012-04-04 23:41:34 -07002744 * The layout insets in pixels, that is the distance in pixels between the
2745 * visible edges of this view its bounds.
2746 */
2747 private Insets mLayoutInsets;
2748
2749 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07002750 * Briefly describes the view and is primarily used for accessibility support.
2751 */
2752 private CharSequence mContentDescription;
2753
2754 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 * Cache the paddingRight set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002756 *
2757 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002758 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002759 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002760 protected int mUserPaddingRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761
2762 /**
2763 * Cache the paddingBottom set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002764 *
2765 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002766 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002767 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002768 protected int mUserPaddingBottom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002770 /**
Adam Powell20232d02010-12-08 21:08:53 -08002771 * Cache the paddingLeft set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002772 *
2773 * @hide
Adam Powell20232d02010-12-08 21:08:53 -08002774 */
2775 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002776 protected int mUserPaddingLeft;
Adam Powell20232d02010-12-08 21:08:53 -08002777
2778 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07002779 * Cache the paddingStart set by the user to append to the scrollbar's size.
2780 *
2781 */
2782 @ViewDebug.ExportedProperty(category = "padding")
2783 int mUserPaddingStart;
2784
2785 /**
2786 * Cache the paddingEnd set by the user to append to the scrollbar's size.
2787 *
2788 */
2789 @ViewDebug.ExportedProperty(category = "padding")
2790 int mUserPaddingEnd;
2791
2792 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07002793 * Whether a left padding has been defined during layout inflation.
2794 *
2795 * @hide
2796 */
2797 boolean mUserPaddingLeftDefined = false;
2798
2799 /**
2800 * Whether a right padding has been defined during layout inflation.
2801 *
2802 * @hide
2803 */
2804 boolean mUserPaddingRightDefined = false;
2805
2806 /**
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07002807 * Default undefined padding
2808 */
2809 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
2810
2811 /**
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002812 * @hide
2813 */
2814 int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2815 /**
2816 * @hide
2817 */
2818 int mOldHeightMeasureSpec = Integer.MIN_VALUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819
Philip Milne6c8ea062012-04-03 17:38:43 -07002820 private Drawable mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821
2822 private int mBackgroundResource;
2823 private boolean mBackgroundSizeChanged;
2824
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002825 static class ListenerInfo {
2826 /**
2827 * Listener used to dispatch focus change events.
2828 * This field should be made private, so it is hidden from the SDK.
2829 * {@hide}
2830 */
2831 protected OnFocusChangeListener mOnFocusChangeListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002833 /**
2834 * Listeners for layout change events.
2835 */
2836 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
Chet Haase21cd1382010-09-01 17:42:29 -07002837
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002838 /**
2839 * Listeners for attach events.
2840 */
2841 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
Adam Powell4afd62b2011-02-18 15:02:18 -08002842
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002843 /**
2844 * Listener used to dispatch click events.
2845 * This field should be made private, so it is hidden from the SDK.
2846 * {@hide}
2847 */
2848 public OnClickListener mOnClickListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002850 /**
2851 * Listener used to dispatch long click events.
2852 * This field should be made private, so it is hidden from the SDK.
2853 * {@hide}
2854 */
2855 protected OnLongClickListener mOnLongClickListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002857 /**
2858 * Listener used to build the context menu.
2859 * This field should be made private, so it is hidden from the SDK.
2860 * {@hide}
2861 */
2862 protected OnCreateContextMenuListener mOnCreateContextMenuListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002864 private OnKeyListener mOnKeyListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002866 private OnTouchListener mOnTouchListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002868 private OnHoverListener mOnHoverListener;
Jeff Brown10b62902011-06-20 16:40:37 -07002869
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002870 private OnGenericMotionListener mOnGenericMotionListener;
Jeff Brown33bbfd22011-02-24 20:55:35 -08002871
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002872 private OnDragListener mOnDragListener;
Chris Tate32affef2010-10-18 15:29:21 -07002873
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002874 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2875 }
2876
2877 ListenerInfo mListenerInfo;
Joe Onorato664644d2011-01-23 17:53:23 -08002878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 /**
2880 * The application environment this view lives in.
2881 * This field should be made private, so it is hidden from the SDK.
2882 * {@hide}
2883 */
2884 protected Context mContext;
2885
Dianne Hackbornab0f4852011-09-12 16:59:06 -07002886 private final Resources mResources;
2887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 private ScrollabilityCache mScrollCache;
2889
2890 private int[] mDrawableState = null;
2891
Romain Guy0211a0a2011-02-14 16:34:59 -08002892 /**
2893 * Set to true when drawing cache is enabled and cannot be created.
Philip Milne6c8ea062012-04-03 17:38:43 -07002894 *
Romain Guy0211a0a2011-02-14 16:34:59 -08002895 * @hide
2896 */
2897 public boolean mCachingFailed;
2898
Romain Guy02890fd2010-08-06 17:58:44 -07002899 private Bitmap mDrawingCache;
2900 private Bitmap mUnscaledDrawingCache;
Romain Guy6c319ca2011-01-11 14:29:25 -08002901 private HardwareLayer mHardwareLayer;
Romain Guy65b345f2011-07-27 18:51:50 -07002902 DisplayList mDisplayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903
2904 /**
2905 * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2906 * the user may specify which view to go to next.
2907 */
2908 private int mNextFocusLeftId = View.NO_ID;
2909
2910 /**
2911 * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2912 * the user may specify which view to go to next.
2913 */
2914 private int mNextFocusRightId = View.NO_ID;
2915
2916 /**
2917 * When this view has focus and the next focus is {@link #FOCUS_UP},
2918 * the user may specify which view to go to next.
2919 */
2920 private int mNextFocusUpId = View.NO_ID;
2921
2922 /**
2923 * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2924 * the user may specify which view to go to next.
2925 */
2926 private int mNextFocusDownId = View.NO_ID;
2927
Jeff Brown4e6319b2010-12-13 10:36:51 -08002928 /**
2929 * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2930 * the user may specify which view to go to next.
2931 */
2932 int mNextFocusForwardId = View.NO_ID;
2933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 private CheckForLongPress mPendingCheckForLongPress;
Adam Powelle14579b2009-12-16 18:39:52 -08002935 private CheckForTap mPendingCheckForTap = null;
Adam Powella35d7682010-03-12 14:48:13 -08002936 private PerformClick mPerformClick;
Svetoslav Ganova0156172011-06-26 17:55:44 -07002937 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
Joe Malin32736f02011-01-19 16:14:20 -08002938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 private UnsetPressedState mUnsetPressedState;
2940
2941 /**
2942 * Whether the long press's action has been invoked. The tap's action is invoked on the
2943 * up event while a long press is invoked as soon as the long press duration is reached, so
2944 * a long press could be performed before the tap is checked, in which case the tap's action
2945 * should not be invoked.
2946 */
2947 private boolean mHasPerformedLongPress;
2948
2949 /**
2950 * The minimum height of the view. We'll try our best to have the height
2951 * of this view to at least this amount.
2952 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002953 @ViewDebug.ExportedProperty(category = "measurement")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 private int mMinHeight;
2955
2956 /**
2957 * The minimum width of the view. We'll try our best to have the width
2958 * of this view to at least this amount.
2959 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002960 @ViewDebug.ExportedProperty(category = "measurement")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 private int mMinWidth;
2962
2963 /**
2964 * The delegate to handle touch events that are physically in this view
2965 * but should be handled by another view.
2966 */
2967 private TouchDelegate mTouchDelegate = null;
2968
2969 /**
2970 * Solid color to use as a background when creating the drawing cache. Enables
2971 * the cache to use 16 bit bitmaps instead of 32 bit.
2972 */
2973 private int mDrawingCacheBackgroundColor = 0;
2974
2975 /**
2976 * Special tree observer used when mAttachInfo is null.
2977 */
2978 private ViewTreeObserver mFloatingTreeObserver;
Joe Malin32736f02011-01-19 16:14:20 -08002979
Adam Powelle14579b2009-12-16 18:39:52 -08002980 /**
2981 * Cache the touch slop from the context that created the view.
2982 */
2983 private int mTouchSlop;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 /**
Chet Haasea00f3862011-02-22 06:34:40 -08002986 * Object that handles automatic animation of view properties.
2987 */
2988 private ViewPropertyAnimator mAnimator = null;
2989
2990 /**
Christopher Tate251602f2011-01-28 17:54:12 -08002991 * Flag indicating that a drag can cross window boundaries. When
2992 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
2993 * with this flag set, all visible applications will be able to participate
2994 * in the drag operation and receive the dragged content.
Christopher Tate7f9ff9d2011-02-14 17:31:13 -08002995 *
2996 * @hide
Christopher Tate02d2b3b2011-01-10 20:43:53 -08002997 */
2998 public static final int DRAG_FLAG_GLOBAL = 1;
2999
3000 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08003001 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3002 */
3003 private float mVerticalScrollFactor;
3004
3005 /**
Adam Powell20232d02010-12-08 21:08:53 -08003006 * Position of the vertical scroll bar.
3007 */
3008 private int mVerticalScrollbarPosition;
3009
3010 /**
3011 * Position the scroll bar at the default position as determined by the system.
3012 */
3013 public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3014
3015 /**
3016 * Position the scroll bar along the left edge.
3017 */
3018 public static final int SCROLLBAR_POSITION_LEFT = 1;
3019
3020 /**
3021 * Position the scroll bar along the right edge.
3022 */
3023 public static final int SCROLLBAR_POSITION_RIGHT = 2;
3024
3025 /**
Romain Guy171c5922011-01-06 10:04:23 -08003026 * Indicates that the view does not have a layer.
Joe Malin32736f02011-01-19 16:14:20 -08003027 *
3028 * @see #getLayerType()
3029 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy171c5922011-01-06 10:04:23 -08003030 * @see #LAYER_TYPE_SOFTWARE
Joe Malin32736f02011-01-19 16:14:20 -08003031 * @see #LAYER_TYPE_HARDWARE
Romain Guy171c5922011-01-06 10:04:23 -08003032 */
3033 public static final int LAYER_TYPE_NONE = 0;
3034
3035 /**
3036 * <p>Indicates that the view has a software layer. A software layer is backed
3037 * by a bitmap and causes the view to be rendered using Android's software
3038 * rendering pipeline, even if hardware acceleration is enabled.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003039 *
Romain Guy171c5922011-01-06 10:04:23 -08003040 * <p>Software layers have various usages:</p>
3041 * <p>When the application is not using hardware acceleration, a software layer
3042 * is useful to apply a specific color filter and/or blending mode and/or
3043 * translucency to a view and all its children.</p>
3044 * <p>When the application is using hardware acceleration, a software layer
3045 * is useful to render drawing primitives not supported by the hardware
3046 * accelerated pipeline. It can also be used to cache a complex view tree
3047 * into a texture and reduce the complexity of drawing operations. For instance,
3048 * when animating a complex view tree with a translation, a software layer can
3049 * be used to render the view tree only once.</p>
3050 * <p>Software layers should be avoided when the affected view tree updates
3051 * often. Every update will require to re-render the software layer, which can
3052 * potentially be slow (particularly when hardware acceleration is turned on
3053 * since the layer will have to be uploaded into a hardware texture after every
3054 * update.)</p>
Joe Malin32736f02011-01-19 16:14:20 -08003055 *
3056 * @see #getLayerType()
3057 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy171c5922011-01-06 10:04:23 -08003058 * @see #LAYER_TYPE_NONE
Joe Malin32736f02011-01-19 16:14:20 -08003059 * @see #LAYER_TYPE_HARDWARE
Romain Guy171c5922011-01-06 10:04:23 -08003060 */
3061 public static final int LAYER_TYPE_SOFTWARE = 1;
3062
3063 /**
3064 * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3065 * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3066 * OpenGL hardware) and causes the view to be rendered using Android's hardware
3067 * rendering pipeline, but only if hardware acceleration is turned on for the
3068 * view hierarchy. When hardware acceleration is turned off, hardware layers
3069 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003070 *
Romain Guy171c5922011-01-06 10:04:23 -08003071 * <p>A hardware layer is useful to apply a specific color filter and/or
3072 * blending mode and/or translucency to a view and all its children.</p>
Romain Guy6c319ca2011-01-11 14:29:25 -08003073 * <p>A hardware layer can be used to cache a complex view tree into a
3074 * texture and reduce the complexity of drawing operations. For instance,
3075 * when animating a complex view tree with a translation, a hardware layer can
3076 * be used to render the view tree only once.</p>
Romain Guy171c5922011-01-06 10:04:23 -08003077 * <p>A hardware layer can also be used to increase the rendering quality when
3078 * rotation transformations are applied on a view. It can also be used to
3079 * prevent potential clipping issues when applying 3D transforms on a view.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003080 *
3081 * @see #getLayerType()
Romain Guy171c5922011-01-06 10:04:23 -08003082 * @see #setLayerType(int, android.graphics.Paint)
3083 * @see #LAYER_TYPE_NONE
3084 * @see #LAYER_TYPE_SOFTWARE
3085 */
3086 public static final int LAYER_TYPE_HARDWARE = 2;
Joe Malin32736f02011-01-19 16:14:20 -08003087
Romain Guy3aaff3a2011-01-12 14:18:47 -08003088 @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3089 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3090 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3091 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3092 })
Romain Guy171c5922011-01-06 10:04:23 -08003093 int mLayerType = LAYER_TYPE_NONE;
3094 Paint mLayerPaint;
Romain Guy3a3133d2011-02-01 22:59:58 -08003095 Rect mLocalDirtyRect;
Romain Guy171c5922011-01-06 10:04:23 -08003096
3097 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07003098 * Set to true when the view is sending hover accessibility events because it
3099 * is the innermost hovered view.
3100 */
3101 private boolean mSendingHoverAccessibilityEvents;
3102
Adam Powella9108a22012-07-18 11:18:09 -07003103 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3104
Jeff Brown87b7f802011-06-21 18:35:45 -07003105 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003106 * Simple constructor to use when creating a view from code.
3107 *
3108 * @param context The Context the view is running in, through which it can
3109 * access the current theme, resources, etc.
3110 */
3111 public View(Context context) {
3112 mContext = context;
3113 mResources = context != null ? context.getResources() : null;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003114 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003115 // Set layout and text direction defaults
3116 mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003117 (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
Svetoslav Ganov42138042012-03-20 11:51:39 -07003118 (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07003119 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
Adam Powelle14579b2009-12-16 18:39:52 -08003120 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
Adam Powell637d3372010-08-25 14:37:03 -07003121 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003122 mUserPaddingStart = UNDEFINED_PADDING;
3123 mUserPaddingEnd = UNDEFINED_PADDING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 }
3125
3126 /**
Chet Haasedb8c9a62012-03-21 18:54:18 -07003127 * Delegate for injecting accessiblity functionality.
3128 */
3129 AccessibilityDelegate mAccessibilityDelegate;
3130
3131 /**
3132 * Consistency verifier for debugging purposes.
3133 * @hide
3134 */
3135 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3136 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3137 new InputEventConsistencyVerifier(this, 0) : null;
3138
3139 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 * Constructor that is called when inflating a view from XML. This is called
3141 * when a view is being constructed from an XML file, supplying attributes
3142 * that were specified in the XML file. This version uses a default style of
3143 * 0, so the only attribute values applied are those in the Context's Theme
3144 * and the given AttributeSet.
3145 *
3146 * <p>
3147 * The method onFinishInflate() will be called after all children have been
3148 * added.
3149 *
3150 * @param context The Context the view is running in, through which it can
3151 * access the current theme, resources, etc.
3152 * @param attrs The attributes of the XML tag that is inflating the view.
3153 * @see #View(Context, AttributeSet, int)
3154 */
3155 public View(Context context, AttributeSet attrs) {
3156 this(context, attrs, 0);
3157 }
3158
3159 /**
3160 * Perform inflation from XML and apply a class-specific base style. This
3161 * constructor of View allows subclasses to use their own base style when
3162 * they are inflating. For example, a Button class's constructor would call
3163 * this version of the super class constructor and supply
3164 * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
3165 * the theme's button style to modify all of the base view attributes (in
3166 * particular its background) as well as the Button class's attributes.
3167 *
3168 * @param context The Context the view is running in, through which it can
3169 * access the current theme, resources, etc.
3170 * @param attrs The attributes of the XML tag that is inflating the view.
3171 * @param defStyle The default style to apply to this view. If 0, no style
3172 * will be applied (beyond what is included in the theme). This may
3173 * either be an attribute resource, whose value will be retrieved
3174 * from the current theme, or an explicit style resource.
3175 * @see #View(Context, AttributeSet)
3176 */
3177 public View(Context context, AttributeSet attrs, int defStyle) {
3178 this(context);
3179
3180 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
3181 defStyle, 0);
3182
3183 Drawable background = null;
3184
3185 int leftPadding = -1;
3186 int topPadding = -1;
3187 int rightPadding = -1;
3188 int bottomPadding = -1;
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003189 int startPadding = UNDEFINED_PADDING;
3190 int endPadding = UNDEFINED_PADDING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003191
3192 int padding = -1;
3193
3194 int viewFlagValues = 0;
3195 int viewFlagMasks = 0;
3196
3197 boolean setScrollContainer = false;
Romain Guy8506ab42009-06-11 17:35:47 -07003198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 int x = 0;
3200 int y = 0;
3201
Chet Haase73066682010-11-29 15:55:32 -08003202 float tx = 0;
3203 float ty = 0;
3204 float rotation = 0;
3205 float rotationX = 0;
3206 float rotationY = 0;
3207 float sx = 1f;
3208 float sy = 1f;
3209 boolean transformSet = false;
3210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
Adam Powell637d3372010-08-25 14:37:03 -07003212 int overScrollMode = mOverScrollMode;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003213 boolean initializeScrollbars = false;
3214
3215 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 final int N = a.getIndexCount();
3218 for (int i = 0; i < N; i++) {
3219 int attr = a.getIndex(i);
3220 switch (attr) {
3221 case com.android.internal.R.styleable.View_background:
3222 background = a.getDrawable(attr);
3223 break;
3224 case com.android.internal.R.styleable.View_padding:
3225 padding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003226 mUserPaddingLeftDefined = true;
3227 mUserPaddingRightDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 break;
3229 case com.android.internal.R.styleable.View_paddingLeft:
3230 leftPadding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003231 mUserPaddingLeftDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 break;
3233 case com.android.internal.R.styleable.View_paddingTop:
3234 topPadding = a.getDimensionPixelSize(attr, -1);
3235 break;
3236 case com.android.internal.R.styleable.View_paddingRight:
3237 rightPadding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003238 mUserPaddingRightDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 break;
3240 case com.android.internal.R.styleable.View_paddingBottom:
3241 bottomPadding = a.getDimensionPixelSize(attr, -1);
3242 break;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003243 case com.android.internal.R.styleable.View_paddingStart:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003244 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003245 break;
3246 case com.android.internal.R.styleable.View_paddingEnd:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003247 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003248 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 case com.android.internal.R.styleable.View_scrollX:
3250 x = a.getDimensionPixelOffset(attr, 0);
3251 break;
3252 case com.android.internal.R.styleable.View_scrollY:
3253 y = a.getDimensionPixelOffset(attr, 0);
3254 break;
Chet Haase73066682010-11-29 15:55:32 -08003255 case com.android.internal.R.styleable.View_alpha:
3256 setAlpha(a.getFloat(attr, 1f));
3257 break;
3258 case com.android.internal.R.styleable.View_transformPivotX:
3259 setPivotX(a.getDimensionPixelOffset(attr, 0));
3260 break;
3261 case com.android.internal.R.styleable.View_transformPivotY:
3262 setPivotY(a.getDimensionPixelOffset(attr, 0));
3263 break;
3264 case com.android.internal.R.styleable.View_translationX:
3265 tx = a.getDimensionPixelOffset(attr, 0);
3266 transformSet = true;
3267 break;
3268 case com.android.internal.R.styleable.View_translationY:
3269 ty = a.getDimensionPixelOffset(attr, 0);
3270 transformSet = true;
3271 break;
3272 case com.android.internal.R.styleable.View_rotation:
3273 rotation = a.getFloat(attr, 0);
3274 transformSet = true;
3275 break;
3276 case com.android.internal.R.styleable.View_rotationX:
3277 rotationX = a.getFloat(attr, 0);
3278 transformSet = true;
3279 break;
3280 case com.android.internal.R.styleable.View_rotationY:
3281 rotationY = a.getFloat(attr, 0);
3282 transformSet = true;
3283 break;
3284 case com.android.internal.R.styleable.View_scaleX:
3285 sx = a.getFloat(attr, 1f);
3286 transformSet = true;
3287 break;
3288 case com.android.internal.R.styleable.View_scaleY:
3289 sy = a.getFloat(attr, 1f);
3290 transformSet = true;
3291 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 case com.android.internal.R.styleable.View_id:
3293 mID = a.getResourceId(attr, NO_ID);
3294 break;
3295 case com.android.internal.R.styleable.View_tag:
3296 mTag = a.getText(attr);
3297 break;
3298 case com.android.internal.R.styleable.View_fitsSystemWindows:
3299 if (a.getBoolean(attr, false)) {
3300 viewFlagValues |= FITS_SYSTEM_WINDOWS;
3301 viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3302 }
3303 break;
3304 case com.android.internal.R.styleable.View_focusable:
3305 if (a.getBoolean(attr, false)) {
3306 viewFlagValues |= FOCUSABLE;
3307 viewFlagMasks |= FOCUSABLE_MASK;
3308 }
3309 break;
3310 case com.android.internal.R.styleable.View_focusableInTouchMode:
3311 if (a.getBoolean(attr, false)) {
3312 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3313 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3314 }
3315 break;
3316 case com.android.internal.R.styleable.View_clickable:
3317 if (a.getBoolean(attr, false)) {
3318 viewFlagValues |= CLICKABLE;
3319 viewFlagMasks |= CLICKABLE;
3320 }
3321 break;
3322 case com.android.internal.R.styleable.View_longClickable:
3323 if (a.getBoolean(attr, false)) {
3324 viewFlagValues |= LONG_CLICKABLE;
3325 viewFlagMasks |= LONG_CLICKABLE;
3326 }
3327 break;
3328 case com.android.internal.R.styleable.View_saveEnabled:
3329 if (!a.getBoolean(attr, true)) {
3330 viewFlagValues |= SAVE_DISABLED;
3331 viewFlagMasks |= SAVE_DISABLED_MASK;
3332 }
3333 break;
3334 case com.android.internal.R.styleable.View_duplicateParentState:
3335 if (a.getBoolean(attr, false)) {
3336 viewFlagValues |= DUPLICATE_PARENT_STATE;
3337 viewFlagMasks |= DUPLICATE_PARENT_STATE;
3338 }
3339 break;
3340 case com.android.internal.R.styleable.View_visibility:
3341 final int visibility = a.getInt(attr, 0);
3342 if (visibility != 0) {
3343 viewFlagValues |= VISIBILITY_FLAGS[visibility];
3344 viewFlagMasks |= VISIBILITY_MASK;
3345 }
3346 break;
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07003347 case com.android.internal.R.styleable.View_layoutDirection:
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003348 // Clear any layout direction flags (included resolved bits) already set
3349 mPrivateFlags2 &= ~(LAYOUT_DIRECTION_MASK | LAYOUT_DIRECTION_RESOLVED_MASK);
3350 // Set the layout direction flags depending on the value of the attribute
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07003351 final int layoutDirection = a.getInt(attr, -1);
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003352 final int value = (layoutDirection != -1) ?
3353 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3354 mPrivateFlags2 |= (value << LAYOUT_DIRECTION_MASK_SHIFT);
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -07003355 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003356 case com.android.internal.R.styleable.View_drawingCacheQuality:
3357 final int cacheQuality = a.getInt(attr, 0);
3358 if (cacheQuality != 0) {
3359 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3360 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3361 }
3362 break;
svetoslavganov75986cf2009-05-14 22:28:01 -07003363 case com.android.internal.R.styleable.View_contentDescription:
Svetoslav Ganove47957a2012-06-05 14:46:50 -07003364 setContentDescription(a.getString(attr));
svetoslavganov75986cf2009-05-14 22:28:01 -07003365 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3367 if (!a.getBoolean(attr, true)) {
3368 viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3369 viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3370 }
Karl Rosaen61ab2702009-06-23 11:10:25 -07003371 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3373 if (!a.getBoolean(attr, true)) {
3374 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3375 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3376 }
Karl Rosaen61ab2702009-06-23 11:10:25 -07003377 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378 case R.styleable.View_scrollbars:
3379 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3380 if (scrollbars != SCROLLBARS_NONE) {
3381 viewFlagValues |= scrollbars;
3382 viewFlagMasks |= SCROLLBARS_MASK;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003383 initializeScrollbars = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 }
3385 break;
Romain Guy2a9fa892011-09-28 16:50:02 -07003386 //noinspection deprecation
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387 case R.styleable.View_fadingEdge:
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003388 if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
Romain Guy1ef3fdb2011-09-09 15:30:30 -07003389 // Ignore the attribute starting with ICS
3390 break;
3391 }
3392 // With builds < ICS, fall through and apply fading edges
3393 case R.styleable.View_requiresFadingEdge:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3395 if (fadingEdge != FADING_EDGE_NONE) {
3396 viewFlagValues |= fadingEdge;
3397 viewFlagMasks |= FADING_EDGE_MASK;
3398 initializeFadingEdge(a);
3399 }
3400 break;
3401 case R.styleable.View_scrollbarStyle:
3402 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3403 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3404 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3405 viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3406 }
3407 break;
3408 case R.styleable.View_isScrollContainer:
3409 setScrollContainer = true;
3410 if (a.getBoolean(attr, false)) {
3411 setScrollContainer(true);
3412 }
3413 break;
3414 case com.android.internal.R.styleable.View_keepScreenOn:
3415 if (a.getBoolean(attr, false)) {
3416 viewFlagValues |= KEEP_SCREEN_ON;
3417 viewFlagMasks |= KEEP_SCREEN_ON;
3418 }
3419 break;
Jeff Brown85a31762010-09-01 17:01:00 -07003420 case R.styleable.View_filterTouchesWhenObscured:
3421 if (a.getBoolean(attr, false)) {
3422 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3423 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3424 }
3425 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 case R.styleable.View_nextFocusLeft:
3427 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3428 break;
3429 case R.styleable.View_nextFocusRight:
3430 mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3431 break;
3432 case R.styleable.View_nextFocusUp:
3433 mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3434 break;
3435 case R.styleable.View_nextFocusDown:
3436 mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3437 break;
Jeff Brown4e6319b2010-12-13 10:36:51 -08003438 case R.styleable.View_nextFocusForward:
3439 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3440 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 case R.styleable.View_minWidth:
3442 mMinWidth = a.getDimensionPixelSize(attr, 0);
3443 break;
3444 case R.styleable.View_minHeight:
3445 mMinHeight = a.getDimensionPixelSize(attr, 0);
3446 break;
Romain Guy9a817362009-05-01 10:57:14 -07003447 case R.styleable.View_onClick:
Romain Guy870e09f2009-07-06 16:35:25 -07003448 if (context.isRestricted()) {
Joe Malin32736f02011-01-19 16:14:20 -08003449 throw new IllegalStateException("The android:onClick attribute cannot "
Romain Guy870e09f2009-07-06 16:35:25 -07003450 + "be used within a restricted context");
3451 }
3452
Romain Guy9a817362009-05-01 10:57:14 -07003453 final String handlerName = a.getString(attr);
3454 if (handlerName != null) {
3455 setOnClickListener(new OnClickListener() {
3456 private Method mHandler;
3457
3458 public void onClick(View v) {
3459 if (mHandler == null) {
3460 try {
3461 mHandler = getContext().getClass().getMethod(handlerName,
3462 View.class);
3463 } catch (NoSuchMethodException e) {
Joe Onorato42e14d72010-03-11 14:51:17 -08003464 int id = getId();
3465 String idText = id == NO_ID ? "" : " with id '"
3466 + getContext().getResources().getResourceEntryName(
3467 id) + "'";
Romain Guy9a817362009-05-01 10:57:14 -07003468 throw new IllegalStateException("Could not find a method " +
Joe Onorato42e14d72010-03-11 14:51:17 -08003469 handlerName + "(View) in the activity "
3470 + getContext().getClass() + " for onClick handler"
3471 + " on view " + View.this.getClass() + idText, e);
Romain Guy9a817362009-05-01 10:57:14 -07003472 }
3473 }
3474
3475 try {
3476 mHandler.invoke(getContext(), View.this);
3477 } catch (IllegalAccessException e) {
3478 throw new IllegalStateException("Could not execute non "
3479 + "public method of the activity", e);
3480 } catch (InvocationTargetException e) {
3481 throw new IllegalStateException("Could not execute "
3482 + "method of the activity", e);
3483 }
3484 }
3485 });
3486 }
3487 break;
Adam Powell637d3372010-08-25 14:37:03 -07003488 case R.styleable.View_overScrollMode:
3489 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3490 break;
Adam Powell20232d02010-12-08 21:08:53 -08003491 case R.styleable.View_verticalScrollbarPosition:
3492 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3493 break;
Romain Guy171c5922011-01-06 10:04:23 -08003494 case R.styleable.View_layerType:
3495 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3496 break;
Fabrice Di Meglio22268862011-06-27 18:13:18 -07003497 case R.styleable.View_textDirection:
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003498 // Clear any text direction flag already set
3499 mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
3500 // Set the text direction flags depending on the value of the attribute
3501 final int textDirection = a.getInt(attr, -1);
3502 if (textDirection != -1) {
3503 mPrivateFlags2 |= TEXT_DIRECTION_FLAGS[textDirection];
3504 }
Fabrice Di Meglio22268862011-06-27 18:13:18 -07003505 break;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003506 case R.styleable.View_textAlignment:
3507 // Clear any text alignment flag already set
3508 mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
3509 // Set the text alignment flag depending on the value of the attribute
3510 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
3511 mPrivateFlags2 |= TEXT_ALIGNMENT_FLAGS[textAlignment];
3512 break;
Svetoslav Ganov42138042012-03-20 11:51:39 -07003513 case R.styleable.View_importantForAccessibility:
3514 setImportantForAccessibility(a.getInt(attr,
3515 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
Svetoslav Ganov86783472012-06-06 21:12:20 -07003516 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003517 }
3518 }
3519
Adam Powell637d3372010-08-25 14:37:03 -07003520 setOverScrollMode(overScrollMode);
3521
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003522 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3523 // the resolved layout direction). Those cached values will be used later during padding
3524 // resolution.
Fabrice Di Megliof9e36502011-06-21 18:41:48 -07003525 mUserPaddingStart = startPadding;
3526 mUserPaddingEnd = endPadding;
3527
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003528 if (background != null) {
3529 setBackground(background);
3530 }
Fabrice Di Meglio509708d2012-03-06 15:41:11 -08003531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 if (padding >= 0) {
3533 leftPadding = padding;
3534 topPadding = padding;
3535 rightPadding = padding;
3536 bottomPadding = padding;
3537 }
3538
3539 // If the user specified the padding (either with android:padding or
3540 // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3541 // use the default padding or the padding from the background drawable
3542 // (stored at this point in mPadding*)
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003543 internalSetPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 topPadding >= 0 ? topPadding : mPaddingTop,
3545 rightPadding >= 0 ? rightPadding : mPaddingRight,
3546 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3547
3548 if (viewFlagMasks != 0) {
3549 setFlags(viewFlagValues, viewFlagMasks);
3550 }
3551
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003552 if (initializeScrollbars) {
3553 initializeScrollbars(a);
3554 }
3555
3556 a.recycle();
3557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 // Needs to be called after mViewFlags is set
3559 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3560 recomputePadding();
3561 }
3562
3563 if (x != 0 || y != 0) {
3564 scrollTo(x, y);
3565 }
3566
Chet Haase73066682010-11-29 15:55:32 -08003567 if (transformSet) {
3568 setTranslationX(tx);
3569 setTranslationY(ty);
3570 setRotation(rotation);
3571 setRotationX(rotationX);
3572 setRotationY(rotationY);
3573 setScaleX(sx);
3574 setScaleY(sy);
3575 }
3576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3578 setScrollContainer(true);
3579 }
Romain Guy8f1344f52009-05-15 16:03:59 -07003580
3581 computeOpaqueFlags();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 }
3583
3584 /**
3585 * Non-public constructor for use in testing
3586 */
3587 View() {
Dianne Hackbornab0f4852011-09-12 16:59:06 -07003588 mResources = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 }
3590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 /**
3592 * <p>
3593 * Initializes the fading edges from a given set of styled attributes. This
3594 * method should be called by subclasses that need fading edges and when an
3595 * instance of these subclasses is created programmatically rather than
3596 * being inflated from XML. This method is automatically called when the XML
3597 * is inflated.
3598 * </p>
3599 *
3600 * @param a the styled attributes set to initialize the fading edges from
3601 */
3602 protected void initializeFadingEdge(TypedArray a) {
3603 initScrollCache();
3604
3605 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3606 R.styleable.View_fadingEdgeLength,
3607 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3608 }
3609
3610 /**
3611 * Returns the size of the vertical faded edges used to indicate that more
3612 * content in this view is visible.
3613 *
3614 * @return The size in pixels of the vertical faded edge or 0 if vertical
3615 * faded edges are not enabled for this view.
3616 * @attr ref android.R.styleable#View_fadingEdgeLength
3617 */
3618 public int getVerticalFadingEdgeLength() {
3619 if (isVerticalFadingEdgeEnabled()) {
3620 ScrollabilityCache cache = mScrollCache;
3621 if (cache != null) {
3622 return cache.fadingEdgeLength;
3623 }
3624 }
3625 return 0;
3626 }
3627
3628 /**
3629 * Set the size of the faded edge used to indicate that more content in this
3630 * view is available. Will not change whether the fading edge is enabled; use
Romain Guy5c22a8c2011-05-13 11:48:45 -07003631 * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3632 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3633 * for the vertical or horizontal fading edges.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 *
3635 * @param length The size in pixels of the faded edge used to indicate that more
3636 * content in this view is visible.
3637 */
3638 public void setFadingEdgeLength(int length) {
3639 initScrollCache();
3640 mScrollCache.fadingEdgeLength = length;
3641 }
3642
3643 /**
3644 * Returns the size of the horizontal faded edges used to indicate that more
3645 * content in this view is visible.
3646 *
3647 * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3648 * faded edges are not enabled for this view.
3649 * @attr ref android.R.styleable#View_fadingEdgeLength
3650 */
3651 public int getHorizontalFadingEdgeLength() {
3652 if (isHorizontalFadingEdgeEnabled()) {
3653 ScrollabilityCache cache = mScrollCache;
3654 if (cache != null) {
3655 return cache.fadingEdgeLength;
3656 }
3657 }
3658 return 0;
3659 }
3660
3661 /**
3662 * Returns the width of the vertical scrollbar.
3663 *
3664 * @return The width in pixels of the vertical scrollbar or 0 if there
3665 * is no vertical scrollbar.
3666 */
3667 public int getVerticalScrollbarWidth() {
3668 ScrollabilityCache cache = mScrollCache;
3669 if (cache != null) {
3670 ScrollBarDrawable scrollBar = cache.scrollBar;
3671 if (scrollBar != null) {
3672 int size = scrollBar.getSize(true);
3673 if (size <= 0) {
3674 size = cache.scrollBarSize;
3675 }
3676 return size;
3677 }
3678 return 0;
3679 }
3680 return 0;
3681 }
3682
3683 /**
3684 * Returns the height of the horizontal scrollbar.
3685 *
3686 * @return The height in pixels of the horizontal scrollbar or 0 if
3687 * there is no horizontal scrollbar.
3688 */
3689 protected int getHorizontalScrollbarHeight() {
3690 ScrollabilityCache cache = mScrollCache;
3691 if (cache != null) {
3692 ScrollBarDrawable scrollBar = cache.scrollBar;
3693 if (scrollBar != null) {
3694 int size = scrollBar.getSize(false);
3695 if (size <= 0) {
3696 size = cache.scrollBarSize;
3697 }
3698 return size;
3699 }
3700 return 0;
3701 }
3702 return 0;
3703 }
3704
3705 /**
3706 * <p>
3707 * Initializes the scrollbars from a given set of styled attributes. This
3708 * method should be called by subclasses that need scrollbars and when an
3709 * instance of these subclasses is created programmatically rather than
3710 * being inflated from XML. This method is automatically called when the XML
3711 * is inflated.
3712 * </p>
3713 *
3714 * @param a the styled attributes set to initialize the scrollbars from
3715 */
3716 protected void initializeScrollbars(TypedArray a) {
3717 initScrollCache();
3718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 final ScrollabilityCache scrollabilityCache = mScrollCache;
Joe Malin32736f02011-01-19 16:14:20 -08003720
Mike Cleronf116bf82009-09-27 19:14:12 -07003721 if (scrollabilityCache.scrollBar == null) {
3722 scrollabilityCache.scrollBar = new ScrollBarDrawable();
3723 }
Joe Malin32736f02011-01-19 16:14:20 -08003724
Romain Guy8bda2482010-03-02 11:42:11 -08003725 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726
Mike Cleronf116bf82009-09-27 19:14:12 -07003727 if (!fadeScrollbars) {
3728 scrollabilityCache.state = ScrollabilityCache.ON;
3729 }
3730 scrollabilityCache.fadeScrollBars = fadeScrollbars;
Joe Malin32736f02011-01-19 16:14:20 -08003731
3732
Mike Cleronf116bf82009-09-27 19:14:12 -07003733 scrollabilityCache.scrollBarFadeDuration = a.getInt(
3734 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3735 .getScrollBarFadeDuration());
3736 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3737 R.styleable.View_scrollbarDefaultDelayBeforeFade,
3738 ViewConfiguration.getScrollDefaultDelay());
3739
Joe Malin32736f02011-01-19 16:14:20 -08003740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3742 com.android.internal.R.styleable.View_scrollbarSize,
3743 ViewConfiguration.get(mContext).getScaledScrollBarSize());
3744
3745 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3746 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3747
3748 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3749 if (thumb != null) {
3750 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3751 }
3752
3753 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3754 false);
3755 if (alwaysDraw) {
3756 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3757 }
3758
3759 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3760 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3761
3762 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3763 if (thumb != null) {
3764 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3765 }
3766
3767 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3768 false);
3769 if (alwaysDraw) {
3770 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3771 }
3772
Fabrice Di Megliob03b4342012-06-04 12:55:30 -07003773 // Apply layout direction to the new Drawables if needed
3774 final int layoutDirection = getResolvedLayoutDirection();
3775 if (track != null) {
3776 track.setLayoutDirection(layoutDirection);
3777 }
3778 if (thumb != null) {
3779 thumb.setLayoutDirection(layoutDirection);
3780 }
3781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 // Re-apply user/background padding so that scrollbar(s) get added
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003783 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 }
3785
3786 /**
3787 * <p>
3788 * Initalizes the scrollability cache if necessary.
3789 * </p>
3790 */
3791 private void initScrollCache() {
3792 if (mScrollCache == null) {
Mike Cleronf116bf82009-09-27 19:14:12 -07003793 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 }
3795 }
3796
Philip Milne6c8ea062012-04-03 17:38:43 -07003797 private ScrollabilityCache getScrollCache() {
3798 initScrollCache();
3799 return mScrollCache;
3800 }
3801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 /**
Adam Powell20232d02010-12-08 21:08:53 -08003803 * Set the position of the vertical scroll bar. Should be one of
3804 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3805 * {@link #SCROLLBAR_POSITION_RIGHT}.
3806 *
3807 * @param position Where the vertical scroll bar should be positioned.
3808 */
3809 public void setVerticalScrollbarPosition(int position) {
3810 if (mVerticalScrollbarPosition != position) {
3811 mVerticalScrollbarPosition = position;
3812 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003813 resolvePadding();
Adam Powell20232d02010-12-08 21:08:53 -08003814 }
3815 }
3816
3817 /**
3818 * @return The position where the vertical scroll bar will show, if applicable.
3819 * @see #setVerticalScrollbarPosition(int)
3820 */
3821 public int getVerticalScrollbarPosition() {
3822 return mVerticalScrollbarPosition;
3823 }
3824
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003825 ListenerInfo getListenerInfo() {
3826 if (mListenerInfo != null) {
3827 return mListenerInfo;
3828 }
3829 mListenerInfo = new ListenerInfo();
3830 return mListenerInfo;
3831 }
3832
Adam Powell20232d02010-12-08 21:08:53 -08003833 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 * Register a callback to be invoked when focus of this view changed.
3835 *
3836 * @param l The callback that will run.
3837 */
3838 public void setOnFocusChangeListener(OnFocusChangeListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003839 getListenerInfo().mOnFocusChangeListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 }
3841
3842 /**
Chet Haase21cd1382010-09-01 17:42:29 -07003843 * Add a listener that will be called when the bounds of the view change due to
3844 * layout processing.
3845 *
3846 * @param listener The listener that will be called when layout bounds change.
3847 */
3848 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003849 ListenerInfo li = getListenerInfo();
3850 if (li.mOnLayoutChangeListeners == null) {
3851 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
Chet Haase21cd1382010-09-01 17:42:29 -07003852 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003853 if (!li.mOnLayoutChangeListeners.contains(listener)) {
3854 li.mOnLayoutChangeListeners.add(listener);
Chet Haase1a76dcd2011-10-06 11:16:40 -07003855 }
Chet Haase21cd1382010-09-01 17:42:29 -07003856 }
3857
3858 /**
3859 * Remove a listener for layout changes.
3860 *
3861 * @param listener The listener for layout bounds change.
3862 */
3863 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003864 ListenerInfo li = mListenerInfo;
3865 if (li == null || li.mOnLayoutChangeListeners == null) {
Chet Haase21cd1382010-09-01 17:42:29 -07003866 return;
3867 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003868 li.mOnLayoutChangeListeners.remove(listener);
Chet Haase21cd1382010-09-01 17:42:29 -07003869 }
3870
3871 /**
Adam Powell4afd62b2011-02-18 15:02:18 -08003872 * Add a listener for attach state changes.
3873 *
3874 * This listener will be called whenever this view is attached or detached
3875 * from a window. Remove the listener using
3876 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3877 *
3878 * @param listener Listener to attach
3879 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3880 */
3881 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003882 ListenerInfo li = getListenerInfo();
3883 if (li.mOnAttachStateChangeListeners == null) {
3884 li.mOnAttachStateChangeListeners
3885 = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
Adam Powell4afd62b2011-02-18 15:02:18 -08003886 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003887 li.mOnAttachStateChangeListeners.add(listener);
Adam Powell4afd62b2011-02-18 15:02:18 -08003888 }
3889
3890 /**
3891 * Remove a listener for attach state changes. The listener will receive no further
3892 * notification of window attach/detach events.
3893 *
3894 * @param listener Listener to remove
3895 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3896 */
3897 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003898 ListenerInfo li = mListenerInfo;
3899 if (li == null || li.mOnAttachStateChangeListeners == null) {
Adam Powell4afd62b2011-02-18 15:02:18 -08003900 return;
3901 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003902 li.mOnAttachStateChangeListeners.remove(listener);
Adam Powell4afd62b2011-02-18 15:02:18 -08003903 }
3904
3905 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 * Returns the focus-change callback registered for this view.
3907 *
3908 * @return The callback, or null if one is not registered.
3909 */
3910 public OnFocusChangeListener getOnFocusChangeListener() {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003911 ListenerInfo li = mListenerInfo;
3912 return li != null ? li.mOnFocusChangeListener : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 }
3914
3915 /**
3916 * Register a callback to be invoked when this view is clicked. If this view is not
3917 * clickable, it becomes clickable.
3918 *
3919 * @param l The callback that will run
3920 *
3921 * @see #setClickable(boolean)
3922 */
3923 public void setOnClickListener(OnClickListener l) {
3924 if (!isClickable()) {
3925 setClickable(true);
3926 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003927 getListenerInfo().mOnClickListener = l;
3928 }
3929
3930 /**
3931 * Return whether this view has an attached OnClickListener. Returns
3932 * true if there is a listener, false if there is none.
3933 */
3934 public boolean hasOnClickListeners() {
3935 ListenerInfo li = mListenerInfo;
3936 return (li != null && li.mOnClickListener != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 }
3938
3939 /**
3940 * Register a callback to be invoked when this view is clicked and held. If this view is not
3941 * long clickable, it becomes long clickable.
3942 *
3943 * @param l The callback that will run
3944 *
3945 * @see #setLongClickable(boolean)
3946 */
3947 public void setOnLongClickListener(OnLongClickListener l) {
3948 if (!isLongClickable()) {
3949 setLongClickable(true);
3950 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003951 getListenerInfo().mOnLongClickListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 }
3953
3954 /**
3955 * Register a callback to be invoked when the context menu for this view is
3956 * being built. If this view is not long clickable, it becomes long clickable.
3957 *
3958 * @param l The callback that will run
3959 *
3960 */
3961 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
3962 if (!isLongClickable()) {
3963 setLongClickable(true);
3964 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003965 getListenerInfo().mOnCreateContextMenuListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 }
3967
3968 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003969 * Call this view's OnClickListener, if it is defined. Performs all normal
3970 * actions associated with clicking: reporting accessibility event, playing
3971 * a sound, etc.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 *
3973 * @return True there was an assigned OnClickListener that was called, false
3974 * otherwise is returned.
3975 */
3976 public boolean performClick() {
svetoslavganov75986cf2009-05-14 22:28:01 -07003977 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
3978
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003979 ListenerInfo li = mListenerInfo;
3980 if (li != null && li.mOnClickListener != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 playSoundEffect(SoundEffectConstants.CLICK);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003982 li.mOnClickListener.onClick(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 return true;
3984 }
3985
3986 return false;
3987 }
3988
3989 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003990 * Directly call any attached OnClickListener. Unlike {@link #performClick()},
3991 * this only calls the listener, and does not do any associated clicking
3992 * actions like reporting an accessibility event.
3993 *
3994 * @return True there was an assigned OnClickListener that was called, false
3995 * otherwise is returned.
3996 */
3997 public boolean callOnClick() {
3998 ListenerInfo li = mListenerInfo;
3999 if (li != null && li.mOnClickListener != null) {
4000 li.mOnClickListener.onClick(this);
4001 return true;
4002 }
4003 return false;
4004 }
4005
4006 /**
Gilles Debunnef788a9f2010-07-22 10:17:23 -07004007 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4008 * OnLongClickListener did not consume the event.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 *
Gilles Debunnef788a9f2010-07-22 10:17:23 -07004010 * @return True if one of the above receivers consumed the event, false otherwise.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 */
4012 public boolean performLongClick() {
svetoslavganov75986cf2009-05-14 22:28:01 -07004013 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 boolean handled = false;
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004016 ListenerInfo li = mListenerInfo;
4017 if (li != null && li.mOnLongClickListener != null) {
4018 handled = li.mOnLongClickListener.onLongClick(View.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 }
4020 if (!handled) {
4021 handled = showContextMenu();
4022 }
4023 if (handled) {
4024 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4025 }
4026 return handled;
4027 }
4028
4029 /**
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004030 * Performs button-related actions during a touch down event.
4031 *
4032 * @param event The event.
4033 * @return True if the down was consumed.
4034 *
4035 * @hide
4036 */
4037 protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4038 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4039 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4040 return true;
4041 }
4042 }
4043 return false;
4044 }
4045
4046 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 * Bring up the context menu for this view.
4048 *
4049 * @return Whether a context menu was displayed.
4050 */
4051 public boolean showContextMenu() {
4052 return getParent().showContextMenuForChild(this);
4053 }
4054
4055 /**
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004056 * Bring up the context menu for this view, referring to the item under the specified point.
4057 *
4058 * @param x The referenced x coordinate.
4059 * @param y The referenced y coordinate.
4060 * @param metaState The keyboard modifiers that were pressed.
4061 * @return Whether a context menu was displayed.
4062 *
4063 * @hide
4064 */
4065 public boolean showContextMenu(float x, float y, int metaState) {
4066 return showContextMenu();
4067 }
4068
4069 /**
Adam Powell6e346362010-07-23 10:18:23 -07004070 * Start an action mode.
4071 *
4072 * @param callback Callback that will control the lifecycle of the action mode
4073 * @return The new action mode if it is started, null otherwise
4074 *
4075 * @see ActionMode
4076 */
4077 public ActionMode startActionMode(ActionMode.Callback callback) {
John Reck5160e2a2012-02-22 09:35:12 -08004078 ViewParent parent = getParent();
4079 if (parent == null) return null;
4080 return parent.startActionModeForChild(this, callback);
Adam Powell6e346362010-07-23 10:18:23 -07004081 }
4082
4083 /**
Jean Chalard405bc512012-05-29 19:12:34 +09004084 * Register a callback to be invoked when a hardware key is pressed in this view.
4085 * Key presses in software input methods will generally not trigger the methods of
4086 * this listener.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 * @param l the key listener to attach to this view
4088 */
4089 public void setOnKeyListener(OnKeyListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004090 getListenerInfo().mOnKeyListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 }
4092
4093 /**
4094 * Register a callback to be invoked when a touch event is sent to this view.
4095 * @param l the touch listener to attach to this view
4096 */
4097 public void setOnTouchListener(OnTouchListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004098 getListenerInfo().mOnTouchListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 }
4100
4101 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08004102 * Register a callback to be invoked when a generic motion event is sent to this view.
4103 * @param l the generic motion listener to attach to this view
4104 */
4105 public void setOnGenericMotionListener(OnGenericMotionListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004106 getListenerInfo().mOnGenericMotionListener = l;
Jeff Brown33bbfd22011-02-24 20:55:35 -08004107 }
4108
4109 /**
Jeff Brown53ca3f12011-06-27 18:36:00 -07004110 * Register a callback to be invoked when a hover event is sent to this view.
4111 * @param l the hover listener to attach to this view
4112 */
4113 public void setOnHoverListener(OnHoverListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004114 getListenerInfo().mOnHoverListener = l;
Jeff Brown53ca3f12011-06-27 18:36:00 -07004115 }
4116
4117 /**
Joe Malin32736f02011-01-19 16:14:20 -08004118 * Register a drag event listener callback object for this View. The parameter is
4119 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4120 * View, the system calls the
4121 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4122 * @param l An implementation of {@link android.view.View.OnDragListener}.
Chris Tate32affef2010-10-18 15:29:21 -07004123 */
4124 public void setOnDragListener(OnDragListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004125 getListenerInfo().mOnDragListener = l;
Chris Tate32affef2010-10-18 15:29:21 -07004126 }
4127
4128 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07004129 * Give this view focus. This will cause
4130 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 *
4132 * Note: this does not check whether this {@link View} should get focus, it just
4133 * gives it focus no matter what. It should only be called internally by framework
4134 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4135 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08004136 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4137 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 * focus moved when requestFocus() is called. It may not always
4139 * apply, in which case use the default View.FOCUS_DOWN.
4140 * @param previouslyFocusedRect The rectangle of the view that had focus
4141 * prior in this View's coordinate system.
4142 */
4143 void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
4144 if (DBG) {
4145 System.out.println(this + " requestFocus()");
4146 }
4147
4148 if ((mPrivateFlags & FOCUSED) == 0) {
4149 mPrivateFlags |= FOCUSED;
4150
4151 if (mParent != null) {
4152 mParent.requestChildFocus(this, this);
4153 }
4154
4155 onFocusChanged(true, direction, previouslyFocusedRect);
4156 refreshDrawableState();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004157
4158 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4159 notifyAccessibilityStateChanged();
4160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 }
4162 }
4163
4164 /**
4165 * Request that a rectangle of this view be visible on the screen,
4166 * scrolling if necessary just enough.
4167 *
4168 * <p>A View should call this if it maintains some notion of which part
4169 * of its content is interesting. For example, a text editing view
4170 * should call this when its cursor moves.
4171 *
4172 * @param rectangle The rectangle.
4173 * @return Whether any parent scrolled.
4174 */
4175 public boolean requestRectangleOnScreen(Rect rectangle) {
4176 return requestRectangleOnScreen(rectangle, false);
4177 }
4178
4179 /**
4180 * Request that a rectangle of this view be visible on the screen,
4181 * scrolling if necessary just enough.
4182 *
4183 * <p>A View should call this if it maintains some notion of which part
4184 * of its content is interesting. For example, a text editing view
4185 * should call this when its cursor moves.
4186 *
4187 * <p>When <code>immediate</code> is set to true, scrolling will not be
4188 * animated.
4189 *
4190 * @param rectangle The rectangle.
4191 * @param immediate True to forbid animated scrolling, false otherwise
4192 * @return Whether any parent scrolled.
4193 */
4194 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4195 View child = this;
4196 ViewParent parent = mParent;
4197 boolean scrolled = false;
4198 while (parent != null) {
4199 scrolled |= parent.requestChildRectangleOnScreen(child,
4200 rectangle, immediate);
4201
4202 // offset rect so next call has the rectangle in the
4203 // coordinate system of its direct child.
4204 rectangle.offset(child.getLeft(), child.getTop());
4205 rectangle.offset(-child.getScrollX(), -child.getScrollY());
4206
4207 if (!(parent instanceof View)) {
4208 break;
4209 }
Romain Guy8506ab42009-06-11 17:35:47 -07004210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004211 child = (View) parent;
4212 parent = child.getParent();
4213 }
4214 return scrolled;
4215 }
4216
4217 /**
Svetoslav Ganov13fd5612012-02-01 17:01:12 -08004218 * Called when this view wants to give up focus. If focus is cleared
4219 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4220 * <p>
4221 * <strong>Note:</strong> When a View clears focus the framework is trying
4222 * to give focus to the first focusable View from the top. Hence, if this
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004223 * View is the first from the top that can take focus, then all callbacks
4224 * related to clearing focus will be invoked after wich the framework will
4225 * give focus to this view.
Svetoslav Ganov13fd5612012-02-01 17:01:12 -08004226 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 */
4228 public void clearFocus() {
4229 if (DBG) {
4230 System.out.println(this + " clearFocus()");
4231 }
4232
4233 if ((mPrivateFlags & FOCUSED) != 0) {
4234 mPrivateFlags &= ~FOCUSED;
4235
4236 if (mParent != null) {
4237 mParent.clearChildFocus(this);
4238 }
4239
4240 onFocusChanged(false, 0, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07004241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 refreshDrawableState();
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004243
4244 ensureInputFocusOnFirstFocusable();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004245
4246 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4247 notifyAccessibilityStateChanged();
4248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 }
4250 }
4251
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004252 void ensureInputFocusOnFirstFocusable() {
4253 View root = getRootView();
4254 if (root != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004255 root.requestFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 }
4257 }
4258
4259 /**
4260 * Called internally by the view system when a new view is getting focus.
4261 * This is what clears the old focus.
4262 */
4263 void unFocus() {
4264 if (DBG) {
4265 System.out.println(this + " unFocus()");
4266 }
4267
4268 if ((mPrivateFlags & FOCUSED) != 0) {
4269 mPrivateFlags &= ~FOCUSED;
4270
4271 onFocusChanged(false, 0, null);
4272 refreshDrawableState();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004273
4274 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4275 notifyAccessibilityStateChanged();
4276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 }
4278 }
4279
4280 /**
4281 * Returns true if this view has focus iteself, or is the ancestor of the
4282 * view that has focus.
4283 *
4284 * @return True if this view has or contains focus, false otherwise.
4285 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07004286 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 public boolean hasFocus() {
4288 return (mPrivateFlags & FOCUSED) != 0;
4289 }
4290
4291 /**
4292 * Returns true if this view is focusable or if it contains a reachable View
4293 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4294 * is a View whose parents do not block descendants focus.
4295 *
4296 * Only {@link #VISIBLE} views are considered focusable.
4297 *
4298 * @return True if the view is focusable or if the view contains a focusable
4299 * View, false otherwise.
4300 *
4301 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4302 */
4303 public boolean hasFocusable() {
4304 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4305 }
4306
4307 /**
4308 * Called by the view system when the focus state of this view changes.
4309 * When the focus change event is caused by directional navigation, direction
4310 * and previouslyFocusedRect provide insight into where the focus is coming from.
4311 * When overriding, be sure to call up through to the super class so that
4312 * the standard focus handling will occur.
Romain Guy8506ab42009-06-11 17:35:47 -07004313 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 * @param gainFocus True if the View has focus; false otherwise.
4315 * @param direction The direction focus has moved when requestFocus()
4316 * is called to give this view focus. Values are
Jeff Brown4e6319b2010-12-13 10:36:51 -08004317 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4318 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4319 * It may not always apply, in which case use the default.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 * @param previouslyFocusedRect The rectangle, in this view's coordinate
4321 * system, of the previously focused view. If applicable, this will be
4322 * passed in as finer grained information about where the focus is coming
4323 * from (in addition to direction). Will be <code>null</code> otherwise.
4324 */
4325 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
svetoslavganov75986cf2009-05-14 22:28:01 -07004326 if (gainFocus) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004327 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4328 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07004329 }
svetoslavganov75986cf2009-05-14 22:28:01 -07004330 }
4331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004332 InputMethodManager imm = InputMethodManager.peekInstance();
4333 if (!gainFocus) {
4334 if (isPressed()) {
4335 setPressed(false);
4336 }
4337 if (imm != null && mAttachInfo != null
4338 && mAttachInfo.mHasWindowFocus) {
4339 imm.focusOut(this);
4340 }
Romain Guya2431d02009-04-30 16:30:00 -07004341 onFocusLost();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 } else if (imm != null && mAttachInfo != null
4343 && mAttachInfo.mHasWindowFocus) {
4344 imm.focusIn(this);
4345 }
Romain Guy8506ab42009-06-11 17:35:47 -07004346
Romain Guy0fd89bf2011-01-26 15:41:30 -08004347 invalidate(true);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004348 ListenerInfo li = mListenerInfo;
4349 if (li != null && li.mOnFocusChangeListener != null) {
4350 li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 }
Joe Malin32736f02011-01-19 16:14:20 -08004352
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07004353 if (mAttachInfo != null) {
4354 mAttachInfo.mKeyDispatchState.reset(this);
4355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 }
4357
4358 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004359 * Sends an accessibility event of the given type. If accessiiblity is
4360 * not enabled this method has no effect. The default implementation calls
4361 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
4362 * to populate information about the event source (this View), then calls
4363 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
4364 * populate the text content of the event source including its descendants,
4365 * and last calls
4366 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
4367 * on its parent to resuest sending of the event to interested parties.
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004368 * <p>
4369 * If an {@link AccessibilityDelegate} has been specified via calling
4370 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4371 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
4372 * responsible for handling this call.
4373 * </p>
Svetoslav Ganov30401322011-05-12 18:53:45 -07004374 *
Scott Mainb303d832011-10-12 16:45:18 -07004375 * @param eventType The type of the event to send, as defined by several types from
4376 * {@link android.view.accessibility.AccessibilityEvent}, such as
4377 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
4378 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004379 *
4380 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4381 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4382 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004383 * @see AccessibilityDelegate
svetoslavganov75986cf2009-05-14 22:28:01 -07004384 */
4385 public void sendAccessibilityEvent(int eventType) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004386 if (mAccessibilityDelegate != null) {
4387 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
4388 } else {
4389 sendAccessibilityEventInternal(eventType);
4390 }
4391 }
4392
4393 /**
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004394 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
4395 * {@link AccessibilityEvent} to make an announcement which is related to some
4396 * sort of a context change for which none of the events representing UI transitions
4397 * is a good fit. For example, announcing a new page in a book. If accessibility
4398 * is not enabled this method does nothing.
4399 *
4400 * @param text The announcement text.
4401 */
4402 public void announceForAccessibility(CharSequence text) {
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004403 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004404 AccessibilityEvent event = AccessibilityEvent.obtain(
4405 AccessibilityEvent.TYPE_ANNOUNCEMENT);
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004406 onInitializeAccessibilityEvent(event);
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004407 event.getText().add(text);
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004408 event.setContentDescription(null);
4409 mParent.requestSendAccessibilityEvent(this, event);
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004410 }
4411 }
4412
4413 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004414 * @see #sendAccessibilityEvent(int)
4415 *
4416 * Note: Called from the default {@link AccessibilityDelegate}.
4417 */
4418 void sendAccessibilityEventInternal(int eventType) {
svetoslavganov75986cf2009-05-14 22:28:01 -07004419 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4420 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
4421 }
4422 }
4423
4424 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004425 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
4426 * takes as an argument an empty {@link AccessibilityEvent} and does not
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004427 * perform a check whether accessibility is enabled.
4428 * <p>
4429 * If an {@link AccessibilityDelegate} has been specified via calling
4430 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4431 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
4432 * is responsible for handling this call.
4433 * </p>
Svetoslav Ganov30401322011-05-12 18:53:45 -07004434 *
4435 * @param event The event to send.
4436 *
4437 * @see #sendAccessibilityEvent(int)
svetoslavganov75986cf2009-05-14 22:28:01 -07004438 */
4439 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004440 if (mAccessibilityDelegate != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004441 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004442 } else {
4443 sendAccessibilityEventUncheckedInternal(event);
4444 }
4445 }
4446
4447 /**
4448 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
4449 *
4450 * Note: Called from the default {@link AccessibilityDelegate}.
4451 */
4452 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
Svetoslav Ganov9cd1eca2011-01-13 14:24:02 -08004453 if (!isShown()) {
4454 return;
4455 }
Svetoslav Ganov30401322011-05-12 18:53:45 -07004456 onInitializeAccessibilityEvent(event);
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07004457 // Only a subset of accessibility events populates text content.
4458 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
4459 dispatchPopulateAccessibilityEvent(event);
4460 }
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004461 // In the beginning we called #isShown(), so we know that getParent() is not null.
4462 getParent().requestSendAccessibilityEvent(this, event);
svetoslavganov75986cf2009-05-14 22:28:01 -07004463 }
4464
4465 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004466 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
4467 * to its children for adding their text content to the event. Note that the
4468 * event text is populated in a separate dispatch path since we add to the
4469 * event not only the text of the source but also the text of all its descendants.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004470 * A typical implementation will call
4471 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4472 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4473 * on each child. Override this method if custom population of the event text
4474 * content is required.
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004475 * <p>
4476 * If an {@link AccessibilityDelegate} has been specified via calling
4477 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4478 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4479 * is responsible for handling this call.
4480 * </p>
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07004481 * <p>
4482 * <em>Note:</em> Accessibility events of certain types are not dispatched for
4483 * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4484 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -07004485 *
4486 * @param event The event.
4487 *
4488 * @return True if the event population was completed.
4489 */
4490 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004491 if (mAccessibilityDelegate != null) {
4492 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4493 } else {
4494 return dispatchPopulateAccessibilityEventInternal(event);
4495 }
4496 }
4497
4498 /**
4499 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4500 *
4501 * Note: Called from the default {@link AccessibilityDelegate}.
4502 */
4503 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004504 onPopulateAccessibilityEvent(event);
svetoslavganov75986cf2009-05-14 22:28:01 -07004505 return false;
4506 }
4507
4508 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004509 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
Svetoslav Ganov30401322011-05-12 18:53:45 -07004510 * giving a chance to this View to populate the accessibility event with its
Scott Mainb303d832011-10-12 16:45:18 -07004511 * text content. While this method is free to modify event
4512 * attributes other than text content, doing so should normally be performed in
Svetoslav Ganov30401322011-05-12 18:53:45 -07004513 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4514 * <p>
4515 * Example: Adding formatted date string to an accessibility event in addition
Scott Mainb303d832011-10-12 16:45:18 -07004516 * to the text added by the super implementation:
4517 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov30401322011-05-12 18:53:45 -07004518 * super.onPopulateAccessibilityEvent(event);
4519 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4520 * String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4521 * mCurrentDate.getTimeInMillis(), flags);
4522 * event.getText().add(selectedDateUtterance);
Scott Mainb303d832011-10-12 16:45:18 -07004523 * }</pre>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004524 * <p>
4525 * If an {@link AccessibilityDelegate} has been specified via calling
4526 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4527 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4528 * is responsible for handling this call.
4529 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07004530 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4531 * information to the event, in case the default implementation has basic information to add.
4532 * </p>
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004533 *
4534 * @param event The accessibility event which to populate.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004535 *
4536 * @see #sendAccessibilityEvent(int)
4537 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004538 */
4539 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004540 if (mAccessibilityDelegate != null) {
4541 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4542 } else {
4543 onPopulateAccessibilityEventInternal(event);
4544 }
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004545 }
4546
4547 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004548 * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4549 *
4550 * Note: Called from the default {@link AccessibilityDelegate}.
4551 */
4552 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4553
4554 }
4555
4556 /**
4557 * Initializes an {@link AccessibilityEvent} with information about
4558 * this View which is the event source. In other words, the source of
4559 * an accessibility event is the view whose state change triggered firing
4560 * the event.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004561 * <p>
4562 * Example: Setting the password property of an event in addition
Scott Mainb303d832011-10-12 16:45:18 -07004563 * to properties set by the super implementation:
4564 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4565 * super.onInitializeAccessibilityEvent(event);
4566 * event.setPassword(true);
4567 * }</pre>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004568 * <p>
4569 * If an {@link AccessibilityDelegate} has been specified via calling
4570 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4571 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4572 * is responsible for handling this call.
4573 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07004574 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4575 * information to the event, in case the default implementation has basic information to add.
4576 * </p>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004577 * @param event The event to initialize.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004578 *
4579 * @see #sendAccessibilityEvent(int)
4580 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4581 */
4582 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004583 if (mAccessibilityDelegate != null) {
4584 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4585 } else {
4586 onInitializeAccessibilityEventInternal(event);
4587 }
4588 }
4589
4590 /**
4591 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4592 *
4593 * Note: Called from the default {@link AccessibilityDelegate}.
4594 */
4595 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004596 event.setSource(this);
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08004597 event.setClassName(View.class.getName());
Svetoslav Ganov30401322011-05-12 18:53:45 -07004598 event.setPackageName(getContext().getPackageName());
4599 event.setEnabled(isEnabled());
4600 event.setContentDescription(mContentDescription);
4601
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -07004602 if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004603 ArrayList<View> focusablesTempList = mAttachInfo.mTempArrayList;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -07004604 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4605 FOCUSABLES_ALL);
4606 event.setItemCount(focusablesTempList.size());
4607 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4608 focusablesTempList.clear();
Svetoslav Ganov30401322011-05-12 18:53:45 -07004609 }
4610 }
4611
4612 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004613 * Returns an {@link AccessibilityNodeInfo} representing this view from the
4614 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4615 * This method is responsible for obtaining an accessibility node info from a
4616 * pool of reusable instances and calling
4617 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4618 * initialize the former.
4619 * <p>
4620 * Note: The client is responsible for recycling the obtained instance by calling
4621 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4622 * </p>
Svetoslav Ganov02107852011-10-03 17:06:56 -07004623 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004624 * @return A populated {@link AccessibilityNodeInfo}.
4625 *
4626 * @see AccessibilityNodeInfo
4627 */
4628 public AccessibilityNodeInfo createAccessibilityNodeInfo() {
Svetoslav Ganov02107852011-10-03 17:06:56 -07004629 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4630 if (provider != null) {
4631 return provider.createAccessibilityNodeInfo(View.NO_ID);
4632 } else {
4633 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4634 onInitializeAccessibilityNodeInfo(info);
4635 return info;
4636 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004637 }
4638
4639 /**
4640 * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4641 * The base implementation sets:
4642 * <ul>
4643 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004644 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4645 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004646 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4647 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4648 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4649 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4650 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4651 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4652 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4653 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4654 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4655 * </ul>
4656 * <p>
4657 * Subclasses should override this method, call the super implementation,
4658 * and set additional attributes.
4659 * </p>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004660 * <p>
4661 * If an {@link AccessibilityDelegate} has been specified via calling
4662 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4663 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4664 * is responsible for handling this call.
4665 * </p>
4666 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004667 * @param info The instance to initialize.
4668 */
4669 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004670 if (mAccessibilityDelegate != null) {
4671 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4672 } else {
4673 onInitializeAccessibilityNodeInfoInternal(info);
4674 }
4675 }
4676
4677 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004678 * Gets the location of this view in screen coordintates.
4679 *
4680 * @param outRect The output location
4681 */
4682 private void getBoundsOnScreen(Rect outRect) {
4683 if (mAttachInfo == null) {
4684 return;
4685 }
4686
4687 RectF position = mAttachInfo.mTmpTransformRect;
Svetoslav Ganov14b2b742012-05-08 16:36:34 -07004688 position.set(0, 0, mRight - mLeft, mBottom - mTop);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004689
4690 if (!hasIdentityMatrix()) {
4691 getMatrix().mapRect(position);
4692 }
4693
Svetoslav Ganov14b2b742012-05-08 16:36:34 -07004694 position.offset(mLeft, mTop);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004695
4696 ViewParent parent = mParent;
4697 while (parent instanceof View) {
4698 View parentView = (View) parent;
4699
4700 position.offset(-parentView.mScrollX, -parentView.mScrollY);
4701
4702 if (!parentView.hasIdentityMatrix()) {
4703 parentView.getMatrix().mapRect(position);
4704 }
4705
4706 position.offset(parentView.mLeft, parentView.mTop);
4707
4708 parent = parentView.mParent;
4709 }
4710
4711 if (parent instanceof ViewRootImpl) {
4712 ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
4713 position.offset(0, -viewRootImpl.mCurScrollY);
4714 }
4715
4716 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
4717
4718 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
4719 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
4720 }
4721
4722 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004723 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4724 *
4725 * Note: Called from the default {@link AccessibilityDelegate}.
4726 */
4727 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004728 Rect bounds = mAttachInfo.mTmpInvalRect;
Svetoslav Ganov983119a2012-07-03 21:04:10 -07004729
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004730 getDrawingRect(bounds);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004731 info.setBoundsInParent(bounds);
4732
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004733 getBoundsOnScreen(bounds);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004734 info.setBoundsInScreen(bounds);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004735
Svetoslav Ganovc406be92012-05-11 16:12:32 -07004736 ViewParent parent = getParentForAccessibility();
4737 if (parent instanceof View) {
4738 info.setParent((View) parent);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004739 }
4740
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004741 info.setVisibleToUser(isVisibleToUser());
4742
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004743 info.setPackageName(mContext.getPackageName());
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08004744 info.setClassName(View.class.getName());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004745 info.setContentDescription(getContentDescription());
4746
4747 info.setEnabled(isEnabled());
4748 info.setClickable(isClickable());
4749 info.setFocusable(isFocusable());
4750 info.setFocused(isFocused());
Svetoslav Ganov42138042012-03-20 11:51:39 -07004751 info.setAccessibilityFocused(isAccessibilityFocused());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004752 info.setSelected(isSelected());
4753 info.setLongClickable(isLongClickable());
4754
4755 // TODO: These make sense only if we are in an AdapterView but all
4756 // views can be selected. Maybe from accessiiblity perspective
4757 // we should report as selectable view in an AdapterView.
4758 info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4759 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4760
4761 if (isFocusable()) {
4762 if (isFocused()) {
4763 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4764 } else {
4765 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4766 }
4767 }
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004768
Svetoslav Ganov02afe2c2012-05-07 17:51:59 -07004769 if (!isAccessibilityFocused()) {
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07004770 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Svetoslav Ganov02afe2c2012-05-07 17:51:59 -07004771 } else {
4772 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
4773 }
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004774
Svetoslav Ganovfb1e80a2012-05-16 17:33:19 -07004775 if (isClickable() && isEnabled()) {
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004776 info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
4777 }
4778
Svetoslav Ganovfb1e80a2012-05-16 17:33:19 -07004779 if (isLongClickable() && isEnabled()) {
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004780 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
4781 }
4782
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07004783 if (mContentDescription != null && mContentDescription.length() > 0) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07004784 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
4785 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
4786 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07004787 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
4788 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004789 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004790 }
4791
4792 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004793 * Computes whether this view is visible to the user. Such a view is
4794 * attached, visible, all its predecessors are visible, it is not clipped
4795 * entirely by its predecessors, and has an alpha greater than zero.
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004796 *
4797 * @return Whether the view is visible on the screen.
Guang Zhu0d607fb2012-05-11 19:34:56 -07004798 *
4799 * @hide
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004800 */
Guang Zhu0d607fb2012-05-11 19:34:56 -07004801 protected boolean isVisibleToUser() {
4802 return isVisibleToUser(null);
4803 }
4804
4805 /**
Romain Guyf0af1d52012-07-11 18:31:21 -07004806 * Computes whether the given portion of this view is visible to the user.
4807 * Such a view is attached, visible, all its predecessors are visible,
4808 * has an alpha greater than zero, and the specified portion is not
4809 * clipped entirely by its predecessors.
Guang Zhu0d607fb2012-05-11 19:34:56 -07004810 *
4811 * @param boundInView the portion of the view to test; coordinates should be relative; may be
4812 * <code>null</code>, and the entire view will be tested in this case.
4813 * When <code>true</code> is returned by the function, the actual visible
4814 * region will be stored in this parameter; that is, if boundInView is fully
4815 * contained within the view, no modification will be made, otherwise regions
4816 * outside of the visible area of the view will be clipped.
4817 *
4818 * @return Whether the specified portion of the view is visible on the screen.
4819 *
4820 * @hide
4821 */
4822 protected boolean isVisibleToUser(Rect boundInView) {
Romain Guyf0af1d52012-07-11 18:31:21 -07004823 if (mAttachInfo != null) {
4824 Rect visibleRect = mAttachInfo.mTmpInvalRect;
4825 Point offset = mAttachInfo.mPoint;
4826 // The first two checks are made also made by isShown() which
4827 // however traverses the tree up to the parent to catch that.
4828 // Therefore, we do some fail fast check to minimize the up
4829 // tree traversal.
4830 boolean isVisible = mAttachInfo.mWindowVisibility == View.VISIBLE
4831 && getAlpha() > 0
4832 && isShown()
4833 && getGlobalVisibleRect(visibleRect, offset);
Guang Zhu0d607fb2012-05-11 19:34:56 -07004834 if (isVisible && boundInView != null) {
4835 visibleRect.offset(-offset.x, -offset.y);
Romain Guyf0af1d52012-07-11 18:31:21 -07004836 // isVisible is always true here, use a simple assignment
4837 isVisible = boundInView.intersect(visibleRect);
Guang Zhu0d607fb2012-05-11 19:34:56 -07004838 }
4839 return isVisible;
Romain Guyf0af1d52012-07-11 18:31:21 -07004840 }
4841
4842 return false;
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004843 }
4844
4845 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004846 * Sets a delegate for implementing accessibility support via compositon as
4847 * opposed to inheritance. The delegate's primary use is for implementing
4848 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4849 *
4850 * @param delegate The delegate instance.
4851 *
4852 * @see AccessibilityDelegate
4853 */
4854 public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4855 mAccessibilityDelegate = delegate;
4856 }
4857
4858 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07004859 * Gets the provider for managing a virtual view hierarchy rooted at this View
4860 * and reported to {@link android.accessibilityservice.AccessibilityService}s
4861 * that explore the window content.
4862 * <p>
4863 * If this method returns an instance, this instance is responsible for managing
4864 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
4865 * View including the one representing the View itself. Similarly the returned
4866 * instance is responsible for performing accessibility actions on any virtual
4867 * view or the root view itself.
4868 * </p>
4869 * <p>
4870 * If an {@link AccessibilityDelegate} has been specified via calling
4871 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4872 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
4873 * is responsible for handling this call.
4874 * </p>
4875 *
4876 * @return The provider.
4877 *
4878 * @see AccessibilityNodeProvider
4879 */
4880 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
4881 if (mAccessibilityDelegate != null) {
4882 return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
4883 } else {
4884 return null;
4885 }
4886 }
4887
4888 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004889 * Gets the unique identifier of this view on the screen for accessibility purposes.
4890 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
4891 *
4892 * @return The view accessibility id.
4893 *
4894 * @hide
4895 */
4896 public int getAccessibilityViewId() {
4897 if (mAccessibilityViewId == NO_ID) {
4898 mAccessibilityViewId = sNextAccessibilityViewId++;
4899 }
4900 return mAccessibilityViewId;
4901 }
4902
4903 /**
4904 * Gets the unique identifier of the window in which this View reseides.
4905 *
4906 * @return The window accessibility id.
4907 *
4908 * @hide
4909 */
4910 public int getAccessibilityWindowId() {
4911 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
4912 }
4913
4914 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07004915 * Gets the {@link View} description. It briefly describes the view and is
4916 * primarily used for accessibility support. Set this property to enable
4917 * better accessibility support for your application. This is especially
4918 * true for views that do not have textual representation (For example,
4919 * ImageButton).
4920 *
Svetoslav Ganov42138042012-03-20 11:51:39 -07004921 * @return The content description.
svetoslavganov75986cf2009-05-14 22:28:01 -07004922 *
4923 * @attr ref android.R.styleable#View_contentDescription
4924 */
Svetoslav Ganov42138042012-03-20 11:51:39 -07004925 @ViewDebug.ExportedProperty(category = "accessibility")
svetoslavganov75986cf2009-05-14 22:28:01 -07004926 public CharSequence getContentDescription() {
4927 return mContentDescription;
4928 }
4929
4930 /**
4931 * Sets the {@link View} description. It briefly describes the view and is
4932 * primarily used for accessibility support. Set this property to enable
4933 * better accessibility support for your application. This is especially
4934 * true for views that do not have textual representation (For example,
4935 * ImageButton).
4936 *
4937 * @param contentDescription The content description.
4938 *
4939 * @attr ref android.R.styleable#View_contentDescription
4940 */
Svetoslav Ganove261e282011-10-18 17:47:04 -07004941 @RemotableViewMethod
svetoslavganov75986cf2009-05-14 22:28:01 -07004942 public void setContentDescription(CharSequence contentDescription) {
4943 mContentDescription = contentDescription;
Svetoslav Ganove47957a2012-06-05 14:46:50 -07004944 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
4945 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
4946 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
4947 }
svetoslavganov75986cf2009-05-14 22:28:01 -07004948 }
4949
4950 /**
Romain Guya2431d02009-04-30 16:30:00 -07004951 * Invoked whenever this view loses focus, either by losing window focus or by losing
4952 * focus within its window. This method can be used to clear any state tied to the
4953 * focus. For instance, if a button is held pressed with the trackball and the window
4954 * loses focus, this method can be used to cancel the press.
4955 *
4956 * Subclasses of View overriding this method should always call super.onFocusLost().
4957 *
4958 * @see #onFocusChanged(boolean, int, android.graphics.Rect)
Romain Guy8506ab42009-06-11 17:35:47 -07004959 * @see #onWindowFocusChanged(boolean)
Romain Guya2431d02009-04-30 16:30:00 -07004960 *
4961 * @hide pending API council approval
4962 */
4963 protected void onFocusLost() {
4964 resetPressedState();
4965 }
4966
4967 private void resetPressedState() {
4968 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
4969 return;
4970 }
4971
4972 if (isPressed()) {
4973 setPressed(false);
4974
4975 if (!mHasPerformedLongPress) {
Maryam Garrett1549dd12009-12-15 16:06:36 -05004976 removeLongPressCallback();
Romain Guya2431d02009-04-30 16:30:00 -07004977 }
4978 }
4979 }
4980
4981 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 * Returns true if this view has focus
4983 *
4984 * @return True if this view has focus, false otherwise.
4985 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07004986 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 public boolean isFocused() {
4988 return (mPrivateFlags & FOCUSED) != 0;
4989 }
4990
4991 /**
4992 * Find the view in the hierarchy rooted at this view that currently has
4993 * focus.
4994 *
4995 * @return The view that currently has focus, or null if no focused view can
4996 * be found.
4997 */
4998 public View findFocus() {
4999 return (mPrivateFlags & FOCUSED) != 0 ? this : null;
5000 }
5001
5002 /**
Philip Milne6c8ea062012-04-03 17:38:43 -07005003 * Indicates whether this view is one of the set of scrollable containers in
5004 * its window.
5005 *
5006 * @return whether this view is one of the set of scrollable containers in
5007 * its window
5008 *
5009 * @attr ref android.R.styleable#View_isScrollContainer
5010 */
5011 public boolean isScrollContainer() {
5012 return (mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0;
5013 }
5014
5015 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 * Change whether this view is one of the set of scrollable containers in
5017 * its window. This will be used to determine whether the window can
5018 * resize or must pan when a soft input area is open -- scrollable
5019 * containers allow the window to use resize mode since the container
5020 * will appropriately shrink.
Philip Milne6c8ea062012-04-03 17:38:43 -07005021 *
5022 * @attr ref android.R.styleable#View_isScrollContainer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 */
5024 public void setScrollContainer(boolean isScrollContainer) {
5025 if (isScrollContainer) {
5026 if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
5027 mAttachInfo.mScrollContainers.add(this);
5028 mPrivateFlags |= SCROLL_CONTAINER_ADDED;
5029 }
5030 mPrivateFlags |= SCROLL_CONTAINER;
5031 } else {
5032 if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
5033 mAttachInfo.mScrollContainers.remove(this);
5034 }
5035 mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
5036 }
5037 }
5038
5039 /**
5040 * Returns the quality of the drawing cache.
5041 *
5042 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5043 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5044 *
5045 * @see #setDrawingCacheQuality(int)
5046 * @see #setDrawingCacheEnabled(boolean)
5047 * @see #isDrawingCacheEnabled()
5048 *
5049 * @attr ref android.R.styleable#View_drawingCacheQuality
5050 */
5051 public int getDrawingCacheQuality() {
5052 return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5053 }
5054
5055 /**
5056 * Set the drawing cache quality of this view. This value is used only when the
5057 * drawing cache is enabled
5058 *
5059 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5060 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5061 *
5062 * @see #getDrawingCacheQuality()
5063 * @see #setDrawingCacheEnabled(boolean)
5064 * @see #isDrawingCacheEnabled()
5065 *
5066 * @attr ref android.R.styleable#View_drawingCacheQuality
5067 */
5068 public void setDrawingCacheQuality(int quality) {
5069 setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5070 }
5071
5072 /**
5073 * Returns whether the screen should remain on, corresponding to the current
5074 * value of {@link #KEEP_SCREEN_ON}.
5075 *
5076 * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5077 *
5078 * @see #setKeepScreenOn(boolean)
5079 *
5080 * @attr ref android.R.styleable#View_keepScreenOn
5081 */
5082 public boolean getKeepScreenOn() {
5083 return (mViewFlags & KEEP_SCREEN_ON) != 0;
5084 }
5085
5086 /**
5087 * Controls whether the screen should remain on, modifying the
5088 * value of {@link #KEEP_SCREEN_ON}.
5089 *
5090 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5091 *
5092 * @see #getKeepScreenOn()
5093 *
5094 * @attr ref android.R.styleable#View_keepScreenOn
5095 */
5096 public void setKeepScreenOn(boolean keepScreenOn) {
5097 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5098 }
5099
5100 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005101 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5102 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 *
5104 * @attr ref android.R.styleable#View_nextFocusLeft
5105 */
5106 public int getNextFocusLeftId() {
5107 return mNextFocusLeftId;
5108 }
5109
5110 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005111 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5112 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5113 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 *
5115 * @attr ref android.R.styleable#View_nextFocusLeft
5116 */
5117 public void setNextFocusLeftId(int nextFocusLeftId) {
5118 mNextFocusLeftId = nextFocusLeftId;
5119 }
5120
5121 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005122 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5123 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 *
5125 * @attr ref android.R.styleable#View_nextFocusRight
5126 */
5127 public int getNextFocusRightId() {
5128 return mNextFocusRightId;
5129 }
5130
5131 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005132 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5133 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5134 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 *
5136 * @attr ref android.R.styleable#View_nextFocusRight
5137 */
5138 public void setNextFocusRightId(int nextFocusRightId) {
5139 mNextFocusRightId = nextFocusRightId;
5140 }
5141
5142 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005143 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5144 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 *
5146 * @attr ref android.R.styleable#View_nextFocusUp
5147 */
5148 public int getNextFocusUpId() {
5149 return mNextFocusUpId;
5150 }
5151
5152 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005153 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5154 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5155 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 *
5157 * @attr ref android.R.styleable#View_nextFocusUp
5158 */
5159 public void setNextFocusUpId(int nextFocusUpId) {
5160 mNextFocusUpId = nextFocusUpId;
5161 }
5162
5163 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005164 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5165 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 *
5167 * @attr ref android.R.styleable#View_nextFocusDown
5168 */
5169 public int getNextFocusDownId() {
5170 return mNextFocusDownId;
5171 }
5172
5173 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005174 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5175 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5176 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 *
5178 * @attr ref android.R.styleable#View_nextFocusDown
5179 */
5180 public void setNextFocusDownId(int nextFocusDownId) {
5181 mNextFocusDownId = nextFocusDownId;
5182 }
5183
5184 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005185 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5186 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5187 *
5188 * @attr ref android.R.styleable#View_nextFocusForward
5189 */
5190 public int getNextFocusForwardId() {
5191 return mNextFocusForwardId;
5192 }
5193
5194 /**
5195 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5196 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5197 * decide automatically.
5198 *
5199 * @attr ref android.R.styleable#View_nextFocusForward
5200 */
5201 public void setNextFocusForwardId(int nextFocusForwardId) {
5202 mNextFocusForwardId = nextFocusForwardId;
5203 }
5204
5205 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 * Returns the visibility of this view and all of its ancestors
5207 *
5208 * @return True if this view and all of its ancestors are {@link #VISIBLE}
5209 */
5210 public boolean isShown() {
5211 View current = this;
5212 //noinspection ConstantConditions
5213 do {
5214 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5215 return false;
5216 }
5217 ViewParent parent = current.mParent;
5218 if (parent == null) {
5219 return false; // We are not attached to the view root
5220 }
5221 if (!(parent instanceof View)) {
5222 return true;
5223 }
5224 current = (View) parent;
5225 } while (current != null);
5226
5227 return false;
5228 }
5229
5230 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005231 * Called by the view hierarchy when the content insets for a window have
5232 * changed, to allow it to adjust its content to fit within those windows.
5233 * The content insets tell you the space that the status bar, input method,
5234 * and other system windows infringe on the application's window.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005236 * <p>You do not normally need to deal with this function, since the default
5237 * window decoration given to applications takes care of applying it to the
5238 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
5239 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
5240 * and your content can be placed under those system elements. You can then
5241 * use this method within your view hierarchy if you have parts of your UI
5242 * which you would like to ensure are not being covered.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005244 * <p>The default implementation of this method simply applies the content
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005245 * inset's to the view's padding, consuming that content (modifying the
5246 * insets to be 0), and returning true. This behavior is off by default, but can
5247 * be enabled through {@link #setFitsSystemWindows(boolean)}.
5248 *
5249 * <p>This function's traversal down the hierarchy is depth-first. The same content
5250 * insets object is propagated down the hierarchy, so any changes made to it will
5251 * be seen by all following views (including potentially ones above in
5252 * the hierarchy since this is a depth-first traversal). The first view
5253 * that returns true will abort the entire traversal.
5254 *
5255 * <p>The default implementation works well for a situation where it is
5256 * used with a container that covers the entire window, allowing it to
5257 * apply the appropriate insets to its content on all edges. If you need
5258 * a more complicated layout (such as two different views fitting system
5259 * windows, one on the top of the window, and one on the bottom),
5260 * you can override the method and handle the insets however you would like.
5261 * Note that the insets provided by the framework are always relative to the
5262 * far edges of the window, not accounting for the location of the called view
5263 * within that window. (In fact when this method is called you do not yet know
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005264 * where the layout will place the view, as it is done before layout happens.)
5265 *
5266 * <p>Note: unlike many View methods, there is no dispatch phase to this
5267 * call. If you are overriding it in a ViewGroup and want to allow the
5268 * call to continue to your children, you must be sure to call the super
5269 * implementation.
5270 *
Dianne Hackborncf675782012-05-10 15:07:24 -07005271 * <p>Here is a sample layout that makes use of fitting system windows
5272 * to have controls for a video view placed inside of the window decorations
5273 * that it hides and shows. This can be used with code like the second
5274 * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
5275 *
5276 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
5277 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005278 * @param insets Current content insets of the window. Prior to
5279 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
5280 * the insets or else you and Android will be unhappy.
5281 *
5282 * @return Return true if this view applied the insets and it should not
5283 * continue propagating further down the hierarchy, false otherwise.
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005284 * @see #getFitsSystemWindows()
Romain Guyf0af1d52012-07-11 18:31:21 -07005285 * @see #setFitsSystemWindows(boolean)
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005286 * @see #setSystemUiVisibility(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 */
5288 protected boolean fitSystemWindows(Rect insets) {
5289 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07005290 mUserPaddingStart = UNDEFINED_PADDING;
5291 mUserPaddingEnd = UNDEFINED_PADDING;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005292 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
5293 || mAttachInfo == null
5294 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
5295 internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
5296 return true;
5297 } else {
5298 internalSetPadding(0, 0, 0, 0);
5299 return false;
5300 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 }
5302 return false;
5303 }
5304
5305 /**
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005306 * Sets whether or not this view should account for system screen decorations
5307 * such as the status bar and inset its content; that is, controlling whether
5308 * the default implementation of {@link #fitSystemWindows(Rect)} will be
5309 * executed. See that method for more details.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005310 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005311 * <p>Note that if you are providing your own implementation of
5312 * {@link #fitSystemWindows(Rect)}, then there is no need to set this
5313 * flag to true -- your implementation will be overriding the default
5314 * implementation that checks this flag.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005315 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005316 * @param fitSystemWindows If true, then the default implementation of
5317 * {@link #fitSystemWindows(Rect)} will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005318 *
5319 * @attr ref android.R.styleable#View_fitsSystemWindows
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005320 * @see #getFitsSystemWindows()
5321 * @see #fitSystemWindows(Rect)
5322 * @see #setSystemUiVisibility(int)
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005323 */
5324 public void setFitsSystemWindows(boolean fitSystemWindows) {
5325 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
5326 }
5327
5328 /**
Dianne Hackborncf675782012-05-10 15:07:24 -07005329 * Check for state of {@link #setFitsSystemWindows(boolean). If this method
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005330 * returns true, the default implementation of {@link #fitSystemWindows(Rect)}
5331 * will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005332 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005333 * @return Returns true if the default implementation of
5334 * {@link #fitSystemWindows(Rect)} will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005335 *
5336 * @attr ref android.R.styleable#View_fitsSystemWindows
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005337 * @see #setFitsSystemWindows()
5338 * @see #fitSystemWindows(Rect)
5339 * @see #setSystemUiVisibility(int)
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005340 */
Dianne Hackborncf675782012-05-10 15:07:24 -07005341 public boolean getFitsSystemWindows() {
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005342 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
5343 }
5344
Dianne Hackbornb1b55e62012-05-10 16:25:54 -07005345 /** @hide */
5346 public boolean fitsSystemWindows() {
5347 return getFitsSystemWindows();
5348 }
5349
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005350 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005351 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
5352 */
5353 public void requestFitSystemWindows() {
5354 if (mParent != null) {
5355 mParent.requestFitSystemWindows();
5356 }
5357 }
5358
5359 /**
5360 * For use by PhoneWindow to make its own system window fitting optional.
5361 * @hide
5362 */
5363 public void makeOptionalFitsSystemWindows() {
5364 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
5365 }
5366
5367 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 * Returns the visibility status for this view.
5369 *
5370 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5371 * @attr ref android.R.styleable#View_visibility
5372 */
5373 @ViewDebug.ExportedProperty(mapping = {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07005374 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
5375 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
5376 @ViewDebug.IntToString(from = GONE, to = "GONE")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 })
5378 public int getVisibility() {
5379 return mViewFlags & VISIBILITY_MASK;
5380 }
5381
5382 /**
5383 * Set the enabled state of this view.
5384 *
5385 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5386 * @attr ref android.R.styleable#View_visibility
5387 */
5388 @RemotableViewMethod
5389 public void setVisibility(int visibility) {
5390 setFlags(visibility, VISIBILITY_MASK);
Philip Milne6c8ea062012-04-03 17:38:43 -07005391 if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005392 }
5393
5394 /**
5395 * Returns the enabled status for this view. The interpretation of the
5396 * enabled state varies by subclass.
5397 *
5398 * @return True if this view is enabled, false otherwise.
5399 */
5400 @ViewDebug.ExportedProperty
5401 public boolean isEnabled() {
5402 return (mViewFlags & ENABLED_MASK) == ENABLED;
5403 }
5404
5405 /**
5406 * Set the enabled state of this view. The interpretation of the enabled
5407 * state varies by subclass.
5408 *
5409 * @param enabled True if this view is enabled, false otherwise.
5410 */
Jeff Sharkey2b95c242010-02-08 17:40:30 -08005411 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 public void setEnabled(boolean enabled) {
Amith Yamasania2ef00b2009-07-30 16:14:34 -07005413 if (enabled == isEnabled()) return;
5414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005415 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
5416
5417 /*
5418 * The View most likely has to change its appearance, so refresh
5419 * the drawable state.
5420 */
5421 refreshDrawableState();
5422
5423 // Invalidate too, since the default behavior for views is to be
5424 // be drawn at 50% alpha rather than to change the drawable.
Romain Guy0fd89bf2011-01-26 15:41:30 -08005425 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 }
5427
5428 /**
5429 * Set whether this view can receive the focus.
5430 *
5431 * Setting this to false will also ensure that this view is not focusable
5432 * in touch mode.
5433 *
5434 * @param focusable If true, this view can receive the focus.
5435 *
5436 * @see #setFocusableInTouchMode(boolean)
5437 * @attr ref android.R.styleable#View_focusable
5438 */
5439 public void setFocusable(boolean focusable) {
5440 if (!focusable) {
5441 setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
5442 }
5443 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
5444 }
5445
5446 /**
5447 * Set whether this view can receive focus while in touch mode.
5448 *
5449 * Setting this to true will also ensure that this view is focusable.
5450 *
5451 * @param focusableInTouchMode If true, this view can receive the focus while
5452 * in touch mode.
5453 *
5454 * @see #setFocusable(boolean)
5455 * @attr ref android.R.styleable#View_focusableInTouchMode
5456 */
5457 public void setFocusableInTouchMode(boolean focusableInTouchMode) {
5458 // Focusable in touch mode should always be set before the focusable flag
5459 // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
5460 // which, in touch mode, will not successfully request focus on this view
5461 // because the focusable in touch mode flag is not set
5462 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
5463 if (focusableInTouchMode) {
5464 setFlags(FOCUSABLE, FOCUSABLE_MASK);
5465 }
5466 }
5467
5468 /**
5469 * Set whether this view should have sound effects enabled for events such as
5470 * clicking and touching.
5471 *
5472 * <p>You may wish to disable sound effects for a view if you already play sounds,
5473 * for instance, a dial key that plays dtmf tones.
5474 *
5475 * @param soundEffectsEnabled whether sound effects are enabled for this view.
5476 * @see #isSoundEffectsEnabled()
5477 * @see #playSoundEffect(int)
5478 * @attr ref android.R.styleable#View_soundEffectsEnabled
5479 */
5480 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
5481 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
5482 }
5483
5484 /**
5485 * @return whether this view should have sound effects enabled for events such as
5486 * clicking and touching.
5487 *
5488 * @see #setSoundEffectsEnabled(boolean)
5489 * @see #playSoundEffect(int)
5490 * @attr ref android.R.styleable#View_soundEffectsEnabled
5491 */
5492 @ViewDebug.ExportedProperty
5493 public boolean isSoundEffectsEnabled() {
5494 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
5495 }
5496
5497 /**
5498 * Set whether this view should have haptic feedback for events such as
5499 * long presses.
5500 *
5501 * <p>You may wish to disable haptic feedback if your view already controls
5502 * its own haptic feedback.
5503 *
5504 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
5505 * @see #isHapticFeedbackEnabled()
5506 * @see #performHapticFeedback(int)
5507 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5508 */
5509 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
5510 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
5511 }
5512
5513 /**
5514 * @return whether this view should have haptic feedback enabled for events
5515 * long presses.
5516 *
5517 * @see #setHapticFeedbackEnabled(boolean)
5518 * @see #performHapticFeedback(int)
5519 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5520 */
5521 @ViewDebug.ExportedProperty
5522 public boolean isHapticFeedbackEnabled() {
5523 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
5524 }
5525
5526 /**
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005527 * Returns the layout direction for this view.
Cibu Johny7632cb92010-02-22 13:01:02 -08005528 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005529 * @return One of {@link #LAYOUT_DIRECTION_LTR},
5530 * {@link #LAYOUT_DIRECTION_RTL},
5531 * {@link #LAYOUT_DIRECTION_INHERIT} or
5532 * {@link #LAYOUT_DIRECTION_LOCALE}.
5533 * @attr ref android.R.styleable#View_layoutDirection
Cibu Johny7632cb92010-02-22 13:01:02 -08005534 */
Fabrice Di Megliobce84d22011-06-02 15:57:01 -07005535 @ViewDebug.ExportedProperty(category = "layout", mapping = {
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005536 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
5537 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"),
5538 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
5539 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
Cibu Johny7632cb92010-02-22 13:01:02 -08005540 })
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005541 public int getLayoutDirection() {
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005542 return (mPrivateFlags2 & LAYOUT_DIRECTION_MASK) >> LAYOUT_DIRECTION_MASK_SHIFT;
Cibu Johny7632cb92010-02-22 13:01:02 -08005543 }
5544
5545 /**
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005546 * Set the layout direction for this view. This will propagate a reset of layout direction
5547 * resolution to the view's children and resolve layout direction for this view.
Cibu Johny7632cb92010-02-22 13:01:02 -08005548 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005549 * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
5550 * {@link #LAYOUT_DIRECTION_RTL},
5551 * {@link #LAYOUT_DIRECTION_INHERIT} or
5552 * {@link #LAYOUT_DIRECTION_LOCALE}.
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005553 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005554 * @attr ref android.R.styleable#View_layoutDirection
Cibu Johny7632cb92010-02-22 13:01:02 -08005555 */
5556 @RemotableViewMethod
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005557 public void setLayoutDirection(int layoutDirection) {
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005558 if (getLayoutDirection() != layoutDirection) {
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -07005559 // Reset the current layout direction and the resolved one
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005560 mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
Fabrice Di Meglio7f86c802011-07-01 15:09:24 -07005561 resetResolvedLayoutDirection();
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005562 // Reset padding resolution
5563 mPrivateFlags2 &= ~PADDING_RESOLVED;
5564 // Set the new layout direction (filtered)
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005565 mPrivateFlags2 |=
5566 ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005567 resolveRtlProperties();
5568 // ... and ask for a layout pass
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005569 requestLayout();
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005570 }
Cibu Johny7632cb92010-02-22 13:01:02 -08005571 }
5572
5573 /**
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005574 * Returns the resolved layout direction for this view.
5575 *
5576 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005577 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005578 */
5579 @ViewDebug.ExportedProperty(category = "layout", mapping = {
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005580 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
5581 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005582 })
5583 public int getResolvedLayoutDirection() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005584 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
5585 if (targetSdkVersion < JELLY_BEAN_MR1) {
5586 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
5587 return LAYOUT_DIRECTION_LTR;
5588 }
Fabrice Di Megliob93911f2012-06-26 19:43:15 -07005589 // The layout direction will be resolved only if needed
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -07005590 if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
5591 resolveLayoutDirection();
5592 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07005593 return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005594 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
5595 }
5596
5597 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005598 * Indicates whether or not this view's layout is right-to-left. This is resolved from
5599 * layout attribute and/or the inherited value from the parent
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005600 *
5601 * @return true if the layout is right-to-left.
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005602 */
5603 @ViewDebug.ExportedProperty(category = "layout")
5604 public boolean isLayoutRtl() {
5605 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
5606 }
5607
5608 /**
Adam Powell539ee872012-02-03 19:00:49 -08005609 * Indicates whether the view is currently tracking transient state that the
5610 * app should not need to concern itself with saving and restoring, but that
5611 * the framework should take special note to preserve when possible.
5612 *
Adam Powell785c4472012-05-02 21:25:39 -07005613 * <p>A view with transient state cannot be trivially rebound from an external
5614 * data source, such as an adapter binding item views in a list. This may be
5615 * because the view is performing an animation, tracking user selection
5616 * of content, or similar.</p>
5617 *
Adam Powell539ee872012-02-03 19:00:49 -08005618 * @return true if the view has transient state
Adam Powell539ee872012-02-03 19:00:49 -08005619 */
5620 @ViewDebug.ExportedProperty(category = "layout")
5621 public boolean hasTransientState() {
5622 return (mPrivateFlags2 & HAS_TRANSIENT_STATE) == HAS_TRANSIENT_STATE;
5623 }
5624
5625 /**
5626 * Set whether this view is currently tracking transient state that the
Chet Haase563d4f22012-04-18 16:20:08 -07005627 * framework should attempt to preserve when possible. This flag is reference counted,
5628 * so every call to setHasTransientState(true) should be paired with a later call
5629 * to setHasTransientState(false).
Adam Powell539ee872012-02-03 19:00:49 -08005630 *
Adam Powell785c4472012-05-02 21:25:39 -07005631 * <p>A view with transient state cannot be trivially rebound from an external
5632 * data source, such as an adapter binding item views in a list. This may be
5633 * because the view is performing an animation, tracking user selection
5634 * of content, or similar.</p>
5635 *
Adam Powell539ee872012-02-03 19:00:49 -08005636 * @param hasTransientState true if this view has transient state
Adam Powell539ee872012-02-03 19:00:49 -08005637 */
5638 public void setHasTransientState(boolean hasTransientState) {
Chet Haase563d4f22012-04-18 16:20:08 -07005639 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
5640 mTransientStateCount - 1;
5641 if (mTransientStateCount < 0) {
5642 mTransientStateCount = 0;
5643 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
5644 "unmatched pair of setHasTransientState calls");
5645 }
5646 if ((hasTransientState && mTransientStateCount == 1) ||
Adam Powell057a5852012-05-11 10:28:38 -07005647 (!hasTransientState && mTransientStateCount == 0)) {
Chet Haase563d4f22012-04-18 16:20:08 -07005648 // update flag if we've just incremented up from 0 or decremented down to 0
5649 mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) |
5650 (hasTransientState ? HAS_TRANSIENT_STATE : 0);
5651 if (mParent != null) {
5652 try {
5653 mParent.childHasTransientStateChanged(this, hasTransientState);
5654 } catch (AbstractMethodError e) {
5655 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
5656 " does not fully implement ViewParent", e);
5657 }
Adam Powell539ee872012-02-03 19:00:49 -08005658 }
5659 }
5660 }
5661
5662 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 * If this view doesn't do any drawing on its own, set this flag to
5664 * allow further optimizations. By default, this flag is not set on
5665 * View, but could be set on some View subclasses such as ViewGroup.
5666 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07005667 * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
5668 * you should clear this flag.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 *
5670 * @param willNotDraw whether or not this View draw on its own
5671 */
5672 public void setWillNotDraw(boolean willNotDraw) {
5673 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
5674 }
5675
5676 /**
5677 * Returns whether or not this View draws on its own.
5678 *
5679 * @return true if this view has nothing to draw, false otherwise
5680 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005681 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 public boolean willNotDraw() {
5683 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
5684 }
5685
5686 /**
5687 * When a View's drawing cache is enabled, drawing is redirected to an
5688 * offscreen bitmap. Some views, like an ImageView, must be able to
5689 * bypass this mechanism if they already draw a single bitmap, to avoid
5690 * unnecessary usage of the memory.
5691 *
5692 * @param willNotCacheDrawing true if this view does not cache its
5693 * drawing, false otherwise
5694 */
5695 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
5696 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
5697 }
5698
5699 /**
5700 * Returns whether or not this View can cache its drawing or not.
5701 *
5702 * @return true if this view does not cache its drawing, false otherwise
5703 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005704 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005705 public boolean willNotCacheDrawing() {
5706 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
5707 }
5708
5709 /**
5710 * Indicates whether this view reacts to click events or not.
5711 *
5712 * @return true if the view is clickable, false otherwise
5713 *
5714 * @see #setClickable(boolean)
5715 * @attr ref android.R.styleable#View_clickable
5716 */
5717 @ViewDebug.ExportedProperty
5718 public boolean isClickable() {
5719 return (mViewFlags & CLICKABLE) == CLICKABLE;
5720 }
5721
5722 /**
5723 * Enables or disables click events for this view. When a view
5724 * is clickable it will change its state to "pressed" on every click.
5725 * Subclasses should set the view clickable to visually react to
5726 * user's clicks.
5727 *
5728 * @param clickable true to make the view clickable, false otherwise
5729 *
5730 * @see #isClickable()
5731 * @attr ref android.R.styleable#View_clickable
5732 */
5733 public void setClickable(boolean clickable) {
5734 setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
5735 }
5736
5737 /**
5738 * Indicates whether this view reacts to long click events or not.
5739 *
5740 * @return true if the view is long clickable, false otherwise
5741 *
5742 * @see #setLongClickable(boolean)
5743 * @attr ref android.R.styleable#View_longClickable
5744 */
5745 public boolean isLongClickable() {
5746 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
5747 }
5748
5749 /**
5750 * Enables or disables long click events for this view. When a view is long
5751 * clickable it reacts to the user holding down the button for a longer
5752 * duration than a tap. This event can either launch the listener or a
5753 * context menu.
5754 *
5755 * @param longClickable true to make the view long clickable, false otherwise
5756 * @see #isLongClickable()
5757 * @attr ref android.R.styleable#View_longClickable
5758 */
5759 public void setLongClickable(boolean longClickable) {
5760 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
5761 }
5762
5763 /**
Chet Haase49afa5b2010-08-23 11:39:53 -07005764 * Sets the pressed state for this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 *
5766 * @see #isClickable()
5767 * @see #setClickable(boolean)
5768 *
5769 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
5770 * the View's internal state from a previously set "pressed" state.
5771 */
5772 public void setPressed(boolean pressed) {
Adam Powell035a1fc2012-02-27 15:23:50 -08005773 final boolean needsRefresh = pressed != ((mPrivateFlags & PRESSED) == PRESSED);
Adam Powell4d6f0662012-02-21 15:11:11 -08005774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005775 if (pressed) {
5776 mPrivateFlags |= PRESSED;
5777 } else {
5778 mPrivateFlags &= ~PRESSED;
5779 }
Adam Powell035a1fc2012-02-27 15:23:50 -08005780
5781 if (needsRefresh) {
5782 refreshDrawableState();
5783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005784 dispatchSetPressed(pressed);
5785 }
5786
5787 /**
5788 * Dispatch setPressed to all of this View's children.
5789 *
5790 * @see #setPressed(boolean)
5791 *
5792 * @param pressed The new pressed state
5793 */
5794 protected void dispatchSetPressed(boolean pressed) {
5795 }
5796
5797 /**
5798 * Indicates whether the view is currently in pressed state. Unless
5799 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
5800 * the pressed state.
5801 *
Philip Milne6c8ea062012-04-03 17:38:43 -07005802 * @see #setPressed(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 * @see #isClickable()
5804 * @see #setClickable(boolean)
5805 *
5806 * @return true if the view is currently pressed, false otherwise
5807 */
5808 public boolean isPressed() {
5809 return (mPrivateFlags & PRESSED) == PRESSED;
5810 }
5811
5812 /**
5813 * Indicates whether this view will save its state (that is,
5814 * whether its {@link #onSaveInstanceState} method will be called).
5815 *
5816 * @return Returns true if the view state saving is enabled, else false.
5817 *
5818 * @see #setSaveEnabled(boolean)
5819 * @attr ref android.R.styleable#View_saveEnabled
5820 */
5821 public boolean isSaveEnabled() {
5822 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
5823 }
5824
5825 /**
5826 * Controls whether the saving of this view's state is
5827 * enabled (that is, whether its {@link #onSaveInstanceState} method
5828 * will be called). Note that even if freezing is enabled, the
Romain Guy5c22a8c2011-05-13 11:48:45 -07005829 * view still must have an id assigned to it (via {@link #setId(int)})
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 * for its state to be saved. This flag can only disable the
5831 * saving of this view; any child views may still have their state saved.
5832 *
5833 * @param enabled Set to false to <em>disable</em> state saving, or true
5834 * (the default) to allow it.
5835 *
5836 * @see #isSaveEnabled()
5837 * @see #setId(int)
5838 * @see #onSaveInstanceState()
5839 * @attr ref android.R.styleable#View_saveEnabled
5840 */
5841 public void setSaveEnabled(boolean enabled) {
5842 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
5843 }
5844
Jeff Brown85a31762010-09-01 17:01:00 -07005845 /**
5846 * Gets whether the framework should discard touches when the view's
5847 * window is obscured by another visible window.
5848 * Refer to the {@link View} security documentation for more details.
5849 *
5850 * @return True if touch filtering is enabled.
5851 *
5852 * @see #setFilterTouchesWhenObscured(boolean)
5853 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5854 */
5855 @ViewDebug.ExportedProperty
5856 public boolean getFilterTouchesWhenObscured() {
5857 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
5858 }
5859
5860 /**
5861 * Sets whether the framework should discard touches when the view's
5862 * window is obscured by another visible window.
5863 * Refer to the {@link View} security documentation for more details.
5864 *
5865 * @param enabled True if touch filtering should be enabled.
5866 *
5867 * @see #getFilterTouchesWhenObscured
5868 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5869 */
5870 public void setFilterTouchesWhenObscured(boolean enabled) {
5871 setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
5872 FILTER_TOUCHES_WHEN_OBSCURED);
5873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874
5875 /**
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07005876 * Indicates whether the entire hierarchy under this view will save its
5877 * state when a state saving traversal occurs from its parent. The default
5878 * is true; if false, these views will not be saved unless
5879 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5880 *
5881 * @return Returns true if the view state saving from parent is enabled, else false.
5882 *
5883 * @see #setSaveFromParentEnabled(boolean)
5884 */
5885 public boolean isSaveFromParentEnabled() {
5886 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
5887 }
5888
5889 /**
5890 * Controls whether the entire hierarchy under this view will save its
5891 * state when a state saving traversal occurs from its parent. The default
5892 * is true; if false, these views will not be saved unless
5893 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5894 *
5895 * @param enabled Set to false to <em>disable</em> state saving, or true
5896 * (the default) to allow it.
5897 *
5898 * @see #isSaveFromParentEnabled()
5899 * @see #setId(int)
5900 * @see #onSaveInstanceState()
5901 */
5902 public void setSaveFromParentEnabled(boolean enabled) {
5903 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
5904 }
5905
5906
5907 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005908 * Returns whether this View is able to take focus.
5909 *
5910 * @return True if this view can take focus, or false otherwise.
5911 * @attr ref android.R.styleable#View_focusable
5912 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005913 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 public final boolean isFocusable() {
5915 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
5916 }
5917
5918 /**
5919 * When a view is focusable, it may not want to take focus when in touch mode.
5920 * For example, a button would like focus when the user is navigating via a D-pad
5921 * so that the user can click on it, but once the user starts touching the screen,
5922 * the button shouldn't take focus
5923 * @return Whether the view is focusable in touch mode.
5924 * @attr ref android.R.styleable#View_focusableInTouchMode
5925 */
5926 @ViewDebug.ExportedProperty
5927 public final boolean isFocusableInTouchMode() {
5928 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
5929 }
5930
5931 /**
5932 * Find the nearest view in the specified direction that can take focus.
5933 * This does not actually give focus to that view.
5934 *
5935 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5936 *
5937 * @return The nearest focusable in the specified direction, or null if none
5938 * can be found.
5939 */
5940 public View focusSearch(int direction) {
5941 if (mParent != null) {
5942 return mParent.focusSearch(this, direction);
5943 } else {
5944 return null;
5945 }
5946 }
5947
5948 /**
5949 * This method is the last chance for the focused view and its ancestors to
5950 * respond to an arrow key. This is called when the focused view did not
5951 * consume the key internally, nor could the view system find a new view in
5952 * the requested direction to give focus to.
5953 *
5954 * @param focused The currently focused view.
5955 * @param direction The direction focus wants to move. One of FOCUS_UP,
5956 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
5957 * @return True if the this view consumed this unhandled move.
5958 */
5959 public boolean dispatchUnhandledMove(View focused, int direction) {
5960 return false;
5961 }
5962
5963 /**
5964 * If a user manually specified the next view id for a particular direction,
Jeff Brown4e6319b2010-12-13 10:36:51 -08005965 * use the root to look up the view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005966 * @param root The root view of the hierarchy containing this view.
Jeff Brown4e6319b2010-12-13 10:36:51 -08005967 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
5968 * or FOCUS_BACKWARD.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 * @return The user specified next view, or null if there is none.
5970 */
5971 View findUserSetNextFocus(View root, int direction) {
5972 switch (direction) {
5973 case FOCUS_LEFT:
5974 if (mNextFocusLeftId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07005975 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 case FOCUS_RIGHT:
5977 if (mNextFocusRightId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07005978 return findViewInsideOutShouldExist(root, mNextFocusRightId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 case FOCUS_UP:
5980 if (mNextFocusUpId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07005981 return findViewInsideOutShouldExist(root, mNextFocusUpId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005982 case FOCUS_DOWN:
5983 if (mNextFocusDownId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07005984 return findViewInsideOutShouldExist(root, mNextFocusDownId);
Jeff Brown4e6319b2010-12-13 10:36:51 -08005985 case FOCUS_FORWARD:
5986 if (mNextFocusForwardId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07005987 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
Jeff Brown4e6319b2010-12-13 10:36:51 -08005988 case FOCUS_BACKWARD: {
John Reck1ecebbb2012-03-06 16:08:54 -08005989 if (mID == View.NO_ID) return null;
Jeff Brown4e6319b2010-12-13 10:36:51 -08005990 final int id = mID;
Jeff Brown4dfbec22011-08-15 14:55:37 -07005991 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
Jeff Brown4e6319b2010-12-13 10:36:51 -08005992 @Override
5993 public boolean apply(View t) {
5994 return t.mNextFocusForwardId == id;
5995 }
5996 });
5997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005998 }
5999 return null;
6000 }
6001
Jeff Brown4dfbec22011-08-15 14:55:37 -07006002 private View findViewInsideOutShouldExist(View root, final int childViewId) {
6003 View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6004 @Override
6005 public boolean apply(View t) {
6006 return t.mID == childViewId;
6007 }
6008 });
6009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 if (result == null) {
6011 Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
6012 + "by user for id " + childViewId);
6013 }
6014 return result;
6015 }
6016
6017 /**
6018 * Find and return all focusable views that are descendants of this view,
6019 * possibly including this view if it is focusable itself.
6020 *
6021 * @param direction The direction of the focus
6022 * @return A list of focusable views
6023 */
6024 public ArrayList<View> getFocusables(int direction) {
6025 ArrayList<View> result = new ArrayList<View>(24);
6026 addFocusables(result, direction);
6027 return result;
6028 }
6029
6030 /**
6031 * Add any focusable views that are descendants of this view (possibly
6032 * including this view if it is focusable itself) to views. If we are in touch mode,
6033 * only add views that are also focusable in touch mode.
6034 *
6035 * @param views Focusable views found so far
6036 * @param direction The direction of the focus
6037 */
6038 public void addFocusables(ArrayList<View> views, int direction) {
svetoslavganov75986cf2009-05-14 22:28:01 -07006039 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
6040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041
svetoslavganov75986cf2009-05-14 22:28:01 -07006042 /**
6043 * Adds any focusable views that are descendants of this view (possibly
6044 * including this view if it is focusable itself) to views. This method
6045 * adds all focusable views regardless if we are in touch mode or
Svetoslav Ganov42138042012-03-20 11:51:39 -07006046 * only views focusable in touch mode if we are in touch mode or
6047 * only views that can take accessibility focus if accessibility is enabeld
6048 * depending on the focusable mode paramater.
svetoslavganov75986cf2009-05-14 22:28:01 -07006049 *
6050 * @param views Focusable views found so far or null if all we are interested is
6051 * the number of focusables.
6052 * @param direction The direction of the focus.
6053 * @param focusableMode The type of focusables to be added.
6054 *
6055 * @see #FOCUSABLES_ALL
6056 * @see #FOCUSABLES_TOUCH_MODE
6057 */
6058 public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006059 if (views == null) {
svetoslavganov75986cf2009-05-14 22:28:01 -07006060 return;
6061 }
Svetoslav Ganov3cb889c2012-04-16 19:10:30 -07006062 if (!isFocusable()) {
6063 return;
svetoslavganov75986cf2009-05-14 22:28:01 -07006064 }
Svetoslav Ganov3cb889c2012-04-16 19:10:30 -07006065 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
6066 && isInTouchMode() && !isFocusableInTouchMode()) {
6067 return;
6068 }
6069 views.add(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 }
6071
6072 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006073 * Finds the Views that contain given text. The containment is case insensitive.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006074 * The search is performed by either the text that the View renders or the content
6075 * description that describes the view for accessibility purposes and the view does
6076 * not render or both. Clients can specify how the search is to be performed via
6077 * passing the {@link #FIND_VIEWS_WITH_TEXT} and
6078 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006079 *
6080 * @param outViews The output list of matching Views.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006081 * @param searched The text to match against.
Svetoslav Ganov02107852011-10-03 17:06:56 -07006082 *
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006083 * @see #FIND_VIEWS_WITH_TEXT
6084 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
6085 * @see #setContentDescription(CharSequence)
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006086 */
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006087 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07006088 if (getAccessibilityNodeProvider() != null) {
6089 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
6090 outViews.add(this);
6091 }
6092 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006093 && (searched != null && searched.length() > 0)
6094 && (mContentDescription != null && mContentDescription.length() > 0)) {
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006095 String searchedLowerCase = searched.toString().toLowerCase();
6096 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
6097 if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
6098 outViews.add(this);
6099 }
6100 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006101 }
6102
6103 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006104 * Find and return all touchable views that are descendants of this view,
6105 * possibly including this view if it is touchable itself.
6106 *
6107 * @return A list of touchable views
6108 */
6109 public ArrayList<View> getTouchables() {
6110 ArrayList<View> result = new ArrayList<View>();
6111 addTouchables(result);
6112 return result;
6113 }
6114
6115 /**
6116 * Add any touchable views that are descendants of this view (possibly
6117 * including this view if it is touchable itself) to views.
6118 *
6119 * @param views Touchable views found so far
6120 */
6121 public void addTouchables(ArrayList<View> views) {
6122 final int viewFlags = mViewFlags;
6123
6124 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
6125 && (viewFlags & ENABLED_MASK) == ENABLED) {
6126 views.add(this);
6127 }
6128 }
6129
6130 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07006131 * Returns whether this View is accessibility focused.
6132 *
6133 * @return True if this View is accessibility focused.
6134 */
6135 boolean isAccessibilityFocused() {
6136 return (mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0;
6137 }
6138
6139 /**
6140 * Call this to try to give accessibility focus to this view.
6141 *
6142 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
6143 * returns false or the view is no visible or the view already has accessibility
6144 * focus.
6145 *
6146 * See also {@link #focusSearch(int)}, which is what you call to say that you
6147 * have focus, and you want your parent to look for the next one.
6148 *
6149 * @return Whether this view actually took accessibility focus.
6150 *
6151 * @hide
6152 */
6153 public boolean requestAccessibilityFocus() {
Svetoslav Ganov07b726c2012-04-30 12:24:57 -07006154 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
6155 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006156 return false;
6157 }
6158 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6159 return false;
6160 }
6161 if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) == 0) {
6162 mPrivateFlags2 |= ACCESSIBILITY_FOCUSED;
6163 ViewRootImpl viewRootImpl = getViewRootImpl();
6164 if (viewRootImpl != null) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006165 viewRootImpl.setAccessibilityFocus(this, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07006166 }
6167 invalidate();
6168 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
6169 notifyAccessibilityStateChanged();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006170 return true;
6171 }
6172 return false;
6173 }
6174
6175 /**
6176 * Call this to try to clear accessibility focus of this view.
6177 *
6178 * See also {@link #focusSearch(int)}, which is what you call to say that you
6179 * have focus, and you want your parent to look for the next one.
6180 *
6181 * @hide
6182 */
6183 public void clearAccessibilityFocus() {
Svetoslav Ganov791fd312012-05-14 15:12:30 -07006184 if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
6185 mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006186 invalidate();
6187 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
6188 notifyAccessibilityStateChanged();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006189 }
Svetoslav Ganovc00d0082012-05-22 18:37:49 -07006190 // Clear the global reference of accessibility focus if this
6191 // view or any of its descendants had accessibility focus.
6192 ViewRootImpl viewRootImpl = getViewRootImpl();
6193 if (viewRootImpl != null) {
6194 View focusHost = viewRootImpl.getAccessibilityFocusedHost();
6195 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006196 viewRootImpl.setAccessibilityFocus(null, null);
Svetoslav Ganovc00d0082012-05-22 18:37:49 -07006197 }
6198 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006199 }
6200
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07006201 private void sendAccessibilityHoverEvent(int eventType) {
6202 // Since we are not delivering to a client accessibility events from not
6203 // important views (unless the clinet request that) we need to fire the
6204 // event from the deepest view exposed to the client. As a consequence if
6205 // the user crosses a not exposed view the client will see enter and exit
6206 // of the exposed predecessor followed by and enter and exit of that same
6207 // predecessor when entering and exiting the not exposed descendant. This
6208 // is fine since the client has a clear idea which view is hovered at the
6209 // price of a couple more events being sent. This is a simple and
6210 // working solution.
6211 View source = this;
6212 while (true) {
6213 if (source.includeForAccessibility()) {
6214 source.sendAccessibilityEvent(eventType);
6215 return;
6216 }
6217 ViewParent parent = source.getParent();
6218 if (parent instanceof View) {
6219 source = (View) parent;
6220 } else {
6221 return;
6222 }
6223 }
6224 }
6225
Svetoslav Ganov42138042012-03-20 11:51:39 -07006226 /**
6227 * Clears accessibility focus without calling any callback methods
6228 * normally invoked in {@link #clearAccessibilityFocus()}. This method
6229 * is used for clearing accessibility focus when giving this focus to
6230 * another view.
6231 */
6232 void clearAccessibilityFocusNoCallbacks() {
6233 if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
6234 mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
6235 invalidate();
6236 }
6237 }
6238
6239 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 * Call this to try to give focus to a specific view or to one of its
6241 * descendants.
6242 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006243 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6244 * false), or if it is focusable and it is not focusable in touch mode
6245 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006246 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006247 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 * have focus, and you want your parent to look for the next one.
6249 *
6250 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
6251 * {@link #FOCUS_DOWN} and <code>null</code>.
6252 *
6253 * @return Whether this view or one of its descendants actually took focus.
6254 */
6255 public final boolean requestFocus() {
6256 return requestFocus(View.FOCUS_DOWN);
6257 }
6258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 /**
6260 * Call this to try to give focus to a specific view or to one of its
6261 * descendants and give it a hint about what direction focus is heading.
6262 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006263 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6264 * false), or if it is focusable and it is not focusable in touch mode
6265 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006266 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006267 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 * have focus, and you want your parent to look for the next one.
6269 *
6270 * This is equivalent to calling {@link #requestFocus(int, Rect)} with
6271 * <code>null</code> set for the previously focused rectangle.
6272 *
6273 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6274 * @return Whether this view or one of its descendants actually took focus.
6275 */
6276 public final boolean requestFocus(int direction) {
6277 return requestFocus(direction, null);
6278 }
6279
6280 /**
6281 * Call this to try to give focus to a specific view or to one of its descendants
6282 * and give it hints about the direction and a specific rectangle that the focus
6283 * is coming from. The rectangle can help give larger views a finer grained hint
6284 * about where focus is coming from, and therefore, where to show selection, or
6285 * forward focus change internally.
6286 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006287 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6288 * false), or if it is focusable and it is not focusable in touch mode
6289 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006290 *
6291 * A View will not take focus if it is not visible.
6292 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006293 * A View will not take focus if one of its parents has
6294 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
6295 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006297 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 * have focus, and you want your parent to look for the next one.
6299 *
6300 * You may wish to override this method if your custom {@link View} has an internal
6301 * {@link View} that it wishes to forward the request to.
6302 *
6303 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6304 * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
6305 * to give a finer grained hint about where focus is coming from. May be null
6306 * if there is no hint.
6307 * @return Whether this view or one of its descendants actually took focus.
6308 */
6309 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006310 return requestFocusNoSearch(direction, previouslyFocusedRect);
6311 }
6312
6313 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 // need to be focusable
6315 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
6316 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6317 return false;
6318 }
6319
6320 // need to be focusable in touch mode if in touch mode
6321 if (isInTouchMode() &&
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006322 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
6323 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006324 }
6325
6326 // need to not have any parents blocking us
6327 if (hasAncestorThatBlocksDescendantFocus()) {
6328 return false;
6329 }
6330
6331 handleFocusGainInternal(direction, previouslyFocusedRect);
6332 return true;
6333 }
6334
6335 /**
6336 * Call this to try to give focus to a specific view or to one of its descendants. This is a
6337 * special variant of {@link #requestFocus() } that will allow views that are not focuable in
6338 * touch mode to request focus when they are touched.
6339 *
6340 * @return Whether this view or one of its descendants actually took focus.
6341 *
6342 * @see #isInTouchMode()
6343 *
6344 */
6345 public final boolean requestFocusFromTouch() {
6346 // Leave touch mode if we need to
6347 if (isInTouchMode()) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006348 ViewRootImpl viewRoot = getViewRootImpl();
Christopher Tate2c095f32010-10-04 14:13:40 -07006349 if (viewRoot != null) {
6350 viewRoot.ensureTouchMode(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 }
6352 }
6353 return requestFocus(View.FOCUS_DOWN);
6354 }
6355
6356 /**
6357 * @return Whether any ancestor of this view blocks descendant focus.
6358 */
6359 private boolean hasAncestorThatBlocksDescendantFocus() {
6360 ViewParent ancestor = mParent;
6361 while (ancestor instanceof ViewGroup) {
6362 final ViewGroup vgAncestor = (ViewGroup) ancestor;
6363 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
6364 return true;
6365 } else {
6366 ancestor = vgAncestor.getParent();
6367 }
6368 }
6369 return false;
6370 }
6371
6372 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07006373 * Gets the mode for determining whether this View is important for accessibility
6374 * which is if it fires accessibility events and if it is reported to
6375 * accessibility services that query the screen.
6376 *
6377 * @return The mode for determining whether a View is important for accessibility.
6378 *
6379 * @attr ref android.R.styleable#View_importantForAccessibility
6380 *
6381 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6382 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6383 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6384 */
6385 @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07006386 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
6387 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
6388 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
Svetoslav Ganov42138042012-03-20 11:51:39 -07006389 })
6390 public int getImportantForAccessibility() {
6391 return (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
6392 >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6393 }
6394
6395 /**
6396 * Sets how to determine whether this view is important for accessibility
6397 * which is if it fires accessibility events and if it is reported to
6398 * accessibility services that query the screen.
6399 *
6400 * @param mode How to determine whether this view is important for accessibility.
6401 *
6402 * @attr ref android.R.styleable#View_importantForAccessibility
6403 *
6404 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6405 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6406 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6407 */
6408 public void setImportantForAccessibility(int mode) {
6409 if (mode != getImportantForAccessibility()) {
6410 mPrivateFlags2 &= ~IMPORTANT_FOR_ACCESSIBILITY_MASK;
6411 mPrivateFlags2 |= (mode << IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
6412 & IMPORTANT_FOR_ACCESSIBILITY_MASK;
6413 notifyAccessibilityStateChanged();
6414 }
6415 }
6416
6417 /**
6418 * Gets whether this view should be exposed for accessibility.
6419 *
6420 * @return Whether the view is exposed for accessibility.
6421 *
6422 * @hide
6423 */
6424 public boolean isImportantForAccessibility() {
6425 final int mode = (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
6426 >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6427 switch (mode) {
6428 case IMPORTANT_FOR_ACCESSIBILITY_YES:
6429 return true;
6430 case IMPORTANT_FOR_ACCESSIBILITY_NO:
6431 return false;
6432 case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
Svetoslav Ganov34caec92012-07-19 18:07:58 -07006433 return isActionableForAccessibility() || hasListenersForAccessibility()
6434 || getAccessibilityNodeProvider() != null;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006435 default:
6436 throw new IllegalArgumentException("Unknow important for accessibility mode: "
6437 + mode);
6438 }
6439 }
6440
6441 /**
6442 * Gets the parent for accessibility purposes. Note that the parent for
6443 * accessibility is not necessary the immediate parent. It is the first
6444 * predecessor that is important for accessibility.
6445 *
6446 * @return The parent for accessibility purposes.
6447 */
6448 public ViewParent getParentForAccessibility() {
6449 if (mParent instanceof View) {
6450 View parentView = (View) mParent;
6451 if (parentView.includeForAccessibility()) {
6452 return mParent;
6453 } else {
6454 return mParent.getParentForAccessibility();
6455 }
6456 }
6457 return null;
6458 }
6459
6460 /**
6461 * Adds the children of a given View for accessibility. Since some Views are
6462 * not important for accessibility the children for accessibility are not
6463 * necessarily direct children of the riew, rather they are the first level of
6464 * descendants important for accessibility.
6465 *
6466 * @param children The list of children for accessibility.
6467 */
6468 public void addChildrenForAccessibility(ArrayList<View> children) {
6469 if (includeForAccessibility()) {
6470 children.add(this);
6471 }
6472 }
6473
6474 /**
6475 * Whether to regard this view for accessibility. A view is regarded for
6476 * accessibility if it is important for accessibility or the querying
6477 * accessibility service has explicitly requested that view not
6478 * important for accessibility are regarded.
6479 *
6480 * @return Whether to regard the view for accessibility.
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006481 *
6482 * @hide
Svetoslav Ganov42138042012-03-20 11:51:39 -07006483 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006484 public boolean includeForAccessibility() {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006485 if (mAttachInfo != null) {
Romain Guyf0af1d52012-07-11 18:31:21 -07006486 return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006487 }
6488 return false;
6489 }
6490
6491 /**
6492 * Returns whether the View is considered actionable from
6493 * accessibility perspective. Such view are important for
6494 * accessiiblity.
6495 *
6496 * @return True if the view is actionable for accessibility.
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006497 *
6498 * @hide
Svetoslav Ganov42138042012-03-20 11:51:39 -07006499 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006500 public boolean isActionableForAccessibility() {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006501 return (isClickable() || isLongClickable() || isFocusable());
6502 }
6503
6504 /**
6505 * Returns whether the View has registered callbacks wich makes it
6506 * important for accessiiblity.
6507 *
6508 * @return True if the view is actionable for accessibility.
6509 */
6510 private boolean hasListenersForAccessibility() {
6511 ListenerInfo info = getListenerInfo();
6512 return mTouchDelegate != null || info.mOnKeyListener != null
6513 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
6514 || info.mOnHoverListener != null || info.mOnDragListener != null;
6515 }
6516
6517 /**
6518 * Notifies accessibility services that some view's important for
6519 * accessibility state has changed. Note that such notifications
6520 * are made at most once every
6521 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
6522 * to avoid unnecessary load to the system. Also once a view has
6523 * made a notifucation this method is a NOP until the notification has
6524 * been sent to clients.
6525 *
6526 * @hide
6527 *
6528 * TODO: Makse sure this method is called for any view state change
6529 * that is interesting for accessilility purposes.
6530 */
6531 public void notifyAccessibilityStateChanged() {
Svetoslav Ganovc406be92012-05-11 16:12:32 -07006532 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
6533 return;
6534 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006535 if ((mPrivateFlags2 & ACCESSIBILITY_STATE_CHANGED) == 0) {
6536 mPrivateFlags2 |= ACCESSIBILITY_STATE_CHANGED;
6537 if (mParent != null) {
6538 mParent.childAccessibilityStateChanged(this);
6539 }
6540 }
6541 }
6542
6543 /**
6544 * Reset the state indicating the this view has requested clients
6545 * interested in its accessiblity state to be notified.
6546 *
6547 * @hide
6548 */
6549 public void resetAccessibilityStateChanged() {
6550 mPrivateFlags2 &= ~ACCESSIBILITY_STATE_CHANGED;
6551 }
6552
6553 /**
6554 * Performs the specified accessibility action on the view. For
6555 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
alanv8eeefef2012-05-07 16:57:53 -07006556 * <p>
6557 * If an {@link AccessibilityDelegate} has been specified via calling
6558 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6559 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
6560 * is responsible for handling this call.
6561 * </p>
Svetoslav Ganov42138042012-03-20 11:51:39 -07006562 *
6563 * @param action The action to perform.
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006564 * @param arguments Optional action arguments.
Svetoslav Ganov42138042012-03-20 11:51:39 -07006565 * @return Whether the action was performed.
6566 */
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006567 public boolean performAccessibilityAction(int action, Bundle arguments) {
alanv8eeefef2012-05-07 16:57:53 -07006568 if (mAccessibilityDelegate != null) {
6569 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
6570 } else {
6571 return performAccessibilityActionInternal(action, arguments);
6572 }
6573 }
6574
6575 /**
6576 * @see #performAccessibilityAction(int, Bundle)
6577 *
6578 * Note: Called from the default {@link AccessibilityDelegate}.
6579 */
6580 boolean performAccessibilityActionInternal(int action, Bundle arguments) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006581 switch (action) {
6582 case AccessibilityNodeInfo.ACTION_CLICK: {
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006583 if (isClickable()) {
Svetoslav Ganov773f2622012-05-05 19:59:42 -07006584 return performClick();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006585 }
6586 } break;
6587 case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
6588 if (isLongClickable()) {
Svetoslav Ganov773f2622012-05-05 19:59:42 -07006589 return performLongClick();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006590 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006591 } break;
6592 case AccessibilityNodeInfo.ACTION_FOCUS: {
6593 if (!hasFocus()) {
6594 // Get out of touch mode since accessibility
6595 // wants to move focus around.
6596 getViewRootImpl().ensureTouchMode(false);
6597 return requestFocus();
6598 }
6599 } break;
6600 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
6601 if (hasFocus()) {
6602 clearFocus();
6603 return !isFocused();
6604 }
6605 } break;
6606 case AccessibilityNodeInfo.ACTION_SELECT: {
6607 if (!isSelected()) {
6608 setSelected(true);
6609 return isSelected();
6610 }
6611 } break;
6612 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
6613 if (isSelected()) {
6614 setSelected(false);
6615 return !isSelected();
6616 }
6617 } break;
6618 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07006619 if (!isAccessibilityFocused()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006620 return requestAccessibilityFocus();
6621 }
6622 } break;
6623 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
6624 if (isAccessibilityFocused()) {
6625 clearAccessibilityFocus();
6626 return true;
6627 }
6628 } break;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006629 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
6630 if (arguments != null) {
6631 final int granularity = arguments.getInt(
6632 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6633 return nextAtGranularity(granularity);
6634 }
6635 } break;
6636 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
6637 if (arguments != null) {
6638 final int granularity = arguments.getInt(
6639 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6640 return previousAtGranularity(granularity);
6641 }
6642 } break;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006643 }
6644 return false;
6645 }
6646
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006647 private boolean nextAtGranularity(int granularity) {
6648 CharSequence text = getIterableTextForAccessibility();
Svetoslav Ganov64899e52012-05-15 21:09:30 -07006649 if (text == null || text.length() == 0) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006650 return false;
6651 }
6652 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6653 if (iterator == null) {
6654 return false;
6655 }
6656 final int current = getAccessibilityCursorPosition();
6657 final int[] range = iterator.following(current);
6658 if (range == null) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006659 return false;
6660 }
6661 final int start = range[0];
6662 final int end = range[1];
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006663 setAccessibilityCursorPosition(end);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006664 sendViewTextTraversedAtGranularityEvent(
6665 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
6666 granularity, start, end);
6667 return true;
6668 }
6669
6670 private boolean previousAtGranularity(int granularity) {
6671 CharSequence text = getIterableTextForAccessibility();
Svetoslav Ganov64899e52012-05-15 21:09:30 -07006672 if (text == null || text.length() == 0) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006673 return false;
6674 }
6675 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6676 if (iterator == null) {
6677 return false;
6678 }
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006679 int current = getAccessibilityCursorPosition();
6680 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
6681 current = text.length();
6682 } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6683 // When traversing by character we always put the cursor after the character
6684 // to ease edit and have to compensate before asking the for previous segment.
6685 current--;
6686 }
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006687 final int[] range = iterator.preceding(current);
6688 if (range == null) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006689 return false;
6690 }
6691 final int start = range[0];
6692 final int end = range[1];
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006693 // Always put the cursor after the character to ease edit.
6694 if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6695 setAccessibilityCursorPosition(end);
6696 } else {
6697 setAccessibilityCursorPosition(start);
6698 }
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006699 sendViewTextTraversedAtGranularityEvent(
6700 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
6701 granularity, start, end);
6702 return true;
6703 }
6704
6705 /**
6706 * Gets the text reported for accessibility purposes.
6707 *
6708 * @return The accessibility text.
6709 *
6710 * @hide
6711 */
6712 public CharSequence getIterableTextForAccessibility() {
6713 return mContentDescription;
6714 }
6715
6716 /**
6717 * @hide
6718 */
6719 public int getAccessibilityCursorPosition() {
6720 return mAccessibilityCursorPosition;
6721 }
6722
6723 /**
6724 * @hide
6725 */
6726 public void setAccessibilityCursorPosition(int position) {
6727 mAccessibilityCursorPosition = position;
6728 }
6729
6730 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
6731 int fromIndex, int toIndex) {
6732 if (mParent == null) {
6733 return;
6734 }
6735 AccessibilityEvent event = AccessibilityEvent.obtain(
6736 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
6737 onInitializeAccessibilityEvent(event);
6738 onPopulateAccessibilityEvent(event);
6739 event.setFromIndex(fromIndex);
6740 event.setToIndex(toIndex);
6741 event.setAction(action);
6742 event.setMovementGranularity(granularity);
6743 mParent.requestSendAccessibilityEvent(this, event);
6744 }
6745
6746 /**
6747 * @hide
6748 */
6749 public TextSegmentIterator getIteratorForGranularity(int granularity) {
6750 switch (granularity) {
6751 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
6752 CharSequence text = getIterableTextForAccessibility();
6753 if (text != null && text.length() > 0) {
6754 CharacterTextSegmentIterator iterator =
Svetoslav Ganovbbd31552012-06-11 12:08:18 -07006755 CharacterTextSegmentIterator.getInstance(
6756 mContext.getResources().getConfiguration().locale);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006757 iterator.initialize(text.toString());
6758 return iterator;
6759 }
6760 } break;
6761 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
6762 CharSequence text = getIterableTextForAccessibility();
6763 if (text != null && text.length() > 0) {
6764 WordTextSegmentIterator iterator =
Svetoslav Ganovbbd31552012-06-11 12:08:18 -07006765 WordTextSegmentIterator.getInstance(
6766 mContext.getResources().getConfiguration().locale);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006767 iterator.initialize(text.toString());
6768 return iterator;
6769 }
6770 } break;
6771 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
6772 CharSequence text = getIterableTextForAccessibility();
6773 if (text != null && text.length() > 0) {
6774 ParagraphTextSegmentIterator iterator =
6775 ParagraphTextSegmentIterator.getInstance();
6776 iterator.initialize(text.toString());
6777 return iterator;
6778 }
6779 } break;
6780 }
6781 return null;
6782 }
6783
Svetoslav Ganov42138042012-03-20 11:51:39 -07006784 /**
Romain Guya440b002010-02-24 15:57:54 -08006785 * @hide
6786 */
6787 public void dispatchStartTemporaryDetach() {
Svetoslav Ganov961bf0e2012-05-08 09:40:03 -07006788 clearAccessibilityFocus();
Romain Guy38c2ece2012-05-24 14:20:56 -07006789 clearDisplayList();
6790
Romain Guya440b002010-02-24 15:57:54 -08006791 onStartTemporaryDetach();
6792 }
6793
6794 /**
6795 * This is called when a container is going to temporarily detach a child, with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006796 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
6797 * It will either be followed by {@link #onFinishTemporaryDetach()} or
Romain Guya440b002010-02-24 15:57:54 -08006798 * {@link #onDetachedFromWindow()} when the container is done.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006799 */
6800 public void onStartTemporaryDetach() {
Romain Guya440b002010-02-24 15:57:54 -08006801 removeUnsetPressCallback();
Romain Guy8afa5152010-02-26 11:56:30 -08006802 mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
Romain Guya440b002010-02-24 15:57:54 -08006803 }
6804
6805 /**
6806 * @hide
6807 */
6808 public void dispatchFinishTemporaryDetach() {
6809 onFinishTemporaryDetach();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006810 }
Romain Guy8506ab42009-06-11 17:35:47 -07006811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 /**
6813 * Called after {@link #onStartTemporaryDetach} when the container is done
6814 * changing the view.
6815 */
6816 public void onFinishTemporaryDetach() {
6817 }
Romain Guy8506ab42009-06-11 17:35:47 -07006818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006819 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006820 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
6821 * for this view's window. Returns null if the view is not currently attached
6822 * to the window. Normally you will not need to use this directly, but
Romain Guy5c22a8c2011-05-13 11:48:45 -07006823 * just use the standard high-level event callbacks like
6824 * {@link #onKeyDown(int, KeyEvent)}.
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006825 */
6826 public KeyEvent.DispatcherState getKeyDispatcherState() {
6827 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
6828 }
Joe Malin32736f02011-01-19 16:14:20 -08006829
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006830 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831 * Dispatch a key event before it is processed by any input method
6832 * associated with the view hierarchy. This can be used to intercept
6833 * key events in special situations before the IME consumes them; a
6834 * typical example would be handling the BACK key to update the application's
6835 * UI instead of allowing the IME to see it and close itself.
6836 *
6837 * @param event The key event to be dispatched.
6838 * @return True if the event was handled, false otherwise.
6839 */
6840 public boolean dispatchKeyEventPreIme(KeyEvent event) {
6841 return onKeyPreIme(event.getKeyCode(), event);
6842 }
6843
6844 /**
6845 * Dispatch a key event to the next view on the focus path. This path runs
6846 * from the top of the view tree down to the currently focused view. If this
6847 * view has focus, it will dispatch to itself. Otherwise it will dispatch
6848 * the next node down the focus path. This method also fires any key
6849 * listeners.
6850 *
6851 * @param event The key event to be dispatched.
6852 * @return True if the event was handled, false otherwise.
6853 */
6854 public boolean dispatchKeyEvent(KeyEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08006855 if (mInputEventConsistencyVerifier != null) {
6856 mInputEventConsistencyVerifier.onKeyEvent(event, 0);
6857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006858
Jeff Brown21bc5c92011-02-28 18:27:14 -08006859 // Give any attached key listener a first crack at the event.
Romain Guyf607bdc2010-09-10 19:20:06 -07006860 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07006861 ListenerInfo li = mListenerInfo;
6862 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
6863 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006864 return true;
6865 }
6866
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006867 if (event.dispatch(this, mAttachInfo != null
6868 ? mAttachInfo.mKeyDispatchState : null, this)) {
6869 return true;
6870 }
6871
6872 if (mInputEventConsistencyVerifier != null) {
6873 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
6874 }
6875 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 }
6877
6878 /**
6879 * Dispatches a key shortcut event.
6880 *
6881 * @param event The key event to be dispatched.
6882 * @return True if the event was handled by the view, false otherwise.
6883 */
6884 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
6885 return onKeyShortcut(event.getKeyCode(), event);
6886 }
6887
6888 /**
6889 * Pass the touch screen motion event down to the target view, or this
6890 * view if it is the target.
6891 *
6892 * @param event The motion event to be dispatched.
6893 * @return True if the event was handled by the view, false otherwise.
6894 */
6895 public boolean dispatchTouchEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08006896 if (mInputEventConsistencyVerifier != null) {
6897 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
6898 }
6899
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006900 if (onFilterTouchEventForSecurity(event)) {
6901 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07006902 ListenerInfo li = mListenerInfo;
6903 if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
6904 && li.mOnTouchListener.onTouch(this, event)) {
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006905 return true;
6906 }
6907
6908 if (onTouchEvent(event)) {
6909 return true;
6910 }
Jeff Brown85a31762010-09-01 17:01:00 -07006911 }
6912
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006913 if (mInputEventConsistencyVerifier != null) {
6914 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 }
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006916 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006917 }
6918
6919 /**
Jeff Brown85a31762010-09-01 17:01:00 -07006920 * Filter the touch event to apply security policies.
6921 *
6922 * @param event The motion event to be filtered.
6923 * @return True if the event should be dispatched, false if the event should be dropped.
Joe Malin32736f02011-01-19 16:14:20 -08006924 *
Jeff Brown85a31762010-09-01 17:01:00 -07006925 * @see #getFilterTouchesWhenObscured
6926 */
6927 public boolean onFilterTouchEventForSecurity(MotionEvent event) {
Romain Guyf607bdc2010-09-10 19:20:06 -07006928 //noinspection RedundantIfStatement
Jeff Brown85a31762010-09-01 17:01:00 -07006929 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
6930 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
6931 // Window is obscured, drop this touch.
6932 return false;
6933 }
6934 return true;
6935 }
6936
6937 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006938 * Pass a trackball motion event down to the focused view.
6939 *
6940 * @param event The motion event to be dispatched.
6941 * @return True if the event was handled by the view, false otherwise.
6942 */
6943 public boolean dispatchTrackballEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08006944 if (mInputEventConsistencyVerifier != null) {
6945 mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
6946 }
6947
Romain Guy02ccac62011-06-24 13:20:23 -07006948 return onTrackballEvent(event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 }
6950
6951 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08006952 * Dispatch a generic motion event.
6953 * <p>
6954 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
6955 * are delivered to the view under the pointer. All other generic motion events are
Jeff Browna032cc02011-03-07 16:56:21 -08006956 * delivered to the focused view. Hover events are handled specially and are delivered
Romain Guy5c22a8c2011-05-13 11:48:45 -07006957 * to {@link #onHoverEvent(MotionEvent)}.
Jeff Brown33bbfd22011-02-24 20:55:35 -08006958 * </p>
Jeff Browncb1404e2011-01-15 18:14:15 -08006959 *
6960 * @param event The motion event to be dispatched.
6961 * @return True if the event was handled by the view, false otherwise.
6962 */
6963 public boolean dispatchGenericMotionEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08006964 if (mInputEventConsistencyVerifier != null) {
6965 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
6966 }
6967
Jeff Browna032cc02011-03-07 16:56:21 -08006968 final int source = event.getSource();
6969 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
6970 final int action = event.getAction();
6971 if (action == MotionEvent.ACTION_HOVER_ENTER
6972 || action == MotionEvent.ACTION_HOVER_MOVE
6973 || action == MotionEvent.ACTION_HOVER_EXIT) {
6974 if (dispatchHoverEvent(event)) {
6975 return true;
6976 }
6977 } else if (dispatchGenericPointerEvent(event)) {
6978 return true;
6979 }
6980 } else if (dispatchGenericFocusedEvent(event)) {
6981 return true;
6982 }
6983
Jeff Brown10b62902011-06-20 16:40:37 -07006984 if (dispatchGenericMotionEventInternal(event)) {
6985 return true;
6986 }
6987
6988 if (mInputEventConsistencyVerifier != null) {
6989 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
6990 }
6991 return false;
6992 }
6993
6994 private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
Romain Guy7b5b6ab2011-03-14 18:05:08 -07006995 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07006996 ListenerInfo li = mListenerInfo;
6997 if (li != null && li.mOnGenericMotionListener != null
6998 && (mViewFlags & ENABLED_MASK) == ENABLED
6999 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08007000 return true;
7001 }
Jeff Brownbbdc50b2011-04-19 23:46:52 -07007002
7003 if (onGenericMotionEvent(event)) {
7004 return true;
7005 }
7006
7007 if (mInputEventConsistencyVerifier != null) {
7008 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7009 }
7010 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08007011 }
7012
7013 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007014 * Dispatch a hover event.
7015 * <p>
Philip Milne6c8ea062012-04-03 17:38:43 -07007016 * Do not call this method directly.
Romain Guy5c22a8c2011-05-13 11:48:45 -07007017 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007018 * </p>
7019 *
7020 * @param event The motion event to be dispatched.
7021 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007022 */
7023 protected boolean dispatchHoverEvent(MotionEvent event) {
Romain Guy02ccac62011-06-24 13:20:23 -07007024 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007025 ListenerInfo li = mListenerInfo;
7026 if (li != null && li.mOnHoverListener != null
7027 && (mViewFlags & ENABLED_MASK) == ENABLED
7028 && li.mOnHoverListener.onHover(this, event)) {
Jeff Brown10b62902011-06-20 16:40:37 -07007029 return true;
7030 }
7031
Jeff Browna032cc02011-03-07 16:56:21 -08007032 return onHoverEvent(event);
7033 }
7034
7035 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07007036 * Returns true if the view has a child to which it has recently sent
7037 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
7038 * it does not have a hovered child, then it must be the innermost hovered view.
7039 * @hide
7040 */
7041 protected boolean hasHoveredChild() {
7042 return false;
7043 }
7044
7045 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007046 * Dispatch a generic motion event to the view under the first pointer.
7047 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007048 * Do not call this method directly.
7049 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007050 * </p>
7051 *
7052 * @param event The motion event to be dispatched.
7053 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007054 */
7055 protected boolean dispatchGenericPointerEvent(MotionEvent event) {
7056 return false;
7057 }
7058
7059 /**
7060 * Dispatch a generic motion event to the currently focused view.
7061 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007062 * Do not call this method directly.
7063 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007064 * </p>
7065 *
7066 * @param event The motion event to be dispatched.
7067 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007068 */
7069 protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
7070 return false;
7071 }
7072
7073 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08007074 * Dispatch a pointer event.
7075 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007076 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
7077 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns
7078 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
Jeff Brown33bbfd22011-02-24 20:55:35 -08007079 * and should not be expected to handle other pointing device features.
7080 * </p>
7081 *
7082 * @param event The motion event to be dispatched.
7083 * @return True if the event was handled by the view, false otherwise.
7084 * @hide
7085 */
7086 public final boolean dispatchPointerEvent(MotionEvent event) {
7087 if (event.isTouchEvent()) {
7088 return dispatchTouchEvent(event);
7089 } else {
7090 return dispatchGenericMotionEvent(event);
7091 }
7092 }
7093
7094 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007095 * Called when the window containing this view gains or loses window focus.
7096 * ViewGroups should override to route to their children.
7097 *
7098 * @param hasFocus True if the window containing this view now has focus,
7099 * false otherwise.
7100 */
7101 public void dispatchWindowFocusChanged(boolean hasFocus) {
7102 onWindowFocusChanged(hasFocus);
7103 }
7104
7105 /**
7106 * Called when the window containing this view gains or loses focus. Note
7107 * that this is separate from view focus: to receive key events, both
7108 * your view and its window must have focus. If a window is displayed
7109 * on top of yours that takes input focus, then your own window will lose
7110 * focus but the view focus will remain unchanged.
7111 *
7112 * @param hasWindowFocus True if the window containing this view now has
7113 * focus, false otherwise.
7114 */
7115 public void onWindowFocusChanged(boolean hasWindowFocus) {
7116 InputMethodManager imm = InputMethodManager.peekInstance();
7117 if (!hasWindowFocus) {
7118 if (isPressed()) {
7119 setPressed(false);
7120 }
7121 if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
7122 imm.focusOut(this);
7123 }
Maryam Garrett1549dd12009-12-15 16:06:36 -05007124 removeLongPressCallback();
Tony Wu26edf202010-09-13 19:54:00 +08007125 removeTapCallback();
Romain Guya2431d02009-04-30 16:30:00 -07007126 onFocusLost();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007127 } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
7128 imm.focusIn(this);
7129 }
7130 refreshDrawableState();
7131 }
7132
7133 /**
7134 * Returns true if this view is in a window that currently has window focus.
7135 * Note that this is not the same as the view itself having focus.
7136 *
7137 * @return True if this view is in a window that currently has window focus.
7138 */
7139 public boolean hasWindowFocus() {
7140 return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
7141 }
7142
7143 /**
Adam Powell326d8082009-12-09 15:10:07 -08007144 * Dispatch a view visibility change down the view hierarchy.
7145 * ViewGroups should override to route to their children.
7146 * @param changedView The view whose visibility changed. Could be 'this' or
7147 * an ancestor view.
Romain Guy43c9cdf2010-01-27 13:53:55 -08007148 * @param visibility The new visibility of changedView: {@link #VISIBLE},
7149 * {@link #INVISIBLE} or {@link #GONE}.
Adam Powell326d8082009-12-09 15:10:07 -08007150 */
7151 protected void dispatchVisibilityChanged(View changedView, int visibility) {
7152 onVisibilityChanged(changedView, visibility);
7153 }
7154
7155 /**
7156 * Called when the visibility of the view or an ancestor of the view is changed.
7157 * @param changedView The view whose visibility changed. Could be 'this' or
7158 * an ancestor view.
Romain Guy43c9cdf2010-01-27 13:53:55 -08007159 * @param visibility The new visibility of changedView: {@link #VISIBLE},
7160 * {@link #INVISIBLE} or {@link #GONE}.
Adam Powell326d8082009-12-09 15:10:07 -08007161 */
7162 protected void onVisibilityChanged(View changedView, int visibility) {
Adam Powell8568c3a2010-04-19 14:26:11 -07007163 if (visibility == VISIBLE) {
7164 if (mAttachInfo != null) {
7165 initialAwakenScrollBars();
7166 } else {
7167 mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
7168 }
7169 }
Adam Powell326d8082009-12-09 15:10:07 -08007170 }
7171
7172 /**
Romain Guy43c9cdf2010-01-27 13:53:55 -08007173 * Dispatch a hint about whether this view is displayed. For instance, when
7174 * a View moves out of the screen, it might receives a display hint indicating
7175 * the view is not displayed. Applications should not <em>rely</em> on this hint
7176 * as there is no guarantee that they will receive one.
Joe Malin32736f02011-01-19 16:14:20 -08007177 *
Romain Guy43c9cdf2010-01-27 13:53:55 -08007178 * @param hint A hint about whether or not this view is displayed:
7179 * {@link #VISIBLE} or {@link #INVISIBLE}.
7180 */
7181 public void dispatchDisplayHint(int hint) {
7182 onDisplayHint(hint);
7183 }
7184
7185 /**
7186 * Gives this view a hint about whether is displayed or not. For instance, when
7187 * a View moves out of the screen, it might receives a display hint indicating
7188 * the view is not displayed. Applications should not <em>rely</em> on this hint
7189 * as there is no guarantee that they will receive one.
Joe Malin32736f02011-01-19 16:14:20 -08007190 *
Romain Guy43c9cdf2010-01-27 13:53:55 -08007191 * @param hint A hint about whether or not this view is displayed:
7192 * {@link #VISIBLE} or {@link #INVISIBLE}.
7193 */
7194 protected void onDisplayHint(int hint) {
7195 }
7196
7197 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198 * Dispatch a window visibility change down the view hierarchy.
7199 * ViewGroups should override to route to their children.
7200 *
7201 * @param visibility The new visibility of the window.
7202 *
Philip Milne6c8ea062012-04-03 17:38:43 -07007203 * @see #onWindowVisibilityChanged(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 */
7205 public void dispatchWindowVisibilityChanged(int visibility) {
7206 onWindowVisibilityChanged(visibility);
7207 }
7208
7209 /**
7210 * Called when the window containing has change its visibility
7211 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
7212 * that this tells you whether or not your window is being made visible
7213 * to the window manager; this does <em>not</em> tell you whether or not
7214 * your window is obscured by other windows on the screen, even if it
7215 * is itself visible.
7216 *
7217 * @param visibility The new visibility of the window.
7218 */
7219 protected void onWindowVisibilityChanged(int visibility) {
Adam Powell8568c3a2010-04-19 14:26:11 -07007220 if (visibility == VISIBLE) {
7221 initialAwakenScrollBars();
7222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007223 }
7224
7225 /**
7226 * Returns the current visibility of the window this view is attached to
7227 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
7228 *
7229 * @return Returns the current visibility of the view's window.
7230 */
7231 public int getWindowVisibility() {
7232 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
7233 }
7234
7235 /**
7236 * Retrieve the overall visible display size in which the window this view is
7237 * attached to has been positioned in. This takes into account screen
7238 * decorations above the window, for both cases where the window itself
7239 * is being position inside of them or the window is being placed under
7240 * then and covered insets are used for the window to position its content
7241 * inside. In effect, this tells you the available area where content can
7242 * be placed and remain visible to users.
7243 *
7244 * <p>This function requires an IPC back to the window manager to retrieve
7245 * the requested information, so should not be used in performance critical
7246 * code like drawing.
7247 *
7248 * @param outRect Filled in with the visible display frame. If the view
7249 * is not attached to a window, this is simply the raw display size.
7250 */
7251 public void getWindowVisibleDisplayFrame(Rect outRect) {
7252 if (mAttachInfo != null) {
7253 try {
7254 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
7255 } catch (RemoteException e) {
7256 return;
7257 }
7258 // XXX This is really broken, and probably all needs to be done
7259 // in the window manager, and we need to know more about whether
7260 // we want the area behind or in front of the IME.
7261 final Rect insets = mAttachInfo.mVisibleInsets;
7262 outRect.left += insets.left;
7263 outRect.top += insets.top;
7264 outRect.right -= insets.right;
7265 outRect.bottom -= insets.bottom;
7266 return;
7267 }
7268 Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07007269 d.getRectSize(outRect);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 }
7271
7272 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007273 * Dispatch a notification about a resource configuration change down
7274 * the view hierarchy.
7275 * ViewGroups should override to route to their children.
7276 *
7277 * @param newConfig The new resource configuration.
7278 *
Philip Milne6c8ea062012-04-03 17:38:43 -07007279 * @see #onConfigurationChanged(android.content.res.Configuration)
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007280 */
7281 public void dispatchConfigurationChanged(Configuration newConfig) {
7282 onConfigurationChanged(newConfig);
7283 }
7284
7285 /**
7286 * Called when the current configuration of the resources being used
7287 * by the application have changed. You can use this to decide when
7288 * to reload resources that can changed based on orientation and other
7289 * configuration characterstics. You only need to use this if you are
7290 * not relying on the normal {@link android.app.Activity} mechanism of
7291 * recreating the activity instance upon a configuration change.
7292 *
7293 * @param newConfig The new resource configuration.
7294 */
7295 protected void onConfigurationChanged(Configuration newConfig) {
7296 }
7297
7298 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 * Private function to aggregate all per-view attributes in to the view
7300 * root.
7301 */
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007302 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7303 performCollectViewAttributes(attachInfo, visibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007304 }
7305
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007306 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7307 if ((visibility & VISIBILITY_MASK) == VISIBLE) {
Joe Onorato664644d2011-01-23 17:53:23 -08007308 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007309 attachInfo.mKeepScreenOn = true;
Joe Onorato664644d2011-01-23 17:53:23 -08007310 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007311 attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007312 ListenerInfo li = mListenerInfo;
7313 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007314 attachInfo.mHasSystemUiListeners = true;
Joe Onorato664644d2011-01-23 17:53:23 -08007315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 }
7317 }
7318
7319 void needGlobalAttributesUpdate(boolean force) {
Joe Onorato664644d2011-01-23 17:53:23 -08007320 final AttachInfo ai = mAttachInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 if (ai != null) {
Joe Onorato664644d2011-01-23 17:53:23 -08007322 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
7323 || ai.mHasSystemUiListeners) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 ai.mRecomputeGlobalAttributes = true;
7325 }
7326 }
7327 }
7328
7329 /**
7330 * Returns whether the device is currently in touch mode. Touch mode is entered
7331 * once the user begins interacting with the device by touch, and affects various
7332 * things like whether focus is always visible to the user.
7333 *
7334 * @return Whether the device is in touch mode.
7335 */
7336 @ViewDebug.ExportedProperty
7337 public boolean isInTouchMode() {
7338 if (mAttachInfo != null) {
7339 return mAttachInfo.mInTouchMode;
7340 } else {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007341 return ViewRootImpl.isInTouchMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 }
7343 }
7344
7345 /**
7346 * Returns the context the view is running in, through which it can
7347 * access the current theme, resources, etc.
7348 *
7349 * @return The view's Context.
7350 */
7351 @ViewDebug.CapturedViewProperty
7352 public final Context getContext() {
7353 return mContext;
7354 }
7355
7356 /**
7357 * Handle a key event before it is processed by any input method
7358 * associated with the view hierarchy. This can be used to intercept
7359 * key events in special situations before the IME consumes them; a
7360 * typical example would be handling the BACK key to update the application's
7361 * UI instead of allowing the IME to see it and close itself.
7362 *
7363 * @param keyCode The value in event.getKeyCode().
7364 * @param event Description of the key event.
7365 * @return If you handled the event, return true. If you want to allow the
7366 * event to be handled by the next receiver, return false.
7367 */
7368 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
7369 return false;
7370 }
7371
7372 /**
Jeff Brown995e7742010-12-22 16:59:36 -08007373 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
7374 * KeyEvent.Callback.onKeyDown()}: perform press of the view
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
7376 * is released, if the view is enabled and clickable.
7377 *
Jean Chalard405bc512012-05-29 19:12:34 +09007378 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7379 * although some may elect to do so in some situations. Do not rely on this to
7380 * catch software key presses.
7381 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 * @param keyCode A key code that represents the button pressed, from
7383 * {@link android.view.KeyEvent}.
7384 * @param event The KeyEvent object that defines the button action.
7385 */
7386 public boolean onKeyDown(int keyCode, KeyEvent event) {
7387 boolean result = false;
7388
7389 switch (keyCode) {
7390 case KeyEvent.KEYCODE_DPAD_CENTER:
7391 case KeyEvent.KEYCODE_ENTER: {
7392 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7393 return true;
7394 }
7395 // Long clickable items don't necessarily have to be clickable
7396 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
7397 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
7398 (event.getRepeatCount() == 0)) {
7399 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007400 checkForLongClick(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 return true;
7402 }
7403 break;
7404 }
7405 }
7406 return result;
7407 }
7408
7409 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007410 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
7411 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
7412 * the event).
Jean Chalard405bc512012-05-29 19:12:34 +09007413 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7414 * although some may elect to do so in some situations. Do not rely on this to
7415 * catch software key presses.
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007416 */
7417 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
7418 return false;
7419 }
7420
7421 /**
Jeff Brown995e7742010-12-22 16:59:36 -08007422 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
7423 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
7425 * {@link KeyEvent#KEYCODE_ENTER} is released.
Jean Chalard405bc512012-05-29 19:12:34 +09007426 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7427 * although some may elect to do so in some situations. Do not rely on this to
7428 * catch software key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007429 *
7430 * @param keyCode A key code that represents the button pressed, from
7431 * {@link android.view.KeyEvent}.
7432 * @param event The KeyEvent object that defines the button action.
7433 */
7434 public boolean onKeyUp(int keyCode, KeyEvent event) {
7435 boolean result = false;
7436
7437 switch (keyCode) {
7438 case KeyEvent.KEYCODE_DPAD_CENTER:
7439 case KeyEvent.KEYCODE_ENTER: {
7440 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7441 return true;
7442 }
7443 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
7444 setPressed(false);
7445
7446 if (!mHasPerformedLongPress) {
7447 // This is a tap, so remove the longpress check
Maryam Garrett1549dd12009-12-15 16:06:36 -05007448 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007449
7450 result = performClick();
7451 }
7452 }
7453 break;
7454 }
7455 }
7456 return result;
7457 }
7458
7459 /**
7460 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
7461 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
7462 * the event).
Jean Chalard405bc512012-05-29 19:12:34 +09007463 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7464 * although some may elect to do so in some situations. Do not rely on this to
7465 * catch software key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466 *
7467 * @param keyCode A key code that represents the button pressed, from
7468 * {@link android.view.KeyEvent}.
7469 * @param repeatCount The number of times the action was made.
7470 * @param event The KeyEvent object that defines the button action.
7471 */
7472 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
7473 return false;
7474 }
7475
7476 /**
Jeff Brown64da12a2011-01-04 19:57:47 -08007477 * Called on the focused view when a key shortcut event is not handled.
7478 * Override this method to implement local key shortcuts for the View.
7479 * Key shortcuts can also be implemented by setting the
7480 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 *
7482 * @param keyCode The value in event.getKeyCode().
7483 * @param event Description of the key event.
7484 * @return If you handled the event, return true. If you want to allow the
7485 * event to be handled by the next receiver, return false.
7486 */
7487 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
7488 return false;
7489 }
7490
7491 /**
7492 * Check whether the called view is a text editor, in which case it
7493 * would make sense to automatically display a soft input window for
7494 * it. Subclasses should override this if they implement
7495 * {@link #onCreateInputConnection(EditorInfo)} to return true if
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007496 * a call on that method would return a non-null InputConnection, and
7497 * they are really a first-class editor that the user would normally
7498 * start typing on when the go into a window containing your view.
Romain Guy8506ab42009-06-11 17:35:47 -07007499 *
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007500 * <p>The default implementation always returns false. This does
7501 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
7502 * will not be called or the user can not otherwise perform edits on your
7503 * view; it is just a hint to the system that this is not the primary
7504 * purpose of this view.
Romain Guy8506ab42009-06-11 17:35:47 -07007505 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 * @return Returns true if this view is a text editor, else false.
7507 */
7508 public boolean onCheckIsTextEditor() {
7509 return false;
7510 }
Romain Guy8506ab42009-06-11 17:35:47 -07007511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512 /**
7513 * Create a new InputConnection for an InputMethod to interact
7514 * with the view. The default implementation returns null, since it doesn't
7515 * support input methods. You can override this to implement such support.
7516 * This is only needed for views that take focus and text input.
Romain Guy8506ab42009-06-11 17:35:47 -07007517 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 * <p>When implementing this, you probably also want to implement
7519 * {@link #onCheckIsTextEditor()} to indicate you will return a
7520 * non-null InputConnection.
7521 *
7522 * @param outAttrs Fill in with attribute information about the connection.
7523 */
7524 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
7525 return null;
7526 }
7527
7528 /**
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007529 * Called by the {@link android.view.inputmethod.InputMethodManager}
7530 * when a view who is not the current
7531 * input connection target is trying to make a call on the manager. The
7532 * default implementation returns false; you can override this to return
7533 * true for certain views if you are performing InputConnection proxying
7534 * to them.
7535 * @param view The View that is making the InputMethodManager call.
7536 * @return Return true to allow the call, false to reject.
7537 */
7538 public boolean checkInputConnectionProxy(View view) {
7539 return false;
7540 }
Romain Guy8506ab42009-06-11 17:35:47 -07007541
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007542 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007543 * Show the context menu for this view. It is not safe to hold on to the
7544 * menu after returning from this method.
7545 *
Gilles Debunnef788a9f2010-07-22 10:17:23 -07007546 * You should normally not overload this method. Overload
7547 * {@link #onCreateContextMenu(ContextMenu)} or define an
7548 * {@link OnCreateContextMenuListener} to add items to the context menu.
7549 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 * @param menu The context menu to populate
7551 */
7552 public void createContextMenu(ContextMenu menu) {
7553 ContextMenuInfo menuInfo = getContextMenuInfo();
7554
7555 // Sets the current menu info so all items added to menu will have
7556 // my extra info set.
7557 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
7558
7559 onCreateContextMenu(menu);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007560 ListenerInfo li = mListenerInfo;
7561 if (li != null && li.mOnCreateContextMenuListener != null) {
7562 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 }
7564
7565 // Clear the extra information so subsequent items that aren't mine don't
7566 // have my extra info.
7567 ((MenuBuilder)menu).setCurrentMenuInfo(null);
7568
7569 if (mParent != null) {
7570 mParent.createContextMenu(menu);
7571 }
7572 }
7573
7574 /**
7575 * Views should implement this if they have extra information to associate
7576 * with the context menu. The return result is supplied as a parameter to
7577 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
7578 * callback.
7579 *
7580 * @return Extra information about the item for which the context menu
7581 * should be shown. This information will vary across different
7582 * subclasses of View.
7583 */
7584 protected ContextMenuInfo getContextMenuInfo() {
7585 return null;
7586 }
7587
7588 /**
7589 * Views should implement this if the view itself is going to add items to
7590 * the context menu.
7591 *
7592 * @param menu the context menu to populate
7593 */
7594 protected void onCreateContextMenu(ContextMenu menu) {
7595 }
7596
7597 /**
7598 * Implement this method to handle trackball motion events. The
7599 * <em>relative</em> movement of the trackball since the last event
7600 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
7601 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
7602 * that a movement of 1 corresponds to the user pressing one DPAD key (so
7603 * they will often be fractional values, representing the more fine-grained
7604 * movement information available from a trackball).
7605 *
7606 * @param event The motion event.
7607 * @return True if the event was handled, false otherwise.
7608 */
7609 public boolean onTrackballEvent(MotionEvent event) {
7610 return false;
7611 }
7612
7613 /**
Jeff Browncb1404e2011-01-15 18:14:15 -08007614 * Implement this method to handle generic motion events.
7615 * <p>
Jeff Brown33bbfd22011-02-24 20:55:35 -08007616 * Generic motion events describe joystick movements, mouse hovers, track pad
7617 * touches, scroll wheel movements and other input events. The
Jeff Browncb1404e2011-01-15 18:14:15 -08007618 * {@link MotionEvent#getSource() source} of the motion event specifies
7619 * the class of input that was received. Implementations of this method
7620 * must examine the bits in the source before processing the event.
7621 * The following code example shows how this is done.
Jeff Brown33bbfd22011-02-24 20:55:35 -08007622 * </p><p>
7623 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7624 * are delivered to the view under the pointer. All other generic motion events are
7625 * delivered to the focused view.
Jeff Browncb1404e2011-01-15 18:14:15 -08007626 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07007627 * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
Jeff Browncb1404e2011-01-15 18:14:15 -08007628 * if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08007629 * if (event.getAction() == MotionEvent.ACTION_MOVE) {
7630 * // process the joystick movement...
7631 * return true;
7632 * }
7633 * }
7634 * if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
7635 * switch (event.getAction()) {
7636 * case MotionEvent.ACTION_HOVER_MOVE:
7637 * // process the mouse hover movement...
7638 * return true;
7639 * case MotionEvent.ACTION_SCROLL:
7640 * // process the scroll wheel movement...
7641 * return true;
7642 * }
Jeff Browncb1404e2011-01-15 18:14:15 -08007643 * }
7644 * return super.onGenericMotionEvent(event);
Scott Mainb303d832011-10-12 16:45:18 -07007645 * }</pre>
Jeff Browncb1404e2011-01-15 18:14:15 -08007646 *
7647 * @param event The generic motion event being processed.
Jeff Browna032cc02011-03-07 16:56:21 -08007648 * @return True if the event was handled, false otherwise.
Jeff Browncb1404e2011-01-15 18:14:15 -08007649 */
7650 public boolean onGenericMotionEvent(MotionEvent event) {
7651 return false;
7652 }
7653
7654 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007655 * Implement this method to handle hover events.
7656 * <p>
Jeff Brown10b62902011-06-20 16:40:37 -07007657 * This method is called whenever a pointer is hovering into, over, or out of the
7658 * bounds of a view and the view is not currently being touched.
7659 * Hover events are represented as pointer events with action
7660 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
7661 * or {@link MotionEvent#ACTION_HOVER_EXIT}.
7662 * </p>
7663 * <ul>
7664 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
7665 * when the pointer enters the bounds of the view.</li>
7666 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
7667 * when the pointer has already entered the bounds of the view and has moved.</li>
7668 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
7669 * when the pointer has exited the bounds of the view or when the pointer is
7670 * about to go down due to a button click, tap, or similar user action that
7671 * causes the view to be touched.</li>
7672 * </ul>
7673 * <p>
7674 * The view should implement this method to return true to indicate that it is
7675 * handling the hover event, such as by changing its drawable state.
Jeff Browna032cc02011-03-07 16:56:21 -08007676 * </p><p>
Jeff Brown10b62902011-06-20 16:40:37 -07007677 * The default implementation calls {@link #setHovered} to update the hovered state
7678 * of the view when a hover enter or hover exit event is received, if the view
Jeff Browna1b24182011-07-28 13:38:24 -07007679 * is enabled and is clickable. The default implementation also sends hover
7680 * accessibility events.
Jeff Browna032cc02011-03-07 16:56:21 -08007681 * </p>
7682 *
7683 * @param event The motion event that describes the hover.
Jeff Brown10b62902011-06-20 16:40:37 -07007684 * @return True if the view handled the hover event.
7685 *
7686 * @see #isHovered
7687 * @see #setHovered
7688 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007689 */
7690 public boolean onHoverEvent(MotionEvent event) {
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007691 // The root view may receive hover (or touch) events that are outside the bounds of
7692 // the window. This code ensures that we only send accessibility events for
7693 // hovers that are actually within the bounds of the root view.
Svetoslav Ganov42138042012-03-20 11:51:39 -07007694 final int action = event.getActionMasked();
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007695 if (!mSendingHoverAccessibilityEvents) {
7696 if ((action == MotionEvent.ACTION_HOVER_ENTER
7697 || action == MotionEvent.ACTION_HOVER_MOVE)
7698 && !hasHoveredChild()
7699 && pointInView(event.getX(), event.getY())) {
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07007700 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007701 mSendingHoverAccessibilityEvents = true;
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007702 }
7703 } else {
7704 if (action == MotionEvent.ACTION_HOVER_EXIT
Svetoslav Ganov42138042012-03-20 11:51:39 -07007705 || (action == MotionEvent.ACTION_MOVE
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007706 && !pointInView(event.getX(), event.getY()))) {
7707 mSendingHoverAccessibilityEvents = false;
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07007708 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007709 // If the window does not have input focus we take away accessibility
7710 // focus as soon as the user stop hovering over the view.
Jeff Brown59a422e2012-04-19 15:19:19 -07007711 if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07007712 getViewRootImpl().setAccessibilityFocus(null, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007713 }
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007714 }
Jeff Browna1b24182011-07-28 13:38:24 -07007715 }
7716
Jeff Brown87b7f802011-06-21 18:35:45 -07007717 if (isHoverable()) {
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007718 switch (action) {
Jeff Brown10b62902011-06-20 16:40:37 -07007719 case MotionEvent.ACTION_HOVER_ENTER:
7720 setHovered(true);
7721 break;
7722 case MotionEvent.ACTION_HOVER_EXIT:
7723 setHovered(false);
7724 break;
7725 }
Jeff Browna1b24182011-07-28 13:38:24 -07007726
7727 // Dispatch the event to onGenericMotionEvent before returning true.
7728 // This is to provide compatibility with existing applications that
7729 // handled HOVER_MOVE events in onGenericMotionEvent and that would
7730 // break because of the new default handling for hoverable views
7731 // in onHoverEvent.
7732 // Note that onGenericMotionEvent will be called by default when
7733 // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
7734 dispatchGenericMotionEventInternal(event);
Jeff Brown10b62902011-06-20 16:40:37 -07007735 return true;
Jeff Browna032cc02011-03-07 16:56:21 -08007736 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07007737
Svetoslav Ganov736c2752011-04-22 18:30:36 -07007738 return false;
Jeff Browna032cc02011-03-07 16:56:21 -08007739 }
7740
7741 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07007742 * Returns true if the view should handle {@link #onHoverEvent}
7743 * by calling {@link #setHovered} to change its hovered state.
7744 *
7745 * @return True if the view is hoverable.
7746 */
7747 private boolean isHoverable() {
7748 final int viewFlags = mViewFlags;
7749 if ((viewFlags & ENABLED_MASK) == DISABLED) {
7750 return false;
7751 }
7752
7753 return (viewFlags & CLICKABLE) == CLICKABLE
7754 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7755 }
7756
7757 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007758 * Returns true if the view is currently hovered.
7759 *
7760 * @return True if the view is currently hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007761 *
7762 * @see #setHovered
7763 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007764 */
Jeff Brown10b62902011-06-20 16:40:37 -07007765 @ViewDebug.ExportedProperty
Jeff Browna032cc02011-03-07 16:56:21 -08007766 public boolean isHovered() {
7767 return (mPrivateFlags & HOVERED) != 0;
7768 }
7769
7770 /**
7771 * Sets whether the view is currently hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007772 * <p>
7773 * Calling this method also changes the drawable state of the view. This
7774 * enables the view to react to hover by using different drawable resources
7775 * to change its appearance.
7776 * </p><p>
7777 * The {@link #onHoverChanged} method is called when the hovered state changes.
7778 * </p>
Jeff Browna032cc02011-03-07 16:56:21 -08007779 *
7780 * @param hovered True if the view is hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007781 *
7782 * @see #isHovered
7783 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007784 */
7785 public void setHovered(boolean hovered) {
7786 if (hovered) {
7787 if ((mPrivateFlags & HOVERED) == 0) {
7788 mPrivateFlags |= HOVERED;
7789 refreshDrawableState();
Jeff Brown10b62902011-06-20 16:40:37 -07007790 onHoverChanged(true);
Jeff Browna032cc02011-03-07 16:56:21 -08007791 }
7792 } else {
7793 if ((mPrivateFlags & HOVERED) != 0) {
7794 mPrivateFlags &= ~HOVERED;
7795 refreshDrawableState();
Jeff Brown10b62902011-06-20 16:40:37 -07007796 onHoverChanged(false);
Jeff Browna032cc02011-03-07 16:56:21 -08007797 }
7798 }
7799 }
7800
7801 /**
Jeff Brown10b62902011-06-20 16:40:37 -07007802 * Implement this method to handle hover state changes.
7803 * <p>
7804 * This method is called whenever the hover state changes as a result of a
7805 * call to {@link #setHovered}.
7806 * </p>
7807 *
7808 * @param hovered The current hover state, as returned by {@link #isHovered}.
7809 *
7810 * @see #isHovered
7811 * @see #setHovered
7812 */
7813 public void onHoverChanged(boolean hovered) {
Jeff Brown10b62902011-06-20 16:40:37 -07007814 }
7815
7816 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 * Implement this method to handle touch screen motion events.
7818 *
7819 * @param event The motion event.
7820 * @return True if the event was handled, false otherwise.
7821 */
7822 public boolean onTouchEvent(MotionEvent event) {
7823 final int viewFlags = mViewFlags;
7824
7825 if ((viewFlags & ENABLED_MASK) == DISABLED) {
Svetoslav Ganov77b80c02011-03-15 20:52:58 -07007826 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
Adam Powell4d6f0662012-02-21 15:11:11 -08007827 setPressed(false);
Svetoslav Ganov77b80c02011-03-15 20:52:58 -07007828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007829 // A disabled view that is clickable still consumes the touch
7830 // events, it just doesn't respond to them.
7831 return (((viewFlags & CLICKABLE) == CLICKABLE ||
7832 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
7833 }
7834
7835 if (mTouchDelegate != null) {
7836 if (mTouchDelegate.onTouchEvent(event)) {
7837 return true;
7838 }
7839 }
7840
7841 if (((viewFlags & CLICKABLE) == CLICKABLE ||
7842 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
7843 switch (event.getAction()) {
7844 case MotionEvent.ACTION_UP:
Adam Powelle14579b2009-12-16 18:39:52 -08007845 boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
7846 if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007847 // take focus if we don't have it already and we should in
7848 // touch mode.
7849 boolean focusTaken = false;
7850 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
7851 focusTaken = requestFocus();
7852 }
7853
Dianne Hackbornbe1f6222011-01-20 15:24:28 -08007854 if (prepressed) {
7855 // The button is being released before we actually
7856 // showed it as pressed. Make it show the pressed
7857 // state now (before scheduling the click) to ensure
7858 // the user sees it.
Adam Powell4d6f0662012-02-21 15:11:11 -08007859 setPressed(true);
Dianne Hackbornbe1f6222011-01-20 15:24:28 -08007860 }
Joe Malin32736f02011-01-19 16:14:20 -08007861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 if (!mHasPerformedLongPress) {
7863 // This is a tap, so remove the longpress check
Maryam Garrett1549dd12009-12-15 16:06:36 -05007864 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865
7866 // Only perform take click actions if we were in the pressed state
7867 if (!focusTaken) {
Adam Powella35d7682010-03-12 14:48:13 -08007868 // Use a Runnable and post this rather than calling
7869 // performClick directly. This lets other visual state
7870 // of the view update before click actions start.
7871 if (mPerformClick == null) {
7872 mPerformClick = new PerformClick();
7873 }
7874 if (!post(mPerformClick)) {
7875 performClick();
7876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007877 }
7878 }
7879
7880 if (mUnsetPressedState == null) {
7881 mUnsetPressedState = new UnsetPressedState();
7882 }
7883
Adam Powelle14579b2009-12-16 18:39:52 -08007884 if (prepressed) {
Adam Powelle14579b2009-12-16 18:39:52 -08007885 postDelayed(mUnsetPressedState,
7886 ViewConfiguration.getPressedStateDuration());
7887 } else if (!post(mUnsetPressedState)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 // If the post failed, unpress right now
7889 mUnsetPressedState.run();
7890 }
Adam Powelle14579b2009-12-16 18:39:52 -08007891 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
7893 break;
7894
7895 case MotionEvent.ACTION_DOWN:
Adam Powell3b023392010-03-11 16:30:28 -08007896 mHasPerformedLongPress = false;
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007897
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07007898 if (performButtonActionOnTouchDown(event)) {
7899 break;
7900 }
7901
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007902 // Walk up the hierarchy to determine if we're inside a scrolling container.
Adam Powell10298662011-08-14 18:26:30 -07007903 boolean isInScrollingContainer = isInScrollingContainer();
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007904
7905 // For views inside a scrolling container, delay the pressed feedback for
7906 // a short period in case this is a scroll.
7907 if (isInScrollingContainer) {
7908 mPrivateFlags |= PREPRESSED;
7909 if (mPendingCheckForTap == null) {
7910 mPendingCheckForTap = new CheckForTap();
7911 }
7912 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
7913 } else {
7914 // Not inside a scrolling container, so show the feedback right away
Adam Powell4d6f0662012-02-21 15:11:11 -08007915 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007916 checkForLongClick(0);
7917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918 break;
7919
7920 case MotionEvent.ACTION_CANCEL:
Adam Powell4d6f0662012-02-21 15:11:11 -08007921 setPressed(false);
Adam Powelle14579b2009-12-16 18:39:52 -08007922 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 break;
7924
7925 case MotionEvent.ACTION_MOVE:
7926 final int x = (int) event.getX();
7927 final int y = (int) event.getY();
7928
7929 // Be lenient about moving outside of buttons
Chet Haasec3aa3612010-06-17 08:50:37 -07007930 if (!pointInView(x, y, mTouchSlop)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007931 // Outside button
Adam Powelle14579b2009-12-16 18:39:52 -08007932 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 if ((mPrivateFlags & PRESSED) != 0) {
Adam Powelle14579b2009-12-16 18:39:52 -08007934 // Remove any future long press/tap checks
Maryam Garrett1549dd12009-12-15 16:06:36 -05007935 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936
Adam Powell4d6f0662012-02-21 15:11:11 -08007937 setPressed(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007939 }
7940 break;
7941 }
7942 return true;
7943 }
7944
7945 return false;
7946 }
7947
7948 /**
Adam Powell10298662011-08-14 18:26:30 -07007949 * @hide
7950 */
7951 public boolean isInScrollingContainer() {
7952 ViewParent p = getParent();
7953 while (p != null && p instanceof ViewGroup) {
7954 if (((ViewGroup) p).shouldDelayChildPressedState()) {
7955 return true;
7956 }
7957 p = p.getParent();
7958 }
7959 return false;
7960 }
7961
7962 /**
Maryam Garrett1549dd12009-12-15 16:06:36 -05007963 * Remove the longpress detection timer.
7964 */
7965 private void removeLongPressCallback() {
7966 if (mPendingCheckForLongPress != null) {
7967 removeCallbacks(mPendingCheckForLongPress);
7968 }
7969 }
Adam Powell3cb8b632011-01-21 15:34:14 -08007970
7971 /**
7972 * Remove the pending click action
7973 */
7974 private void removePerformClickCallback() {
7975 if (mPerformClick != null) {
7976 removeCallbacks(mPerformClick);
7977 }
7978 }
7979
Adam Powelle14579b2009-12-16 18:39:52 -08007980 /**
Romain Guya440b002010-02-24 15:57:54 -08007981 * Remove the prepress detection timer.
7982 */
7983 private void removeUnsetPressCallback() {
7984 if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
7985 setPressed(false);
7986 removeCallbacks(mUnsetPressedState);
7987 }
7988 }
7989
7990 /**
Adam Powelle14579b2009-12-16 18:39:52 -08007991 * Remove the tap detection timer.
7992 */
7993 private void removeTapCallback() {
7994 if (mPendingCheckForTap != null) {
7995 mPrivateFlags &= ~PREPRESSED;
7996 removeCallbacks(mPendingCheckForTap);
7997 }
7998 }
Maryam Garrett1549dd12009-12-15 16:06:36 -05007999
8000 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008001 * Cancels a pending long press. Your subclass can use this if you
8002 * want the context menu to come up if the user presses and holds
8003 * at the same place, but you don't want it to come up if they press
8004 * and then move around enough to cause scrolling.
8005 */
8006 public void cancelLongPress() {
Maryam Garrett1549dd12009-12-15 16:06:36 -05008007 removeLongPressCallback();
Adam Powell732ebb12010-02-02 15:28:14 -08008008
8009 /*
8010 * The prepressed state handled by the tap callback is a display
8011 * construct, but the tap callback will post a long press callback
8012 * less its own timeout. Remove it here.
8013 */
8014 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 }
8016
8017 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07008018 * Remove the pending callback for sending a
8019 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
8020 */
8021 private void removeSendViewScrolledAccessibilityEventCallback() {
8022 if (mSendViewScrolledAccessibilityEvent != null) {
8023 removeCallbacks(mSendViewScrolledAccessibilityEvent);
Svetoslav Ganov4a812ae2012-05-29 16:46:10 -07008024 mSendViewScrolledAccessibilityEvent.mIsPending = false;
Svetoslav Ganova0156172011-06-26 17:55:44 -07008025 }
8026 }
8027
8028 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008029 * Sets the TouchDelegate for this View.
8030 */
8031 public void setTouchDelegate(TouchDelegate delegate) {
8032 mTouchDelegate = delegate;
8033 }
8034
8035 /**
8036 * Gets the TouchDelegate for this View.
8037 */
8038 public TouchDelegate getTouchDelegate() {
8039 return mTouchDelegate;
8040 }
8041
8042 /**
8043 * Set flags controlling behavior of this view.
8044 *
8045 * @param flags Constant indicating the value which should be set
8046 * @param mask Constant indicating the bit range that should be changed
8047 */
8048 void setFlags(int flags, int mask) {
8049 int old = mViewFlags;
8050 mViewFlags = (mViewFlags & ~mask) | (flags & mask);
8051
8052 int changed = mViewFlags ^ old;
8053 if (changed == 0) {
8054 return;
8055 }
8056 int privateFlags = mPrivateFlags;
8057
8058 /* Check if the FOCUSABLE bit has changed */
8059 if (((changed & FOCUSABLE_MASK) != 0) &&
8060 ((privateFlags & HAS_BOUNDS) !=0)) {
8061 if (((old & FOCUSABLE_MASK) == FOCUSABLE)
8062 && ((privateFlags & FOCUSED) != 0)) {
8063 /* Give up focus if we are no longer focusable */
8064 clearFocus();
8065 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
8066 && ((privateFlags & FOCUSED) == 0)) {
8067 /*
8068 * Tell the view system that we are now available to take focus
8069 * if no one else already has it.
8070 */
8071 if (mParent != null) mParent.focusableViewAvailable(this);
8072 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07008073 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8074 notifyAccessibilityStateChanged();
8075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 }
8077
8078 if ((flags & VISIBILITY_MASK) == VISIBLE) {
8079 if ((changed & VISIBILITY_MASK) != 0) {
8080 /*
Chet Haase4324ead2011-08-24 21:31:03 -07008081 * If this view is becoming visible, invalidate it in case it changed while
Chet Haaseaceafe62011-08-26 15:44:33 -07008082 * it was not visible. Marking it drawn ensures that the invalidation will
8083 * go through.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008084 */
Chet Haaseaceafe62011-08-26 15:44:33 -07008085 mPrivateFlags |= DRAWN;
Chet Haase4324ead2011-08-24 21:31:03 -07008086 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008087
8088 needGlobalAttributesUpdate(true);
8089
8090 // a view becoming visible is worth notifying the parent
8091 // about in case nothing has focus. even if this specific view
8092 // isn't focusable, it may contain something that is, so let
8093 // the root view try to give this focus if nothing else does.
8094 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
8095 mParent.focusableViewAvailable(this);
8096 }
8097 }
8098 }
8099
8100 /* Check if the GONE bit has changed */
8101 if ((changed & GONE) != 0) {
8102 needGlobalAttributesUpdate(false);
8103 requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104
Romain Guyecd80ee2009-12-03 17:13:02 -08008105 if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
8106 if (hasFocus()) clearFocus();
Svetoslav Ganov42138042012-03-20 11:51:39 -07008107 clearAccessibilityFocus();
Romain Guyecd80ee2009-12-03 17:13:02 -08008108 destroyDrawingCache();
Chet Haaseaceafe62011-08-26 15:44:33 -07008109 if (mParent instanceof View) {
8110 // GONE views noop invalidation, so invalidate the parent
8111 ((View) mParent).invalidate(true);
8112 }
8113 // Mark the view drawn to ensure that it gets invalidated properly the next
8114 // time it is visible and gets invalidated
8115 mPrivateFlags |= DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116 }
8117 if (mAttachInfo != null) {
8118 mAttachInfo.mViewVisibilityChanged = true;
8119 }
8120 }
8121
8122 /* Check if the VISIBLE bit has changed */
8123 if ((changed & INVISIBLE) != 0) {
8124 needGlobalAttributesUpdate(false);
Chet Haasec8a9a702011-06-17 12:13:42 -07008125 /*
8126 * If this view is becoming invisible, set the DRAWN flag so that
8127 * the next invalidate() will not be skipped.
8128 */
8129 mPrivateFlags |= DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008130
8131 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07008132 // root view becoming invisible shouldn't clear focus and accessibility focus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008133 if (getRootView() != this) {
8134 clearFocus();
Svetoslav Ganov42138042012-03-20 11:51:39 -07008135 clearAccessibilityFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008136 }
8137 }
8138 if (mAttachInfo != null) {
8139 mAttachInfo.mViewVisibilityChanged = true;
8140 }
8141 }
8142
Adam Powell326d8082009-12-09 15:10:07 -08008143 if ((changed & VISIBILITY_MASK) != 0) {
Chet Haase5e25c2c2010-09-16 11:15:56 -07008144 if (mParent instanceof ViewGroup) {
Romain Guyfe455af2012-02-15 16:40:20 -08008145 ((ViewGroup) mParent).onChildVisibilityChanged(this,
8146 (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
Romain Guy0fd89bf2011-01-26 15:41:30 -08008147 ((View) mParent).invalidate(true);
Chet Haasee4e6e202011-08-29 14:34:30 -07008148 } else if (mParent != null) {
8149 mParent.invalidateChild(this, null);
Chet Haase5e25c2c2010-09-16 11:15:56 -07008150 }
Adam Powell326d8082009-12-09 15:10:07 -08008151 dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
8152 }
8153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008154 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
8155 destroyDrawingCache();
8156 }
8157
8158 if ((changed & DRAWING_CACHE_ENABLED) != 0) {
8159 destroyDrawingCache();
8160 mPrivateFlags &= ~DRAWING_CACHE_VALID;
Romain Guy0fd89bf2011-01-26 15:41:30 -08008161 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 }
8163
8164 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
8165 destroyDrawingCache();
8166 mPrivateFlags &= ~DRAWING_CACHE_VALID;
8167 }
8168
8169 if ((changed & DRAW_MASK) != 0) {
8170 if ((mViewFlags & WILL_NOT_DRAW) != 0) {
Philip Milne6c8ea062012-04-03 17:38:43 -07008171 if (mBackground != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172 mPrivateFlags &= ~SKIP_DRAW;
8173 mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
8174 } else {
8175 mPrivateFlags |= SKIP_DRAW;
8176 }
8177 } else {
8178 mPrivateFlags &= ~SKIP_DRAW;
8179 }
8180 requestLayout();
Romain Guy0fd89bf2011-01-26 15:41:30 -08008181 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008182 }
8183
8184 if ((changed & KEEP_SCREEN_ON) != 0) {
Joe Onorato664644d2011-01-23 17:53:23 -08008185 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 mParent.recomputeViewAttributes(this);
8187 }
8188 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07008189
8190 if (AccessibilityManager.getInstance(mContext).isEnabled()
8191 && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
8192 || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
8193 notifyAccessibilityStateChanged();
8194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008195 }
8196
8197 /**
8198 * Change the view's z order in the tree, so it's on top of other sibling
8199 * views
8200 */
8201 public void bringToFront() {
8202 if (mParent != null) {
8203 mParent.bringChildToFront(this);
8204 }
8205 }
8206
8207 /**
8208 * This is called in response to an internal scroll in this view (i.e., the
8209 * view scrolled its own contents). This is typically as a result of
8210 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
8211 * called.
8212 *
8213 * @param l Current horizontal scroll origin.
8214 * @param t Current vertical scroll origin.
8215 * @param oldl Previous horizontal scroll origin.
8216 * @param oldt Previous vertical scroll origin.
8217 */
8218 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
Svetoslav Ganova0156172011-06-26 17:55:44 -07008219 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8220 postSendViewScrolledAccessibilityEventCallback();
8221 }
8222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 mBackgroundSizeChanged = true;
8224
8225 final AttachInfo ai = mAttachInfo;
8226 if (ai != null) {
8227 ai.mViewScrollChanged = true;
8228 }
8229 }
8230
8231 /**
Chet Haase21cd1382010-09-01 17:42:29 -07008232 * Interface definition for a callback to be invoked when the layout bounds of a view
8233 * changes due to layout processing.
8234 */
8235 public interface OnLayoutChangeListener {
8236 /**
8237 * Called when the focus state of a view has changed.
8238 *
8239 * @param v The view whose state has changed.
8240 * @param left The new value of the view's left property.
8241 * @param top The new value of the view's top property.
8242 * @param right The new value of the view's right property.
8243 * @param bottom The new value of the view's bottom property.
8244 * @param oldLeft The previous value of the view's left property.
8245 * @param oldTop The previous value of the view's top property.
8246 * @param oldRight The previous value of the view's right property.
8247 * @param oldBottom The previous value of the view's bottom property.
8248 */
8249 void onLayoutChange(View v, int left, int top, int right, int bottom,
8250 int oldLeft, int oldTop, int oldRight, int oldBottom);
8251 }
8252
8253 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 * This is called during layout when the size of this view has changed. If
8255 * you were just added to the view hierarchy, you're called with the old
8256 * values of 0.
8257 *
8258 * @param w Current width of this view.
8259 * @param h Current height of this view.
8260 * @param oldw Old width of this view.
8261 * @param oldh Old height of this view.
8262 */
8263 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
8264 }
8265
8266 /**
8267 * Called by draw to draw the child views. This may be overridden
8268 * by derived classes to gain control just before its children are drawn
8269 * (but after its own view has been drawn).
8270 * @param canvas the canvas on which to draw the view
8271 */
8272 protected void dispatchDraw(Canvas canvas) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07008273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008274 }
8275
8276 /**
8277 * Gets the parent of this view. Note that the parent is a
8278 * ViewParent and not necessarily a View.
8279 *
8280 * @return Parent of this view.
8281 */
8282 public final ViewParent getParent() {
8283 return mParent;
8284 }
8285
8286 /**
Chet Haasecca2c982011-05-20 14:34:18 -07008287 * Set the horizontal scrolled position of your view. This will cause a call to
8288 * {@link #onScrollChanged(int, int, int, int)} and the view will be
8289 * invalidated.
8290 * @param value the x position to scroll to
8291 */
8292 public void setScrollX(int value) {
8293 scrollTo(value, mScrollY);
8294 }
8295
8296 /**
8297 * Set the vertical scrolled position of your view. This will cause a call to
8298 * {@link #onScrollChanged(int, int, int, int)} and the view will be
8299 * invalidated.
8300 * @param value the y position to scroll to
8301 */
8302 public void setScrollY(int value) {
8303 scrollTo(mScrollX, value);
8304 }
8305
8306 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008307 * Return the scrolled left position of this view. This is the left edge of
8308 * the displayed part of your view. You do not need to draw any pixels
8309 * farther left, since those are outside of the frame of your view on
8310 * screen.
8311 *
8312 * @return The left edge of the displayed part of your view, in pixels.
8313 */
8314 public final int getScrollX() {
8315 return mScrollX;
8316 }
8317
8318 /**
8319 * Return the scrolled top position of this view. This is the top edge of
8320 * the displayed part of your view. You do not need to draw any pixels above
8321 * it, since those are outside of the frame of your view on screen.
8322 *
8323 * @return The top edge of the displayed part of your view, in pixels.
8324 */
8325 public final int getScrollY() {
8326 return mScrollY;
8327 }
8328
8329 /**
8330 * Return the width of the your view.
8331 *
8332 * @return The width of your view, in pixels.
8333 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07008334 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 public final int getWidth() {
8336 return mRight - mLeft;
8337 }
8338
8339 /**
8340 * Return the height of your view.
8341 *
8342 * @return The height of your view, in pixels.
8343 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07008344 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 public final int getHeight() {
8346 return mBottom - mTop;
8347 }
8348
8349 /**
8350 * Return the visible drawing bounds of your view. Fills in the output
8351 * rectangle with the values from getScrollX(), getScrollY(),
8352 * getWidth(), and getHeight().
8353 *
8354 * @param outRect The (scrolled) drawing bounds of the view.
8355 */
8356 public void getDrawingRect(Rect outRect) {
8357 outRect.left = mScrollX;
8358 outRect.top = mScrollY;
8359 outRect.right = mScrollX + (mRight - mLeft);
8360 outRect.bottom = mScrollY + (mBottom - mTop);
8361 }
8362
8363 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008364 * Like {@link #getMeasuredWidthAndState()}, but only returns the
8365 * raw width component (that is the result is masked by
8366 * {@link #MEASURED_SIZE_MASK}).
8367 *
8368 * @return The raw measured width of this view.
8369 */
8370 public final int getMeasuredWidth() {
8371 return mMeasuredWidth & MEASURED_SIZE_MASK;
8372 }
8373
8374 /**
8375 * Return the full width measurement information for this view as computed
Romain Guy5c22a8c2011-05-13 11:48:45 -07008376 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
Dianne Hackborn189ee182010-12-02 21:48:53 -08008377 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008378 * This should be used during measurement and layout calculations only. Use
8379 * {@link #getWidth()} to see how wide a view is after layout.
8380 *
Dianne Hackborn189ee182010-12-02 21:48:53 -08008381 * @return The measured width of this view as a bit mask.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008382 */
Dianne Hackborn189ee182010-12-02 21:48:53 -08008383 public final int getMeasuredWidthAndState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 return mMeasuredWidth;
8385 }
8386
8387 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008388 * Like {@link #getMeasuredHeightAndState()}, but only returns the
8389 * raw width component (that is the result is masked by
8390 * {@link #MEASURED_SIZE_MASK}).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 *
Dianne Hackborn189ee182010-12-02 21:48:53 -08008392 * @return The raw measured height of this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 */
8394 public final int getMeasuredHeight() {
Dianne Hackborn189ee182010-12-02 21:48:53 -08008395 return mMeasuredHeight & MEASURED_SIZE_MASK;
8396 }
8397
8398 /**
8399 * Return the full height measurement information for this view as computed
Romain Guy5c22a8c2011-05-13 11:48:45 -07008400 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
Dianne Hackborn189ee182010-12-02 21:48:53 -08008401 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8402 * This should be used during measurement and layout calculations only. Use
8403 * {@link #getHeight()} to see how wide a view is after layout.
8404 *
8405 * @return The measured width of this view as a bit mask.
8406 */
8407 public final int getMeasuredHeightAndState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008408 return mMeasuredHeight;
8409 }
8410
8411 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008412 * Return only the state bits of {@link #getMeasuredWidthAndState()}
8413 * and {@link #getMeasuredHeightAndState()}, combined into one integer.
8414 * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
8415 * and the height component is at the shifted bits
8416 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
8417 */
8418 public final int getMeasuredState() {
8419 return (mMeasuredWidth&MEASURED_STATE_MASK)
8420 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
8421 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
8422 }
8423
8424 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008425 * The transform matrix of this view, which is calculated based on the current
8426 * roation, scale, and pivot properties.
8427 *
8428 * @see #getRotation()
8429 * @see #getScaleX()
8430 * @see #getScaleY()
8431 * @see #getPivotX()
8432 * @see #getPivotY()
8433 * @return The current transform matrix for the view
8434 */
8435 public Matrix getMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008436 if (mTransformationInfo != null) {
8437 updateMatrix();
8438 return mTransformationInfo.mMatrix;
8439 }
8440 return Matrix.IDENTITY_MATRIX;
Romain Guy33e72ae2010-07-17 12:40:29 -07008441 }
8442
8443 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07008444 * Utility function to determine if the value is far enough away from zero to be
8445 * considered non-zero.
8446 * @param value A floating point value to check for zero-ness
8447 * @return whether the passed-in value is far enough away from zero to be considered non-zero
8448 */
8449 private static boolean nonzero(float value) {
8450 return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
8451 }
8452
8453 /**
Jeff Brown86671742010-09-30 20:00:15 -07008454 * Returns true if the transform matrix is the identity matrix.
8455 * Recomputes the matrix if necessary.
Joe Malin32736f02011-01-19 16:14:20 -08008456 *
Romain Guy33e72ae2010-07-17 12:40:29 -07008457 * @return True if the transform matrix is the identity matrix, false otherwise.
8458 */
Jeff Brown86671742010-09-30 20:00:15 -07008459 final boolean hasIdentityMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008460 if (mTransformationInfo != null) {
8461 updateMatrix();
8462 return mTransformationInfo.mMatrixIsIdentity;
8463 }
8464 return true;
8465 }
8466
8467 void ensureTransformationInfo() {
8468 if (mTransformationInfo == null) {
8469 mTransformationInfo = new TransformationInfo();
8470 }
Jeff Brown86671742010-09-30 20:00:15 -07008471 }
8472
8473 /**
8474 * Recomputes the transform matrix if necessary.
8475 */
Romain Guy2fe9a8f2010-10-04 20:17:01 -07008476 private void updateMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008477 final TransformationInfo info = mTransformationInfo;
8478 if (info == null) {
8479 return;
8480 }
8481 if (info.mMatrixDirty) {
Chet Haasec3aa3612010-06-17 08:50:37 -07008482 // transform-related properties have changed since the last time someone
8483 // asked for the matrix; recalculate it with the current values
Chet Haasefd2b0022010-08-06 13:08:56 -07008484
8485 // Figure out if we need to update the pivot point
8486 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008487 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
8488 info.mPrevWidth = mRight - mLeft;
8489 info.mPrevHeight = mBottom - mTop;
8490 info.mPivotX = info.mPrevWidth / 2f;
8491 info.mPivotY = info.mPrevHeight / 2f;
Chet Haasefd2b0022010-08-06 13:08:56 -07008492 }
8493 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008494 info.mMatrix.reset();
8495 if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
8496 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
8497 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
8498 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
Chet Haase897247b2010-09-09 14:54:47 -07008499 } else {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008500 if (info.mCamera == null) {
8501 info.mCamera = new Camera();
8502 info.matrix3D = new Matrix();
Chet Haasefd2b0022010-08-06 13:08:56 -07008503 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008504 info.mCamera.save();
8505 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8506 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
8507 info.mCamera.getMatrix(info.matrix3D);
8508 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
8509 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
8510 info.mPivotY + info.mTranslationY);
8511 info.mMatrix.postConcat(info.matrix3D);
8512 info.mCamera.restore();
Chet Haasefd2b0022010-08-06 13:08:56 -07008513 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008514 info.mMatrixDirty = false;
8515 info.mMatrixIsIdentity = info.mMatrix.isIdentity();
8516 info.mInverseMatrixDirty = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07008517 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008518 }
8519
8520 /**
Tobias Duboisdefdb1e2010-12-15 11:35:30 +01008521 * When searching for a view to focus this rectangle is used when considering if this view is
8522 * a good candidate for receiving focus.
8523 *
8524 * By default, the rectangle is the {@link #getDrawingRect}) of the view.
8525 *
8526 * @param r The rectangle to fill in, in this view's coordinates.
8527 */
8528 public void getFocusRect(Rect r) {
8529 getDrawingRect(r);
8530 }
8531
8532 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008533 * Utility method to retrieve the inverse of the current mMatrix property.
8534 * We cache the matrix to avoid recalculating it when transform properties
8535 * have not changed.
8536 *
8537 * @return The inverse of the current matrix of this view.
8538 */
Jeff Brown86671742010-09-30 20:00:15 -07008539 final Matrix getInverseMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008540 final TransformationInfo info = mTransformationInfo;
8541 if (info != null) {
8542 updateMatrix();
8543 if (info.mInverseMatrixDirty) {
8544 if (info.mInverseMatrix == null) {
8545 info.mInverseMatrix = new Matrix();
8546 }
8547 info.mMatrix.invert(info.mInverseMatrix);
8548 info.mInverseMatrixDirty = false;
Chet Haasec3aa3612010-06-17 08:50:37 -07008549 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008550 return info.mInverseMatrix;
Chet Haasec3aa3612010-06-17 08:50:37 -07008551 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008552 return Matrix.IDENTITY_MATRIX;
Chet Haasec3aa3612010-06-17 08:50:37 -07008553 }
8554
8555 /**
Chet Haasea1cff502012-02-21 13:43:44 -08008556 * Gets the distance along the Z axis from the camera to this view.
8557 *
8558 * @see #setCameraDistance(float)
8559 *
8560 * @return The distance along the Z axis.
8561 */
8562 public float getCameraDistance() {
8563 ensureTransformationInfo();
8564 final float dpi = mResources.getDisplayMetrics().densityDpi;
8565 final TransformationInfo info = mTransformationInfo;
8566 if (info.mCamera == null) {
8567 info.mCamera = new Camera();
8568 info.matrix3D = new Matrix();
8569 }
8570 return -(info.mCamera.getLocationZ() * dpi);
8571 }
8572
8573 /**
Romain Guya5364ee2011-02-24 14:46:04 -08008574 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
8575 * views are drawn) from the camera to this view. The camera's distance
8576 * affects 3D transformations, for instance rotations around the X and Y
8577 * axis. If the rotationX or rotationY properties are changed and this view is
Philip Milne6c8ea062012-04-03 17:38:43 -07008578 * large (more than half the size of the screen), it is recommended to always
Romain Guya5364ee2011-02-24 14:46:04 -08008579 * use a camera distance that's greater than the height (X axis rotation) or
8580 * the width (Y axis rotation) of this view.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008581 *
Romain Guya5364ee2011-02-24 14:46:04 -08008582 * <p>The distance of the camera from the view plane can have an affect on the
8583 * perspective distortion of the view when it is rotated around the x or y axis.
8584 * For example, a large distance will result in a large viewing angle, and there
8585 * will not be much perspective distortion of the view as it rotates. A short
Philip Milne6c8ea062012-04-03 17:38:43 -07008586 * distance may cause much more perspective distortion upon rotation, and can
Romain Guya5364ee2011-02-24 14:46:04 -08008587 * also result in some drawing artifacts if the rotated view ends up partially
8588 * behind the camera (which is why the recommendation is to use a distance at
8589 * least as far as the size of the view, if the view is to be rotated.)</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008590 *
Romain Guya5364ee2011-02-24 14:46:04 -08008591 * <p>The distance is expressed in "depth pixels." The default distance depends
8592 * on the screen density. For instance, on a medium density display, the
8593 * default distance is 1280. On a high density display, the default distance
8594 * is 1920.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008595 *
Romain Guya5364ee2011-02-24 14:46:04 -08008596 * <p>If you want to specify a distance that leads to visually consistent
8597 * results across various densities, use the following formula:</p>
8598 * <pre>
8599 * float scale = context.getResources().getDisplayMetrics().density;
8600 * view.setCameraDistance(distance * scale);
8601 * </pre>
Philip Milne6c8ea062012-04-03 17:38:43 -07008602 *
Romain Guya5364ee2011-02-24 14:46:04 -08008603 * <p>The density scale factor of a high density display is 1.5,
8604 * and 1920 = 1280 * 1.5.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008605 *
Romain Guya5364ee2011-02-24 14:46:04 -08008606 * @param distance The distance in "depth pixels", if negative the opposite
8607 * value is used
Philip Milne6c8ea062012-04-03 17:38:43 -07008608 *
8609 * @see #setRotationX(float)
8610 * @see #setRotationY(float)
Romain Guya5364ee2011-02-24 14:46:04 -08008611 */
8612 public void setCameraDistance(float distance) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008613 invalidateViewProperty(true, false);
Romain Guya5364ee2011-02-24 14:46:04 -08008614
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008615 ensureTransformationInfo();
Romain Guya5364ee2011-02-24 14:46:04 -08008616 final float dpi = mResources.getDisplayMetrics().densityDpi;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008617 final TransformationInfo info = mTransformationInfo;
8618 if (info.mCamera == null) {
8619 info.mCamera = new Camera();
8620 info.matrix3D = new Matrix();
Romain Guya5364ee2011-02-24 14:46:04 -08008621 }
8622
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008623 info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
8624 info.mMatrixDirty = true;
Romain Guya5364ee2011-02-24 14:46:04 -08008625
Chet Haase9d1992d2012-03-13 11:03:25 -07008626 invalidateViewProperty(false, false);
Chet Haase1271e2c2012-04-20 09:54:27 -07008627 if (mDisplayList != null) {
Chet Haaseb85967b2012-03-26 14:37:51 -07008628 mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
Chet Haasea1cff502012-02-21 13:43:44 -08008629 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008630 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8631 // View was rejected last time it was drawn by its parent; this may have changed
8632 invalidateParentIfNeeded();
8633 }
Romain Guya5364ee2011-02-24 14:46:04 -08008634 }
8635
8636 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008637 * The degrees that the view is rotated around the pivot point.
8638 *
Philip Milne6c8ea062012-04-03 17:38:43 -07008639 * @see #setRotation(float)
Chet Haasec3aa3612010-06-17 08:50:37 -07008640 * @see #getPivotX()
8641 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008642 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008643 * @return The degrees of rotation.
8644 */
Chet Haasea5531132012-02-02 13:41:44 -08008645 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008646 public float getRotation() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008647 return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07008648 }
8649
8650 /**
Chet Haase897247b2010-09-09 14:54:47 -07008651 * Sets the degrees that the view is rotated around the pivot point. Increasing values
8652 * result in clockwise rotation.
Chet Haasec3aa3612010-06-17 08:50:37 -07008653 *
8654 * @param rotation The degrees of rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008655 *
8656 * @see #getRotation()
Chet Haasec3aa3612010-06-17 08:50:37 -07008657 * @see #getPivotX()
8658 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008659 * @see #setRotationX(float)
8660 * @see #setRotationY(float)
Chet Haase73066682010-11-29 15:55:32 -08008661 *
8662 * @attr ref android.R.styleable#View_rotation
Chet Haasec3aa3612010-06-17 08:50:37 -07008663 */
8664 public void setRotation(float rotation) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008665 ensureTransformationInfo();
8666 final TransformationInfo info = mTransformationInfo;
8667 if (info.mRotation != rotation) {
Chet Haasec3aa3612010-06-17 08:50:37 -07008668 // Double-invalidation is necessary to capture view's old and new areas
Chet Haase9d1992d2012-03-13 11:03:25 -07008669 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008670 info.mRotation = rotation;
8671 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008672 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008673 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008674 mDisplayList.setRotation(rotation);
8675 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008676 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8677 // View was rejected last time it was drawn by its parent; this may have changed
8678 invalidateParentIfNeeded();
8679 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008680 }
8681 }
8682
8683 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07008684 * The degrees that the view is rotated around the vertical axis through the pivot point.
8685 *
8686 * @see #getPivotX()
8687 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008688 * @see #setRotationY(float)
8689 *
Chet Haasefd2b0022010-08-06 13:08:56 -07008690 * @return The degrees of Y rotation.
8691 */
Chet Haasea5531132012-02-02 13:41:44 -08008692 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasefd2b0022010-08-06 13:08:56 -07008693 public float getRotationY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008694 return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
Chet Haasefd2b0022010-08-06 13:08:56 -07008695 }
8696
8697 /**
Chet Haase897247b2010-09-09 14:54:47 -07008698 * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
8699 * Increasing values result in counter-clockwise rotation from the viewpoint of looking
8700 * down the y axis.
Philip Milne6c8ea062012-04-03 17:38:43 -07008701 *
Romain Guya5364ee2011-02-24 14:46:04 -08008702 * When rotating large views, it is recommended to adjust the camera distance
8703 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
Chet Haasefd2b0022010-08-06 13:08:56 -07008704 *
8705 * @param rotationY The degrees of Y rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008706 *
8707 * @see #getRotationY()
Chet Haasefd2b0022010-08-06 13:08:56 -07008708 * @see #getPivotX()
8709 * @see #getPivotY()
Romain Guya5364ee2011-02-24 14:46:04 -08008710 * @see #setRotation(float)
Philip Milne6c8ea062012-04-03 17:38:43 -07008711 * @see #setRotationX(float)
8712 * @see #setCameraDistance(float)
Chet Haase73066682010-11-29 15:55:32 -08008713 *
8714 * @attr ref android.R.styleable#View_rotationY
Chet Haasefd2b0022010-08-06 13:08:56 -07008715 */
8716 public void setRotationY(float rotationY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008717 ensureTransformationInfo();
8718 final TransformationInfo info = mTransformationInfo;
8719 if (info.mRotationY != rotationY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008720 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008721 info.mRotationY = rotationY;
8722 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008723 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008724 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008725 mDisplayList.setRotationY(rotationY);
8726 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008727 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8728 // View was rejected last time it was drawn by its parent; this may have changed
8729 invalidateParentIfNeeded();
8730 }
Chet Haasefd2b0022010-08-06 13:08:56 -07008731 }
8732 }
8733
8734 /**
8735 * The degrees that the view is rotated around the horizontal axis through the pivot point.
8736 *
8737 * @see #getPivotX()
8738 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008739 * @see #setRotationX(float)
8740 *
Chet Haasefd2b0022010-08-06 13:08:56 -07008741 * @return The degrees of X rotation.
8742 */
Chet Haasea5531132012-02-02 13:41:44 -08008743 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasefd2b0022010-08-06 13:08:56 -07008744 public float getRotationX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008745 return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
Chet Haasefd2b0022010-08-06 13:08:56 -07008746 }
8747
8748 /**
Chet Haase897247b2010-09-09 14:54:47 -07008749 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
8750 * Increasing values result in clockwise rotation from the viewpoint of looking down the
8751 * x axis.
Philip Milne6c8ea062012-04-03 17:38:43 -07008752 *
Romain Guya5364ee2011-02-24 14:46:04 -08008753 * When rotating large views, it is recommended to adjust the camera distance
8754 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
Chet Haasefd2b0022010-08-06 13:08:56 -07008755 *
8756 * @param rotationX The degrees of X rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008757 *
8758 * @see #getRotationX()
Chet Haasefd2b0022010-08-06 13:08:56 -07008759 * @see #getPivotX()
8760 * @see #getPivotY()
Romain Guya5364ee2011-02-24 14:46:04 -08008761 * @see #setRotation(float)
Philip Milne6c8ea062012-04-03 17:38:43 -07008762 * @see #setRotationY(float)
8763 * @see #setCameraDistance(float)
Chet Haase73066682010-11-29 15:55:32 -08008764 *
8765 * @attr ref android.R.styleable#View_rotationX
Chet Haasefd2b0022010-08-06 13:08:56 -07008766 */
8767 public void setRotationX(float rotationX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008768 ensureTransformationInfo();
8769 final TransformationInfo info = mTransformationInfo;
8770 if (info.mRotationX != rotationX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008771 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008772 info.mRotationX = rotationX;
8773 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008774 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008775 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008776 mDisplayList.setRotationX(rotationX);
8777 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008778 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8779 // View was rejected last time it was drawn by its parent; this may have changed
8780 invalidateParentIfNeeded();
8781 }
Chet Haasefd2b0022010-08-06 13:08:56 -07008782 }
8783 }
8784
8785 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008786 * The amount that the view is scaled in x around the pivot point, as a proportion of
8787 * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
8788 *
Joe Onorato93162322010-09-16 15:42:01 -04008789 * <p>By default, this is 1.0f.
8790 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008791 * @see #getPivotX()
8792 * @see #getPivotY()
8793 * @return The scaling factor.
8794 */
Chet Haasea5531132012-02-02 13:41:44 -08008795 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008796 public float getScaleX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008797 return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07008798 }
8799
8800 /**
8801 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
8802 * the view's unscaled width. A value of 1 means that no scaling is applied.
8803 *
8804 * @param scaleX The scaling factor.
8805 * @see #getPivotX()
8806 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008807 *
8808 * @attr ref android.R.styleable#View_scaleX
Chet Haasec3aa3612010-06-17 08:50:37 -07008809 */
8810 public void setScaleX(float scaleX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008811 ensureTransformationInfo();
8812 final TransformationInfo info = mTransformationInfo;
8813 if (info.mScaleX != scaleX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008814 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008815 info.mScaleX = scaleX;
8816 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008817 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008818 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008819 mDisplayList.setScaleX(scaleX);
8820 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008821 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8822 // View was rejected last time it was drawn by its parent; this may have changed
8823 invalidateParentIfNeeded();
8824 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008825 }
8826 }
8827
8828 /**
8829 * The amount that the view is scaled in y around the pivot point, as a proportion of
8830 * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
8831 *
Joe Onorato93162322010-09-16 15:42:01 -04008832 * <p>By default, this is 1.0f.
8833 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008834 * @see #getPivotX()
8835 * @see #getPivotY()
8836 * @return The scaling factor.
8837 */
Chet Haasea5531132012-02-02 13:41:44 -08008838 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008839 public float getScaleY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008840 return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07008841 }
8842
8843 /**
8844 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
8845 * the view's unscaled width. A value of 1 means that no scaling is applied.
8846 *
8847 * @param scaleY The scaling factor.
8848 * @see #getPivotX()
8849 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008850 *
8851 * @attr ref android.R.styleable#View_scaleY
Chet Haasec3aa3612010-06-17 08:50:37 -07008852 */
8853 public void setScaleY(float scaleY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008854 ensureTransformationInfo();
8855 final TransformationInfo info = mTransformationInfo;
8856 if (info.mScaleY != scaleY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008857 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008858 info.mScaleY = scaleY;
8859 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008860 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008861 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008862 mDisplayList.setScaleY(scaleY);
8863 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008864 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8865 // View was rejected last time it was drawn by its parent; this may have changed
8866 invalidateParentIfNeeded();
8867 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008868 }
8869 }
8870
8871 /**
8872 * The x location of the point around which the view is {@link #setRotation(float) rotated}
8873 * and {@link #setScaleX(float) scaled}.
8874 *
8875 * @see #getRotation()
8876 * @see #getScaleX()
8877 * @see #getScaleY()
8878 * @see #getPivotY()
8879 * @return The x location of the pivot point.
Philip Milne6c8ea062012-04-03 17:38:43 -07008880 *
8881 * @attr ref android.R.styleable#View_transformPivotX
Chet Haasec3aa3612010-06-17 08:50:37 -07008882 */
Chet Haasea5531132012-02-02 13:41:44 -08008883 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008884 public float getPivotX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008885 return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07008886 }
8887
8888 /**
8889 * Sets the x location of the point around which the view is
8890 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
Chet Haasefd2b0022010-08-06 13:08:56 -07008891 * By default, the pivot point is centered on the object.
8892 * Setting this property disables this behavior and causes the view to use only the
8893 * explicitly set pivotX and pivotY values.
Chet Haasec3aa3612010-06-17 08:50:37 -07008894 *
8895 * @param pivotX The x location of the pivot point.
8896 * @see #getRotation()
8897 * @see #getScaleX()
8898 * @see #getScaleY()
8899 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008900 *
8901 * @attr ref android.R.styleable#View_transformPivotX
Chet Haasec3aa3612010-06-17 08:50:37 -07008902 */
8903 public void setPivotX(float pivotX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008904 ensureTransformationInfo();
Chet Haasefd2b0022010-08-06 13:08:56 -07008905 mPrivateFlags |= PIVOT_EXPLICITLY_SET;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008906 final TransformationInfo info = mTransformationInfo;
8907 if (info.mPivotX != pivotX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008908 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008909 info.mPivotX = pivotX;
8910 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008911 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008912 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008913 mDisplayList.setPivotX(pivotX);
8914 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008915 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8916 // View was rejected last time it was drawn by its parent; this may have changed
8917 invalidateParentIfNeeded();
8918 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008919 }
8920 }
8921
8922 /**
8923 * The y location of the point around which the view is {@link #setRotation(float) rotated}
8924 * and {@link #setScaleY(float) scaled}.
8925 *
8926 * @see #getRotation()
8927 * @see #getScaleX()
8928 * @see #getScaleY()
8929 * @see #getPivotY()
8930 * @return The y location of the pivot point.
Philip Milne6c8ea062012-04-03 17:38:43 -07008931 *
8932 * @attr ref android.R.styleable#View_transformPivotY
Chet Haasec3aa3612010-06-17 08:50:37 -07008933 */
Chet Haasea5531132012-02-02 13:41:44 -08008934 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008935 public float getPivotY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008936 return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07008937 }
8938
8939 /**
8940 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
Chet Haasefd2b0022010-08-06 13:08:56 -07008941 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
8942 * Setting this property disables this behavior and causes the view to use only the
8943 * explicitly set pivotX and pivotY values.
Chet Haasec3aa3612010-06-17 08:50:37 -07008944 *
8945 * @param pivotY The y location of the pivot point.
8946 * @see #getRotation()
8947 * @see #getScaleX()
8948 * @see #getScaleY()
8949 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008950 *
8951 * @attr ref android.R.styleable#View_transformPivotY
Chet Haasec3aa3612010-06-17 08:50:37 -07008952 */
8953 public void setPivotY(float pivotY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008954 ensureTransformationInfo();
Chet Haasefd2b0022010-08-06 13:08:56 -07008955 mPrivateFlags |= PIVOT_EXPLICITLY_SET;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008956 final TransformationInfo info = mTransformationInfo;
8957 if (info.mPivotY != pivotY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008958 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008959 info.mPivotY = pivotY;
8960 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008961 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008962 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008963 mDisplayList.setPivotY(pivotY);
8964 }
Chet Haase1a3ab172012-05-11 08:41:20 -07008965 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8966 // View was rejected last time it was drawn by its parent; this may have changed
8967 invalidateParentIfNeeded();
8968 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008969 }
8970 }
8971
8972 /**
8973 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
8974 * completely transparent and 1 means the view is completely opaque.
8975 *
Joe Onorato93162322010-09-16 15:42:01 -04008976 * <p>By default this is 1.0f.
Chet Haasec3aa3612010-06-17 08:50:37 -07008977 * @return The opacity of the view.
8978 */
Chet Haasea5531132012-02-02 13:41:44 -08008979 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008980 public float getAlpha() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008981 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07008982 }
8983
8984 /**
Chet Haasedb8c9a62012-03-21 18:54:18 -07008985 * Returns whether this View has content which overlaps. This function, intended to be
8986 * overridden by specific View types, is an optimization when alpha is set on a view. If
8987 * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
8988 * and then composited it into place, which can be expensive. If the view has no overlapping
8989 * rendering, the view can draw each primitive with the appropriate alpha value directly.
8990 * An example of overlapping rendering is a TextView with a background image, such as a
8991 * Button. An example of non-overlapping rendering is a TextView with no background, or
8992 * an ImageView with only the foreground image. The default implementation returns true;
8993 * subclasses should override if they have cases which can be optimized.
8994 *
8995 * @return true if the content in this view might overlap, false otherwise.
8996 */
8997 public boolean hasOverlappingRendering() {
8998 return true;
8999 }
9000
9001 /**
Romain Guy171c5922011-01-06 10:04:23 -08009002 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
9003 * completely transparent and 1 means the view is completely opaque.</p>
Joe Malin32736f02011-01-19 16:14:20 -08009004 *
Romain Guy171c5922011-01-06 10:04:23 -08009005 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
9006 * responsible for applying the opacity itself. Otherwise, calling this method is
9007 * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
Joe Malin32736f02011-01-19 16:14:20 -08009008 * setting a hardware layer.</p>
Chet Haasec3aa3612010-06-17 08:50:37 -07009009 *
Chet Haasea5531132012-02-02 13:41:44 -08009010 * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
9011 * performance implications. It is generally best to use the alpha property sparingly and
9012 * transiently, as in the case of fading animations.</p>
9013 *
Chet Haasec3aa3612010-06-17 08:50:37 -07009014 * @param alpha The opacity of the view.
Chet Haase73066682010-11-29 15:55:32 -08009015 *
Joe Malin32736f02011-01-19 16:14:20 -08009016 * @see #setLayerType(int, android.graphics.Paint)
9017 *
Chet Haase73066682010-11-29 15:55:32 -08009018 * @attr ref android.R.styleable#View_alpha
Chet Haasec3aa3612010-06-17 08:50:37 -07009019 */
9020 public void setAlpha(float alpha) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009021 ensureTransformationInfo();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009022 if (mTransformationInfo.mAlpha != alpha) {
9023 mTransformationInfo.mAlpha = alpha;
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009024 if (onSetAlpha((int) (alpha * 255))) {
9025 mPrivateFlags |= ALPHA_SET;
9026 // subclass is handling alpha - don't optimize rendering cache invalidation
Chet Haase9d1992d2012-03-13 11:03:25 -07009027 invalidateParentCaches();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009028 invalidate(true);
9029 } else {
9030 mPrivateFlags &= ~ALPHA_SET;
Chet Haase9d1992d2012-03-13 11:03:25 -07009031 invalidateViewProperty(true, false);
Chet Haase1271e2c2012-04-20 09:54:27 -07009032 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009033 mDisplayList.setAlpha(alpha);
9034 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009035 }
Chet Haaseed032702010-10-01 14:05:54 -07009036 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009037 }
9038
9039 /**
Chet Haasea00f3862011-02-22 06:34:40 -08009040 * Faster version of setAlpha() which performs the same steps except there are
9041 * no calls to invalidate(). The caller of this function should perform proper invalidation
9042 * on the parent and this object. The return value indicates whether the subclass handles
9043 * alpha (the return value for onSetAlpha()).
9044 *
9045 * @param alpha The new value for the alpha property
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009046 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
9047 * the new value for the alpha property is different from the old value
Chet Haasea00f3862011-02-22 06:34:40 -08009048 */
9049 boolean setAlphaNoInvalidation(float alpha) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009050 ensureTransformationInfo();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009051 if (mTransformationInfo.mAlpha != alpha) {
9052 mTransformationInfo.mAlpha = alpha;
9053 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
9054 if (subclassHandlesAlpha) {
9055 mPrivateFlags |= ALPHA_SET;
9056 return true;
9057 } else {
9058 mPrivateFlags &= ~ALPHA_SET;
Chet Haase1271e2c2012-04-20 09:54:27 -07009059 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009060 mDisplayList.setAlpha(alpha);
9061 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009062 }
Chet Haasea00f3862011-02-22 06:34:40 -08009063 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009064 return false;
Chet Haasea00f3862011-02-22 06:34:40 -08009065 }
9066
9067 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 * Top position of this view relative to its parent.
9069 *
9070 * @return The top of this view, in pixels.
9071 */
9072 @ViewDebug.CapturedViewProperty
9073 public final int getTop() {
9074 return mTop;
9075 }
9076
9077 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009078 * Sets the top position of this view relative to its parent. This method is meant to be called
9079 * by the layout system and should not generally be called otherwise, because the property
9080 * may be changed at any time by the layout.
9081 *
9082 * @param top The top of this view, in pixels.
9083 */
9084 public final void setTop(int top) {
9085 if (top != mTop) {
Jeff Brown86671742010-09-30 20:00:15 -07009086 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009087 final boolean matrixIsIdentity = mTransformationInfo == null
9088 || mTransformationInfo.mMatrixIsIdentity;
9089 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009090 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009091 int minTop;
9092 int yLoc;
9093 if (top < mTop) {
9094 minTop = top;
9095 yLoc = top - mTop;
9096 } else {
9097 minTop = mTop;
9098 yLoc = 0;
9099 }
Chet Haasee9140a72011-02-16 16:23:29 -08009100 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009101 }
9102 } else {
9103 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009104 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009105 }
9106
Chet Haaseed032702010-10-01 14:05:54 -07009107 int width = mRight - mLeft;
9108 int oldHeight = mBottom - mTop;
9109
Chet Haase21cd1382010-09-01 17:42:29 -07009110 mTop = top;
Chet Haase1271e2c2012-04-20 09:54:27 -07009111 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009112 mDisplayList.setTop(mTop);
9113 }
Chet Haase21cd1382010-09-01 17:42:29 -07009114
Chet Haaseed032702010-10-01 14:05:54 -07009115 onSizeChanged(width, mBottom - mTop, width, oldHeight);
9116
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009117 if (!matrixIsIdentity) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009118 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
9119 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009120 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009121 }
Chet Haase21cd1382010-09-01 17:42:29 -07009122 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009123 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009124 }
Chet Haase55dbb652010-12-21 20:15:08 -08009125 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009126 invalidateParentIfNeeded();
Chet Haase1a3ab172012-05-11 08:41:20 -07009127 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9128 // View was rejected last time it was drawn by its parent; this may have changed
9129 invalidateParentIfNeeded();
9130 }
Chet Haase21cd1382010-09-01 17:42:29 -07009131 }
9132 }
9133
9134 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009135 * Bottom position of this view relative to its parent.
9136 *
9137 * @return The bottom of this view, in pixels.
9138 */
9139 @ViewDebug.CapturedViewProperty
9140 public final int getBottom() {
9141 return mBottom;
9142 }
9143
9144 /**
Michael Jurkadab559a2011-01-04 20:31:51 -08009145 * True if this view has changed since the last time being drawn.
9146 *
9147 * @return The dirty state of this view.
9148 */
9149 public boolean isDirty() {
9150 return (mPrivateFlags & DIRTY_MASK) != 0;
9151 }
9152
9153 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009154 * Sets the bottom position of this view relative to its parent. This method is meant to be
9155 * called by the layout system and should not generally be called otherwise, because the
9156 * property may be changed at any time by the layout.
9157 *
9158 * @param bottom The bottom of this view, in pixels.
9159 */
9160 public final void setBottom(int bottom) {
9161 if (bottom != mBottom) {
Jeff Brown86671742010-09-30 20:00:15 -07009162 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009163 final boolean matrixIsIdentity = mTransformationInfo == null
9164 || mTransformationInfo.mMatrixIsIdentity;
9165 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009166 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009167 int maxBottom;
9168 if (bottom < mBottom) {
9169 maxBottom = mBottom;
9170 } else {
9171 maxBottom = bottom;
9172 }
Chet Haasee9140a72011-02-16 16:23:29 -08009173 invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009174 }
9175 } else {
9176 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009177 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009178 }
9179
Chet Haaseed032702010-10-01 14:05:54 -07009180 int width = mRight - mLeft;
9181 int oldHeight = mBottom - mTop;
9182
Chet Haase21cd1382010-09-01 17:42:29 -07009183 mBottom = bottom;
Chet Haase1271e2c2012-04-20 09:54:27 -07009184 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009185 mDisplayList.setBottom(mBottom);
9186 }
Chet Haase21cd1382010-09-01 17:42:29 -07009187
Chet Haaseed032702010-10-01 14:05:54 -07009188 onSizeChanged(width, mBottom - mTop, width, oldHeight);
9189
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009190 if (!matrixIsIdentity) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009191 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
9192 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009193 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009194 }
Chet Haase21cd1382010-09-01 17:42:29 -07009195 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009196 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009197 }
Chet Haase55dbb652010-12-21 20:15:08 -08009198 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009199 invalidateParentIfNeeded();
Chet Haase1a3ab172012-05-11 08:41:20 -07009200 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9201 // View was rejected last time it was drawn by its parent; this may have changed
9202 invalidateParentIfNeeded();
9203 }
Chet Haase21cd1382010-09-01 17:42:29 -07009204 }
9205 }
9206
9207 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 * Left position of this view relative to its parent.
9209 *
9210 * @return The left edge of this view, in pixels.
9211 */
9212 @ViewDebug.CapturedViewProperty
9213 public final int getLeft() {
9214 return mLeft;
9215 }
9216
9217 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009218 * Sets the left position of this view relative to its parent. This method is meant to be called
9219 * by the layout system and should not generally be called otherwise, because the property
9220 * may be changed at any time by the layout.
9221 *
9222 * @param left The bottom of this view, in pixels.
9223 */
9224 public final void setLeft(int left) {
9225 if (left != mLeft) {
Jeff Brown86671742010-09-30 20:00:15 -07009226 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009227 final boolean matrixIsIdentity = mTransformationInfo == null
9228 || mTransformationInfo.mMatrixIsIdentity;
9229 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009230 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009231 int minLeft;
9232 int xLoc;
9233 if (left < mLeft) {
9234 minLeft = left;
9235 xLoc = left - mLeft;
9236 } else {
9237 minLeft = mLeft;
9238 xLoc = 0;
9239 }
Chet Haasee9140a72011-02-16 16:23:29 -08009240 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009241 }
9242 } else {
9243 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009244 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009245 }
9246
Chet Haaseed032702010-10-01 14:05:54 -07009247 int oldWidth = mRight - mLeft;
9248 int height = mBottom - mTop;
9249
Chet Haase21cd1382010-09-01 17:42:29 -07009250 mLeft = left;
Chet Haase1271e2c2012-04-20 09:54:27 -07009251 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009252 mDisplayList.setLeft(left);
9253 }
Chet Haase21cd1382010-09-01 17:42:29 -07009254
Chet Haaseed032702010-10-01 14:05:54 -07009255 onSizeChanged(mRight - mLeft, height, oldWidth, height);
9256
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009257 if (!matrixIsIdentity) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009258 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
9259 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009260 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009261 }
Chet Haase21cd1382010-09-01 17:42:29 -07009262 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009263 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009264 }
Chet Haase55dbb652010-12-21 20:15:08 -08009265 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009266 invalidateParentIfNeeded();
Chet Haase1a3ab172012-05-11 08:41:20 -07009267 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9268 // View was rejected last time it was drawn by its parent; this may have changed
9269 invalidateParentIfNeeded();
9270 }
Chet Haase21cd1382010-09-01 17:42:29 -07009271 }
9272 }
9273
9274 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009275 * Right position of this view relative to its parent.
9276 *
9277 * @return The right edge of this view, in pixels.
9278 */
9279 @ViewDebug.CapturedViewProperty
9280 public final int getRight() {
9281 return mRight;
9282 }
9283
9284 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009285 * Sets the right position of this view relative to its parent. This method is meant to be called
9286 * by the layout system and should not generally be called otherwise, because the property
9287 * may be changed at any time by the layout.
9288 *
9289 * @param right The bottom of this view, in pixels.
9290 */
9291 public final void setRight(int right) {
9292 if (right != mRight) {
Jeff Brown86671742010-09-30 20:00:15 -07009293 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009294 final boolean matrixIsIdentity = mTransformationInfo == null
9295 || mTransformationInfo.mMatrixIsIdentity;
9296 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009297 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009298 int maxRight;
9299 if (right < mRight) {
9300 maxRight = mRight;
9301 } else {
9302 maxRight = right;
9303 }
Chet Haasee9140a72011-02-16 16:23:29 -08009304 invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009305 }
9306 } else {
9307 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009308 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009309 }
9310
Chet Haaseed032702010-10-01 14:05:54 -07009311 int oldWidth = mRight - mLeft;
9312 int height = mBottom - mTop;
9313
Chet Haase21cd1382010-09-01 17:42:29 -07009314 mRight = right;
Chet Haase1271e2c2012-04-20 09:54:27 -07009315 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009316 mDisplayList.setRight(mRight);
9317 }
Chet Haase21cd1382010-09-01 17:42:29 -07009318
Chet Haaseed032702010-10-01 14:05:54 -07009319 onSizeChanged(mRight - mLeft, height, oldWidth, height);
9320
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009321 if (!matrixIsIdentity) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009322 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
9323 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009324 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009325 }
Chet Haase21cd1382010-09-01 17:42:29 -07009326 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009327 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009328 }
Chet Haase55dbb652010-12-21 20:15:08 -08009329 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009330 invalidateParentIfNeeded();
Chet Haase1a3ab172012-05-11 08:41:20 -07009331 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9332 // View was rejected last time it was drawn by its parent; this may have changed
9333 invalidateParentIfNeeded();
9334 }
Chet Haase21cd1382010-09-01 17:42:29 -07009335 }
9336 }
9337
9338 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009339 * The visual x position of this view, in pixels. This is equivalent to the
9340 * {@link #setTranslationX(float) translationX} property plus the current
Joe Malin32736f02011-01-19 16:14:20 -08009341 * {@link #getLeft() left} property.
Chet Haasec3aa3612010-06-17 08:50:37 -07009342 *
Chet Haasedf030d22010-07-30 17:22:38 -07009343 * @return The visual x position of this view, in pixels.
Chet Haasec3aa3612010-06-17 08:50:37 -07009344 */
Chet Haasea5531132012-02-02 13:41:44 -08009345 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009346 public float getX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009347 return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
Chet Haasedf030d22010-07-30 17:22:38 -07009348 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009349
Chet Haasedf030d22010-07-30 17:22:38 -07009350 /**
9351 * Sets the visual x position of this view, in pixels. This is equivalent to setting the
9352 * {@link #setTranslationX(float) translationX} property to be the difference between
9353 * the x value passed in and the current {@link #getLeft() left} property.
9354 *
9355 * @param x The visual x position of this view, in pixels.
9356 */
9357 public void setX(float x) {
9358 setTranslationX(x - mLeft);
9359 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009360
Chet Haasedf030d22010-07-30 17:22:38 -07009361 /**
9362 * The visual y position of this view, in pixels. This is equivalent to the
9363 * {@link #setTranslationY(float) translationY} property plus the current
9364 * {@link #getTop() top} property.
9365 *
9366 * @return The visual y position of this view, in pixels.
9367 */
Chet Haasea5531132012-02-02 13:41:44 -08009368 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009369 public float getY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009370 return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
Chet Haasedf030d22010-07-30 17:22:38 -07009371 }
9372
9373 /**
9374 * Sets the visual y position of this view, in pixels. This is equivalent to setting the
9375 * {@link #setTranslationY(float) translationY} property to be the difference between
9376 * the y value passed in and the current {@link #getTop() top} property.
9377 *
9378 * @param y The visual y position of this view, in pixels.
9379 */
9380 public void setY(float y) {
9381 setTranslationY(y - mTop);
9382 }
9383
9384
9385 /**
9386 * The horizontal location of this view relative to its {@link #getLeft() left} position.
9387 * This position is post-layout, in addition to wherever the object's
9388 * layout placed it.
9389 *
9390 * @return The horizontal position of this view relative to its left position, in pixels.
9391 */
Chet Haasea5531132012-02-02 13:41:44 -08009392 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009393 public float getTranslationX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009394 return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
Chet Haasedf030d22010-07-30 17:22:38 -07009395 }
9396
9397 /**
9398 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
9399 * This effectively positions the object post-layout, in addition to wherever the object's
9400 * layout placed it.
9401 *
9402 * @param translationX The horizontal position of this view relative to its left position,
9403 * in pixels.
Chet Haase73066682010-11-29 15:55:32 -08009404 *
9405 * @attr ref android.R.styleable#View_translationX
Chet Haasedf030d22010-07-30 17:22:38 -07009406 */
9407 public void setTranslationX(float translationX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009408 ensureTransformationInfo();
9409 final TransformationInfo info = mTransformationInfo;
9410 if (info.mTranslationX != translationX) {
Chet Haasedf030d22010-07-30 17:22:38 -07009411 // Double-invalidation is necessary to capture view's old and new areas
Chet Haase9d1992d2012-03-13 11:03:25 -07009412 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009413 info.mTranslationX = translationX;
9414 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009415 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009416 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009417 mDisplayList.setTranslationX(translationX);
9418 }
Chet Haase1a3ab172012-05-11 08:41:20 -07009419 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9420 // View was rejected last time it was drawn by its parent; this may have changed
9421 invalidateParentIfNeeded();
9422 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009423 }
9424 }
9425
9426 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009427 * The horizontal location of this view relative to its {@link #getTop() top} position.
9428 * This position is post-layout, in addition to wherever the object's
9429 * layout placed it.
Chet Haasec3aa3612010-06-17 08:50:37 -07009430 *
Chet Haasedf030d22010-07-30 17:22:38 -07009431 * @return The vertical position of this view relative to its top position,
9432 * in pixels.
Chet Haasec3aa3612010-06-17 08:50:37 -07009433 */
Chet Haasea5531132012-02-02 13:41:44 -08009434 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009435 public float getTranslationY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009436 return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07009437 }
9438
9439 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009440 * Sets the vertical location of this view relative to its {@link #getTop() top} position.
9441 * This effectively positions the object post-layout, in addition to wherever the object's
9442 * layout placed it.
Chet Haasec3aa3612010-06-17 08:50:37 -07009443 *
Chet Haasedf030d22010-07-30 17:22:38 -07009444 * @param translationY The vertical position of this view relative to its top position,
9445 * in pixels.
Chet Haase73066682010-11-29 15:55:32 -08009446 *
9447 * @attr ref android.R.styleable#View_translationY
Chet Haasec3aa3612010-06-17 08:50:37 -07009448 */
Chet Haasedf030d22010-07-30 17:22:38 -07009449 public void setTranslationY(float translationY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009450 ensureTransformationInfo();
9451 final TransformationInfo info = mTransformationInfo;
9452 if (info.mTranslationY != translationY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009453 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009454 info.mTranslationY = translationY;
9455 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009456 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009457 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009458 mDisplayList.setTranslationY(translationY);
9459 }
Chet Haase1a3ab172012-05-11 08:41:20 -07009460 if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9461 // View was rejected last time it was drawn by its parent; this may have changed
9462 invalidateParentIfNeeded();
9463 }
Chet Haasedf030d22010-07-30 17:22:38 -07009464 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009465 }
9466
9467 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009468 * Hit rectangle in parent's coordinates
9469 *
9470 * @param outRect The hit rectangle of the view.
9471 */
9472 public void getHitRect(Rect outRect) {
Jeff Brown86671742010-09-30 20:00:15 -07009473 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009474 final TransformationInfo info = mTransformationInfo;
9475 if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009476 outRect.set(mLeft, mTop, mRight, mBottom);
9477 } else {
9478 final RectF tmpRect = mAttachInfo.mTmpTransformRect;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009479 tmpRect.set(-info.mPivotX, -info.mPivotY,
9480 getWidth() - info.mPivotX, getHeight() - info.mPivotY);
9481 info.mMatrix.mapRect(tmpRect);
Romain Guy33e72ae2010-07-17 12:40:29 -07009482 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
9483 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
Chet Haasec3aa3612010-06-17 08:50:37 -07009484 }
9485 }
9486
9487 /**
Jeff Brown20e987b2010-08-23 12:01:02 -07009488 * Determines whether the given point, in local coordinates is inside the view.
9489 */
9490 /*package*/ final boolean pointInView(float localX, float localY) {
9491 return localX >= 0 && localX < (mRight - mLeft)
9492 && localY >= 0 && localY < (mBottom - mTop);
9493 }
9494
9495 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07009496 * Utility method to determine whether the given point, in local coordinates,
9497 * is inside the view, where the area of the view is expanded by the slop factor.
9498 * This method is called while processing touch-move events to determine if the event
9499 * is still within the view.
9500 */
9501 private boolean pointInView(float localX, float localY, float slop) {
Jeff Brown20e987b2010-08-23 12:01:02 -07009502 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
Romain Guy33e72ae2010-07-17 12:40:29 -07009503 localY < ((mBottom - mTop) + slop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009504 }
9505
9506 /**
9507 * When a view has focus and the user navigates away from it, the next view is searched for
9508 * starting from the rectangle filled in by this method.
9509 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07009510 * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
9511 * of the view. However, if your view maintains some idea of internal selection,
9512 * such as a cursor, or a selected row or column, you should override this method and
9513 * fill in a more specific rectangle.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009514 *
9515 * @param r The rectangle to fill in, in this view's coordinates.
9516 */
9517 public void getFocusedRect(Rect r) {
9518 getDrawingRect(r);
9519 }
9520
9521 /**
9522 * If some part of this view is not clipped by any of its parents, then
9523 * return that area in r in global (root) coordinates. To convert r to local
Gilles Debunnecea45132011-11-24 02:19:27 +01009524 * coordinates (without taking possible View rotations into account), offset
9525 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
9526 * If the view is completely clipped or translated out, return false.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527 *
9528 * @param r If true is returned, r holds the global coordinates of the
9529 * visible portion of this view.
9530 * @param globalOffset If true is returned, globalOffset holds the dx,dy
9531 * between this view and its root. globalOffet may be null.
9532 * @return true if r is non-empty (i.e. part of the view is visible at the
9533 * root level.
9534 */
9535 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
9536 int width = mRight - mLeft;
9537 int height = mBottom - mTop;
9538 if (width > 0 && height > 0) {
9539 r.set(0, 0, width, height);
9540 if (globalOffset != null) {
9541 globalOffset.set(-mScrollX, -mScrollY);
9542 }
9543 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
9544 }
9545 return false;
9546 }
9547
9548 public final boolean getGlobalVisibleRect(Rect r) {
9549 return getGlobalVisibleRect(r, null);
9550 }
9551
9552 public final boolean getLocalVisibleRect(Rect r) {
Romain Guyab4c4f4f2012-05-06 13:11:24 -07009553 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 if (getGlobalVisibleRect(r, offset)) {
9555 r.offset(-offset.x, -offset.y); // make r local
9556 return true;
9557 }
9558 return false;
9559 }
9560
9561 /**
9562 * Offset this view's vertical location by the specified number of pixels.
9563 *
9564 * @param offset the number of pixels to offset the view by
9565 */
9566 public void offsetTopAndBottom(int offset) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009567 if (offset != 0) {
Jeff Brown86671742010-09-30 20:00:15 -07009568 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009569 final boolean matrixIsIdentity = mTransformationInfo == null
9570 || mTransformationInfo.mMatrixIsIdentity;
9571 if (matrixIsIdentity) {
Chet Haase1271e2c2012-04-20 09:54:27 -07009572 if (mDisplayList != null) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009573 invalidateViewProperty(false, false);
9574 } else {
9575 final ViewParent p = mParent;
9576 if (p != null && mAttachInfo != null) {
9577 final Rect r = mAttachInfo.mTmpInvalRect;
9578 int minTop;
9579 int maxBottom;
9580 int yLoc;
9581 if (offset < 0) {
9582 minTop = mTop + offset;
9583 maxBottom = mBottom;
9584 yLoc = offset;
9585 } else {
9586 minTop = mTop;
9587 maxBottom = mBottom + offset;
9588 yLoc = 0;
9589 }
9590 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
9591 p.invalidateChild(this, r);
Chet Haase8fbf8d22010-07-30 15:01:32 -07009592 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009593 }
9594 } else {
Chet Haase9d1992d2012-03-13 11:03:25 -07009595 invalidateViewProperty(false, false);
Chet Haasec3aa3612010-06-17 08:50:37 -07009596 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009597
Chet Haasec3aa3612010-06-17 08:50:37 -07009598 mTop += offset;
9599 mBottom += offset;
Chet Haase1271e2c2012-04-20 09:54:27 -07009600 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009601 mDisplayList.offsetTopBottom(offset);
Chet Haase9d1992d2012-03-13 11:03:25 -07009602 invalidateViewProperty(false, false);
9603 } else {
9604 if (!matrixIsIdentity) {
9605 invalidateViewProperty(false, true);
9606 }
9607 invalidateParentIfNeeded();
Chet Haasea1cff502012-02-21 13:43:44 -08009608 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009610 }
9611
9612 /**
9613 * Offset this view's horizontal location by the specified amount of pixels.
9614 *
9615 * @param offset the numer of pixels to offset the view by
9616 */
9617 public void offsetLeftAndRight(int offset) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009618 if (offset != 0) {
Jeff Brown86671742010-09-30 20:00:15 -07009619 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009620 final boolean matrixIsIdentity = mTransformationInfo == null
9621 || mTransformationInfo.mMatrixIsIdentity;
9622 if (matrixIsIdentity) {
Chet Haase1271e2c2012-04-20 09:54:27 -07009623 if (mDisplayList != null) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009624 invalidateViewProperty(false, false);
9625 } else {
9626 final ViewParent p = mParent;
9627 if (p != null && mAttachInfo != null) {
9628 final Rect r = mAttachInfo.mTmpInvalRect;
9629 int minLeft;
9630 int maxRight;
9631 if (offset < 0) {
9632 minLeft = mLeft + offset;
9633 maxRight = mRight;
9634 } else {
9635 minLeft = mLeft;
9636 maxRight = mRight + offset;
9637 }
9638 r.set(0, 0, maxRight - minLeft, mBottom - mTop);
9639 p.invalidateChild(this, r);
Chet Haase8fbf8d22010-07-30 15:01:32 -07009640 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009641 }
9642 } else {
Chet Haase9d1992d2012-03-13 11:03:25 -07009643 invalidateViewProperty(false, false);
Chet Haasec3aa3612010-06-17 08:50:37 -07009644 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009645
Chet Haasec3aa3612010-06-17 08:50:37 -07009646 mLeft += offset;
9647 mRight += offset;
Chet Haase1271e2c2012-04-20 09:54:27 -07009648 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009649 mDisplayList.offsetLeftRight(offset);
Chet Haase9d1992d2012-03-13 11:03:25 -07009650 invalidateViewProperty(false, false);
9651 } else {
9652 if (!matrixIsIdentity) {
9653 invalidateViewProperty(false, true);
9654 }
9655 invalidateParentIfNeeded();
Chet Haasea1cff502012-02-21 13:43:44 -08009656 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658 }
9659
9660 /**
9661 * Get the LayoutParams associated with this view. All views should have
9662 * layout parameters. These supply parameters to the <i>parent</i> of this
9663 * view specifying how it should be arranged. There are many subclasses of
9664 * ViewGroup.LayoutParams, and these correspond to the different subclasses
9665 * of ViewGroup that are responsible for arranging their children.
Romain Guy01c174b2011-02-22 11:51:06 -08009666 *
9667 * This method may return null if this View is not attached to a parent
9668 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
9669 * was not invoked successfully. When a View is attached to a parent
9670 * ViewGroup, this method must not return null.
9671 *
9672 * @return The LayoutParams associated with this view, or null if no
9673 * parameters have been set yet
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009674 */
Konstantin Lopyrev91a7f5f2010-08-10 18:54:54 -07009675 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 public ViewGroup.LayoutParams getLayoutParams() {
9677 return mLayoutParams;
9678 }
9679
9680 /**
9681 * Set the layout parameters associated with this view. These supply
9682 * parameters to the <i>parent</i> of this view specifying how it should be
9683 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
9684 * correspond to the different subclasses of ViewGroup that are responsible
9685 * for arranging their children.
9686 *
Romain Guy01c174b2011-02-22 11:51:06 -08009687 * @param params The layout parameters for this view, cannot be null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009688 */
9689 public void setLayoutParams(ViewGroup.LayoutParams params) {
9690 if (params == null) {
Romain Guy01c174b2011-02-22 11:51:06 -08009691 throw new NullPointerException("Layout parameters cannot be null");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 }
9693 mLayoutParams = params;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07009694 resolveLayoutParams();
Philip Milned7dd8902012-01-26 16:55:30 -08009695 if (mParent instanceof ViewGroup) {
9696 ((ViewGroup) mParent).onSetLayoutParams(this, params);
9697 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 requestLayout();
9699 }
9700
9701 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07009702 * Resolve the layout parameters depending on the resolved layout direction
9703 */
9704 private void resolveLayoutParams() {
9705 if (mLayoutParams != null) {
9706 mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
9707 }
9708 }
9709
9710 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 * Set the scrolled position of your view. This will cause a call to
9712 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9713 * invalidated.
9714 * @param x the x position to scroll to
9715 * @param y the y position to scroll to
9716 */
9717 public void scrollTo(int x, int y) {
9718 if (mScrollX != x || mScrollY != y) {
9719 int oldX = mScrollX;
9720 int oldY = mScrollY;
9721 mScrollX = x;
9722 mScrollY = y;
Romain Guy0fd89bf2011-01-26 15:41:30 -08009723 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009724 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
Mike Cleronf116bf82009-09-27 19:14:12 -07009725 if (!awakenScrollBars()) {
Adam Powelldf3ae4f2012-04-10 18:55:22 -07009726 postInvalidateOnAnimation();
Mike Cleronf116bf82009-09-27 19:14:12 -07009727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 }
9729 }
9730
9731 /**
9732 * Move the scrolled position of your view. This will cause a call to
9733 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9734 * invalidated.
9735 * @param x the amount of pixels to scroll by horizontally
9736 * @param y the amount of pixels to scroll by vertically
9737 */
9738 public void scrollBy(int x, int y) {
9739 scrollTo(mScrollX + x, mScrollY + y);
9740 }
9741
9742 /**
Mike Cleronf116bf82009-09-27 19:14:12 -07009743 * <p>Trigger the scrollbars to draw. When invoked this method starts an
9744 * animation to fade the scrollbars out after a default delay. If a subclass
9745 * provides animated scrolling, the start delay should equal the duration
9746 * of the scrolling animation.</p>
9747 *
9748 * <p>The animation starts only if at least one of the scrollbars is
9749 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
9750 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9751 * this method returns true, and false otherwise. If the animation is
9752 * started, this method calls {@link #invalidate()}; in that case the
9753 * caller should not call {@link #invalidate()}.</p>
9754 *
9755 * <p>This method should be invoked every time a subclass directly updates
Mike Cleronfe81d382009-09-28 14:22:16 -07009756 * the scroll parameters.</p>
Mike Cleronf116bf82009-09-27 19:14:12 -07009757 *
9758 * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
9759 * and {@link #scrollTo(int, int)}.</p>
9760 *
9761 * @return true if the animation is played, false otherwise
9762 *
9763 * @see #awakenScrollBars(int)
Mike Cleronf116bf82009-09-27 19:14:12 -07009764 * @see #scrollBy(int, int)
9765 * @see #scrollTo(int, int)
9766 * @see #isHorizontalScrollBarEnabled()
9767 * @see #isVerticalScrollBarEnabled()
9768 * @see #setHorizontalScrollBarEnabled(boolean)
9769 * @see #setVerticalScrollBarEnabled(boolean)
9770 */
9771 protected boolean awakenScrollBars() {
9772 return mScrollCache != null &&
Mike Cleron290947b2009-09-29 18:34:32 -07009773 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
Mike Cleronf116bf82009-09-27 19:14:12 -07009774 }
9775
9776 /**
Adam Powell8568c3a2010-04-19 14:26:11 -07009777 * Trigger the scrollbars to draw.
9778 * This method differs from awakenScrollBars() only in its default duration.
9779 * initialAwakenScrollBars() will show the scroll bars for longer than
9780 * usual to give the user more of a chance to notice them.
9781 *
9782 * @return true if the animation is played, false otherwise.
9783 */
9784 private boolean initialAwakenScrollBars() {
9785 return mScrollCache != null &&
9786 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
9787 }
9788
9789 /**
Mike Cleronf116bf82009-09-27 19:14:12 -07009790 * <p>
9791 * Trigger the scrollbars to draw. When invoked this method starts an
9792 * animation to fade the scrollbars out after a fixed delay. If a subclass
9793 * provides animated scrolling, the start delay should equal the duration of
9794 * the scrolling animation.
9795 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009796 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009797 * <p>
9798 * The animation starts only if at least one of the scrollbars is enabled,
9799 * as specified by {@link #isHorizontalScrollBarEnabled()} and
9800 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9801 * this method returns true, and false otherwise. If the animation is
9802 * started, this method calls {@link #invalidate()}; in that case the caller
9803 * should not call {@link #invalidate()}.
9804 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009805 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009806 * <p>
9807 * This method should be invoked everytime a subclass directly updates the
Mike Cleronfe81d382009-09-28 14:22:16 -07009808 * scroll parameters.
Mike Cleronf116bf82009-09-27 19:14:12 -07009809 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009810 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009811 * @param startDelay the delay, in milliseconds, after which the animation
9812 * should start; when the delay is 0, the animation starts
9813 * immediately
9814 * @return true if the animation is played, false otherwise
Joe Malin32736f02011-01-19 16:14:20 -08009815 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009816 * @see #scrollBy(int, int)
9817 * @see #scrollTo(int, int)
9818 * @see #isHorizontalScrollBarEnabled()
9819 * @see #isVerticalScrollBarEnabled()
9820 * @see #setHorizontalScrollBarEnabled(boolean)
9821 * @see #setVerticalScrollBarEnabled(boolean)
9822 */
9823 protected boolean awakenScrollBars(int startDelay) {
Mike Cleron290947b2009-09-29 18:34:32 -07009824 return awakenScrollBars(startDelay, true);
9825 }
Joe Malin32736f02011-01-19 16:14:20 -08009826
Mike Cleron290947b2009-09-29 18:34:32 -07009827 /**
9828 * <p>
9829 * Trigger the scrollbars to draw. When invoked this method starts an
9830 * animation to fade the scrollbars out after a fixed delay. If a subclass
9831 * provides animated scrolling, the start delay should equal the duration of
9832 * the scrolling animation.
9833 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009834 *
Mike Cleron290947b2009-09-29 18:34:32 -07009835 * <p>
9836 * The animation starts only if at least one of the scrollbars is enabled,
9837 * as specified by {@link #isHorizontalScrollBarEnabled()} and
9838 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9839 * this method returns true, and false otherwise. If the animation is
Joe Malin32736f02011-01-19 16:14:20 -08009840 * started, this method calls {@link #invalidate()} if the invalidate parameter
Mike Cleron290947b2009-09-29 18:34:32 -07009841 * is set to true; in that case the caller
9842 * should not call {@link #invalidate()}.
9843 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009844 *
Mike Cleron290947b2009-09-29 18:34:32 -07009845 * <p>
9846 * This method should be invoked everytime a subclass directly updates the
9847 * scroll parameters.
9848 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009849 *
Mike Cleron290947b2009-09-29 18:34:32 -07009850 * @param startDelay the delay, in milliseconds, after which the animation
9851 * should start; when the delay is 0, the animation starts
9852 * immediately
Joe Malin32736f02011-01-19 16:14:20 -08009853 *
Mike Cleron290947b2009-09-29 18:34:32 -07009854 * @param invalidate Wheter this method should call invalidate
Joe Malin32736f02011-01-19 16:14:20 -08009855 *
Mike Cleron290947b2009-09-29 18:34:32 -07009856 * @return true if the animation is played, false otherwise
Joe Malin32736f02011-01-19 16:14:20 -08009857 *
Mike Cleron290947b2009-09-29 18:34:32 -07009858 * @see #scrollBy(int, int)
9859 * @see #scrollTo(int, int)
9860 * @see #isHorizontalScrollBarEnabled()
9861 * @see #isVerticalScrollBarEnabled()
9862 * @see #setHorizontalScrollBarEnabled(boolean)
9863 * @see #setVerticalScrollBarEnabled(boolean)
9864 */
9865 protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
Mike Cleronf116bf82009-09-27 19:14:12 -07009866 final ScrollabilityCache scrollCache = mScrollCache;
Joe Malin32736f02011-01-19 16:14:20 -08009867
Mike Cleronf116bf82009-09-27 19:14:12 -07009868 if (scrollCache == null || !scrollCache.fadeScrollBars) {
9869 return false;
9870 }
9871
9872 if (scrollCache.scrollBar == null) {
9873 scrollCache.scrollBar = new ScrollBarDrawable();
9874 }
9875
9876 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
9877
Mike Cleron290947b2009-09-29 18:34:32 -07009878 if (invalidate) {
9879 // Invalidate to show the scrollbars
Adam Powelldf3ae4f2012-04-10 18:55:22 -07009880 postInvalidateOnAnimation();
Mike Cleron290947b2009-09-29 18:34:32 -07009881 }
Mike Cleronf116bf82009-09-27 19:14:12 -07009882
9883 if (scrollCache.state == ScrollabilityCache.OFF) {
9884 // FIXME: this is copied from WindowManagerService.
9885 // We should get this value from the system when it
9886 // is possible to do so.
9887 final int KEY_REPEAT_FIRST_DELAY = 750;
9888 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
9889 }
9890
9891 // Tell mScrollCache when we should start fading. This may
9892 // extend the fade start time if one was already scheduled
Mike Cleron3ecd58c2009-09-28 11:39:02 -07009893 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
Mike Cleronf116bf82009-09-27 19:14:12 -07009894 scrollCache.fadeStartTime = fadeStartTime;
9895 scrollCache.state = ScrollabilityCache.ON;
9896
9897 // Schedule our fader to run, unscheduling any old ones first
9898 if (mAttachInfo != null) {
9899 mAttachInfo.mHandler.removeCallbacks(scrollCache);
9900 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
9901 }
9902
9903 return true;
9904 }
9905
9906 return false;
9907 }
9908
9909 /**
Chet Haaseaceafe62011-08-26 15:44:33 -07009910 * Do not invalidate views which are not visible and which are not running an animation. They
9911 * will not get drawn and they should not set dirty flags as if they will be drawn
9912 */
9913 private boolean skipInvalidate() {
9914 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
9915 (!(mParent instanceof ViewGroup) ||
9916 !((ViewGroup) mParent).isViewTransitioning(this));
9917 }
9918 /**
Joe Fernandez558459f2011-10-13 16:47:36 -07009919 * Mark the area defined by dirty as needing to be drawn. If the view is
Romain Guy5c22a8c2011-05-13 11:48:45 -07009920 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
9921 * in the future. This must be called from a UI thread. To call from a non-UI
9922 * thread, call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923 *
9924 * WARNING: This method is destructive to dirty.
9925 * @param dirty the rectangle representing the bounds of the dirty region
9926 */
9927 public void invalidate(Rect dirty) {
Chet Haaseaceafe62011-08-26 15:44:33 -07009928 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -07009929 return;
9930 }
Romain Guy2fe9a8f2010-10-04 20:17:01 -07009931 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
Chet Haasedaf98e92011-01-10 14:10:36 -08009932 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
9933 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009934 mPrivateFlags &= ~DRAWING_CACHE_VALID;
Chet Haasedaf98e92011-01-10 14:10:36 -08009935 mPrivateFlags |= INVALIDATED;
Chet Haasef186f302011-09-11 11:06:06 -07009936 mPrivateFlags |= DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009937 final ViewParent p = mParent;
9938 final AttachInfo ai = mAttachInfo;
Romain Guy7d7b5492011-01-24 16:33:45 -08009939 //noinspection PointlessBooleanExpression,ConstantConditions
9940 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
9941 if (p != null && ai != null && ai.mHardwareAccelerated) {
9942 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -07009943 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -08009944 p.invalidateChild(this, null);
9945 return;
9946 }
Romain Guyaf636eb2010-12-09 17:47:21 -08009947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009948 if (p != null && ai != null) {
9949 final int scrollX = mScrollX;
9950 final int scrollY = mScrollY;
9951 final Rect r = ai.mTmpInvalRect;
9952 r.set(dirty.left - scrollX, dirty.top - scrollY,
9953 dirty.right - scrollX, dirty.bottom - scrollY);
9954 mParent.invalidateChild(this, r);
9955 }
9956 }
9957 }
9958
9959 /**
Joe Fernandez558459f2011-10-13 16:47:36 -07009960 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961 * The coordinates of the dirty rect are relative to the view.
Romain Guy5c22a8c2011-05-13 11:48:45 -07009962 * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
9963 * will be called at some point in the future. This must be called from
9964 * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 * @param l the left position of the dirty region
9966 * @param t the top position of the dirty region
9967 * @param r the right position of the dirty region
9968 * @param b the bottom position of the dirty region
9969 */
9970 public void invalidate(int l, int t, int r, int b) {
Chet Haaseaceafe62011-08-26 15:44:33 -07009971 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -07009972 return;
9973 }
Romain Guy2fe9a8f2010-10-04 20:17:01 -07009974 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
Chet Haasedaf98e92011-01-10 14:10:36 -08009975 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
9976 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 mPrivateFlags &= ~DRAWING_CACHE_VALID;
Chet Haasedaf98e92011-01-10 14:10:36 -08009978 mPrivateFlags |= INVALIDATED;
Chet Haasef186f302011-09-11 11:06:06 -07009979 mPrivateFlags |= DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 final ViewParent p = mParent;
9981 final AttachInfo ai = mAttachInfo;
Romain Guy7d7b5492011-01-24 16:33:45 -08009982 //noinspection PointlessBooleanExpression,ConstantConditions
9983 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
9984 if (p != null && ai != null && ai.mHardwareAccelerated) {
9985 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -07009986 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -08009987 p.invalidateChild(this, null);
9988 return;
9989 }
Chet Haasef2f7d8f2010-12-03 14:08:14 -08009990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 if (p != null && ai != null && l < r && t < b) {
9992 final int scrollX = mScrollX;
9993 final int scrollY = mScrollY;
9994 final Rect tmpr = ai.mTmpInvalRect;
9995 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
9996 p.invalidateChild(this, tmpr);
9997 }
9998 }
9999 }
10000
10001 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070010002 * Invalidate the whole view. If the view is visible,
10003 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
10004 * the future. This must be called from a UI thread. To call from a non-UI thread,
10005 * call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 */
10007 public void invalidate() {
Chet Haaseed032702010-10-01 14:05:54 -070010008 invalidate(true);
10009 }
Joe Malin32736f02011-01-19 16:14:20 -080010010
Chet Haaseed032702010-10-01 14:05:54 -070010011 /**
10012 * This is where the invalidate() work actually happens. A full invalidate()
10013 * causes the drawing cache to be invalidated, but this function can be called with
10014 * invalidateCache set to false to skip that invalidation step for cases that do not
10015 * need it (for example, a component that remains at the same dimensions with the same
10016 * content).
10017 *
10018 * @param invalidateCache Whether the drawing cache for this view should be invalidated as
10019 * well. This is usually true for a full invalidate, but may be set to false if the
10020 * View's contents or dimensions have not changed.
10021 */
Romain Guy849d0a32011-02-01 17:20:48 -080010022 void invalidate(boolean invalidateCache) {
Chet Haaseaceafe62011-08-26 15:44:33 -070010023 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -070010024 return;
10025 }
Romain Guy2fe9a8f2010-10-04 20:17:01 -070010026 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
Romain Guyc5d55862011-01-21 19:01:46 -080010027 (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
Romain Guy0fd89bf2011-01-26 15:41:30 -080010028 (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
10029 mLastIsOpaque = isOpaque();
Chet Haaseed032702010-10-01 14:05:54 -070010030 mPrivateFlags &= ~DRAWN;
Chet Haasef186f302011-09-11 11:06:06 -070010031 mPrivateFlags |= DIRTY;
Chet Haaseed032702010-10-01 14:05:54 -070010032 if (invalidateCache) {
Chet Haasedaf98e92011-01-10 14:10:36 -080010033 mPrivateFlags |= INVALIDATED;
Chet Haaseed032702010-10-01 14:05:54 -070010034 mPrivateFlags &= ~DRAWING_CACHE_VALID;
10035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 final AttachInfo ai = mAttachInfo;
Chet Haase70d4ba12010-10-06 09:46:45 -070010037 final ViewParent p = mParent;
Romain Guy7d7b5492011-01-24 16:33:45 -080010038 //noinspection PointlessBooleanExpression,ConstantConditions
10039 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10040 if (p != null && ai != null && ai.mHardwareAccelerated) {
10041 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070010042 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -080010043 p.invalidateChild(this, null);
10044 return;
10045 }
Chet Haasef2f7d8f2010-12-03 14:08:14 -080010046 }
Michael Jurkaebefea42010-11-15 16:04:01 -080010047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010048 if (p != null && ai != null) {
10049 final Rect r = ai.mTmpInvalRect;
10050 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10051 // Don't call invalidate -- we don't want to internally scroll
10052 // our own bounds
10053 p.invalidateChild(this, r);
10054 }
10055 }
10056 }
10057
10058 /**
Chet Haase9d1992d2012-03-13 11:03:25 -070010059 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
10060 * set any flags or handle all of the cases handled by the default invalidation methods.
10061 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
10062 * dirty rect. This method calls into fast invalidation methods in ViewGroup that
10063 * walk up the hierarchy, transforming the dirty rect as necessary.
10064 *
10065 * The method also handles normal invalidation logic if display list properties are not
10066 * being used in this view. The invalidateParent and forceRedraw flags are used by that
10067 * backup approach, to handle these cases used in the various property-setting methods.
10068 *
10069 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
10070 * are not being used in this view
10071 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
10072 * list properties are not being used in this view
10073 */
10074 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
Chet Haase1271e2c2012-04-20 09:54:27 -070010075 if (mDisplayList == null || (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
Chet Haase9d1992d2012-03-13 11:03:25 -070010076 if (invalidateParent) {
10077 invalidateParentCaches();
10078 }
10079 if (forceRedraw) {
10080 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
10081 }
10082 invalidate(false);
10083 } else {
10084 final AttachInfo ai = mAttachInfo;
10085 final ViewParent p = mParent;
10086 if (p != null && ai != null) {
10087 final Rect r = ai.mTmpInvalRect;
10088 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10089 if (mParent instanceof ViewGroup) {
10090 ((ViewGroup) mParent).invalidateChildFast(this, r);
10091 } else {
10092 mParent.invalidateChild(this, r);
10093 }
10094 }
10095 }
10096 }
10097
10098 /**
10099 * Utility method to transform a given Rect by the current matrix of this view.
10100 */
10101 void transformRect(final Rect rect) {
10102 if (!getMatrix().isIdentity()) {
10103 RectF boundingRect = mAttachInfo.mTmpTransformRect;
10104 boundingRect.set(rect);
10105 getMatrix().mapRect(boundingRect);
10106 rect.set((int) (boundingRect.left - 0.5f),
10107 (int) (boundingRect.top - 0.5f),
10108 (int) (boundingRect.right + 0.5f),
10109 (int) (boundingRect.bottom + 0.5f));
10110 }
10111 }
10112
10113 /**
Romain Guy0fd89bf2011-01-26 15:41:30 -080010114 * Used to indicate that the parent of this view should clear its caches. This functionality
Chet Haasedaf98e92011-01-10 14:10:36 -080010115 * is used to force the parent to rebuild its display list (when hardware-accelerated),
10116 * which is necessary when various parent-managed properties of the view change, such as
Romain Guy0fd89bf2011-01-26 15:41:30 -080010117 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
10118 * clears the parent caches and does not causes an invalidate event.
Chet Haasedaf98e92011-01-10 14:10:36 -080010119 *
10120 * @hide
10121 */
Romain Guy0fd89bf2011-01-26 15:41:30 -080010122 protected void invalidateParentCaches() {
10123 if (mParent instanceof View) {
10124 ((View) mParent).mPrivateFlags |= INVALIDATED;
10125 }
10126 }
Joe Malin32736f02011-01-19 16:14:20 -080010127
Romain Guy0fd89bf2011-01-26 15:41:30 -080010128 /**
10129 * Used to indicate that the parent of this view should be invalidated. This functionality
10130 * is used to force the parent to rebuild its display list (when hardware-accelerated),
10131 * which is necessary when various parent-managed properties of the view change, such as
10132 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
10133 * an invalidation event to the parent.
10134 *
10135 * @hide
10136 */
10137 protected void invalidateParentIfNeeded() {
Chet Haasedaf98e92011-01-10 14:10:36 -080010138 if (isHardwareAccelerated() && mParent instanceof View) {
Romain Guy0fd89bf2011-01-26 15:41:30 -080010139 ((View) mParent).invalidate(true);
Chet Haasedaf98e92011-01-10 14:10:36 -080010140 }
10141 }
10142
10143 /**
Romain Guy24443ea2009-05-11 11:56:30 -070010144 * Indicates whether this View is opaque. An opaque View guarantees that it will
10145 * draw all the pixels overlapping its bounds using a fully opaque color.
10146 *
10147 * Subclasses of View should override this method whenever possible to indicate
10148 * whether an instance is opaque. Opaque Views are treated in a special way by
10149 * the View hierarchy, possibly allowing it to perform optimizations during
10150 * invalidate/draw passes.
Romain Guy8506ab42009-06-11 17:35:47 -070010151 *
Romain Guy24443ea2009-05-11 11:56:30 -070010152 * @return True if this View is guaranteed to be fully opaque, false otherwise.
Romain Guy24443ea2009-05-11 11:56:30 -070010153 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070010154 @ViewDebug.ExportedProperty(category = "drawing")
Romain Guy24443ea2009-05-11 11:56:30 -070010155 public boolean isOpaque() {
Chet Haase70d4ba12010-10-06 09:46:45 -070010156 return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
Romain Guyf8773082012-07-12 18:01:00 -070010157 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
Romain Guy8f1344f52009-05-15 16:03:59 -070010158 }
10159
Adam Powell20232d02010-12-08 21:08:53 -080010160 /**
10161 * @hide
10162 */
10163 protected void computeOpaqueFlags() {
Romain Guy8f1344f52009-05-15 16:03:59 -070010164 // Opaque if:
10165 // - Has a background
10166 // - Background is opaque
10167 // - Doesn't have scrollbars or scrollbars are inside overlay
10168
Philip Milne6c8ea062012-04-03 17:38:43 -070010169 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
Romain Guy8f1344f52009-05-15 16:03:59 -070010170 mPrivateFlags |= OPAQUE_BACKGROUND;
10171 } else {
10172 mPrivateFlags &= ~OPAQUE_BACKGROUND;
10173 }
10174
10175 final int flags = mViewFlags;
10176 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
10177 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
10178 mPrivateFlags |= OPAQUE_SCROLLBARS;
10179 } else {
10180 mPrivateFlags &= ~OPAQUE_SCROLLBARS;
10181 }
10182 }
10183
10184 /**
10185 * @hide
10186 */
10187 protected boolean hasOpaqueScrollbars() {
10188 return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
Romain Guy24443ea2009-05-11 11:56:30 -070010189 }
10190
10191 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 * @return A handler associated with the thread running the View. This
10193 * handler can be used to pump events in the UI events queue.
10194 */
10195 public Handler getHandler() {
10196 if (mAttachInfo != null) {
10197 return mAttachInfo.mHandler;
10198 }
10199 return null;
10200 }
10201
10202 /**
Jeff Browna175a5b2012-02-15 19:18:31 -080010203 * Gets the view root associated with the View.
10204 * @return The view root, or null if none.
10205 * @hide
10206 */
10207 public ViewRootImpl getViewRootImpl() {
10208 if (mAttachInfo != null) {
10209 return mAttachInfo.mViewRootImpl;
10210 }
10211 return null;
10212 }
10213
10214 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010215 * <p>Causes the Runnable to be added to the message queue.
10216 * The runnable will be run on the user interface thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010217 *
Romain Guye63a4f32011-08-11 11:33:31 -070010218 * <p>This method can be invoked from outside of the UI thread
10219 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010220 *
10221 * @param action The Runnable that will be executed.
10222 *
10223 * @return Returns true if the Runnable was successfully placed in to the
10224 * message queue. Returns false on failure, usually because the
10225 * looper processing the message queue is exiting.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010226 *
10227 * @see #postDelayed
10228 * @see #removeCallbacks
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 */
10230 public boolean post(Runnable action) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010231 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010232 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010233 return attachInfo.mHandler.post(action);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 }
Jeff Browna175a5b2012-02-15 19:18:31 -080010235 // Assume that post will succeed later
10236 ViewRootImpl.getRunQueue().post(action);
10237 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 }
10239
10240 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010241 * <p>Causes the Runnable to be added to the message queue, to be run
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 * after the specified amount of time elapses.
Romain Guye63a4f32011-08-11 11:33:31 -070010243 * The runnable will be run on the user interface thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010244 *
Romain Guye63a4f32011-08-11 11:33:31 -070010245 * <p>This method can be invoked from outside of the UI thread
10246 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010247 *
10248 * @param action The Runnable that will be executed.
10249 * @param delayMillis The delay (in milliseconds) until the Runnable
10250 * will be executed.
10251 *
10252 * @return true if the Runnable was successfully placed in to the
10253 * message queue. Returns false on failure, usually because the
10254 * looper processing the message queue is exiting. Note that a
10255 * result of true does not mean the Runnable will be processed --
10256 * if the looper is quit before the delivery time of the message
10257 * occurs then the message will be dropped.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010258 *
10259 * @see #post
10260 * @see #removeCallbacks
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 */
10262 public boolean postDelayed(Runnable action, long delayMillis) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010263 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010264 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010265 return attachInfo.mHandler.postDelayed(action, delayMillis);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 }
Jeff Browna175a5b2012-02-15 19:18:31 -080010267 // Assume that post will succeed later
10268 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10269 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010270 }
10271
10272 /**
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010273 * <p>Causes the Runnable to execute on the next animation time step.
10274 * The runnable will be run on the user interface thread.</p>
10275 *
10276 * <p>This method can be invoked from outside of the UI thread
10277 * only when this View is attached to a window.</p>
10278 *
10279 * @param action The Runnable that will be executed.
10280 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010281 * @see #postOnAnimationDelayed
10282 * @see #removeCallbacks
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010283 */
10284 public void postOnAnimation(Runnable action) {
10285 final AttachInfo attachInfo = mAttachInfo;
10286 if (attachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010287 attachInfo.mViewRootImpl.mChoreographer.postCallback(
10288 Choreographer.CALLBACK_ANIMATION, action, null);
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010289 } else {
10290 // Assume that post will succeed later
10291 ViewRootImpl.getRunQueue().post(action);
10292 }
10293 }
10294
10295 /**
10296 * <p>Causes the Runnable to execute on the next animation time step,
10297 * after the specified amount of time elapses.
10298 * The runnable will be run on the user interface thread.</p>
10299 *
10300 * <p>This method can be invoked from outside of the UI thread
10301 * only when this View is attached to a window.</p>
10302 *
10303 * @param action The Runnable that will be executed.
10304 * @param delayMillis The delay (in milliseconds) until the Runnable
10305 * will be executed.
10306 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010307 * @see #postOnAnimation
10308 * @see #removeCallbacks
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010309 */
10310 public void postOnAnimationDelayed(Runnable action, long delayMillis) {
10311 final AttachInfo attachInfo = mAttachInfo;
10312 if (attachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010313 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
10314 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010315 } else {
10316 // Assume that post will succeed later
10317 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10318 }
10319 }
10320
10321 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010322 * <p>Removes the specified Runnable from the message queue.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010323 *
Romain Guye63a4f32011-08-11 11:33:31 -070010324 * <p>This method can be invoked from outside of the UI thread
10325 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010326 *
10327 * @param action The Runnable to remove from the message handling queue
10328 *
10329 * @return true if this view could ask the Handler to remove the Runnable,
10330 * false otherwise. When the returned value is true, the Runnable
10331 * may or may not have been actually removed from the message queue
10332 * (for instance, if the Runnable was not in the queue already.)
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010333 *
10334 * @see #post
10335 * @see #postDelayed
10336 * @see #postOnAnimation
10337 * @see #postOnAnimationDelayed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 */
10339 public boolean removeCallbacks(Runnable action) {
Jeff Brown43ea54b2012-03-09 14:37:48 -080010340 if (action != null) {
10341 final AttachInfo attachInfo = mAttachInfo;
10342 if (attachInfo != null) {
10343 attachInfo.mHandler.removeCallbacks(action);
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010344 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
10345 Choreographer.CALLBACK_ANIMATION, action, null);
Jeff Brown43ea54b2012-03-09 14:37:48 -080010346 } else {
10347 // Assume that post will succeed later
10348 ViewRootImpl.getRunQueue().removeCallbacks(action);
10349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 return true;
10352 }
10353
10354 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010355 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
10356 * Use this to invalidate the View from a non-UI thread.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 *
Romain Guye63a4f32011-08-11 11:33:31 -070010358 * <p>This method can be invoked from outside of the UI thread
10359 * only when this View is attached to a window.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010360 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 * @see #invalidate()
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010362 * @see #postInvalidateDelayed(long)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 */
10364 public void postInvalidate() {
10365 postInvalidateDelayed(0);
10366 }
10367
10368 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010369 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10370 * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010371 *
Romain Guye63a4f32011-08-11 11:33:31 -070010372 * <p>This method can be invoked from outside of the UI thread
10373 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010374 *
10375 * @param left The left coordinate of the rectangle to invalidate.
10376 * @param top The top coordinate of the rectangle to invalidate.
10377 * @param right The right coordinate of the rectangle to invalidate.
10378 * @param bottom The bottom coordinate of the rectangle to invalidate.
10379 *
10380 * @see #invalidate(int, int, int, int)
10381 * @see #invalidate(Rect)
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010382 * @see #postInvalidateDelayed(long, int, int, int, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 */
10384 public void postInvalidate(int left, int top, int right, int bottom) {
10385 postInvalidateDelayed(0, left, top, right, bottom);
10386 }
10387
10388 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010389 * <p>Cause an invalidate to happen on a subsequent cycle through the event
10390 * loop. Waits for the specified amount of time.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010391 *
Romain Guye63a4f32011-08-11 11:33:31 -070010392 * <p>This method can be invoked from outside of the UI thread
10393 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 *
10395 * @param delayMilliseconds the duration in milliseconds to delay the
10396 * invalidation by
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010397 *
10398 * @see #invalidate()
10399 * @see #postInvalidate()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400 */
10401 public void postInvalidateDelayed(long delayMilliseconds) {
10402 // We try only with the AttachInfo because there's no point in invalidating
10403 // if we are not attached to our window
Jeff Browna175a5b2012-02-15 19:18:31 -080010404 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010405 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010406 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 }
10408 }
10409
10410 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010411 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10412 * through the event loop. Waits for the specified amount of time.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010413 *
Romain Guye63a4f32011-08-11 11:33:31 -070010414 * <p>This method can be invoked from outside of the UI thread
10415 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 *
10417 * @param delayMilliseconds the duration in milliseconds to delay the
10418 * invalidation by
10419 * @param left The left coordinate of the rectangle to invalidate.
10420 * @param top The top coordinate of the rectangle to invalidate.
10421 * @param right The right coordinate of the rectangle to invalidate.
10422 * @param bottom The bottom coordinate of the rectangle to invalidate.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010423 *
10424 * @see #invalidate(int, int, int, int)
10425 * @see #invalidate(Rect)
10426 * @see #postInvalidate(int, int, int, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 */
10428 public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
10429 int right, int bottom) {
10430
10431 // We try only with the AttachInfo because there's no point in invalidating
10432 // if we are not attached to our window
Jeff Browna175a5b2012-02-15 19:18:31 -080010433 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010434 if (attachInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10436 info.target = this;
10437 info.left = left;
10438 info.top = top;
10439 info.right = right;
10440 info.bottom = bottom;
10441
Jeff Browna175a5b2012-02-15 19:18:31 -080010442 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 }
10444 }
10445
10446 /**
Jeff Brown6cb7b462012-03-05 13:21:17 -080010447 * <p>Cause an invalidate to happen on the next animation time step, typically the
10448 * next display frame.</p>
10449 *
10450 * <p>This method can be invoked from outside of the UI thread
10451 * only when this View is attached to a window.</p>
10452 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010453 * @see #invalidate()
Jeff Brown6cb7b462012-03-05 13:21:17 -080010454 */
10455 public void postInvalidateOnAnimation() {
10456 // We try only with the AttachInfo because there's no point in invalidating
10457 // if we are not attached to our window
10458 final AttachInfo attachInfo = mAttachInfo;
10459 if (attachInfo != null) {
10460 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
10461 }
10462 }
10463
10464 /**
10465 * <p>Cause an invalidate of the specified area to happen on the next animation
10466 * time step, typically the next display frame.</p>
10467 *
10468 * <p>This method can be invoked from outside of the UI thread
10469 * only when this View is attached to a window.</p>
10470 *
10471 * @param left The left coordinate of the rectangle to invalidate.
10472 * @param top The top coordinate of the rectangle to invalidate.
10473 * @param right The right coordinate of the rectangle to invalidate.
10474 * @param bottom The bottom coordinate of the rectangle to invalidate.
10475 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010476 * @see #invalidate(int, int, int, int)
10477 * @see #invalidate(Rect)
Jeff Brown6cb7b462012-03-05 13:21:17 -080010478 */
10479 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
10480 // We try only with the AttachInfo because there's no point in invalidating
10481 // if we are not attached to our window
10482 final AttachInfo attachInfo = mAttachInfo;
10483 if (attachInfo != null) {
10484 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10485 info.target = this;
10486 info.left = left;
10487 info.top = top;
10488 info.right = right;
10489 info.bottom = bottom;
10490
10491 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
10492 }
10493 }
10494
10495 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -070010496 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
10497 * This event is sent at most once every
10498 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
10499 */
10500 private void postSendViewScrolledAccessibilityEventCallback() {
10501 if (mSendViewScrolledAccessibilityEvent == null) {
10502 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
10503 }
10504 if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
10505 mSendViewScrolledAccessibilityEvent.mIsPending = true;
10506 postDelayed(mSendViewScrolledAccessibilityEvent,
10507 ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
10508 }
10509 }
10510
10511 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 * Called by a parent to request that a child update its values for mScrollX
10513 * and mScrollY if necessary. This will typically be done if the child is
10514 * animating a scroll using a {@link android.widget.Scroller Scroller}
10515 * object.
10516 */
10517 public void computeScroll() {
10518 }
10519
10520 /**
10521 * <p>Indicate whether the horizontal edges are faded when the view is
10522 * scrolled horizontally.</p>
10523 *
10524 * @return true if the horizontal edges should are faded on scroll, false
10525 * otherwise
10526 *
10527 * @see #setHorizontalFadingEdgeEnabled(boolean)
Philip Milne6c8ea062012-04-03 17:38:43 -070010528 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010529 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010530 */
10531 public boolean isHorizontalFadingEdgeEnabled() {
10532 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
10533 }
10534
10535 /**
10536 * <p>Define whether the horizontal edges should be faded when this view
10537 * is scrolled horizontally.</p>
10538 *
10539 * @param horizontalFadingEdgeEnabled true if the horizontal edges should
10540 * be faded when the view is scrolled
10541 * horizontally
10542 *
10543 * @see #isHorizontalFadingEdgeEnabled()
Philip Milne6c8ea062012-04-03 17:38:43 -070010544 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010545 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 */
10547 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
10548 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
10549 if (horizontalFadingEdgeEnabled) {
10550 initScrollCache();
10551 }
10552
10553 mViewFlags ^= FADING_EDGE_HORIZONTAL;
10554 }
10555 }
10556
10557 /**
10558 * <p>Indicate whether the vertical edges are faded when the view is
10559 * scrolled horizontally.</p>
10560 *
10561 * @return true if the vertical edges should are faded on scroll, false
10562 * otherwise
10563 *
10564 * @see #setVerticalFadingEdgeEnabled(boolean)
Philip Milne6c8ea062012-04-03 17:38:43 -070010565 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010566 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010567 */
10568 public boolean isVerticalFadingEdgeEnabled() {
10569 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
10570 }
10571
10572 /**
10573 * <p>Define whether the vertical edges should be faded when this view
10574 * is scrolled vertically.</p>
10575 *
10576 * @param verticalFadingEdgeEnabled true if the vertical edges should
10577 * be faded when the view is scrolled
10578 * vertically
10579 *
10580 * @see #isVerticalFadingEdgeEnabled()
Philip Milne6c8ea062012-04-03 17:38:43 -070010581 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010582 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 */
10584 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
10585 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
10586 if (verticalFadingEdgeEnabled) {
10587 initScrollCache();
10588 }
10589
10590 mViewFlags ^= FADING_EDGE_VERTICAL;
10591 }
10592 }
10593
10594 /**
10595 * Returns the strength, or intensity, of the top faded edge. The strength is
10596 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10597 * returns 0.0 or 1.0 but no value in between.
10598 *
10599 * Subclasses should override this method to provide a smoother fade transition
10600 * when scrolling occurs.
10601 *
10602 * @return the intensity of the top fade as a float between 0.0f and 1.0f
10603 */
10604 protected float getTopFadingEdgeStrength() {
10605 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
10606 }
10607
10608 /**
10609 * Returns the strength, or intensity, of the bottom faded edge. The strength is
10610 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10611 * returns 0.0 or 1.0 but no value in between.
10612 *
10613 * Subclasses should override this method to provide a smoother fade transition
10614 * when scrolling occurs.
10615 *
10616 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
10617 */
10618 protected float getBottomFadingEdgeStrength() {
10619 return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
10620 computeVerticalScrollRange() ? 1.0f : 0.0f;
10621 }
10622
10623 /**
10624 * Returns the strength, or intensity, of the left faded edge. The strength is
10625 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10626 * returns 0.0 or 1.0 but no value in between.
10627 *
10628 * Subclasses should override this method to provide a smoother fade transition
10629 * when scrolling occurs.
10630 *
10631 * @return the intensity of the left fade as a float between 0.0f and 1.0f
10632 */
10633 protected float getLeftFadingEdgeStrength() {
10634 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
10635 }
10636
10637 /**
10638 * Returns the strength, or intensity, of the right faded edge. The strength is
10639 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10640 * returns 0.0 or 1.0 but no value in between.
10641 *
10642 * Subclasses should override this method to provide a smoother fade transition
10643 * when scrolling occurs.
10644 *
10645 * @return the intensity of the right fade as a float between 0.0f and 1.0f
10646 */
10647 protected float getRightFadingEdgeStrength() {
10648 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
10649 computeHorizontalScrollRange() ? 1.0f : 0.0f;
10650 }
10651
10652 /**
10653 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
10654 * scrollbar is not drawn by default.</p>
10655 *
10656 * @return true if the horizontal scrollbar should be painted, false
10657 * otherwise
10658 *
10659 * @see #setHorizontalScrollBarEnabled(boolean)
10660 */
10661 public boolean isHorizontalScrollBarEnabled() {
10662 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
10663 }
10664
10665 /**
10666 * <p>Define whether the horizontal scrollbar should be drawn or not. The
10667 * scrollbar is not drawn by default.</p>
10668 *
10669 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
10670 * be painted
10671 *
10672 * @see #isHorizontalScrollBarEnabled()
10673 */
10674 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
10675 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
10676 mViewFlags ^= SCROLLBARS_HORIZONTAL;
Romain Guy8f1344f52009-05-15 16:03:59 -070010677 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010678 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 }
10680 }
10681
10682 /**
10683 * <p>Indicate whether the vertical scrollbar should be drawn or not. The
10684 * scrollbar is not drawn by default.</p>
10685 *
10686 * @return true if the vertical scrollbar should be painted, false
10687 * otherwise
10688 *
10689 * @see #setVerticalScrollBarEnabled(boolean)
10690 */
10691 public boolean isVerticalScrollBarEnabled() {
10692 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
10693 }
10694
10695 /**
10696 * <p>Define whether the vertical scrollbar should be drawn or not. The
10697 * scrollbar is not drawn by default.</p>
10698 *
10699 * @param verticalScrollBarEnabled true if the vertical scrollbar should
10700 * be painted
10701 *
10702 * @see #isVerticalScrollBarEnabled()
10703 */
10704 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
10705 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
10706 mViewFlags ^= SCROLLBARS_VERTICAL;
Romain Guy8f1344f52009-05-15 16:03:59 -070010707 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010708 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 }
10710 }
10711
Adam Powell20232d02010-12-08 21:08:53 -080010712 /**
10713 * @hide
10714 */
10715 protected void recomputePadding() {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070010716 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010717 }
Joe Malin32736f02011-01-19 16:14:20 -080010718
Mike Cleronfe81d382009-09-28 14:22:16 -070010719 /**
10720 * Define whether scrollbars will fade when the view is not scrolling.
Joe Malin32736f02011-01-19 16:14:20 -080010721 *
Mike Cleronfe81d382009-09-28 14:22:16 -070010722 * @param fadeScrollbars wheter to enable fading
Joe Malin32736f02011-01-19 16:14:20 -080010723 *
Philip Milne6c8ea062012-04-03 17:38:43 -070010724 * @attr ref android.R.styleable#View_fadeScrollbars
Mike Cleronfe81d382009-09-28 14:22:16 -070010725 */
10726 public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
10727 initScrollCache();
10728 final ScrollabilityCache scrollabilityCache = mScrollCache;
10729 scrollabilityCache.fadeScrollBars = fadeScrollbars;
Mike Cleron52f0a642009-09-28 18:21:37 -070010730 if (fadeScrollbars) {
10731 scrollabilityCache.state = ScrollabilityCache.OFF;
10732 } else {
Mike Cleronfe81d382009-09-28 14:22:16 -070010733 scrollabilityCache.state = ScrollabilityCache.ON;
10734 }
10735 }
Joe Malin32736f02011-01-19 16:14:20 -080010736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 /**
Joe Malin32736f02011-01-19 16:14:20 -080010738 *
Mike Cleron52f0a642009-09-28 18:21:37 -070010739 * Returns true if scrollbars will fade when this view is not scrolling
Joe Malin32736f02011-01-19 16:14:20 -080010740 *
Mike Cleron52f0a642009-09-28 18:21:37 -070010741 * @return true if scrollbar fading is enabled
Philip Milne6c8ea062012-04-03 17:38:43 -070010742 *
10743 * @attr ref android.R.styleable#View_fadeScrollbars
Mike Cleron52f0a642009-09-28 18:21:37 -070010744 */
10745 public boolean isScrollbarFadingEnabled() {
Joe Malin32736f02011-01-19 16:14:20 -080010746 return mScrollCache != null && mScrollCache.fadeScrollBars;
Mike Cleron52f0a642009-09-28 18:21:37 -070010747 }
Joe Malin32736f02011-01-19 16:14:20 -080010748
Mike Cleron52f0a642009-09-28 18:21:37 -070010749 /**
Philip Milne6c8ea062012-04-03 17:38:43 -070010750 *
10751 * Returns the delay before scrollbars fade.
10752 *
10753 * @return the delay before scrollbars fade
10754 *
10755 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10756 */
10757 public int getScrollBarDefaultDelayBeforeFade() {
10758 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
10759 mScrollCache.scrollBarDefaultDelayBeforeFade;
10760 }
10761
10762 /**
10763 * Define the delay before scrollbars fade.
10764 *
10765 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
10766 *
10767 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10768 */
10769 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
10770 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
10771 }
10772
10773 /**
10774 *
10775 * Returns the scrollbar fade duration.
10776 *
10777 * @return the scrollbar fade duration
10778 *
10779 * @attr ref android.R.styleable#View_scrollbarFadeDuration
10780 */
10781 public int getScrollBarFadeDuration() {
10782 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
10783 mScrollCache.scrollBarFadeDuration;
10784 }
10785
10786 /**
10787 * Define the scrollbar fade duration.
10788 *
10789 * @param scrollBarFadeDuration - the scrollbar fade duration
10790 *
10791 * @attr ref android.R.styleable#View_scrollbarFadeDuration
10792 */
10793 public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
10794 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
10795 }
10796
10797 /**
10798 *
10799 * Returns the scrollbar size.
10800 *
10801 * @return the scrollbar size
10802 *
10803 * @attr ref android.R.styleable#View_scrollbarSize
10804 */
10805 public int getScrollBarSize() {
Romain Guyeb378892012-04-12 11:33:14 -070010806 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
Philip Milne6c8ea062012-04-03 17:38:43 -070010807 mScrollCache.scrollBarSize;
10808 }
10809
10810 /**
10811 * Define the scrollbar size.
10812 *
10813 * @param scrollBarSize - the scrollbar size
10814 *
10815 * @attr ref android.R.styleable#View_scrollbarSize
10816 */
10817 public void setScrollBarSize(int scrollBarSize) {
10818 getScrollCache().scrollBarSize = scrollBarSize;
10819 }
10820
10821 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
10823 * inset. When inset, they add to the padding of the view. And the scrollbars
10824 * can be drawn inside the padding area or on the edge of the view. For example,
10825 * if a view has a background drawable and you want to draw the scrollbars
10826 * inside the padding specified by the drawable, you can use
10827 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
10828 * appear at the edge of the view, ignoring the padding, then you can use
10829 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
10830 * @param style the style of the scrollbars. Should be one of
10831 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
10832 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
10833 * @see #SCROLLBARS_INSIDE_OVERLAY
10834 * @see #SCROLLBARS_INSIDE_INSET
10835 * @see #SCROLLBARS_OUTSIDE_OVERLAY
10836 * @see #SCROLLBARS_OUTSIDE_INSET
Philip Milne6c8ea062012-04-03 17:38:43 -070010837 *
10838 * @attr ref android.R.styleable#View_scrollbarStyle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 */
10840 public void setScrollBarStyle(int style) {
10841 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
10842 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
Romain Guy8f1344f52009-05-15 16:03:59 -070010843 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010844 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010845 }
10846 }
10847
10848 /**
10849 * <p>Returns the current scrollbar style.</p>
10850 * @return the current scrollbar style
10851 * @see #SCROLLBARS_INSIDE_OVERLAY
10852 * @see #SCROLLBARS_INSIDE_INSET
10853 * @see #SCROLLBARS_OUTSIDE_OVERLAY
10854 * @see #SCROLLBARS_OUTSIDE_INSET
Philip Milne6c8ea062012-04-03 17:38:43 -070010855 *
10856 * @attr ref android.R.styleable#View_scrollbarStyle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857 */
Jeff Sharkey010d7e52011-08-08 21:05:02 -070010858 @ViewDebug.ExportedProperty(mapping = {
10859 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
10860 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
10861 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
10862 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
10863 })
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 public int getScrollBarStyle() {
10865 return mViewFlags & SCROLLBARS_STYLE_MASK;
10866 }
10867
10868 /**
10869 * <p>Compute the horizontal range that the horizontal scrollbar
10870 * represents.</p>
10871 *
10872 * <p>The range is expressed in arbitrary units that must be the same as the
10873 * units used by {@link #computeHorizontalScrollExtent()} and
10874 * {@link #computeHorizontalScrollOffset()}.</p>
10875 *
10876 * <p>The default range is the drawing width of this view.</p>
10877 *
10878 * @return the total horizontal range represented by the horizontal
10879 * scrollbar
10880 *
10881 * @see #computeHorizontalScrollExtent()
10882 * @see #computeHorizontalScrollOffset()
10883 * @see android.widget.ScrollBarDrawable
10884 */
10885 protected int computeHorizontalScrollRange() {
10886 return getWidth();
10887 }
10888
10889 /**
10890 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
10891 * within the horizontal range. This value is used to compute the position
10892 * of the thumb within the scrollbar's track.</p>
10893 *
10894 * <p>The range is expressed in arbitrary units that must be the same as the
10895 * units used by {@link #computeHorizontalScrollRange()} and
10896 * {@link #computeHorizontalScrollExtent()}.</p>
10897 *
10898 * <p>The default offset is the scroll offset of this view.</p>
10899 *
10900 * @return the horizontal offset of the scrollbar's thumb
10901 *
10902 * @see #computeHorizontalScrollRange()
10903 * @see #computeHorizontalScrollExtent()
10904 * @see android.widget.ScrollBarDrawable
10905 */
10906 protected int computeHorizontalScrollOffset() {
10907 return mScrollX;
10908 }
10909
10910 /**
10911 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
10912 * within the horizontal range. This value is used to compute the length
10913 * of the thumb within the scrollbar's track.</p>
10914 *
10915 * <p>The range is expressed in arbitrary units that must be the same as the
10916 * units used by {@link #computeHorizontalScrollRange()} and
10917 * {@link #computeHorizontalScrollOffset()}.</p>
10918 *
10919 * <p>The default extent is the drawing width of this view.</p>
10920 *
10921 * @return the horizontal extent of the scrollbar's thumb
10922 *
10923 * @see #computeHorizontalScrollRange()
10924 * @see #computeHorizontalScrollOffset()
10925 * @see android.widget.ScrollBarDrawable
10926 */
10927 protected int computeHorizontalScrollExtent() {
10928 return getWidth();
10929 }
10930
10931 /**
10932 * <p>Compute the vertical range that the vertical scrollbar represents.</p>
10933 *
10934 * <p>The range is expressed in arbitrary units that must be the same as the
10935 * units used by {@link #computeVerticalScrollExtent()} and
10936 * {@link #computeVerticalScrollOffset()}.</p>
10937 *
10938 * @return the total vertical range represented by the vertical scrollbar
10939 *
10940 * <p>The default range is the drawing height of this view.</p>
10941 *
10942 * @see #computeVerticalScrollExtent()
10943 * @see #computeVerticalScrollOffset()
10944 * @see android.widget.ScrollBarDrawable
10945 */
10946 protected int computeVerticalScrollRange() {
10947 return getHeight();
10948 }
10949
10950 /**
10951 * <p>Compute the vertical offset of the vertical scrollbar's thumb
10952 * within the horizontal range. This value is used to compute the position
10953 * of the thumb within the scrollbar's track.</p>
10954 *
10955 * <p>The range is expressed in arbitrary units that must be the same as the
10956 * units used by {@link #computeVerticalScrollRange()} and
10957 * {@link #computeVerticalScrollExtent()}.</p>
10958 *
10959 * <p>The default offset is the scroll offset of this view.</p>
10960 *
10961 * @return the vertical offset of the scrollbar's thumb
10962 *
10963 * @see #computeVerticalScrollRange()
10964 * @see #computeVerticalScrollExtent()
10965 * @see android.widget.ScrollBarDrawable
10966 */
10967 protected int computeVerticalScrollOffset() {
10968 return mScrollY;
10969 }
10970
10971 /**
10972 * <p>Compute the vertical extent of the horizontal scrollbar's thumb
10973 * within the vertical range. This value is used to compute the length
10974 * of the thumb within the scrollbar's track.</p>
10975 *
10976 * <p>The range is expressed in arbitrary units that must be the same as the
Gilles Debunne52964242010-02-24 11:05:19 -080010977 * units used by {@link #computeVerticalScrollRange()} and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 * {@link #computeVerticalScrollOffset()}.</p>
10979 *
10980 * <p>The default extent is the drawing height of this view.</p>
10981 *
10982 * @return the vertical extent of the scrollbar's thumb
10983 *
10984 * @see #computeVerticalScrollRange()
10985 * @see #computeVerticalScrollOffset()
10986 * @see android.widget.ScrollBarDrawable
10987 */
10988 protected int computeVerticalScrollExtent() {
10989 return getHeight();
10990 }
10991
10992 /**
Adam Powell69159442011-06-13 17:53:06 -070010993 * Check if this view can be scrolled horizontally in a certain direction.
10994 *
10995 * @param direction Negative to check scrolling left, positive to check scrolling right.
10996 * @return true if this view can be scrolled in the specified direction, false otherwise.
10997 */
10998 public boolean canScrollHorizontally(int direction) {
10999 final int offset = computeHorizontalScrollOffset();
11000 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
11001 if (range == 0) return false;
11002 if (direction < 0) {
11003 return offset > 0;
11004 } else {
11005 return offset < range - 1;
11006 }
11007 }
11008
11009 /**
11010 * Check if this view can be scrolled vertically in a certain direction.
11011 *
11012 * @param direction Negative to check scrolling up, positive to check scrolling down.
11013 * @return true if this view can be scrolled in the specified direction, false otherwise.
11014 */
11015 public boolean canScrollVertically(int direction) {
11016 final int offset = computeVerticalScrollOffset();
11017 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
11018 if (range == 0) return false;
11019 if (direction < 0) {
11020 return offset > 0;
11021 } else {
11022 return offset < range - 1;
11023 }
11024 }
11025
11026 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 * <p>Request the drawing of the horizontal and the vertical scrollbar. The
11028 * scrollbars are painted only if they have been awakened first.</p>
11029 *
11030 * @param canvas the canvas on which to draw the scrollbars
Joe Malin32736f02011-01-19 16:14:20 -080011031 *
Mike Cleronf116bf82009-09-27 19:14:12 -070011032 * @see #awakenScrollBars(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 */
Romain Guy1d5b3a62009-11-05 18:44:12 -080011034 protected final void onDrawScrollBars(Canvas canvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 // scrollbars are drawn only when the animation is running
11036 final ScrollabilityCache cache = mScrollCache;
11037 if (cache != null) {
Joe Malin32736f02011-01-19 16:14:20 -080011038
Mike Cleronf116bf82009-09-27 19:14:12 -070011039 int state = cache.state;
Joe Malin32736f02011-01-19 16:14:20 -080011040
Mike Cleronf116bf82009-09-27 19:14:12 -070011041 if (state == ScrollabilityCache.OFF) {
11042 return;
11043 }
Joe Malin32736f02011-01-19 16:14:20 -080011044
Mike Cleronf116bf82009-09-27 19:14:12 -070011045 boolean invalidate = false;
Joe Malin32736f02011-01-19 16:14:20 -080011046
Mike Cleronf116bf82009-09-27 19:14:12 -070011047 if (state == ScrollabilityCache.FADING) {
11048 // We're fading -- get our fade interpolation
11049 if (cache.interpolatorValues == null) {
11050 cache.interpolatorValues = new float[1];
11051 }
Joe Malin32736f02011-01-19 16:14:20 -080011052
Mike Cleronf116bf82009-09-27 19:14:12 -070011053 float[] values = cache.interpolatorValues;
Joe Malin32736f02011-01-19 16:14:20 -080011054
Mike Cleronf116bf82009-09-27 19:14:12 -070011055 // Stops the animation if we're done
11056 if (cache.scrollBarInterpolator.timeToValues(values) ==
11057 Interpolator.Result.FREEZE_END) {
11058 cache.state = ScrollabilityCache.OFF;
11059 } else {
11060 cache.scrollBar.setAlpha(Math.round(values[0]));
11061 }
Joe Malin32736f02011-01-19 16:14:20 -080011062
11063 // This will make the scroll bars inval themselves after
Mike Cleronf116bf82009-09-27 19:14:12 -070011064 // drawing. We only want this when we're fading so that
11065 // we prevent excessive redraws
11066 invalidate = true;
11067 } else {
11068 // We're just on -- but we may have been fading before so
11069 // reset alpha
11070 cache.scrollBar.setAlpha(255);
11071 }
11072
Joe Malin32736f02011-01-19 16:14:20 -080011073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074 final int viewFlags = mViewFlags;
11075
11076 final boolean drawHorizontalScrollBar =
11077 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11078 final boolean drawVerticalScrollBar =
11079 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
11080 && !isVerticalScrollBarHidden();
11081
11082 if (drawVerticalScrollBar || drawHorizontalScrollBar) {
11083 final int width = mRight - mLeft;
11084 final int height = mBottom - mTop;
11085
11086 final ScrollBarDrawable scrollBar = cache.scrollBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087
Mike Reede8853fc2009-09-04 14:01:48 -040011088 final int scrollX = mScrollX;
11089 final int scrollY = mScrollY;
11090 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
11091
Mike Cleronf116bf82009-09-27 19:14:12 -070011092 int left, top, right, bottom;
Joe Malin32736f02011-01-19 16:14:20 -080011093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011094 if (drawHorizontalScrollBar) {
Adam Powell3ba67742011-01-27 14:16:55 -080011095 int size = scrollBar.getSize(false);
11096 if (size <= 0) {
11097 size = cache.scrollBarSize;
11098 }
11099
Mike Cleronf116bf82009-09-27 19:14:12 -070011100 scrollBar.setParameters(computeHorizontalScrollRange(),
Mike Reede8853fc2009-09-04 14:01:48 -040011101 computeHorizontalScrollOffset(),
11102 computeHorizontalScrollExtent(), false);
Mike Reede8853fc2009-09-04 14:01:48 -040011103 final int verticalScrollBarGap = drawVerticalScrollBar ?
Mike Cleronf116bf82009-09-27 19:14:12 -070011104 getVerticalScrollbarWidth() : 0;
Joe Malin32736f02011-01-19 16:14:20 -080011105 top = scrollY + height - size - (mUserPaddingBottom & inside);
Mike Cleronf116bf82009-09-27 19:14:12 -070011106 left = scrollX + (mPaddingLeft & inside);
11107 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
11108 bottom = top + size;
11109 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
11110 if (invalidate) {
11111 invalidate(left, top, right, bottom);
11112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 }
11114
11115 if (drawVerticalScrollBar) {
Adam Powell3ba67742011-01-27 14:16:55 -080011116 int size = scrollBar.getSize(true);
11117 if (size <= 0) {
11118 size = cache.scrollBarSize;
11119 }
11120
Mike Reede8853fc2009-09-04 14:01:48 -040011121 scrollBar.setParameters(computeVerticalScrollRange(),
11122 computeVerticalScrollOffset(),
11123 computeVerticalScrollExtent(), true);
Fabrice Di Meglioc91b6ca2012-06-22 14:51:15 -070011124 int verticalScrollbarPosition = mVerticalScrollbarPosition;
11125 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
11126 verticalScrollbarPosition = isLayoutRtl() ?
11127 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
11128 }
11129 switch (verticalScrollbarPosition) {
Adam Powell20232d02010-12-08 21:08:53 -080011130 default:
Adam Powell20232d02010-12-08 21:08:53 -080011131 case SCROLLBAR_POSITION_RIGHT:
11132 left = scrollX + width - size - (mUserPaddingRight & inside);
11133 break;
11134 case SCROLLBAR_POSITION_LEFT:
11135 left = scrollX + (mUserPaddingLeft & inside);
11136 break;
11137 }
Mike Cleronf116bf82009-09-27 19:14:12 -070011138 top = scrollY + (mPaddingTop & inside);
11139 right = left + size;
11140 bottom = scrollY + height - (mUserPaddingBottom & inside);
11141 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
11142 if (invalidate) {
11143 invalidate(left, top, right, bottom);
11144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 }
11146 }
11147 }
11148 }
Romain Guy8506ab42009-06-11 17:35:47 -070011149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 /**
Romain Guy8506ab42009-06-11 17:35:47 -070011151 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 * FastScroller is visible.
11153 * @return whether to temporarily hide the vertical scrollbar
11154 * @hide
11155 */
11156 protected boolean isVerticalScrollBarHidden() {
11157 return false;
11158 }
11159
11160 /**
11161 * <p>Draw the horizontal scrollbar if
11162 * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
11163 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 * @param canvas the canvas on which to draw the scrollbar
11165 * @param scrollBar the scrollbar's drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 *
11167 * @see #isHorizontalScrollBarEnabled()
11168 * @see #computeHorizontalScrollRange()
11169 * @see #computeHorizontalScrollExtent()
11170 * @see #computeHorizontalScrollOffset()
11171 * @see android.widget.ScrollBarDrawable
Mike Cleronf116bf82009-09-27 19:14:12 -070011172 * @hide
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011173 */
Romain Guy8fb95422010-08-17 18:38:51 -070011174 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
11175 int l, int t, int r, int b) {
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011176 scrollBar.setBounds(l, t, r, b);
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011177 scrollBar.draw(canvas);
11178 }
Mike Reede8853fc2009-09-04 14:01:48 -040011179
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011180 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
11182 * returns true.</p>
11183 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 * @param canvas the canvas on which to draw the scrollbar
11185 * @param scrollBar the scrollbar's drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 *
11187 * @see #isVerticalScrollBarEnabled()
11188 * @see #computeVerticalScrollRange()
11189 * @see #computeVerticalScrollExtent()
11190 * @see #computeVerticalScrollOffset()
11191 * @see android.widget.ScrollBarDrawable
Mike Reede8853fc2009-09-04 14:01:48 -040011192 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011193 */
Romain Guy8fb95422010-08-17 18:38:51 -070011194 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
11195 int l, int t, int r, int b) {
Mike Reede8853fc2009-09-04 14:01:48 -040011196 scrollBar.setBounds(l, t, r, b);
11197 scrollBar.draw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 }
11199
11200 /**
11201 * Implement this to do your drawing.
11202 *
11203 * @param canvas the canvas on which the background will be drawn
11204 */
11205 protected void onDraw(Canvas canvas) {
11206 }
11207
11208 /*
11209 * Caller is responsible for calling requestLayout if necessary.
11210 * (This allows addViewInLayout to not request a new layout.)
11211 */
11212 void assignParent(ViewParent parent) {
11213 if (mParent == null) {
11214 mParent = parent;
11215 } else if (parent == null) {
11216 mParent = null;
11217 } else {
11218 throw new RuntimeException("view " + this + " being added, but"
11219 + " it already has a parent");
11220 }
11221 }
11222
11223 /**
11224 * This is called when the view is attached to a window. At this point it
11225 * has a Surface and will start drawing. Note that this function is
Romain Guy5c22a8c2011-05-13 11:48:45 -070011226 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
11227 * however it may be called any time before the first onDraw -- including
11228 * before or after {@link #onMeasure(int, int)}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 *
11230 * @see #onDetachedFromWindow()
11231 */
11232 protected void onAttachedToWindow() {
11233 if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
11234 mParent.requestTransparentRegion(this);
11235 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011236
Adam Powell8568c3a2010-04-19 14:26:11 -070011237 if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
11238 initialAwakenScrollBars();
11239 mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
11240 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011241
Chet Haasea9b61ac2010-12-20 07:40:25 -080011242 jumpDrawablesToCurrentState();
Romain Guy2a0f2282012-05-08 14:43:12 -070011243
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011244 resolveRtlProperties();
Romain Guy2a0f2282012-05-08 14:43:12 -070011245
Svetoslav Ganov42138042012-03-20 11:51:39 -070011246 clearAccessibilityFocus();
Amith Yamasani4503c8d2011-06-17 12:36:14 -070011247 if (isFocused()) {
11248 InputMethodManager imm = InputMethodManager.peekInstance();
11249 imm.focusIn(this);
11250 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011251
11252 if (mAttachInfo != null && mDisplayList != null) {
11253 mAttachInfo.mViewRootImpl.dequeueDisplayList(mDisplayList);
11254 }
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011255 }
Cibu Johny86666632010-02-22 13:01:02 -080011256
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011257 void resolveRtlProperties() {
11258 // Order is important here: LayoutDirection MUST be resolved first...
11259 resolveLayoutDirection();
11260 // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11261 resolvePadding();
11262 resolveLayoutParams();
11263 resolveTextDirection();
11264 resolveTextAlignment();
11265 }
11266
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011267 /**
Romain Guybb9908b2012-03-08 11:14:07 -080011268 * @see #onScreenStateChanged(int)
11269 */
11270 void dispatchScreenStateChanged(int screenState) {
11271 onScreenStateChanged(screenState);
11272 }
11273
11274 /**
11275 * This method is called whenever the state of the screen this view is
11276 * attached to changes. A state change will usually occurs when the screen
11277 * turns on or off (whether it happens automatically or the user does it
11278 * manually.)
11279 *
11280 * @param screenState The new state of the screen. Can be either
11281 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
11282 */
11283 public void onScreenStateChanged(int screenState) {
11284 }
11285
11286 /**
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011287 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
11288 */
11289 private boolean hasRtlSupport() {
11290 return mContext.getApplicationInfo().hasRtlSupport();
11291 }
11292
11293 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011294 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
11295 * that the parent directionality can and will be resolved before its children.
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011296 * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011297 */
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011298 public void resolveLayoutDirection() {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011299 // Clear any previous layout direction resolution
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -070011300 mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011301
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011302 if (hasRtlSupport()) {
11303 // Set resolved depending on layout direction
11304 switch (getLayoutDirection()) {
11305 case LAYOUT_DIRECTION_INHERIT:
Fabrice Di Megliob93911f2012-06-26 19:43:15 -070011306 // We cannot resolve yet. LTR is by default and let the resolution happen again
11307 // later to get the correct resolved value
11308 if (!canResolveLayoutDirection()) return;
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011309
Fabrice Di Megliob93911f2012-06-26 19:43:15 -070011310 ViewGroup viewGroup = ((ViewGroup) mParent);
11311
11312 // We cannot resolve yet on the parent too. LTR is by default and let the
11313 // resolution happen again later
11314 if (!viewGroup.canResolveLayoutDirection()) return;
11315
11316 if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11317 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011318 }
11319 break;
11320 case LAYOUT_DIRECTION_RTL:
11321 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
11322 break;
11323 case LAYOUT_DIRECTION_LOCALE:
11324 if(isLayoutDirectionRtl(Locale.getDefault())) {
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011325 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
11326 }
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011327 break;
11328 default:
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011329 // Nothing to do, LTR by default
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011330 }
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011331 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011332
11333 // Set to resolved
11334 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011335 onResolvedLayoutDirectionChanged();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011336 }
11337
Fabrice Di Meglioaff599b2011-07-20 19:05:01 -070011338 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011339 * Called when layout direction has been resolved.
11340 *
11341 * The default implementation does nothing.
11342 */
11343 public void onResolvedLayoutDirectionChanged() {
11344 }
11345
11346 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011347 * Return if padding has been resolved
11348 */
11349 boolean isPaddingResolved() {
11350 return (mPrivateFlags2 & PADDING_RESOLVED) != 0;
11351 }
11352
11353 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011354 * Resolve padding depending on layout direction.
Fabrice Di Meglioaff599b2011-07-20 19:05:01 -070011355 */
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011356 public void resolvePadding() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011357 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11358 if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
11359 // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
11360 // left / right padding are used if defined. If they are not defined and start / end
11361 // padding are defined (e.g. in Frameworks resources), then we use start / end and
11362 // resolve them as left / right (layout direction is not taken into account).
11363 if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
11364 mUserPaddingLeft = mUserPaddingStart;
11365 }
11366 if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
11367 mUserPaddingRight = mUserPaddingEnd;
11368 }
11369
11370 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11371
11372 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11373 mUserPaddingBottom);
11374 } else {
11375 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11376 // If start / end padding are defined, they will be resolved (hence overriding) to
11377 // left / right or right / left depending on the resolved layout direction.
11378 // If start / end padding are not defined, use the left / right ones.
11379 int resolvedLayoutDirection = getResolvedLayoutDirection();
11380 switch (resolvedLayoutDirection) {
11381 case LAYOUT_DIRECTION_RTL:
11382 if (mUserPaddingStart != UNDEFINED_PADDING) {
11383 mUserPaddingRight = mUserPaddingStart;
11384 }
11385 if (mUserPaddingEnd != UNDEFINED_PADDING) {
11386 mUserPaddingLeft = mUserPaddingEnd;
11387 }
11388 break;
11389 case LAYOUT_DIRECTION_LTR:
11390 default:
11391 if (mUserPaddingStart != UNDEFINED_PADDING) {
11392 mUserPaddingLeft = mUserPaddingStart;
11393 }
11394 if (mUserPaddingEnd != UNDEFINED_PADDING) {
11395 mUserPaddingRight = mUserPaddingEnd;
11396 }
11397 }
11398
11399 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11400
11401 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11402 mUserPaddingBottom);
11403 onPaddingChanged(resolvedLayoutDirection);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011404 }
11405
Adam Powell0090f202012-08-07 17:15:30 -070011406 mPrivateFlags2 |= PADDING_RESOLVED;
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011407 }
11408
11409 /**
11410 * Resolve padding depending on the layout direction. Subclasses that care about
11411 * padding resolution should override this method. The default implementation does
11412 * nothing.
11413 *
11414 * @param layoutDirection the direction of the layout
11415 *
Fabrice Di Meglioe8dc07d2012-03-09 17:10:19 -080011416 * @see {@link #LAYOUT_DIRECTION_LTR}
11417 * @see {@link #LAYOUT_DIRECTION_RTL}
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011418 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011419 public void onPaddingChanged(int layoutDirection) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011420 }
11421
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011422 /**
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011423 * Check if layout direction resolution can be done.
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011424 *
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011425 * @return true if layout direction resolution can be done otherwise return false.
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011426 */
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011427 public boolean canResolveLayoutDirection() {
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011428 switch (getLayoutDirection()) {
11429 case LAYOUT_DIRECTION_INHERIT:
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011430 return (mParent != null) && (mParent instanceof ViewGroup);
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011431 default:
11432 return true;
11433 }
11434 }
11435
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011436 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011437 * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
11438 * when reset is done.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011439 */
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011440 public void resetResolvedLayoutDirection() {
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -070011441 // Reset the current resolved bits
11442 mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011443 onResolvedLayoutDirectionReset();
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080011444 // Reset also the text direction
11445 resetResolvedTextDirection();
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011446 }
11447
11448 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011449 * Called during reset of resolved layout direction.
11450 *
11451 * Subclasses need to override this method to clear cached information that depends on the
11452 * resolved layout direction, or to inform child views that inherit their layout direction.
11453 *
11454 * The default implementation does nothing.
11455 */
11456 public void onResolvedLayoutDirectionReset() {
11457 }
11458
11459 /**
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011460 * Check if a Locale uses an RTL script.
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011461 *
11462 * @param locale Locale to check
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011463 * @return true if the Locale uses an RTL script.
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011464 */
Fabrice Di Meglio22268862011-06-27 18:13:18 -070011465 protected static boolean isLayoutDirectionRtl(Locale locale) {
Fabrice Di Meglio3fb824b2012-02-28 17:58:31 -080011466 return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 }
11468
11469 /**
11470 * This is called when the view is detached from a window. At this point it
11471 * no longer has a surface for drawing.
11472 *
11473 * @see #onAttachedToWindow()
11474 */
11475 protected void onDetachedFromWindow() {
Romain Guy8afa5152010-02-26 11:56:30 -080011476 mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
Romain Guy6c319ca2011-01-11 14:29:25 -080011477
Romain Guya440b002010-02-24 15:57:54 -080011478 removeUnsetPressCallback();
Maryam Garrett1549dd12009-12-15 16:06:36 -050011479 removeLongPressCallback();
Adam Powell3cb8b632011-01-21 15:34:14 -080011480 removePerformClickCallback();
Svetoslav Ganova0156172011-06-26 17:55:44 -070011481 removeSendViewScrolledAccessibilityEventCallback();
Romain Guy6c319ca2011-01-11 14:29:25 -080011482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483 destroyDrawingCache();
Romain Guy6c319ca2011-01-11 14:29:25 -080011484
Romain Guya998dff2012-03-23 18:58:36 -070011485 destroyLayer(false);
Romain Guy8dd5b1e2011-01-14 17:28:51 -080011486
11487 if (mAttachInfo != null) {
Romain Guy51e4d4d2012-03-15 18:30:47 -070011488 if (mDisplayList != null) {
Romain Guy2a0f2282012-05-08 14:43:12 -070011489 mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
Romain Guy51e4d4d2012-03-15 18:30:47 -070011490 }
Jeff Browna175a5b2012-02-15 19:18:31 -080011491 mAttachInfo.mViewRootImpl.cancelInvalidate(this);
Romain Guy51e4d4d2012-03-15 18:30:47 -070011492 } else {
Romain Guy38c2ece2012-05-24 14:20:56 -070011493 // Should never happen
11494 clearDisplayList();
Romain Guy8dd5b1e2011-01-14 17:28:51 -080011495 }
11496
Patrick Dubroyec84c3a2011-01-13 17:55:37 -080011497 mCurrentAnimation = null;
Fabrice Di Meglio7f86c802011-07-01 15:09:24 -070011498
11499 resetResolvedLayoutDirection();
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070011500 resetResolvedTextAlignment();
Svetoslav Ganov42138042012-03-20 11:51:39 -070011501 resetAccessibilityStateChanged();
Adam Powell0090f202012-08-07 17:15:30 -070011502 mPrivateFlags2 &= ~PADDING_RESOLVED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 }
11504
11505 /**
11506 * @return The number of times this view has been attached to a window
11507 */
11508 protected int getWindowAttachCount() {
11509 return mWindowAttachCount;
11510 }
11511
11512 /**
11513 * Retrieve a unique token identifying the window this view is attached to.
11514 * @return Return the window's token for use in
11515 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
11516 */
11517 public IBinder getWindowToken() {
11518 return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
11519 }
11520
11521 /**
11522 * Retrieve a unique token identifying the top-level "real" window of
11523 * the window that this view is attached to. That is, this is like
11524 * {@link #getWindowToken}, except if the window this view in is a panel
11525 * window (attached to another containing window), then the token of
11526 * the containing window is returned instead.
11527 *
11528 * @return Returns the associated window token, either
11529 * {@link #getWindowToken()} or the containing window's token.
11530 */
11531 public IBinder getApplicationWindowToken() {
11532 AttachInfo ai = mAttachInfo;
11533 if (ai != null) {
11534 IBinder appWindowToken = ai.mPanelParentWindowToken;
11535 if (appWindowToken == null) {
11536 appWindowToken = ai.mWindowToken;
11537 }
11538 return appWindowToken;
11539 }
11540 return null;
11541 }
11542
11543 /**
11544 * Retrieve private session object this view hierarchy is using to
11545 * communicate with the window manager.
11546 * @return the session object to communicate with the window manager
11547 */
11548 /*package*/ IWindowSession getWindowSession() {
11549 return mAttachInfo != null ? mAttachInfo.mSession : null;
11550 }
11551
11552 /**
11553 * @param info the {@link android.view.View.AttachInfo} to associated with
11554 * this view
11555 */
11556 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
11557 //System.out.println("Attached! " + this);
11558 mAttachInfo = info;
11559 mWindowAttachCount++;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080011560 // We will need to evaluate the drawable state at least once.
11561 mPrivateFlags |= DRAWABLE_STATE_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011562 if (mFloatingTreeObserver != null) {
11563 info.mTreeObserver.merge(mFloatingTreeObserver);
11564 mFloatingTreeObserver = null;
11565 }
11566 if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
11567 mAttachInfo.mScrollContainers.add(this);
11568 mPrivateFlags |= SCROLL_CONTAINER_ADDED;
11569 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070011570 performCollectViewAttributes(mAttachInfo, visibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 onAttachedToWindow();
Adam Powell4afd62b2011-02-18 15:02:18 -080011572
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011573 ListenerInfo li = mListenerInfo;
Adam Powell4afd62b2011-02-18 15:02:18 -080011574 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011575 li != null ? li.mOnAttachStateChangeListeners : null;
Adam Powell4afd62b2011-02-18 15:02:18 -080011576 if (listeners != null && listeners.size() > 0) {
11577 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11578 // perform the dispatching. The iterator is a safe guard against listeners that
11579 // could mutate the list by calling the various add/remove methods. This prevents
11580 // the array from being modified while we iterate it.
11581 for (OnAttachStateChangeListener listener : listeners) {
11582 listener.onViewAttachedToWindow(this);
11583 }
11584 }
11585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011586 int vis = info.mWindowVisibility;
11587 if (vis != GONE) {
11588 onWindowVisibilityChanged(vis);
11589 }
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080011590 if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
11591 // If nobody has evaluated the drawable state yet, then do it now.
11592 refreshDrawableState();
11593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 }
11595
11596 void dispatchDetachedFromWindow() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011597 AttachInfo info = mAttachInfo;
11598 if (info != null) {
11599 int vis = info.mWindowVisibility;
11600 if (vis != GONE) {
11601 onWindowVisibilityChanged(GONE);
11602 }
11603 }
11604
11605 onDetachedFromWindow();
Romain Guy01d5edc2011-01-28 11:28:53 -080011606
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011607 ListenerInfo li = mListenerInfo;
Adam Powell4afd62b2011-02-18 15:02:18 -080011608 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011609 li != null ? li.mOnAttachStateChangeListeners : null;
Adam Powell4afd62b2011-02-18 15:02:18 -080011610 if (listeners != null && listeners.size() > 0) {
11611 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11612 // perform the dispatching. The iterator is a safe guard against listeners that
11613 // could mutate the list by calling the various add/remove methods. This prevents
11614 // the array from being modified while we iterate it.
11615 for (OnAttachStateChangeListener listener : listeners) {
11616 listener.onViewDetachedFromWindow(this);
11617 }
11618 }
11619
Romain Guy01d5edc2011-01-28 11:28:53 -080011620 if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 mAttachInfo.mScrollContainers.remove(this);
11622 mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
11623 }
Romain Guy01d5edc2011-01-28 11:28:53 -080011624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 mAttachInfo = null;
11626 }
11627
11628 /**
11629 * Store this view hierarchy's frozen state into the given container.
11630 *
11631 * @param container The SparseArray in which to save the view's state.
11632 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011633 * @see #restoreHierarchyState(android.util.SparseArray)
11634 * @see #dispatchSaveInstanceState(android.util.SparseArray)
11635 * @see #onSaveInstanceState()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 */
11637 public void saveHierarchyState(SparseArray<Parcelable> container) {
11638 dispatchSaveInstanceState(container);
11639 }
11640
11641 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070011642 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
11643 * this view and its children. May be overridden to modify how freezing happens to a
11644 * view's children; for example, some views may want to not store state for their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 *
11646 * @param container The SparseArray in which to save the view's state.
11647 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011648 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11649 * @see #saveHierarchyState(android.util.SparseArray)
11650 * @see #onSaveInstanceState()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011651 */
11652 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
11653 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
11654 mPrivateFlags &= ~SAVE_STATE_CALLED;
11655 Parcelable state = onSaveInstanceState();
11656 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
11657 throw new IllegalStateException(
11658 "Derived class did not call super.onSaveInstanceState()");
11659 }
11660 if (state != null) {
11661 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
11662 // + ": " + state);
11663 container.put(mID, state);
11664 }
11665 }
11666 }
11667
11668 /**
11669 * Hook allowing a view to generate a representation of its internal state
11670 * that can later be used to create a new instance with that same state.
11671 * This state should only contain information that is not persistent or can
11672 * not be reconstructed later. For example, you will never store your
11673 * current position on screen because that will be computed again when a
11674 * new instance of the view is placed in its view hierarchy.
11675 * <p>
11676 * Some examples of things you may store here: the current cursor position
11677 * in a text view (but usually not the text itself since that is stored in a
11678 * content provider or other persistent storage), the currently selected
11679 * item in a list view.
11680 *
11681 * @return Returns a Parcelable object containing the view's current dynamic
11682 * state, or null if there is nothing interesting to save. The
11683 * default implementation returns null.
Philip Milne6c8ea062012-04-03 17:38:43 -070011684 * @see #onRestoreInstanceState(android.os.Parcelable)
11685 * @see #saveHierarchyState(android.util.SparseArray)
11686 * @see #dispatchSaveInstanceState(android.util.SparseArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 * @see #setSaveEnabled(boolean)
11688 */
11689 protected Parcelable onSaveInstanceState() {
11690 mPrivateFlags |= SAVE_STATE_CALLED;
11691 return BaseSavedState.EMPTY_STATE;
11692 }
11693
11694 /**
11695 * Restore this view hierarchy's frozen state from the given container.
11696 *
11697 * @param container The SparseArray which holds previously frozen states.
11698 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011699 * @see #saveHierarchyState(android.util.SparseArray)
11700 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11701 * @see #onRestoreInstanceState(android.os.Parcelable)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 */
11703 public void restoreHierarchyState(SparseArray<Parcelable> container) {
11704 dispatchRestoreInstanceState(container);
11705 }
11706
11707 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070011708 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
11709 * state for this view and its children. May be overridden to modify how restoring
11710 * happens to a view's children; for example, some views may want to not store state
11711 * for their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712 *
11713 * @param container The SparseArray which holds previously saved state.
11714 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011715 * @see #dispatchSaveInstanceState(android.util.SparseArray)
11716 * @see #restoreHierarchyState(android.util.SparseArray)
11717 * @see #onRestoreInstanceState(android.os.Parcelable)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 */
11719 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
11720 if (mID != NO_ID) {
11721 Parcelable state = container.get(mID);
11722 if (state != null) {
11723 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
11724 // + ": " + state);
11725 mPrivateFlags &= ~SAVE_STATE_CALLED;
11726 onRestoreInstanceState(state);
11727 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
11728 throw new IllegalStateException(
11729 "Derived class did not call super.onRestoreInstanceState()");
11730 }
11731 }
11732 }
11733 }
11734
11735 /**
11736 * Hook allowing a view to re-apply a representation of its internal state that had previously
11737 * been generated by {@link #onSaveInstanceState}. This function will never be called with a
11738 * null state.
11739 *
11740 * @param state The frozen state that had previously been returned by
11741 * {@link #onSaveInstanceState}.
11742 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011743 * @see #onSaveInstanceState()
11744 * @see #restoreHierarchyState(android.util.SparseArray)
11745 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 */
11747 protected void onRestoreInstanceState(Parcelable state) {
11748 mPrivateFlags |= SAVE_STATE_CALLED;
11749 if (state != BaseSavedState.EMPTY_STATE && state != null) {
Romain Guy237c1ce2009-12-08 11:30:25 -080011750 throw new IllegalArgumentException("Wrong state class, expecting View State but "
11751 + "received " + state.getClass().toString() + " instead. This usually happens "
Joe Malin32736f02011-01-19 16:14:20 -080011752 + "when two views of different type have the same id in the same hierarchy. "
11753 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
Romain Guy237c1ce2009-12-08 11:30:25 -080011754 + "other views do not use the same id.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011755 }
11756 }
11757
11758 /**
11759 * <p>Return the time at which the drawing of the view hierarchy started.</p>
11760 *
11761 * @return the drawing start time in milliseconds
11762 */
11763 public long getDrawingTime() {
11764 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
11765 }
11766
11767 /**
11768 * <p>Enables or disables the duplication of the parent's state into this view. When
11769 * duplication is enabled, this view gets its drawable state from its parent rather
11770 * than from its own internal properties.</p>
11771 *
11772 * <p>Note: in the current implementation, setting this property to true after the
11773 * view was added to a ViewGroup might have no effect at all. This property should
11774 * always be used from XML or set to true before adding this view to a ViewGroup.</p>
11775 *
11776 * <p>Note: if this view's parent addStateFromChildren property is enabled and this
11777 * property is enabled, an exception will be thrown.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011778 *
Gilles Debunnefb817032011-01-13 13:52:49 -080011779 * <p>Note: if the child view uses and updates additionnal states which are unknown to the
11780 * parent, these states should not be affected by this method.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011781 *
11782 * @param enabled True to enable duplication of the parent's drawable state, false
11783 * to disable it.
11784 *
11785 * @see #getDrawableState()
11786 * @see #isDuplicateParentStateEnabled()
11787 */
11788 public void setDuplicateParentStateEnabled(boolean enabled) {
11789 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
11790 }
11791
11792 /**
11793 * <p>Indicates whether this duplicates its drawable state from its parent.</p>
11794 *
11795 * @return True if this view's drawable state is duplicated from the parent,
11796 * false otherwise
11797 *
11798 * @see #getDrawableState()
11799 * @see #setDuplicateParentStateEnabled(boolean)
11800 */
11801 public boolean isDuplicateParentStateEnabled() {
11802 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
11803 }
11804
11805 /**
Romain Guy171c5922011-01-06 10:04:23 -080011806 * <p>Specifies the type of layer backing this view. The layer can be
11807 * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
11808 * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011809 *
Romain Guy171c5922011-01-06 10:04:23 -080011810 * <p>A layer is associated with an optional {@link android.graphics.Paint}
11811 * instance that controls how the layer is composed on screen. The following
11812 * properties of the paint are taken into account when composing the layer:</p>
11813 * <ul>
11814 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
11815 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
11816 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
11817 * </ul>
Joe Malin32736f02011-01-19 16:14:20 -080011818 *
Romain Guy171c5922011-01-06 10:04:23 -080011819 * <p>If this view has an alpha value set to < 1.0 by calling
11820 * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
11821 * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
11822 * equivalent to setting a hardware layer on this view and providing a paint with
11823 * the desired alpha value.<p>
Joe Malin32736f02011-01-19 16:14:20 -080011824 *
Romain Guy171c5922011-01-06 10:04:23 -080011825 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
11826 * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
11827 * for more information on when and how to use layers.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011828 *
Romain Guy171c5922011-01-06 10:04:23 -080011829 * @param layerType The ype of layer to use with this view, must be one of
11830 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
11831 * {@link #LAYER_TYPE_HARDWARE}
11832 * @param paint The paint used to compose the layer. This argument is optional
11833 * and can be null. It is ignored when the layer type is
11834 * {@link #LAYER_TYPE_NONE}
Joe Malin32736f02011-01-19 16:14:20 -080011835 *
11836 * @see #getLayerType()
Romain Guy171c5922011-01-06 10:04:23 -080011837 * @see #LAYER_TYPE_NONE
11838 * @see #LAYER_TYPE_SOFTWARE
11839 * @see #LAYER_TYPE_HARDWARE
Joe Malin32736f02011-01-19 16:14:20 -080011840 * @see #setAlpha(float)
11841 *
Romain Guy171c5922011-01-06 10:04:23 -080011842 * @attr ref android.R.styleable#View_layerType
11843 */
11844 public void setLayerType(int layerType, Paint paint) {
11845 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
Joe Malin32736f02011-01-19 16:14:20 -080011846 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
Romain Guy171c5922011-01-06 10:04:23 -080011847 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
11848 }
Chet Haasedaf98e92011-01-10 14:10:36 -080011849
Romain Guyd6cd5722011-01-17 14:42:41 -080011850 if (layerType == mLayerType) {
11851 if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
11852 mLayerPaint = paint == null ? new Paint() : paint;
Romain Guy0fd89bf2011-01-26 15:41:30 -080011853 invalidateParentCaches();
11854 invalidate(true);
Romain Guyd6cd5722011-01-17 14:42:41 -080011855 }
11856 return;
11857 }
Romain Guy171c5922011-01-06 10:04:23 -080011858
11859 // Destroy any previous software drawing cache if needed
Romain Guy6c319ca2011-01-11 14:29:25 -080011860 switch (mLayerType) {
Chet Haase6f33e812011-05-17 12:42:19 -070011861 case LAYER_TYPE_HARDWARE:
Romain Guya998dff2012-03-23 18:58:36 -070011862 destroyLayer(false);
Romain Guy31f2c2e2011-11-21 10:55:41 -080011863 // fall through - non-accelerated views may use software layer mechanism instead
Romain Guy6c319ca2011-01-11 14:29:25 -080011864 case LAYER_TYPE_SOFTWARE:
Romain Guy6d7475d2011-07-27 16:28:21 -070011865 destroyDrawingCache();
Romain Guy6c319ca2011-01-11 14:29:25 -080011866 break;
Romain Guy6c319ca2011-01-11 14:29:25 -080011867 default:
11868 break;
Romain Guy171c5922011-01-06 10:04:23 -080011869 }
11870
11871 mLayerType = layerType;
Romain Guy3a3133d2011-02-01 22:59:58 -080011872 final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
11873 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
11874 mLocalDirtyRect = layerDisabled ? null : new Rect();
Romain Guy171c5922011-01-06 10:04:23 -080011875
Romain Guy0fd89bf2011-01-26 15:41:30 -080011876 invalidateParentCaches();
11877 invalidate(true);
Romain Guy171c5922011-01-06 10:04:23 -080011878 }
11879
11880 /**
Romain Guy59c7f802011-09-29 17:21:45 -070011881 * Indicates whether this view has a static layer. A view with layer type
11882 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
11883 * dynamic.
11884 */
11885 boolean hasStaticLayer() {
Romain Guy2bf68f02012-03-02 13:37:47 -080011886 return true;
Romain Guy59c7f802011-09-29 17:21:45 -070011887 }
11888
11889 /**
Romain Guy171c5922011-01-06 10:04:23 -080011890 * Indicates what type of layer is currently associated with this view. By default
11891 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
11892 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
11893 * for more information on the different types of layers.
Joe Malin32736f02011-01-19 16:14:20 -080011894 *
Romain Guy171c5922011-01-06 10:04:23 -080011895 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
11896 * {@link #LAYER_TYPE_HARDWARE}
Joe Malin32736f02011-01-19 16:14:20 -080011897 *
11898 * @see #setLayerType(int, android.graphics.Paint)
Philip Milne6c8ea062012-04-03 17:38:43 -070011899 * @see #buildLayer()
Romain Guy171c5922011-01-06 10:04:23 -080011900 * @see #LAYER_TYPE_NONE
11901 * @see #LAYER_TYPE_SOFTWARE
11902 * @see #LAYER_TYPE_HARDWARE
11903 */
11904 public int getLayerType() {
11905 return mLayerType;
11906 }
Joe Malin32736f02011-01-19 16:14:20 -080011907
Romain Guy6c319ca2011-01-11 14:29:25 -080011908 /**
Romain Guyf1ae1062011-03-02 18:16:04 -080011909 * Forces this view's layer to be created and this view to be rendered
11910 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
11911 * invoking this method will have no effect.
Philip Milne6c8ea062012-04-03 17:38:43 -070011912 *
Romain Guyf1ae1062011-03-02 18:16:04 -080011913 * This method can for instance be used to render a view into its layer before
11914 * starting an animation. If this view is complex, rendering into the layer
11915 * before starting the animation will avoid skipping frames.
Philip Milne6c8ea062012-04-03 17:38:43 -070011916 *
Romain Guyf1ae1062011-03-02 18:16:04 -080011917 * @throws IllegalStateException If this view is not attached to a window
Philip Milne6c8ea062012-04-03 17:38:43 -070011918 *
11919 * @see #setLayerType(int, android.graphics.Paint)
Romain Guyf1ae1062011-03-02 18:16:04 -080011920 */
11921 public void buildLayer() {
11922 if (mLayerType == LAYER_TYPE_NONE) return;
11923
11924 if (mAttachInfo == null) {
11925 throw new IllegalStateException("This view must be attached to a window first");
11926 }
11927
11928 switch (mLayerType) {
11929 case LAYER_TYPE_HARDWARE:
Romain Guyd0609e42011-11-21 17:21:15 -080011930 if (mAttachInfo.mHardwareRenderer != null &&
11931 mAttachInfo.mHardwareRenderer.isEnabled() &&
11932 mAttachInfo.mHardwareRenderer.validate()) {
Michael Jurka7e52caf2012-03-06 15:57:06 -080011933 getHardwareLayer();
Romain Guyd0609e42011-11-21 17:21:15 -080011934 }
Romain Guyf1ae1062011-03-02 18:16:04 -080011935 break;
11936 case LAYER_TYPE_SOFTWARE:
11937 buildDrawingCache(true);
11938 break;
11939 }
11940 }
Philip Milne6c8ea062012-04-03 17:38:43 -070011941
Romain Guyf1ae1062011-03-02 18:16:04 -080011942 /**
Romain Guy6c319ca2011-01-11 14:29:25 -080011943 * <p>Returns a hardware layer that can be used to draw this view again
11944 * without executing its draw method.</p>
11945 *
11946 * @return A HardwareLayer ready to render, or null if an error occurred.
11947 */
Michael Jurka7e52caf2012-03-06 15:57:06 -080011948 HardwareLayer getHardwareLayer() {
Romain Guyea835032011-07-28 19:24:37 -070011949 if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
11950 !mAttachInfo.mHardwareRenderer.isEnabled()) {
Romain Guy6c319ca2011-01-11 14:29:25 -080011951 return null;
11952 }
Philip Milne6c8ea062012-04-03 17:38:43 -070011953
Romain Guy9c4b79a2011-11-10 19:23:58 -080011954 if (!mAttachInfo.mHardwareRenderer.validate()) return null;
Romain Guy6c319ca2011-01-11 14:29:25 -080011955
11956 final int width = mRight - mLeft;
11957 final int height = mBottom - mTop;
Joe Malin32736f02011-01-19 16:14:20 -080011958
Romain Guy6c319ca2011-01-11 14:29:25 -080011959 if (width == 0 || height == 0) {
11960 return null;
11961 }
11962
11963 if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
11964 if (mHardwareLayer == null) {
11965 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
11966 width, height, isOpaque());
Michael Jurka952e02b2012-03-13 18:34:35 -070011967 mLocalDirtyRect.set(0, 0, width, height);
Romain Guy846a5332012-07-11 17:44:57 -070011968 } else {
11969 if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
11970 mHardwareLayer.resize(width, height);
11971 mLocalDirtyRect.set(0, 0, width, height);
11972 }
11973
11974 // This should not be necessary but applications that change
11975 // the parameters of their background drawable without calling
11976 // this.setBackground(Drawable) can leave the view in a bad state
11977 // (for instance isOpaque() returns true, but the background is
11978 // not opaque.)
11979 computeOpaqueFlags();
11980
11981 final boolean opaque = isOpaque();
11982 if (mHardwareLayer.isOpaque() != opaque) {
11983 mHardwareLayer.setOpaque(opaque);
11984 mLocalDirtyRect.set(0, 0, width, height);
11985 }
Romain Guy6c319ca2011-01-11 14:29:25 -080011986 }
11987
Romain Guy5cd5c3f2011-10-17 17:10:02 -070011988 // The layer is not valid if the underlying GPU resources cannot be allocated
11989 if (!mHardwareLayer.isValid()) {
11990 return null;
11991 }
11992
Chet Haasea1cff502012-02-21 13:43:44 -080011993 mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
Michael Jurka7e52caf2012-03-06 15:57:06 -080011994 mLocalDirtyRect.setEmpty();
Romain Guy6c319ca2011-01-11 14:29:25 -080011995 }
11996
11997 return mHardwareLayer;
11998 }
Romain Guy171c5922011-01-06 10:04:23 -080011999
Romain Guy589b0bb2011-10-10 13:57:47 -070012000 /**
12001 * Destroys this View's hardware layer if possible.
Philip Milne6c8ea062012-04-03 17:38:43 -070012002 *
Romain Guy589b0bb2011-10-10 13:57:47 -070012003 * @return True if the layer was destroyed, false otherwise.
Philip Milne6c8ea062012-04-03 17:38:43 -070012004 *
12005 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy589b0bb2011-10-10 13:57:47 -070012006 * @see #LAYER_TYPE_HARDWARE
12007 */
Romain Guya998dff2012-03-23 18:58:36 -070012008 boolean destroyLayer(boolean valid) {
Romain Guy6d7475d2011-07-27 16:28:21 -070012009 if (mHardwareLayer != null) {
Romain Guy9c4b79a2011-11-10 19:23:58 -080012010 AttachInfo info = mAttachInfo;
12011 if (info != null && info.mHardwareRenderer != null &&
Romain Guya998dff2012-03-23 18:58:36 -070012012 info.mHardwareRenderer.isEnabled() &&
12013 (valid || info.mHardwareRenderer.validate())) {
Romain Guy9c4b79a2011-11-10 19:23:58 -080012014 mHardwareLayer.destroy();
12015 mHardwareLayer = null;
Romain Guy31f2c2e2011-11-21 10:55:41 -080012016
Romain Guy9c4b79a2011-11-10 19:23:58 -080012017 invalidate(true);
12018 invalidateParentCaches();
12019 }
Romain Guy65b345f2011-07-27 18:51:50 -070012020 return true;
Romain Guy6d7475d2011-07-27 16:28:21 -070012021 }
Romain Guy65b345f2011-07-27 18:51:50 -070012022 return false;
Romain Guy6d7475d2011-07-27 16:28:21 -070012023 }
12024
Romain Guy171c5922011-01-06 10:04:23 -080012025 /**
Romain Guy31f2c2e2011-11-21 10:55:41 -080012026 * Destroys all hardware rendering resources. This method is invoked
12027 * when the system needs to reclaim resources. Upon execution of this
12028 * method, you should free any OpenGL resources created by the view.
Philip Milne6c8ea062012-04-03 17:38:43 -070012029 *
Romain Guy31f2c2e2011-11-21 10:55:41 -080012030 * Note: you <strong>must</strong> call
12031 * <code>super.destroyHardwareResources()</code> when overriding
12032 * this method.
Philip Milne6c8ea062012-04-03 17:38:43 -070012033 *
Romain Guy31f2c2e2011-11-21 10:55:41 -080012034 * @hide
12035 */
12036 protected void destroyHardwareResources() {
Romain Guya998dff2012-03-23 18:58:36 -070012037 destroyLayer(true);
Romain Guy31f2c2e2011-11-21 10:55:41 -080012038 }
12039
12040 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
12042 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
12043 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
12044 * the cache is enabled. To benefit from the cache, you must request the drawing cache by
12045 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
12046 * null.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012047 *
Romain Guy171c5922011-01-06 10:04:23 -080012048 * <p>Enabling the drawing cache is similar to
12049 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
Chet Haasedaf98e92011-01-10 14:10:36 -080012050 * acceleration is turned off. When hardware acceleration is turned on, enabling the
12051 * drawing cache has no effect on rendering because the system uses a different mechanism
12052 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
12053 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
12054 * for information on how to enable software and hardware layers.</p>
12055 *
12056 * <p>This API can be used to manually generate
12057 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
12058 * {@link #getDrawingCache()}.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012059 *
12060 * @param enabled true to enable the drawing cache, false otherwise
12061 *
12062 * @see #isDrawingCacheEnabled()
12063 * @see #getDrawingCache()
12064 * @see #buildDrawingCache()
Joe Malin32736f02011-01-19 16:14:20 -080012065 * @see #setLayerType(int, android.graphics.Paint)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012066 */
12067 public void setDrawingCacheEnabled(boolean enabled) {
Romain Guy0211a0a2011-02-14 16:34:59 -080012068 mCachingFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012069 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
12070 }
12071
12072 /**
12073 * <p>Indicates whether the drawing cache is enabled for this view.</p>
12074 *
12075 * @return true if the drawing cache is enabled
12076 *
12077 * @see #setDrawingCacheEnabled(boolean)
12078 * @see #getDrawingCache()
12079 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070012080 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012081 public boolean isDrawingCacheEnabled() {
12082 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
12083 }
12084
12085 /**
Chet Haasedaf98e92011-01-10 14:10:36 -080012086 * Debugging utility which recursively outputs the dirty state of a view and its
12087 * descendants.
Joe Malin32736f02011-01-19 16:14:20 -080012088 *
Chet Haasedaf98e92011-01-10 14:10:36 -080012089 * @hide
12090 */
Romain Guy676b1732011-02-14 14:45:33 -080012091 @SuppressWarnings({"UnusedDeclaration"})
Chet Haasedaf98e92011-01-10 14:10:36 -080012092 public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
12093 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
12094 ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
12095 (mPrivateFlags & View.DRAWING_CACHE_VALID) +
12096 ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
12097 if (clear) {
12098 mPrivateFlags &= clearMask;
12099 }
12100 if (this instanceof ViewGroup) {
12101 ViewGroup parent = (ViewGroup) this;
12102 final int count = parent.getChildCount();
12103 for (int i = 0; i < count; i++) {
Romain Guy7d7b5492011-01-24 16:33:45 -080012104 final View child = parent.getChildAt(i);
Chet Haasedaf98e92011-01-10 14:10:36 -080012105 child.outputDirtyFlags(indent + " ", clear, clearMask);
12106 }
12107 }
12108 }
12109
12110 /**
12111 * This method is used by ViewGroup to cause its children to restore or recreate their
12112 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
12113 * to recreate its own display list, which would happen if it went through the normal
12114 * draw/dispatchDraw mechanisms.
12115 *
12116 * @hide
12117 */
12118 protected void dispatchGetDisplayList() {}
Chet Haasef4ac5472011-01-27 10:30:25 -080012119
12120 /**
12121 * A view that is not attached or hardware accelerated cannot create a display list.
12122 * This method checks these conditions and returns the appropriate result.
12123 *
12124 * @return true if view has the ability to create a display list, false otherwise.
12125 *
12126 * @hide
12127 */
12128 public boolean canHaveDisplayList() {
Romain Guy676b1732011-02-14 14:45:33 -080012129 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
Chet Haasef4ac5472011-01-27 10:30:25 -080012130 }
Joe Malin32736f02011-01-19 16:14:20 -080012131
Chet Haasedaf98e92011-01-10 14:10:36 -080012132 /**
Gilles Debunneb35ab7b2011-12-05 15:54:00 -080012133 * @return The HardwareRenderer associated with that view or null if hardware rendering
12134 * is not supported or this this has not been attached to a window.
12135 *
12136 * @hide
12137 */
12138 public HardwareRenderer getHardwareRenderer() {
12139 if (mAttachInfo != null) {
12140 return mAttachInfo.mHardwareRenderer;
12141 }
12142 return null;
12143 }
12144
12145 /**
Chet Haasea1cff502012-02-21 13:43:44 -080012146 * Returns a DisplayList. If the incoming displayList is null, one will be created.
12147 * Otherwise, the same display list will be returned (after having been rendered into
12148 * along the way, depending on the invalidation state of the view).
12149 *
12150 * @param displayList The previous version of this displayList, could be null.
12151 * @param isLayer Whether the requester of the display list is a layer. If so,
12152 * the view will avoid creating a layer inside the resulting display list.
12153 * @return A new or reused DisplayList object.
12154 */
12155 private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
12156 if (!canHaveDisplayList()) {
12157 return null;
12158 }
12159
12160 if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
12161 displayList == null || !displayList.isValid() ||
12162 (!isLayer && mRecreateDisplayList))) {
12163 // Don't need to recreate the display list, just need to tell our
12164 // children to restore/recreate theirs
12165 if (displayList != null && displayList.isValid() &&
12166 !isLayer && !mRecreateDisplayList) {
12167 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
12168 mPrivateFlags &= ~DIRTY_MASK;
12169 dispatchGetDisplayList();
12170
12171 return displayList;
12172 }
12173
12174 if (!isLayer) {
12175 // If we got here, we're recreating it. Mark it as such to ensure that
12176 // we copy in child display lists into ours in drawChild()
12177 mRecreateDisplayList = true;
12178 }
12179 if (displayList == null) {
12180 final String name = getClass().getSimpleName();
12181 displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
12182 // If we're creating a new display list, make sure our parent gets invalidated
12183 // since they will need to recreate their display list to account for this
12184 // new child display list.
12185 invalidateParentCaches();
12186 }
12187
12188 boolean caching = false;
12189 final HardwareCanvas canvas = displayList.start();
Chet Haasea1cff502012-02-21 13:43:44 -080012190 int width = mRight - mLeft;
12191 int height = mBottom - mTop;
12192
12193 try {
12194 canvas.setViewport(width, height);
12195 // The dirty rect should always be null for a display list
12196 canvas.onPreDraw(null);
Michael Jurkaba649742012-06-28 19:12:58 -070012197 int layerType = getLayerType();
Chet Haase1271e2c2012-04-20 09:54:27 -070012198 if (!isLayer && layerType != LAYER_TYPE_NONE) {
Chet Haaseb85967b2012-03-26 14:37:51 -070012199 if (layerType == LAYER_TYPE_HARDWARE) {
12200 final HardwareLayer layer = getHardwareLayer();
12201 if (layer != null && layer.isValid()) {
12202 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
12203 } else {
12204 canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
12205 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
12206 Canvas.CLIP_TO_LAYER_SAVE_FLAG);
12207 }
12208 caching = true;
Chet Haasea1cff502012-02-21 13:43:44 -080012209 } else {
Chet Haaseb85967b2012-03-26 14:37:51 -070012210 buildDrawingCache(true);
12211 Bitmap cache = getDrawingCache(true);
12212 if (cache != null) {
12213 canvas.drawBitmap(cache, 0, 0, mLayerPaint);
12214 caching = true;
12215 }
Chet Haasea1cff502012-02-21 13:43:44 -080012216 }
Chet Haasea1cff502012-02-21 13:43:44 -080012217 } else {
12218
12219 computeScroll();
12220
Chet Haasea1cff502012-02-21 13:43:44 -080012221 canvas.translate(-mScrollX, -mScrollY);
12222 if (!isLayer) {
12223 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
12224 mPrivateFlags &= ~DIRTY_MASK;
12225 }
12226
12227 // Fast path for layouts with no backgrounds
12228 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
12229 dispatchDraw(canvas);
12230 } else {
12231 draw(canvas);
12232 }
12233 }
12234 } finally {
Chet Haasea1cff502012-02-21 13:43:44 -080012235 canvas.onPostDraw();
12236
12237 displayList.end();
Chet Haase1271e2c2012-04-20 09:54:27 -070012238 displayList.setCaching(caching);
12239 if (isLayer) {
Chet Haasea1cff502012-02-21 13:43:44 -080012240 displayList.setLeftTopRightBottom(0, 0, width, height);
12241 } else {
12242 setDisplayListProperties(displayList);
12243 }
12244 }
12245 } else if (!isLayer) {
12246 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
12247 mPrivateFlags &= ~DIRTY_MASK;
12248 }
12249
12250 return displayList;
12251 }
12252
12253 /**
12254 * Get the DisplayList for the HardwareLayer
12255 *
12256 * @param layer The HardwareLayer whose DisplayList we want
12257 * @return A DisplayList fopr the specified HardwareLayer
12258 */
12259 private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
12260 DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
12261 layer.setDisplayList(displayList);
12262 return displayList;
12263 }
12264
12265
12266 /**
Romain Guyb051e892010-09-28 19:09:36 -070012267 * <p>Returns a display list that can be used to draw this view again
12268 * without executing its draw method.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012269 *
Romain Guyb051e892010-09-28 19:09:36 -070012270 * @return A DisplayList ready to replay, or null if caching is not enabled.
Chet Haasedaf98e92011-01-10 14:10:36 -080012271 *
12272 * @hide
Romain Guyb051e892010-09-28 19:09:36 -070012273 */
Chet Haasedaf98e92011-01-10 14:10:36 -080012274 public DisplayList getDisplayList() {
Chet Haasea1cff502012-02-21 13:43:44 -080012275 mDisplayList = getDisplayList(mDisplayList, false);
Romain Guyb051e892010-09-28 19:09:36 -070012276 return mDisplayList;
12277 }
12278
Romain Guy38c2ece2012-05-24 14:20:56 -070012279 private void clearDisplayList() {
12280 if (mDisplayList != null) {
12281 mDisplayList.invalidate();
12282 mDisplayList.clear();
12283 }
12284 }
12285
Romain Guyb051e892010-09-28 19:09:36 -070012286 /**
Romain Guyfbd8f692009-06-26 14:51:58 -070012287 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012288 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012289 * @return A non-scaled bitmap representing this view or null if cache is disabled.
Joe Malin32736f02011-01-19 16:14:20 -080012290 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012291 * @see #getDrawingCache(boolean)
12292 */
12293 public Bitmap getDrawingCache() {
12294 return getDrawingCache(false);
12295 }
12296
12297 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012298 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
12299 * is null when caching is disabled. If caching is enabled and the cache is not ready,
12300 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
12301 * draw from the cache when the cache is enabled. To benefit from the cache, you must
12302 * request the drawing cache by calling this method and draw it on screen if the
12303 * returned bitmap is not null.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012304 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012305 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12306 * this method will create a bitmap of the same size as this view. Because this bitmap
12307 * will be drawn scaled by the parent ViewGroup, the result on screen might show
12308 * scaling artifacts. To avoid such artifacts, you should call this method by setting
12309 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12310 * size than the view. This implies that your application must be able to handle this
12311 * size.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012312 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012313 * @param autoScale Indicates whether the generated bitmap should be scaled based on
12314 * the current density of the screen when the application is in compatibility
12315 * mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012316 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012317 * @return A bitmap representing this view or null if cache is disabled.
Joe Malin32736f02011-01-19 16:14:20 -080012318 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012319 * @see #setDrawingCacheEnabled(boolean)
12320 * @see #isDrawingCacheEnabled()
Romain Guyfbd8f692009-06-26 14:51:58 -070012321 * @see #buildDrawingCache(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012322 * @see #destroyDrawingCache()
12323 */
Romain Guyfbd8f692009-06-26 14:51:58 -070012324 public Bitmap getDrawingCache(boolean autoScale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012325 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
12326 return null;
12327 }
12328 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012329 buildDrawingCache(autoScale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 }
Romain Guy02890fd2010-08-06 17:58:44 -070012331 return autoScale ? mDrawingCache : mUnscaledDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012332 }
12333
12334 /**
12335 * <p>Frees the resources used by the drawing cache. If you call
12336 * {@link #buildDrawingCache()} manually without calling
12337 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12338 * should cleanup the cache with this method afterwards.</p>
12339 *
12340 * @see #setDrawingCacheEnabled(boolean)
12341 * @see #buildDrawingCache()
12342 * @see #getDrawingCache()
12343 */
12344 public void destroyDrawingCache() {
12345 if (mDrawingCache != null) {
Romain Guy02890fd2010-08-06 17:58:44 -070012346 mDrawingCache.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 mDrawingCache = null;
12348 }
Romain Guyfbd8f692009-06-26 14:51:58 -070012349 if (mUnscaledDrawingCache != null) {
Romain Guy02890fd2010-08-06 17:58:44 -070012350 mUnscaledDrawingCache.recycle();
Romain Guyfbd8f692009-06-26 14:51:58 -070012351 mUnscaledDrawingCache = null;
12352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012353 }
12354
12355 /**
12356 * Setting a solid background color for the drawing cache's bitmaps will improve
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070012357 * performance and memory usage. Note, though that this should only be used if this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358 * view will always be drawn on top of a solid color.
12359 *
12360 * @param color The background color to use for the drawing cache's bitmap
12361 *
12362 * @see #setDrawingCacheEnabled(boolean)
12363 * @see #buildDrawingCache()
12364 * @see #getDrawingCache()
12365 */
12366 public void setDrawingCacheBackgroundColor(int color) {
Romain Guy52e2ef82010-01-14 12:11:48 -080012367 if (color != mDrawingCacheBackgroundColor) {
12368 mDrawingCacheBackgroundColor = color;
12369 mPrivateFlags &= ~DRAWING_CACHE_VALID;
12370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 }
12372
12373 /**
12374 * @see #setDrawingCacheBackgroundColor(int)
12375 *
12376 * @return The background color to used for the drawing cache's bitmap
12377 */
12378 public int getDrawingCacheBackgroundColor() {
12379 return mDrawingCacheBackgroundColor;
12380 }
12381
12382 /**
Romain Guyfbd8f692009-06-26 14:51:58 -070012383 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012384 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012385 * @see #buildDrawingCache(boolean)
12386 */
12387 public void buildDrawingCache() {
12388 buildDrawingCache(false);
12389 }
Gilles Debunne2ed2eac2011-02-24 16:29:48 -080012390
Romain Guyfbd8f692009-06-26 14:51:58 -070012391 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012392 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
12393 *
12394 * <p>If you call {@link #buildDrawingCache()} manually without calling
12395 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12396 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012397 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012398 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12399 * this method will create a bitmap of the same size as this view. Because this bitmap
12400 * will be drawn scaled by the parent ViewGroup, the result on screen might show
12401 * scaling artifacts. To avoid such artifacts, you should call this method by setting
12402 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12403 * size than the view. This implies that your application must be able to handle this
12404 * size.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012405 *
Romain Guy0d9275e2010-10-26 14:22:30 -070012406 * <p>You should avoid calling this method when hardware acceleration is enabled. If
12407 * you do not need the drawing cache bitmap, calling this method will increase memory
Joe Malin32736f02011-01-19 16:14:20 -080012408 * usage and cause the view to be rendered in software once, thus negatively impacting
Romain Guy0d9275e2010-10-26 14:22:30 -070012409 * performance.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012410 *
12411 * @see #getDrawingCache()
12412 * @see #destroyDrawingCache()
12413 */
Romain Guyfbd8f692009-06-26 14:51:58 -070012414 public void buildDrawingCache(boolean autoScale) {
12415 if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
Romain Guy02890fd2010-08-06 17:58:44 -070012416 mDrawingCache == null : mUnscaledDrawingCache == null)) {
Romain Guy0211a0a2011-02-14 16:34:59 -080012417 mCachingFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418
Romain Guy8506ab42009-06-11 17:35:47 -070012419 int width = mRight - mLeft;
12420 int height = mBottom - mTop;
12421
12422 final AttachInfo attachInfo = mAttachInfo;
Romain Guye1123222009-06-29 14:24:56 -070012423 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
Romain Guyfbd8f692009-06-26 14:51:58 -070012424
Romain Guye1123222009-06-29 14:24:56 -070012425 if (autoScale && scalingRequired) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012426 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
12427 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
Romain Guy8506ab42009-06-11 17:35:47 -070012428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012429
12430 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
Romain Guy35b38ce2009-10-07 13:38:55 -070012431 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
Adam Powell26153a32010-11-08 15:22:27 -080012432 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012433
12434 if (width <= 0 || height <= 0 ||
Romain Guy35b38ce2009-10-07 13:38:55 -070012435 // Projected bitmap size in bytes
Adam Powell26153a32010-11-08 15:22:27 -080012436 (width * height * (opaque && !use32BitCache ? 2 : 4) >
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012437 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
12438 destroyDrawingCache();
Romain Guy0211a0a2011-02-14 16:34:59 -080012439 mCachingFailed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 return;
12441 }
12442
12443 boolean clear = true;
Romain Guy02890fd2010-08-06 17:58:44 -070012444 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445
12446 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 Bitmap.Config quality;
12448 if (!opaque) {
Romain Guy676b1732011-02-14 14:45:33 -080012449 // Never pick ARGB_4444 because it looks awful
12450 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012451 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
12452 case DRAWING_CACHE_QUALITY_AUTO:
12453 quality = Bitmap.Config.ARGB_8888;
12454 break;
12455 case DRAWING_CACHE_QUALITY_LOW:
Romain Guy676b1732011-02-14 14:45:33 -080012456 quality = Bitmap.Config.ARGB_8888;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012457 break;
12458 case DRAWING_CACHE_QUALITY_HIGH:
12459 quality = Bitmap.Config.ARGB_8888;
12460 break;
12461 default:
12462 quality = Bitmap.Config.ARGB_8888;
12463 break;
12464 }
12465 } else {
Romain Guy35b38ce2009-10-07 13:38:55 -070012466 // Optimization for translucent windows
12467 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
Adam Powell26153a32010-11-08 15:22:27 -080012468 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012469 }
12470
12471 // Try to cleanup memory
12472 if (bitmap != null) bitmap.recycle();
12473
12474 try {
Dianne Hackborndde331c2012-08-03 14:01:57 -070012475 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12476 width, height, quality);
Dianne Hackborn11ea3342009-07-22 21:48:55 -070012477 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
Romain Guyfbd8f692009-06-26 14:51:58 -070012478 if (autoScale) {
Romain Guy02890fd2010-08-06 17:58:44 -070012479 mDrawingCache = bitmap;
Romain Guyfbd8f692009-06-26 14:51:58 -070012480 } else {
Romain Guy02890fd2010-08-06 17:58:44 -070012481 mUnscaledDrawingCache = bitmap;
Romain Guyfbd8f692009-06-26 14:51:58 -070012482 }
Adam Powell26153a32010-11-08 15:22:27 -080012483 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012484 } catch (OutOfMemoryError e) {
12485 // If there is not enough memory to create the bitmap cache, just
12486 // ignore the issue as bitmap caches are not required to draw the
12487 // view hierarchy
Romain Guyfbd8f692009-06-26 14:51:58 -070012488 if (autoScale) {
12489 mDrawingCache = null;
12490 } else {
12491 mUnscaledDrawingCache = null;
12492 }
Romain Guy0211a0a2011-02-14 16:34:59 -080012493 mCachingFailed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 return;
12495 }
12496
12497 clear = drawingCacheBackgroundColor != 0;
12498 }
12499
12500 Canvas canvas;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012501 if (attachInfo != null) {
12502 canvas = attachInfo.mCanvas;
12503 if (canvas == null) {
12504 canvas = new Canvas();
12505 }
12506 canvas.setBitmap(bitmap);
12507 // Temporarily clobber the cached Canvas in case one of our children
12508 // is also using a drawing cache. Without this, the children would
12509 // steal the canvas by attaching their own bitmap to it and bad, bad
12510 // thing would happen (invisible views, corrupted drawings, etc.)
12511 attachInfo.mCanvas = null;
12512 } else {
12513 // This case should hopefully never or seldom happen
12514 canvas = new Canvas(bitmap);
12515 }
12516
12517 if (clear) {
12518 bitmap.eraseColor(drawingCacheBackgroundColor);
12519 }
12520
12521 computeScroll();
12522 final int restoreCount = canvas.save();
Joe Malin32736f02011-01-19 16:14:20 -080012523
Romain Guye1123222009-06-29 14:24:56 -070012524 if (autoScale && scalingRequired) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012525 final float scale = attachInfo.mApplicationScale;
12526 canvas.scale(scale, scale);
12527 }
Joe Malin32736f02011-01-19 16:14:20 -080012528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012529 canvas.translate(-mScrollX, -mScrollY);
12530
Romain Guy5bcdff42009-05-14 21:27:18 -070012531 mPrivateFlags |= DRAWN;
Romain Guy171c5922011-01-06 10:04:23 -080012532 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
12533 mLayerType != LAYER_TYPE_NONE) {
Romain Guy0d9275e2010-10-26 14:22:30 -070012534 mPrivateFlags |= DRAWING_CACHE_VALID;
12535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012536
12537 // Fast path for layouts with no backgrounds
12538 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
Romain Guy5bcdff42009-05-14 21:27:18 -070012539 mPrivateFlags &= ~DIRTY_MASK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012540 dispatchDraw(canvas);
12541 } else {
12542 draw(canvas);
12543 }
12544
12545 canvas.restoreToCount(restoreCount);
Dianne Hackborn6311d0a2011-08-02 16:37:58 -070012546 canvas.setBitmap(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012547
12548 if (attachInfo != null) {
12549 // Restore the cached Canvas for our siblings
12550 attachInfo.mCanvas = canvas;
12551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012552 }
12553 }
12554
12555 /**
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012556 * Create a snapshot of the view into a bitmap. We should probably make
12557 * some form of this public, but should think about the API.
12558 */
Romain Guy223ff5c2010-03-02 17:07:47 -080012559 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012560 int width = mRight - mLeft;
12561 int height = mBottom - mTop;
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012562
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012563 final AttachInfo attachInfo = mAttachInfo;
Romain Guy8c11e312009-09-14 15:15:30 -070012564 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012565 width = (int) ((width * scale) + 0.5f);
12566 height = (int) ((height * scale) + 0.5f);
Joe Malin32736f02011-01-19 16:14:20 -080012567
Dianne Hackborndde331c2012-08-03 14:01:57 -070012568 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12569 width > 0 ? width : 1, height > 0 ? height : 1, quality);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012570 if (bitmap == null) {
12571 throw new OutOfMemoryError();
12572 }
12573
Romain Guyc529d8d2011-09-06 15:01:39 -070012574 Resources resources = getResources();
12575 if (resources != null) {
12576 bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
12577 }
Joe Malin32736f02011-01-19 16:14:20 -080012578
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012579 Canvas canvas;
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012580 if (attachInfo != null) {
12581 canvas = attachInfo.mCanvas;
12582 if (canvas == null) {
12583 canvas = new Canvas();
12584 }
12585 canvas.setBitmap(bitmap);
12586 // Temporarily clobber the cached Canvas in case one of our children
12587 // is also using a drawing cache. Without this, the children would
12588 // steal the canvas by attaching their own bitmap to it and bad, bad
12589 // things would happen (invisible views, corrupted drawings, etc.)
12590 attachInfo.mCanvas = null;
12591 } else {
12592 // This case should hopefully never or seldom happen
12593 canvas = new Canvas(bitmap);
12594 }
12595
Romain Guy5bcdff42009-05-14 21:27:18 -070012596 if ((backgroundColor & 0xff000000) != 0) {
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012597 bitmap.eraseColor(backgroundColor);
12598 }
12599
12600 computeScroll();
12601 final int restoreCount = canvas.save();
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012602 canvas.scale(scale, scale);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012603 canvas.translate(-mScrollX, -mScrollY);
12604
Romain Guy5bcdff42009-05-14 21:27:18 -070012605 // Temporarily remove the dirty mask
12606 int flags = mPrivateFlags;
12607 mPrivateFlags &= ~DIRTY_MASK;
12608
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012609 // Fast path for layouts with no backgrounds
12610 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
12611 dispatchDraw(canvas);
12612 } else {
12613 draw(canvas);
12614 }
12615
Romain Guy5bcdff42009-05-14 21:27:18 -070012616 mPrivateFlags = flags;
12617
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012618 canvas.restoreToCount(restoreCount);
Dianne Hackborn6311d0a2011-08-02 16:37:58 -070012619 canvas.setBitmap(null);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012620
12621 if (attachInfo != null) {
12622 // Restore the cached Canvas for our siblings
12623 attachInfo.mCanvas = canvas;
12624 }
Romain Guy8506ab42009-06-11 17:35:47 -070012625
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012626 return bitmap;
12627 }
12628
12629 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012630 * Indicates whether this View is currently in edit mode. A View is usually
12631 * in edit mode when displayed within a developer tool. For instance, if
12632 * this View is being drawn by a visual user interface builder, this method
12633 * should return true.
12634 *
12635 * Subclasses should check the return value of this method to provide
12636 * different behaviors if their normal behavior might interfere with the
12637 * host environment. For instance: the class spawns a thread in its
12638 * constructor, the drawing code relies on device-specific features, etc.
12639 *
12640 * This method is usually checked in the drawing code of custom widgets.
12641 *
12642 * @return True if this View is in edit mode, false otherwise.
12643 */
12644 public boolean isInEditMode() {
12645 return false;
12646 }
12647
12648 /**
12649 * If the View draws content inside its padding and enables fading edges,
12650 * it needs to support padding offsets. Padding offsets are added to the
12651 * fading edges to extend the length of the fade so that it covers pixels
12652 * drawn inside the padding.
12653 *
12654 * Subclasses of this class should override this method if they need
12655 * to draw content inside the padding.
12656 *
12657 * @return True if padding offset must be applied, false otherwise.
12658 *
12659 * @see #getLeftPaddingOffset()
12660 * @see #getRightPaddingOffset()
12661 * @see #getTopPaddingOffset()
12662 * @see #getBottomPaddingOffset()
12663 *
12664 * @since CURRENT
12665 */
12666 protected boolean isPaddingOffsetRequired() {
12667 return false;
12668 }
12669
12670 /**
12671 * Amount by which to extend the left fading region. Called only when
12672 * {@link #isPaddingOffsetRequired()} returns true.
12673 *
12674 * @return The left padding offset in pixels.
12675 *
12676 * @see #isPaddingOffsetRequired()
12677 *
12678 * @since CURRENT
12679 */
12680 protected int getLeftPaddingOffset() {
12681 return 0;
12682 }
12683
12684 /**
12685 * Amount by which to extend the right fading region. Called only when
12686 * {@link #isPaddingOffsetRequired()} returns true.
12687 *
12688 * @return The right padding offset in pixels.
12689 *
12690 * @see #isPaddingOffsetRequired()
12691 *
12692 * @since CURRENT
12693 */
12694 protected int getRightPaddingOffset() {
12695 return 0;
12696 }
12697
12698 /**
12699 * Amount by which to extend the top fading region. Called only when
12700 * {@link #isPaddingOffsetRequired()} returns true.
12701 *
12702 * @return The top padding offset in pixels.
12703 *
12704 * @see #isPaddingOffsetRequired()
12705 *
12706 * @since CURRENT
12707 */
12708 protected int getTopPaddingOffset() {
12709 return 0;
12710 }
12711
12712 /**
12713 * Amount by which to extend the bottom fading region. Called only when
12714 * {@link #isPaddingOffsetRequired()} returns true.
12715 *
12716 * @return The bottom padding offset in pixels.
12717 *
12718 * @see #isPaddingOffsetRequired()
12719 *
12720 * @since CURRENT
12721 */
12722 protected int getBottomPaddingOffset() {
12723 return 0;
12724 }
12725
12726 /**
Romain Guyf2fc4602011-07-19 15:20:03 -070012727 * @hide
12728 * @param offsetRequired
12729 */
12730 protected int getFadeTop(boolean offsetRequired) {
12731 int top = mPaddingTop;
12732 if (offsetRequired) top += getTopPaddingOffset();
12733 return top;
12734 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012735
Romain Guyf2fc4602011-07-19 15:20:03 -070012736 /**
12737 * @hide
12738 * @param offsetRequired
12739 */
12740 protected int getFadeHeight(boolean offsetRequired) {
12741 int padding = mPaddingTop;
Philip Milne6c8ea062012-04-03 17:38:43 -070012742 if (offsetRequired) padding += getTopPaddingOffset();
Romain Guyf2fc4602011-07-19 15:20:03 -070012743 return mBottom - mTop - mPaddingBottom - padding;
12744 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012745
Romain Guyf2fc4602011-07-19 15:20:03 -070012746 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090012747 * <p>Indicates whether this view is attached to a hardware accelerated
Romain Guy2bffd262010-09-12 17:40:02 -070012748 * window or not.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012749 *
Romain Guy2bffd262010-09-12 17:40:02 -070012750 * <p>Even if this method returns true, it does not mean that every call
12751 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
12752 * accelerated {@link android.graphics.Canvas}. For instance, if this view
Ken Wakasaf76a50c2012-03-09 19:56:35 +090012753 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
Romain Guy2bffd262010-09-12 17:40:02 -070012754 * window is hardware accelerated,
12755 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
12756 * return false, and this method will return true.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012757 *
Romain Guy2bffd262010-09-12 17:40:02 -070012758 * @return True if the view is attached to a window and the window is
12759 * hardware accelerated; false in any other case.
12760 */
12761 public boolean isHardwareAccelerated() {
12762 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
12763 }
Joe Malin32736f02011-01-19 16:14:20 -080012764
Romain Guy2bffd262010-09-12 17:40:02 -070012765 /**
Chet Haasebcca79a2012-02-14 08:45:14 -080012766 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
12767 * case of an active Animation being run on the view.
12768 */
12769 private boolean drawAnimation(ViewGroup parent, long drawingTime,
12770 Animation a, boolean scalingRequired) {
12771 Transformation invalidationTransform;
12772 final int flags = parent.mGroupFlags;
12773 final boolean initialized = a.isInitialized();
12774 if (!initialized) {
Chet Haase1fb8a9e2012-04-19 09:22:34 -070012775 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
Chet Haasebcca79a2012-02-14 08:45:14 -080012776 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
Romain Guy393a52c2012-05-22 20:21:08 -070012777 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
Chet Haasebcca79a2012-02-14 08:45:14 -080012778 onAnimationStart();
12779 }
12780
12781 boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
12782 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
12783 if (parent.mInvalidationTransformation == null) {
12784 parent.mInvalidationTransformation = new Transformation();
12785 }
12786 invalidationTransform = parent.mInvalidationTransformation;
12787 a.getTransformation(drawingTime, invalidationTransform, 1f);
12788 } else {
12789 invalidationTransform = parent.mChildTransformation;
12790 }
Romain Guy393a52c2012-05-22 20:21:08 -070012791
Chet Haasebcca79a2012-02-14 08:45:14 -080012792 if (more) {
12793 if (!a.willChangeBounds()) {
Romain Guyf0af1d52012-07-11 18:31:21 -070012794 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
12795 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
12796 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
12797 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
Chet Haasebcca79a2012-02-14 08:45:14 -080012798 // The child need to draw an animation, potentially offscreen, so
12799 // make sure we do not cancel invalidate requests
12800 parent.mPrivateFlags |= DRAW_ANIMATION;
12801 parent.invalidate(mLeft, mTop, mRight, mBottom);
12802 }
12803 } else {
12804 if (parent.mInvalidateRegion == null) {
12805 parent.mInvalidateRegion = new RectF();
12806 }
12807 final RectF region = parent.mInvalidateRegion;
12808 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
12809 invalidationTransform);
12810
12811 // The child need to draw an animation, potentially offscreen, so
12812 // make sure we do not cancel invalidate requests
12813 parent.mPrivateFlags |= DRAW_ANIMATION;
12814
12815 final int left = mLeft + (int) region.left;
12816 final int top = mTop + (int) region.top;
12817 parent.invalidate(left, top, left + (int) (region.width() + .5f),
12818 top + (int) (region.height() + .5f));
12819 }
12820 }
12821 return more;
12822 }
12823
Chet Haasea1cff502012-02-21 13:43:44 -080012824 /**
12825 * This method is called by getDisplayList() when a display list is created or re-rendered.
12826 * It sets or resets the current value of all properties on that display list (resetting is
12827 * necessary when a display list is being re-created, because we need to make sure that
12828 * previously-set transform values
12829 */
12830 void setDisplayListProperties(DisplayList displayList) {
Chet Haase1271e2c2012-04-20 09:54:27 -070012831 if (displayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080012832 displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
Chet Haasedb8c9a62012-03-21 18:54:18 -070012833 displayList.setHasOverlappingRendering(hasOverlappingRendering());
Chet Haasea1cff502012-02-21 13:43:44 -080012834 if (mParent instanceof ViewGroup) {
12835 displayList.setClipChildren(
12836 (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
12837 }
Chet Haase9420abd2012-03-29 16:28:32 -070012838 float alpha = 1;
12839 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
12840 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
12841 ViewGroup parentVG = (ViewGroup) mParent;
12842 final boolean hasTransform =
12843 parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
12844 if (hasTransform) {
12845 Transformation transform = parentVG.mChildTransformation;
12846 final int transformType = parentVG.mChildTransformation.getTransformationType();
12847 if (transformType != Transformation.TYPE_IDENTITY) {
12848 if ((transformType & Transformation.TYPE_ALPHA) != 0) {
12849 alpha = transform.getAlpha();
12850 }
12851 if ((transformType & Transformation.TYPE_MATRIX) != 0) {
12852 displayList.setStaticMatrix(transform.getMatrix());
12853 }
12854 }
12855 }
Chet Haasea1cff502012-02-21 13:43:44 -080012856 }
12857 if (mTransformationInfo != null) {
Chet Haase9420abd2012-03-29 16:28:32 -070012858 alpha *= mTransformationInfo.mAlpha;
12859 if (alpha < 1) {
12860 final int multipliedAlpha = (int) (255 * alpha);
12861 if (onSetAlpha(multipliedAlpha)) {
12862 alpha = 1;
12863 }
12864 }
12865 displayList.setTransformationInfo(alpha,
Chet Haasea1cff502012-02-21 13:43:44 -080012866 mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
12867 mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
12868 mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
12869 mTransformationInfo.mScaleY);
Chet Haaseb85967b2012-03-26 14:37:51 -070012870 if (mTransformationInfo.mCamera == null) {
12871 mTransformationInfo.mCamera = new Camera();
12872 mTransformationInfo.matrix3D = new Matrix();
12873 }
12874 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
Chet Haasea1cff502012-02-21 13:43:44 -080012875 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == PIVOT_EXPLICITLY_SET) {
12876 displayList.setPivotX(getPivotX());
12877 displayList.setPivotY(getPivotY());
12878 }
Chet Haase9420abd2012-03-29 16:28:32 -070012879 } else if (alpha < 1) {
12880 displayList.setAlpha(alpha);
Chet Haasea1cff502012-02-21 13:43:44 -080012881 }
12882 }
12883 }
12884
Chet Haasebcca79a2012-02-14 08:45:14 -080012885 /**
Chet Haase64a48c12012-02-13 16:33:29 -080012886 * This method is called by ViewGroup.drawChild() to have each child view draw itself.
12887 * This draw() method is an implementation detail and is not intended to be overridden or
12888 * to be called from anywhere else other than ViewGroup.drawChild().
12889 */
12890 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
Chet Haase1271e2c2012-04-20 09:54:27 -070012891 boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
Chet Haase64a48c12012-02-13 16:33:29 -080012892 boolean more = false;
Chet Haase64a48c12012-02-13 16:33:29 -080012893 final boolean childHasIdentityMatrix = hasIdentityMatrix();
Chet Haase64a48c12012-02-13 16:33:29 -080012894 final int flags = parent.mGroupFlags;
12895
Chet Haasea1cff502012-02-21 13:43:44 -080012896 if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
Chet Haase64a48c12012-02-13 16:33:29 -080012897 parent.mChildTransformation.clear();
Chet Haasea1cff502012-02-21 13:43:44 -080012898 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080012899 }
12900
12901 Transformation transformToApply = null;
Chet Haase64a48c12012-02-13 16:33:29 -080012902 boolean concatMatrix = false;
12903
12904 boolean scalingRequired = false;
12905 boolean caching;
Michael Jurkaba649742012-06-28 19:12:58 -070012906 int layerType = getLayerType();
Chet Haase64a48c12012-02-13 16:33:29 -080012907
12908 final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
Chet Haasea1cff502012-02-21 13:43:44 -080012909 if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
12910 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
Chet Haase64a48c12012-02-13 16:33:29 -080012911 caching = true;
Chet Haase9420abd2012-03-29 16:28:32 -070012912 // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
Chet Haase64a48c12012-02-13 16:33:29 -080012913 if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
12914 } else {
12915 caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
12916 }
12917
Chet Haasebcca79a2012-02-14 08:45:14 -080012918 final Animation a = getAnimation();
Chet Haase64a48c12012-02-13 16:33:29 -080012919 if (a != null) {
Chet Haasebcca79a2012-02-14 08:45:14 -080012920 more = drawAnimation(parent, drawingTime, a, scalingRequired);
Chet Haase64a48c12012-02-13 16:33:29 -080012921 concatMatrix = a.willChangeTransformationMatrix();
Chet Haaseafd5c3e2012-05-10 13:21:10 -070012922 if (concatMatrix) {
Chet Haase21433372012-06-05 07:54:09 -070012923 mPrivateFlags3 |= VIEW_IS_ANIMATING_TRANSFORM;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070012924 }
Chet Haasebcca79a2012-02-14 08:45:14 -080012925 transformToApply = parent.mChildTransformation;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070012926 } else {
Chet Haase21433372012-06-05 07:54:09 -070012927 if ((mPrivateFlags3 & VIEW_IS_ANIMATING_TRANSFORM) == VIEW_IS_ANIMATING_TRANSFORM &&
Chet Haaseafd5c3e2012-05-10 13:21:10 -070012928 mDisplayList != null) {
12929 // No longer animating: clear out old animation matrix
12930 mDisplayList.setAnimationMatrix(null);
Chet Haase21433372012-06-05 07:54:09 -070012931 mPrivateFlags3 &= ~VIEW_IS_ANIMATING_TRANSFORM;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070012932 }
12933 if (!useDisplayListProperties &&
12934 (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
12935 final boolean hasTransform =
12936 parent.getChildStaticTransformation(this, parent.mChildTransformation);
12937 if (hasTransform) {
12938 final int transformType = parent.mChildTransformation.getTransformationType();
12939 transformToApply = transformType != Transformation.TYPE_IDENTITY ?
12940 parent.mChildTransformation : null;
12941 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
12942 }
Chet Haase64a48c12012-02-13 16:33:29 -080012943 }
12944 }
12945
12946 concatMatrix |= !childHasIdentityMatrix;
12947
12948 // Sets the flag as early as possible to allow draw() implementations
12949 // to call invalidate() successfully when doing animations
12950 mPrivateFlags |= DRAWN;
12951
Chet Haase599913d2012-07-23 16:22:05 -070012952 if (!concatMatrix && (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) == 0 &&
12953 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
Chet Haase64a48c12012-02-13 16:33:29 -080012954 (mPrivateFlags & DRAW_ANIMATION) == 0) {
Chet Haase1a3ab172012-05-11 08:41:20 -070012955 mPrivateFlags2 |= VIEW_QUICK_REJECTED;
Chet Haase64a48c12012-02-13 16:33:29 -080012956 return more;
12957 }
Chet Haase1a3ab172012-05-11 08:41:20 -070012958 mPrivateFlags2 &= ~VIEW_QUICK_REJECTED;
Chet Haase64a48c12012-02-13 16:33:29 -080012959
12960 if (hardwareAccelerated) {
12961 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
12962 // retain the flag's value temporarily in the mRecreateDisplayList flag
12963 mRecreateDisplayList = (mPrivateFlags & INVALIDATED) == INVALIDATED;
12964 mPrivateFlags &= ~INVALIDATED;
12965 }
12966
Chet Haase64a48c12012-02-13 16:33:29 -080012967 DisplayList displayList = null;
12968 Bitmap cache = null;
12969 boolean hasDisplayList = false;
12970 if (caching) {
12971 if (!hardwareAccelerated) {
12972 if (layerType != LAYER_TYPE_NONE) {
12973 layerType = LAYER_TYPE_SOFTWARE;
12974 buildDrawingCache(true);
12975 }
12976 cache = getDrawingCache(true);
12977 } else {
12978 switch (layerType) {
12979 case LAYER_TYPE_SOFTWARE:
Chet Haaseb85967b2012-03-26 14:37:51 -070012980 if (useDisplayListProperties) {
12981 hasDisplayList = canHaveDisplayList();
12982 } else {
12983 buildDrawingCache(true);
12984 cache = getDrawingCache(true);
12985 }
Chet Haase64a48c12012-02-13 16:33:29 -080012986 break;
Chet Haasea1cff502012-02-21 13:43:44 -080012987 case LAYER_TYPE_HARDWARE:
12988 if (useDisplayListProperties) {
12989 hasDisplayList = canHaveDisplayList();
12990 }
12991 break;
Chet Haase64a48c12012-02-13 16:33:29 -080012992 case LAYER_TYPE_NONE:
12993 // Delay getting the display list until animation-driven alpha values are
12994 // set up and possibly passed on to the view
12995 hasDisplayList = canHaveDisplayList();
12996 break;
12997 }
12998 }
12999 }
Chet Haasea1cff502012-02-21 13:43:44 -080013000 useDisplayListProperties &= hasDisplayList;
Chet Haase9420abd2012-03-29 16:28:32 -070013001 if (useDisplayListProperties) {
13002 displayList = getDisplayList();
13003 if (!displayList.isValid()) {
13004 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13005 // to getDisplayList(), the display list will be marked invalid and we should not
13006 // try to use it again.
13007 displayList = null;
13008 hasDisplayList = false;
13009 useDisplayListProperties = false;
13010 }
13011 }
Chet Haase64a48c12012-02-13 16:33:29 -080013012
Chet Haase526057b2012-07-12 17:50:41 -070013013 int sx = 0;
13014 int sy = 0;
13015 if (!hasDisplayList) {
13016 computeScroll();
13017 sx = mScrollX;
13018 sy = mScrollY;
13019 }
13020
Chet Haase64a48c12012-02-13 16:33:29 -080013021 final boolean hasNoCache = cache == null || hasDisplayList;
13022 final boolean offsetForScroll = cache == null && !hasDisplayList &&
13023 layerType != LAYER_TYPE_HARDWARE;
13024
Chet Haasea1cff502012-02-21 13:43:44 -080013025 int restoreTo = -1;
Chet Haase89b7f2e2012-03-21 11:15:37 -070013026 if (!useDisplayListProperties || transformToApply != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080013027 restoreTo = canvas.save();
13028 }
Chet Haase64a48c12012-02-13 16:33:29 -080013029 if (offsetForScroll) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013030 canvas.translate(mLeft - sx, mTop - sy);
Chet Haase64a48c12012-02-13 16:33:29 -080013031 } else {
Chet Haasea1cff502012-02-21 13:43:44 -080013032 if (!useDisplayListProperties) {
13033 canvas.translate(mLeft, mTop);
13034 }
Chet Haase64a48c12012-02-13 16:33:29 -080013035 if (scalingRequired) {
Chet Haasea1cff502012-02-21 13:43:44 -080013036 if (useDisplayListProperties) {
Chet Haase9420abd2012-03-29 16:28:32 -070013037 // TODO: Might not need this if we put everything inside the DL
Chet Haasea1cff502012-02-21 13:43:44 -080013038 restoreTo = canvas.save();
13039 }
Chet Haase64a48c12012-02-13 16:33:29 -080013040 // mAttachInfo cannot be null, otherwise scalingRequired == false
13041 final float scale = 1.0f / mAttachInfo.mApplicationScale;
13042 canvas.scale(scale, scale);
13043 }
13044 }
13045
Chet Haasea1cff502012-02-21 13:43:44 -080013046 float alpha = useDisplayListProperties ? 1 : getAlpha();
Chet Haase21433372012-06-05 07:54:09 -070013047 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
13048 (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
Chet Haase64a48c12012-02-13 16:33:29 -080013049 if (transformToApply != null || !childHasIdentityMatrix) {
13050 int transX = 0;
13051 int transY = 0;
13052
13053 if (offsetForScroll) {
13054 transX = -sx;
13055 transY = -sy;
13056 }
13057
13058 if (transformToApply != null) {
13059 if (concatMatrix) {
Chet Haase9420abd2012-03-29 16:28:32 -070013060 if (useDisplayListProperties) {
13061 displayList.setAnimationMatrix(transformToApply.getMatrix());
13062 } else {
13063 // Undo the scroll translation, apply the transformation matrix,
13064 // then redo the scroll translate to get the correct result.
13065 canvas.translate(-transX, -transY);
13066 canvas.concat(transformToApply.getMatrix());
13067 canvas.translate(transX, transY);
13068 }
Chet Haasea1cff502012-02-21 13:43:44 -080013069 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013070 }
13071
13072 float transformAlpha = transformToApply.getAlpha();
Chet Haase9420abd2012-03-29 16:28:32 -070013073 if (transformAlpha < 1) {
Chet Haase21433372012-06-05 07:54:09 -070013074 alpha *= transformAlpha;
Chet Haasea1cff502012-02-21 13:43:44 -080013075 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013076 }
13077 }
13078
Chet Haasea1cff502012-02-21 13:43:44 -080013079 if (!childHasIdentityMatrix && !useDisplayListProperties) {
Chet Haase64a48c12012-02-13 16:33:29 -080013080 canvas.translate(-transX, -transY);
13081 canvas.concat(getMatrix());
13082 canvas.translate(transX, transY);
13083 }
13084 }
13085
Chet Haase21433372012-06-05 07:54:09 -070013086 // Deal with alpha if it is or used to be <1
13087 if (alpha < 1 ||
13088 (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
13089 if (alpha < 1) {
13090 mPrivateFlags3 |= VIEW_IS_ANIMATING_ALPHA;
13091 } else {
13092 mPrivateFlags3 &= ~VIEW_IS_ANIMATING_ALPHA;
13093 }
Chet Haasea1cff502012-02-21 13:43:44 -080013094 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013095 if (hasNoCache) {
13096 final int multipliedAlpha = (int) (255 * alpha);
13097 if (!onSetAlpha(multipliedAlpha)) {
13098 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
Chet Haasea1cff502012-02-21 13:43:44 -080013099 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
Chet Haase64a48c12012-02-13 16:33:29 -080013100 layerType != LAYER_TYPE_NONE) {
13101 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
13102 }
Chet Haase9420abd2012-03-29 16:28:32 -070013103 if (useDisplayListProperties) {
13104 displayList.setAlpha(alpha * getAlpha());
13105 } else if (layerType == LAYER_TYPE_NONE) {
Chet Haase89b7f2e2012-03-21 11:15:37 -070013106 final int scrollX = hasDisplayList ? 0 : sx;
13107 final int scrollY = hasDisplayList ? 0 : sy;
13108 canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
13109 scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
Chet Haase64a48c12012-02-13 16:33:29 -080013110 }
13111 } else {
13112 // Alpha is handled by the child directly, clobber the layer's alpha
13113 mPrivateFlags |= ALPHA_SET;
13114 }
13115 }
13116 }
13117 } else if ((mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
13118 onSetAlpha(255);
13119 mPrivateFlags &= ~ALPHA_SET;
13120 }
13121
Chet Haasea1cff502012-02-21 13:43:44 -080013122 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
13123 !useDisplayListProperties) {
Chet Haase64a48c12012-02-13 16:33:29 -080013124 if (offsetForScroll) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013125 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
Chet Haase64a48c12012-02-13 16:33:29 -080013126 } else {
13127 if (!scalingRequired || cache == null) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013128 canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
Chet Haase64a48c12012-02-13 16:33:29 -080013129 } else {
13130 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
13131 }
13132 }
13133 }
13134
Chet Haase9420abd2012-03-29 16:28:32 -070013135 if (!useDisplayListProperties && hasDisplayList) {
Chet Haase64a48c12012-02-13 16:33:29 -080013136 displayList = getDisplayList();
13137 if (!displayList.isValid()) {
13138 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13139 // to getDisplayList(), the display list will be marked invalid and we should not
13140 // try to use it again.
13141 displayList = null;
13142 hasDisplayList = false;
13143 }
13144 }
13145
13146 if (hasNoCache) {
13147 boolean layerRendered = false;
Chet Haasea1cff502012-02-21 13:43:44 -080013148 if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
Michael Jurka7e52caf2012-03-06 15:57:06 -080013149 final HardwareLayer layer = getHardwareLayer();
Chet Haase64a48c12012-02-13 16:33:29 -080013150 if (layer != null && layer.isValid()) {
13151 mLayerPaint.setAlpha((int) (alpha * 255));
13152 ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
13153 layerRendered = true;
13154 } else {
13155 final int scrollX = hasDisplayList ? 0 : sx;
13156 final int scrollY = hasDisplayList ? 0 : sy;
13157 canvas.saveLayer(scrollX, scrollY,
Chet Haasebcca79a2012-02-14 08:45:14 -080013158 scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
Chet Haase64a48c12012-02-13 16:33:29 -080013159 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13160 }
13161 }
13162
13163 if (!layerRendered) {
13164 if (!hasDisplayList) {
13165 // Fast path for layouts with no backgrounds
13166 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
Chet Haase64a48c12012-02-13 16:33:29 -080013167 mPrivateFlags &= ~DIRTY_MASK;
13168 dispatchDraw(canvas);
13169 } else {
13170 draw(canvas);
13171 }
13172 } else {
13173 mPrivateFlags &= ~DIRTY_MASK;
Chet Haase1271e2c2012-04-20 09:54:27 -070013174 ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
Chet Haase64a48c12012-02-13 16:33:29 -080013175 }
13176 }
13177 } else if (cache != null) {
13178 mPrivateFlags &= ~DIRTY_MASK;
13179 Paint cachePaint;
13180
13181 if (layerType == LAYER_TYPE_NONE) {
13182 cachePaint = parent.mCachePaint;
13183 if (cachePaint == null) {
13184 cachePaint = new Paint();
13185 cachePaint.setDither(false);
13186 parent.mCachePaint = cachePaint;
13187 }
Chet Haase9420abd2012-03-29 16:28:32 -070013188 if (alpha < 1) {
Chet Haase64a48c12012-02-13 16:33:29 -080013189 cachePaint.setAlpha((int) (alpha * 255));
Chet Haasea1cff502012-02-21 13:43:44 -080013190 parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13191 } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
Chet Haase64a48c12012-02-13 16:33:29 -080013192 cachePaint.setAlpha(255);
Chet Haasea1cff502012-02-21 13:43:44 -080013193 parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
Chet Haase64a48c12012-02-13 16:33:29 -080013194 }
13195 } else {
13196 cachePaint = mLayerPaint;
13197 cachePaint.setAlpha((int) (alpha * 255));
13198 }
13199 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
13200 }
13201
Chet Haasea1cff502012-02-21 13:43:44 -080013202 if (restoreTo >= 0) {
13203 canvas.restoreToCount(restoreTo);
13204 }
Chet Haase64a48c12012-02-13 16:33:29 -080013205
13206 if (a != null && !more) {
13207 if (!hardwareAccelerated && !a.getFillAfter()) {
13208 onSetAlpha(255);
13209 }
13210 parent.finishAnimatingView(this, a);
13211 }
13212
13213 if (more && hardwareAccelerated) {
13214 // invalidation is the trigger to recreate display lists, so if we're using
13215 // display lists to render, force an invalidate to allow the animation to
13216 // continue drawing another frame
13217 parent.invalidate(true);
13218 if (a.hasAlpha() && (mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
13219 // alpha animations should cause the child to recreate its display list
13220 invalidate(true);
13221 }
13222 }
13223
13224 mRecreateDisplayList = false;
13225
13226 return more;
13227 }
13228
13229 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 * Manually render this view (and all of its children) to the given Canvas.
13231 * The view must have already done a full layout before this function is
Romain Guy5c22a8c2011-05-13 11:48:45 -070013232 * called. When implementing a view, implement
13233 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
13234 * If you do need to override this method, call the superclass version.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013235 *
13236 * @param canvas The Canvas to which the View is rendered.
13237 */
13238 public void draw(Canvas canvas) {
Romain Guy5bcdff42009-05-14 21:27:18 -070013239 final int privateFlags = mPrivateFlags;
13240 final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
13241 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
13242 mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
Romain Guy24443ea2009-05-11 11:56:30 -070013243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013244 /*
13245 * Draw traversal performs several drawing steps which must be executed
13246 * in the appropriate order:
13247 *
13248 * 1. Draw the background
13249 * 2. If necessary, save the canvas' layers to prepare for fading
13250 * 3. Draw view's content
13251 * 4. Draw children
13252 * 5. If necessary, draw the fading edges and restore layers
13253 * 6. Draw decorations (scrollbars for instance)
13254 */
13255
13256 // Step 1, draw the background, if needed
13257 int saveCount;
13258
Romain Guy24443ea2009-05-11 11:56:30 -070013259 if (!dirtyOpaque) {
Philip Milne6c8ea062012-04-03 17:38:43 -070013260 final Drawable background = mBackground;
Romain Guy24443ea2009-05-11 11:56:30 -070013261 if (background != null) {
13262 final int scrollX = mScrollX;
13263 final int scrollY = mScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013264
Romain Guy24443ea2009-05-11 11:56:30 -070013265 if (mBackgroundSizeChanged) {
13266 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
13267 mBackgroundSizeChanged = false;
13268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013269
Romain Guy24443ea2009-05-11 11:56:30 -070013270 if ((scrollX | scrollY) == 0) {
13271 background.draw(canvas);
13272 } else {
13273 canvas.translate(scrollX, scrollY);
13274 background.draw(canvas);
13275 canvas.translate(-scrollX, -scrollY);
13276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013277 }
13278 }
13279
13280 // skip step 2 & 5 if possible (common case)
13281 final int viewFlags = mViewFlags;
13282 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
13283 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
13284 if (!verticalEdges && !horizontalEdges) {
13285 // Step 3, draw the content
Romain Guy24443ea2009-05-11 11:56:30 -070013286 if (!dirtyOpaque) onDraw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013287
13288 // Step 4, draw the children
13289 dispatchDraw(canvas);
13290
13291 // Step 6, draw decorations (scrollbars)
13292 onDrawScrollBars(canvas);
13293
13294 // we're done...
13295 return;
13296 }
13297
13298 /*
13299 * Here we do the full fledged routine...
13300 * (this is an uncommon case where speed matters less,
13301 * this is why we repeat some of the tests that have been
13302 * done above)
13303 */
13304
13305 boolean drawTop = false;
13306 boolean drawBottom = false;
13307 boolean drawLeft = false;
13308 boolean drawRight = false;
13309
13310 float topFadeStrength = 0.0f;
13311 float bottomFadeStrength = 0.0f;
13312 float leftFadeStrength = 0.0f;
13313 float rightFadeStrength = 0.0f;
13314
13315 // Step 2, save the canvas' layers
13316 int paddingLeft = mPaddingLeft;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013317
13318 final boolean offsetRequired = isPaddingOffsetRequired();
13319 if (offsetRequired) {
13320 paddingLeft += getLeftPaddingOffset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013321 }
13322
13323 int left = mScrollX + paddingLeft;
13324 int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
Romain Guyf2fc4602011-07-19 15:20:03 -070013325 int top = mScrollY + getFadeTop(offsetRequired);
13326 int bottom = top + getFadeHeight(offsetRequired);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013327
13328 if (offsetRequired) {
13329 right += getRightPaddingOffset();
13330 bottom += getBottomPaddingOffset();
13331 }
13332
13333 final ScrollabilityCache scrollabilityCache = mScrollCache;
Philip Milne6c8ea062012-04-03 17:38:43 -070013334 final float fadeHeight = scrollabilityCache.fadingEdgeLength;
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013335 int length = (int) fadeHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013336
13337 // clip the fade length if top and bottom fades overlap
13338 // overlapping fades produce odd-looking artifacts
13339 if (verticalEdges && (top + length > bottom - length)) {
13340 length = (bottom - top) / 2;
13341 }
13342
13343 // also clip horizontal fades if necessary
13344 if (horizontalEdges && (left + length > right - length)) {
13345 length = (right - left) / 2;
13346 }
13347
13348 if (verticalEdges) {
13349 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013350 drawTop = topFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013351 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013352 drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013353 }
13354
13355 if (horizontalEdges) {
13356 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013357 drawLeft = leftFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013359 drawRight = rightFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 }
13361
13362 saveCount = canvas.getSaveCount();
13363
13364 int solidColor = getSolidColor();
Romain Guyf607bdc2010-09-10 19:20:06 -070013365 if (solidColor == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013366 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13367
13368 if (drawTop) {
13369 canvas.saveLayer(left, top, right, top + length, null, flags);
13370 }
13371
13372 if (drawBottom) {
13373 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
13374 }
13375
13376 if (drawLeft) {
13377 canvas.saveLayer(left, top, left + length, bottom, null, flags);
13378 }
13379
13380 if (drawRight) {
13381 canvas.saveLayer(right - length, top, right, bottom, null, flags);
13382 }
13383 } else {
13384 scrollabilityCache.setFadeColor(solidColor);
13385 }
13386
13387 // Step 3, draw the content
Romain Guy24443ea2009-05-11 11:56:30 -070013388 if (!dirtyOpaque) onDraw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013389
13390 // Step 4, draw the children
13391 dispatchDraw(canvas);
13392
13393 // Step 5, draw the fade effect and restore layers
13394 final Paint p = scrollabilityCache.paint;
13395 final Matrix matrix = scrollabilityCache.matrix;
13396 final Shader fade = scrollabilityCache.shader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397
13398 if (drawTop) {
13399 matrix.setScale(1, fadeHeight * topFadeStrength);
13400 matrix.postTranslate(left, top);
13401 fade.setLocalMatrix(matrix);
13402 canvas.drawRect(left, top, right, top + length, p);
13403 }
13404
13405 if (drawBottom) {
13406 matrix.setScale(1, fadeHeight * bottomFadeStrength);
13407 matrix.postRotate(180);
13408 matrix.postTranslate(left, bottom);
13409 fade.setLocalMatrix(matrix);
13410 canvas.drawRect(left, bottom - length, right, bottom, p);
13411 }
13412
13413 if (drawLeft) {
13414 matrix.setScale(1, fadeHeight * leftFadeStrength);
13415 matrix.postRotate(-90);
13416 matrix.postTranslate(left, top);
13417 fade.setLocalMatrix(matrix);
13418 canvas.drawRect(left, top, left + length, bottom, p);
13419 }
13420
13421 if (drawRight) {
13422 matrix.setScale(1, fadeHeight * rightFadeStrength);
13423 matrix.postRotate(90);
13424 matrix.postTranslate(right, top);
13425 fade.setLocalMatrix(matrix);
13426 canvas.drawRect(right - length, top, right, bottom, p);
13427 }
13428
13429 canvas.restoreToCount(saveCount);
13430
13431 // Step 6, draw decorations (scrollbars)
13432 onDrawScrollBars(canvas);
13433 }
13434
13435 /**
13436 * Override this if your view is known to always be drawn on top of a solid color background,
13437 * and needs to draw fading edges. Returning a non-zero color enables the view system to
13438 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
13439 * should be set to 0xFF.
13440 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013441 * @see #setVerticalFadingEdgeEnabled(boolean)
13442 * @see #setHorizontalFadingEdgeEnabled(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013443 *
13444 * @return The known solid color background for this view, or 0 if the color may vary
13445 */
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013446 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 public int getSolidColor() {
13448 return 0;
13449 }
13450
13451 /**
13452 * Build a human readable string representation of the specified view flags.
13453 *
13454 * @param flags the view flags to convert to a string
13455 * @return a String representing the supplied flags
13456 */
13457 private static String printFlags(int flags) {
13458 String output = "";
13459 int numFlags = 0;
13460 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
13461 output += "TAKES_FOCUS";
13462 numFlags++;
13463 }
13464
13465 switch (flags & VISIBILITY_MASK) {
13466 case INVISIBLE:
13467 if (numFlags > 0) {
13468 output += " ";
13469 }
13470 output += "INVISIBLE";
13471 // USELESS HERE numFlags++;
13472 break;
13473 case GONE:
13474 if (numFlags > 0) {
13475 output += " ";
13476 }
13477 output += "GONE";
13478 // USELESS HERE numFlags++;
13479 break;
13480 default:
13481 break;
13482 }
13483 return output;
13484 }
13485
13486 /**
13487 * Build a human readable string representation of the specified private
13488 * view flags.
13489 *
13490 * @param privateFlags the private view flags to convert to a string
13491 * @return a String representing the supplied flags
13492 */
13493 private static String printPrivateFlags(int privateFlags) {
13494 String output = "";
13495 int numFlags = 0;
13496
13497 if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
13498 output += "WANTS_FOCUS";
13499 numFlags++;
13500 }
13501
13502 if ((privateFlags & FOCUSED) == FOCUSED) {
13503 if (numFlags > 0) {
13504 output += " ";
13505 }
13506 output += "FOCUSED";
13507 numFlags++;
13508 }
13509
13510 if ((privateFlags & SELECTED) == SELECTED) {
13511 if (numFlags > 0) {
13512 output += " ";
13513 }
13514 output += "SELECTED";
13515 numFlags++;
13516 }
13517
13518 if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
13519 if (numFlags > 0) {
13520 output += " ";
13521 }
13522 output += "IS_ROOT_NAMESPACE";
13523 numFlags++;
13524 }
13525
13526 if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
13527 if (numFlags > 0) {
13528 output += " ";
13529 }
13530 output += "HAS_BOUNDS";
13531 numFlags++;
13532 }
13533
13534 if ((privateFlags & DRAWN) == DRAWN) {
13535 if (numFlags > 0) {
13536 output += " ";
13537 }
13538 output += "DRAWN";
13539 // USELESS HERE numFlags++;
13540 }
13541 return output;
13542 }
13543
13544 /**
13545 * <p>Indicates whether or not this view's layout will be requested during
13546 * the next hierarchy layout pass.</p>
13547 *
13548 * @return true if the layout will be forced during next layout pass
13549 */
13550 public boolean isLayoutRequested() {
13551 return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
13552 }
13553
13554 /**
13555 * Assign a size and position to a view and all of its
13556 * descendants
13557 *
13558 * <p>This is the second phase of the layout mechanism.
13559 * (The first is measuring). In this phase, each parent calls
13560 * layout on all of its children to position them.
13561 * This is typically done using the child measurements
Chet Haase9c087442011-01-12 16:20:16 -080013562 * that were stored in the measure pass().</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013563 *
Chet Haase9c087442011-01-12 16:20:16 -080013564 * <p>Derived classes should not override this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013565 * Derived classes with children should override
13566 * onLayout. In that method, they should
Chet Haase9c087442011-01-12 16:20:16 -080013567 * call layout on each of their children.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013568 *
13569 * @param l Left position, relative to parent
13570 * @param t Top position, relative to parent
13571 * @param r Right position, relative to parent
13572 * @param b Bottom position, relative to parent
13573 */
Romain Guy5429e1d2010-09-07 12:38:00 -070013574 @SuppressWarnings({"unchecked"})
Chet Haase9c087442011-01-12 16:20:16 -080013575 public void layout(int l, int t, int r, int b) {
Chet Haase21cd1382010-09-01 17:42:29 -070013576 int oldL = mLeft;
13577 int oldT = mTop;
13578 int oldB = mBottom;
13579 int oldR = mRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013580 boolean changed = setFrame(l, t, r, b);
13581 if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013582 onLayout(changed, l, t, r, b);
13583 mPrivateFlags &= ~LAYOUT_REQUIRED;
Chet Haase21cd1382010-09-01 17:42:29 -070013584
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070013585 ListenerInfo li = mListenerInfo;
13586 if (li != null && li.mOnLayoutChangeListeners != null) {
Chet Haase21cd1382010-09-01 17:42:29 -070013587 ArrayList<OnLayoutChangeListener> listenersCopy =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070013588 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
Chet Haase21cd1382010-09-01 17:42:29 -070013589 int numListeners = listenersCopy.size();
13590 for (int i = 0; i < numListeners; ++i) {
Chet Haase7c608f22010-10-22 17:54:04 -070013591 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
Chet Haase21cd1382010-09-01 17:42:29 -070013592 }
13593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013594 }
13595 mPrivateFlags &= ~FORCE_LAYOUT;
13596 }
13597
13598 /**
13599 * Called from layout when this view should
13600 * assign a size and position to each of its children.
13601 *
13602 * Derived classes with children should override
13603 * this method and call layout on each of
Chet Haase21cd1382010-09-01 17:42:29 -070013604 * their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 * @param changed This is a new size or position for this view
13606 * @param left Left position, relative to parent
13607 * @param top Top position, relative to parent
13608 * @param right Right position, relative to parent
13609 * @param bottom Bottom position, relative to parent
13610 */
13611 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
13612 }
13613
13614 /**
13615 * Assign a size and position to this view.
13616 *
13617 * This is called from layout.
13618 *
13619 * @param left Left position, relative to parent
13620 * @param top Top position, relative to parent
13621 * @param right Right position, relative to parent
13622 * @param bottom Bottom position, relative to parent
13623 * @return true if the new size and position are different than the
13624 * previous ones
13625 * {@hide}
13626 */
13627 protected boolean setFrame(int left, int top, int right, int bottom) {
13628 boolean changed = false;
13629
13630 if (DBG) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -070013631 Log.d("View", this + " View.setFrame(" + left + "," + top + ","
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013632 + right + "," + bottom + ")");
13633 }
13634
13635 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
13636 changed = true;
13637
13638 // Remember our drawn bit
13639 int drawn = mPrivateFlags & DRAWN;
13640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013641 int oldWidth = mRight - mLeft;
13642 int oldHeight = mBottom - mTop;
Chet Haase75755e22011-07-18 17:48:25 -070013643 int newWidth = right - left;
13644 int newHeight = bottom - top;
13645 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
13646
13647 // Invalidate our old position
13648 invalidate(sizeChanged);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013649
13650 mLeft = left;
13651 mTop = top;
13652 mRight = right;
13653 mBottom = bottom;
Chet Haase1271e2c2012-04-20 09:54:27 -070013654 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080013655 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013657
13658 mPrivateFlags |= HAS_BOUNDS;
13659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013660
Chet Haase75755e22011-07-18 17:48:25 -070013661 if (sizeChanged) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013662 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
13663 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -070013664 if (mTransformationInfo != null) {
13665 mTransformationInfo.mMatrixDirty = true;
13666 }
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013668 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
13669 }
13670
13671 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
13672 // If we are visible, force the DRAWN bit to on so that
13673 // this invalidate will go through (at least to our parent).
13674 // This is because someone may have invalidated this view
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013675 // before this call to setFrame came in, thereby clearing
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 // the DRAWN bit.
13677 mPrivateFlags |= DRAWN;
Chet Haase75755e22011-07-18 17:48:25 -070013678 invalidate(sizeChanged);
Chet Haasef28595e2011-01-31 18:52:12 -080013679 // parent display list may need to be recreated based on a change in the bounds
13680 // of any child
13681 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 }
13683
13684 // Reset drawn bit to original value (invalidate turns it off)
13685 mPrivateFlags |= drawn;
13686
13687 mBackgroundSizeChanged = true;
13688 }
13689 return changed;
13690 }
13691
13692 /**
13693 * Finalize inflating a view from XML. This is called as the last phase
13694 * of inflation, after all child views have been added.
13695 *
13696 * <p>Even if the subclass overrides onFinishInflate, they should always be
13697 * sure to call the super method, so that we get called.
13698 */
13699 protected void onFinishInflate() {
13700 }
13701
13702 /**
13703 * Returns the resources associated with this view.
13704 *
13705 * @return Resources object.
13706 */
13707 public Resources getResources() {
13708 return mResources;
13709 }
13710
13711 /**
13712 * Invalidates the specified Drawable.
13713 *
13714 * @param drawable the drawable to invalidate
13715 */
13716 public void invalidateDrawable(Drawable drawable) {
13717 if (verifyDrawable(drawable)) {
13718 final Rect dirty = drawable.getBounds();
13719 final int scrollX = mScrollX;
13720 final int scrollY = mScrollY;
13721
13722 invalidate(dirty.left + scrollX, dirty.top + scrollY,
13723 dirty.right + scrollX, dirty.bottom + scrollY);
13724 }
13725 }
13726
13727 /**
13728 * Schedules an action on a drawable to occur at a specified time.
13729 *
13730 * @param who the recipient of the action
13731 * @param what the action to run on the drawable
13732 * @param when the time at which the action must occur. Uses the
13733 * {@link SystemClock#uptimeMillis} timebase.
13734 */
13735 public void scheduleDrawable(Drawable who, Runnable what, long when) {
Adam Powell37419d72011-11-10 11:32:09 -080013736 if (verifyDrawable(who) && what != null) {
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080013737 final long delay = when - SystemClock.uptimeMillis();
Adam Powell37419d72011-11-10 11:32:09 -080013738 if (mAttachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013739 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13740 Choreographer.CALLBACK_ANIMATION, what, who,
13741 Choreographer.subtractFrameDelay(delay));
Adam Powell37419d72011-11-10 11:32:09 -080013742 } else {
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080013743 ViewRootImpl.getRunQueue().postDelayed(what, delay);
Adam Powell37419d72011-11-10 11:32:09 -080013744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013745 }
13746 }
13747
13748 /**
13749 * Cancels a scheduled action on a drawable.
13750 *
13751 * @param who the recipient of the action
13752 * @param what the action to cancel
13753 */
13754 public void unscheduleDrawable(Drawable who, Runnable what) {
Adam Powell37419d72011-11-10 11:32:09 -080013755 if (verifyDrawable(who) && what != null) {
13756 if (mAttachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013757 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13758 Choreographer.CALLBACK_ANIMATION, what, who);
Adam Powell37419d72011-11-10 11:32:09 -080013759 } else {
13760 ViewRootImpl.getRunQueue().removeCallbacks(what);
13761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 }
13763 }
13764
13765 /**
13766 * Unschedule any events associated with the given Drawable. This can be
13767 * used when selecting a new Drawable into a view, so that the previous
13768 * one is completely unscheduled.
13769 *
13770 * @param who The Drawable to unschedule.
13771 *
13772 * @see #drawableStateChanged
13773 */
13774 public void unscheduleDrawable(Drawable who) {
Jeff Brown43ea54b2012-03-09 14:37:48 -080013775 if (mAttachInfo != null && who != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013776 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13777 Choreographer.CALLBACK_ANIMATION, null, who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013778 }
13779 }
13780
Fabrice Di Meglioc0053222011-06-13 12:16:51 -070013781 /**
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070013782 * Resolve the Drawables depending on the layout direction. This is implicitly supposing
13783 * that the View directionality can and will be resolved before its Drawables.
13784 *
13785 * Will call {@link View#onResolveDrawables} when resolution is done.
13786 */
13787 public void resolveDrawables() {
13788 if (mBackground != null) {
13789 mBackground.setLayoutDirection(getResolvedLayoutDirection());
13790 }
13791 onResolveDrawables(getResolvedLayoutDirection());
13792 }
13793
13794 /**
13795 * Called when layout direction has been resolved.
13796 *
13797 * The default implementation does nothing.
13798 *
13799 * @param layoutDirection The resolved layout direction.
13800 *
13801 * @see {@link #LAYOUT_DIRECTION_LTR}
13802 * @see {@link #LAYOUT_DIRECTION_RTL}
13803 */
13804 public void onResolveDrawables(int layoutDirection) {
Fabrice Di Meglio6a036402011-05-23 14:43:23 -070013805 }
13806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013807 /**
13808 * If your view subclass is displaying its own Drawable objects, it should
13809 * override this function and return true for any Drawable it is
13810 * displaying. This allows animations for those drawables to be
13811 * scheduled.
13812 *
13813 * <p>Be sure to call through to the super class when overriding this
13814 * function.
13815 *
13816 * @param who The Drawable to verify. Return true if it is one you are
13817 * displaying, else return the result of calling through to the
13818 * super class.
13819 *
13820 * @return boolean If true than the Drawable is being displayed in the
13821 * view; else false and it is not allowed to animate.
13822 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013823 * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
13824 * @see #drawableStateChanged()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013825 */
13826 protected boolean verifyDrawable(Drawable who) {
Philip Milne6c8ea062012-04-03 17:38:43 -070013827 return who == mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013828 }
13829
13830 /**
13831 * This function is called whenever the state of the view changes in such
13832 * a way that it impacts the state of drawables being shown.
13833 *
13834 * <p>Be sure to call through to the superclass when overriding this
13835 * function.
13836 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013837 * @see Drawable#setState(int[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013838 */
13839 protected void drawableStateChanged() {
Philip Milne6c8ea062012-04-03 17:38:43 -070013840 Drawable d = mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013841 if (d != null && d.isStateful()) {
13842 d.setState(getDrawableState());
13843 }
13844 }
13845
13846 /**
13847 * Call this to force a view to update its drawable state. This will cause
13848 * drawableStateChanged to be called on this view. Views that are interested
13849 * in the new state should call getDrawableState.
13850 *
13851 * @see #drawableStateChanged
13852 * @see #getDrawableState
13853 */
13854 public void refreshDrawableState() {
13855 mPrivateFlags |= DRAWABLE_STATE_DIRTY;
13856 drawableStateChanged();
13857
13858 ViewParent parent = mParent;
13859 if (parent != null) {
13860 parent.childDrawableStateChanged(this);
13861 }
13862 }
13863
13864 /**
13865 * Return an array of resource IDs of the drawable states representing the
13866 * current state of the view.
13867 *
13868 * @return The current drawable state
13869 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013870 * @see Drawable#setState(int[])
13871 * @see #drawableStateChanged()
13872 * @see #onCreateDrawableState(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873 */
13874 public final int[] getDrawableState() {
13875 if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
13876 return mDrawableState;
13877 } else {
13878 mDrawableState = onCreateDrawableState(0);
13879 mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
13880 return mDrawableState;
13881 }
13882 }
13883
13884 /**
13885 * Generate the new {@link android.graphics.drawable.Drawable} state for
13886 * this view. This is called by the view
13887 * system when the cached Drawable state is determined to be invalid. To
13888 * retrieve the current state, you should use {@link #getDrawableState}.
13889 *
13890 * @param extraSpace if non-zero, this is the number of extra entries you
13891 * would like in the returned array in which you can place your own
13892 * states.
13893 *
13894 * @return Returns an array holding the current {@link Drawable} state of
13895 * the view.
13896 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013897 * @see #mergeDrawableStates(int[], int[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013898 */
13899 protected int[] onCreateDrawableState(int extraSpace) {
13900 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
13901 mParent instanceof View) {
13902 return ((View) mParent).onCreateDrawableState(extraSpace);
13903 }
13904
13905 int[] drawableState;
13906
13907 int privateFlags = mPrivateFlags;
13908
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070013909 int viewStateIndex = 0;
13910 if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
13911 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
13912 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
Neel Parekhe5378582010-10-06 11:36:50 -070013913 if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070013914 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
13915 if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
Adam Powell5a7e94e2011-04-25 15:30:43 -070013916 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
13917 HardwareRenderer.isAvailable()) {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080013918 // This is set if HW acceleration is requested, even if the current
13919 // process doesn't allow it. This is just to allow app preview
13920 // windows to better match their app.
13921 viewStateIndex |= VIEW_STATE_ACCELERATED;
13922 }
PY Laligandc33d8d49e2011-03-14 18:22:53 -070013923 if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013924
Christopher Tate3d4bf172011-03-28 16:16:46 -070013925 final int privateFlags2 = mPrivateFlags2;
13926 if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
13927 if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
13928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013929 drawableState = VIEW_STATE_SETS[viewStateIndex];
13930
13931 //noinspection ConstantIfStatement
13932 if (false) {
13933 Log.i("View", "drawableStateIndex=" + viewStateIndex);
13934 Log.i("View", toString()
13935 + " pressed=" + ((privateFlags & PRESSED) != 0)
13936 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
13937 + " fo=" + hasFocus()
13938 + " sl=" + ((privateFlags & SELECTED) != 0)
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070013939 + " wf=" + hasWindowFocus()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013940 + ": " + Arrays.toString(drawableState));
13941 }
13942
13943 if (extraSpace == 0) {
13944 return drawableState;
13945 }
13946
13947 final int[] fullState;
13948 if (drawableState != null) {
13949 fullState = new int[drawableState.length + extraSpace];
13950 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
13951 } else {
13952 fullState = new int[extraSpace];
13953 }
13954
13955 return fullState;
13956 }
13957
13958 /**
13959 * Merge your own state values in <var>additionalState</var> into the base
13960 * state values <var>baseState</var> that were returned by
Romain Guy5c22a8c2011-05-13 11:48:45 -070013961 * {@link #onCreateDrawableState(int)}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013962 *
13963 * @param baseState The base state values returned by
Romain Guy5c22a8c2011-05-13 11:48:45 -070013964 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013965 * own additional state values.
13966 *
13967 * @param additionalState The additional state values you would like
13968 * added to <var>baseState</var>; this array is not modified.
13969 *
13970 * @return As a convenience, the <var>baseState</var> array you originally
13971 * passed into the function is returned.
13972 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013973 * @see #onCreateDrawableState(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013974 */
13975 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
13976 final int N = baseState.length;
13977 int i = N - 1;
13978 while (i >= 0 && baseState[i] == 0) {
13979 i--;
13980 }
13981 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
13982 return baseState;
13983 }
13984
13985 /**
Dianne Hackborn079e2352010-10-18 17:02:43 -070013986 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
13987 * on all Drawable objects associated with this view.
13988 */
13989 public void jumpDrawablesToCurrentState() {
Philip Milne6c8ea062012-04-03 17:38:43 -070013990 if (mBackground != null) {
13991 mBackground.jumpToCurrentState();
Dianne Hackborn079e2352010-10-18 17:02:43 -070013992 }
13993 }
13994
13995 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013996 * Sets the background color for this view.
13997 * @param color the color of the background
13998 */
Bjorn Bringert8354fa62010-02-24 23:54:29 +000013999 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014000 public void setBackgroundColor(int color) {
Philip Milne6c8ea062012-04-03 17:38:43 -070014001 if (mBackground instanceof ColorDrawable) {
14002 ((ColorDrawable) mBackground).setColor(color);
Romain Guy7d3082a2012-07-11 17:52:54 -070014003 computeOpaqueFlags();
Chet Haase70d4ba12010-10-06 09:46:45 -070014004 } else {
Philip Milne6c8ea062012-04-03 17:38:43 -070014005 setBackground(new ColorDrawable(color));
Chet Haase70d4ba12010-10-06 09:46:45 -070014006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014007 }
14008
14009 /**
14010 * Set the background to a given resource. The resource should refer to
Wink Saville7cd88e12009-08-04 14:45:10 -070014011 * a Drawable object or 0 to remove the background.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014012 * @param resid The identifier of the resource.
Philip Milne6c8ea062012-04-03 17:38:43 -070014013 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014014 * @attr ref android.R.styleable#View_background
14015 */
Bjorn Bringert8354fa62010-02-24 23:54:29 +000014016 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014017 public void setBackgroundResource(int resid) {
14018 if (resid != 0 && resid == mBackgroundResource) {
14019 return;
14020 }
14021
14022 Drawable d= null;
14023 if (resid != 0) {
14024 d = mResources.getDrawable(resid);
14025 }
Philip Milne6c8ea062012-04-03 17:38:43 -070014026 setBackground(d);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014027
14028 mBackgroundResource = resid;
14029 }
14030
14031 /**
14032 * Set the background to a given Drawable, or remove the background. If the
14033 * background has padding, this View's padding is set to the background's
14034 * padding. However, when a background is removed, this View's padding isn't
14035 * touched. If setting the padding is desired, please use
14036 * {@link #setPadding(int, int, int, int)}.
14037 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014038 * @param background The Drawable to use as the background, or null to remove the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014039 * background
14040 */
Philip Milne6c8ea062012-04-03 17:38:43 -070014041 public void setBackground(Drawable background) {
Romain Guyeb378892012-04-12 11:33:14 -070014042 //noinspection deprecation
Philip Milne6c8ea062012-04-03 17:38:43 -070014043 setBackgroundDrawable(background);
14044 }
14045
14046 /**
14047 * @deprecated use {@link #setBackground(Drawable)} instead
14048 */
14049 @Deprecated
14050 public void setBackgroundDrawable(Drawable background) {
Romain Guy846a5332012-07-11 17:44:57 -070014051 computeOpaqueFlags();
14052
Philip Milne6c8ea062012-04-03 17:38:43 -070014053 if (background == mBackground) {
Adam Powell4d36ec12011-07-17 16:44:16 -070014054 return;
14055 }
14056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014057 boolean requestLayout = false;
14058
14059 mBackgroundResource = 0;
14060
14061 /*
14062 * Regardless of whether we're setting a new background or not, we want
14063 * to clear the previous drawable.
14064 */
Philip Milne6c8ea062012-04-03 17:38:43 -070014065 if (mBackground != null) {
14066 mBackground.setCallback(null);
14067 unscheduleDrawable(mBackground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014068 }
14069
Philip Milne6c8ea062012-04-03 17:38:43 -070014070 if (background != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014071 Rect padding = sThreadLocal.get();
14072 if (padding == null) {
14073 padding = new Rect();
14074 sThreadLocal.set(padding);
14075 }
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070014076 background.setLayoutDirection(getResolvedLayoutDirection());
Philip Milne6c8ea062012-04-03 17:38:43 -070014077 if (background.getPadding(padding)) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014078 // Reset padding resolution
14079 mPrivateFlags2 &= ~PADDING_RESOLVED;
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070014080 switch (background.getLayoutDirection()) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014081 case LAYOUT_DIRECTION_RTL:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014082 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014083 break;
14084 case LAYOUT_DIRECTION_LTR:
14085 default:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014086 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014088 }
14089
14090 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
14091 // if it has a different minimum size, we should layout again
Philip Milne6c8ea062012-04-03 17:38:43 -070014092 if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
14093 mBackground.getMinimumWidth() != background.getMinimumWidth()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014094 requestLayout = true;
14095 }
14096
Philip Milne6c8ea062012-04-03 17:38:43 -070014097 background.setCallback(this);
14098 if (background.isStateful()) {
14099 background.setState(getDrawableState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014100 }
Philip Milne6c8ea062012-04-03 17:38:43 -070014101 background.setVisible(getVisibility() == VISIBLE, false);
14102 mBackground = background;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014103
14104 if ((mPrivateFlags & SKIP_DRAW) != 0) {
14105 mPrivateFlags &= ~SKIP_DRAW;
14106 mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
14107 requestLayout = true;
14108 }
14109 } else {
14110 /* Remove the background */
Philip Milne6c8ea062012-04-03 17:38:43 -070014111 mBackground = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014112
14113 if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
14114 /*
14115 * This view ONLY drew the background before and we're removing
14116 * the background, so now it won't draw anything
14117 * (hence we SKIP_DRAW)
14118 */
14119 mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
14120 mPrivateFlags |= SKIP_DRAW;
14121 }
14122
14123 /*
14124 * When the background is set, we try to apply its padding to this
14125 * View. When the background is removed, we don't touch this View's
14126 * padding. This is noted in the Javadocs. Hence, we don't need to
14127 * requestLayout(), the invalidate() below is sufficient.
14128 */
14129
14130 // The old background's minimum size could have affected this
14131 // View's layout, so let's requestLayout
14132 requestLayout = true;
14133 }
14134
Romain Guy8f1344f52009-05-15 16:03:59 -070014135 computeOpaqueFlags();
14136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014137 if (requestLayout) {
14138 requestLayout();
14139 }
14140
14141 mBackgroundSizeChanged = true;
Romain Guy0fd89bf2011-01-26 15:41:30 -080014142 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014143 }
14144
14145 /**
14146 * Gets the background drawable
Philip Milne6c8ea062012-04-03 17:38:43 -070014147 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014148 * @return The drawable used as the background for this view, if any.
Philip Milne6c8ea062012-04-03 17:38:43 -070014149 *
14150 * @see #setBackground(Drawable)
14151 *
14152 * @attr ref android.R.styleable#View_background
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014153 */
14154 public Drawable getBackground() {
Philip Milne6c8ea062012-04-03 17:38:43 -070014155 return mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014156 }
14157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014158 /**
14159 * Sets the padding. The view may add on the space required to display
14160 * the scrollbars, depending on the style and visibility of the scrollbars.
14161 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
14162 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
14163 * from the values set in this call.
14164 *
14165 * @attr ref android.R.styleable#View_padding
14166 * @attr ref android.R.styleable#View_paddingBottom
14167 * @attr ref android.R.styleable#View_paddingLeft
14168 * @attr ref android.R.styleable#View_paddingRight
14169 * @attr ref android.R.styleable#View_paddingTop
14170 * @param left the left padding in pixels
14171 * @param top the top padding in pixels
14172 * @param right the right padding in pixels
14173 * @param bottom the bottom padding in pixels
14174 */
14175 public void setPadding(int left, int top, int right, int bottom) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014176 // Reset padding resolution
14177 mPrivateFlags2 &= ~PADDING_RESOLVED;
14178
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014179 mUserPaddingStart = UNDEFINED_PADDING;
14180 mUserPaddingEnd = UNDEFINED_PADDING;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014181
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014182 internalSetPadding(left, top, right, bottom);
14183 }
14184
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014185 /**
14186 * @hide
14187 */
14188 protected void internalSetPadding(int left, int top, int right, int bottom) {
Adam Powell20232d02010-12-08 21:08:53 -080014189 mUserPaddingLeft = left;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014190 mUserPaddingRight = right;
14191 mUserPaddingBottom = bottom;
14192
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014193 final int viewFlags = mViewFlags;
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014194 boolean changed = false;
Romain Guy8506ab42009-06-11 17:35:47 -070014195
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014196 // Common case is there are no scroll bars.
14197 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014198 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
Adam Powell20232d02010-12-08 21:08:53 -080014199 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014200 ? 0 : getVerticalScrollbarWidth();
Adam Powell20232d02010-12-08 21:08:53 -080014201 switch (mVerticalScrollbarPosition) {
14202 case SCROLLBAR_POSITION_DEFAULT:
Fabrice Di Meglioc91b6ca2012-06-22 14:51:15 -070014203 if (isLayoutRtl()) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014204 left += offset;
14205 } else {
14206 right += offset;
14207 }
14208 break;
Adam Powell20232d02010-12-08 21:08:53 -080014209 case SCROLLBAR_POSITION_RIGHT:
14210 right += offset;
14211 break;
14212 case SCROLLBAR_POSITION_LEFT:
14213 left += offset;
14214 break;
14215 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014216 }
Adam Powell20232d02010-12-08 21:08:53 -080014217 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014218 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
14219 ? 0 : getHorizontalScrollbarHeight();
14220 }
14221 }
Romain Guy8506ab42009-06-11 17:35:47 -070014222
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014223 if (mPaddingLeft != left) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014224 changed = true;
14225 mPaddingLeft = left;
14226 }
14227 if (mPaddingTop != top) {
14228 changed = true;
14229 mPaddingTop = top;
14230 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014231 if (mPaddingRight != right) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014232 changed = true;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014233 mPaddingRight = right;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014234 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014235 if (mPaddingBottom != bottom) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014236 changed = true;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014237 mPaddingBottom = bottom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014238 }
14239
14240 if (changed) {
14241 requestLayout();
14242 }
14243 }
14244
14245 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014246 * Sets the relative padding. The view may add on the space required to display
14247 * the scrollbars, depending on the style and visibility of the scrollbars.
14248 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
14249 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
14250 * from the values set in this call.
14251 *
14252 * @attr ref android.R.styleable#View_padding
14253 * @attr ref android.R.styleable#View_paddingBottom
14254 * @attr ref android.R.styleable#View_paddingStart
14255 * @attr ref android.R.styleable#View_paddingEnd
14256 * @attr ref android.R.styleable#View_paddingTop
14257 * @param start the start padding in pixels
14258 * @param top the top padding in pixels
14259 * @param end the end padding in pixels
14260 * @param bottom the bottom padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014261 */
14262 public void setPaddingRelative(int start, int top, int end, int bottom) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014263 // Reset padding resolution
14264 mPrivateFlags2 &= ~PADDING_RESOLVED;
14265
Fabrice Di Megliof9e36502011-06-21 18:41:48 -070014266 mUserPaddingStart = start;
14267 mUserPaddingEnd = end;
14268
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014269 switch(getResolvedLayoutDirection()) {
14270 case LAYOUT_DIRECTION_RTL:
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014271 internalSetPadding(end, top, start, bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014272 break;
14273 case LAYOUT_DIRECTION_LTR:
14274 default:
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014275 internalSetPadding(start, top, end, bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014276 }
14277 }
14278
14279 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014280 * Returns the top padding of this view.
14281 *
14282 * @return the top padding in pixels
14283 */
14284 public int getPaddingTop() {
14285 return mPaddingTop;
14286 }
14287
14288 /**
14289 * Returns the bottom padding of this view. If there are inset and enabled
14290 * scrollbars, this value may include the space required to display the
14291 * scrollbars as well.
14292 *
14293 * @return the bottom padding in pixels
14294 */
14295 public int getPaddingBottom() {
14296 return mPaddingBottom;
14297 }
14298
14299 /**
14300 * Returns the left padding of this view. If there are inset and enabled
14301 * scrollbars, this value may include the space required to display the
14302 * scrollbars as well.
14303 *
14304 * @return the left padding in pixels
14305 */
14306 public int getPaddingLeft() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014307 if (!isPaddingResolved()) {
14308 resolvePadding();
14309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014310 return mPaddingLeft;
14311 }
14312
14313 /**
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -070014314 * Returns the start padding of this view depending on its resolved layout direction.
14315 * If there are inset and enabled scrollbars, this value may include the space
14316 * required to display the scrollbars as well.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014317 *
14318 * @return the start padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014319 */
14320 public int getPaddingStart() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014321 if (!isPaddingResolved()) {
14322 resolvePadding();
14323 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014324 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14325 mPaddingRight : mPaddingLeft;
14326 }
14327
14328 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014329 * Returns the right padding of this view. If there are inset and enabled
14330 * scrollbars, this value may include the space required to display the
14331 * scrollbars as well.
14332 *
14333 * @return the right padding in pixels
14334 */
14335 public int getPaddingRight() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014336 if (!isPaddingResolved()) {
14337 resolvePadding();
14338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014339 return mPaddingRight;
14340 }
14341
14342 /**
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -070014343 * Returns the end padding of this view depending on its resolved layout direction.
14344 * If there are inset and enabled scrollbars, this value may include the space
14345 * required to display the scrollbars as well.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014346 *
14347 * @return the end padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014348 */
14349 public int getPaddingEnd() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014350 if (!isPaddingResolved()) {
14351 resolvePadding();
14352 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014353 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14354 mPaddingLeft : mPaddingRight;
14355 }
14356
14357 /**
14358 * Return if the padding as been set thru relative values
14359 * {@link #setPaddingRelative(int, int, int, int)} or thru
14360 * @attr ref android.R.styleable#View_paddingStart or
14361 * @attr ref android.R.styleable#View_paddingEnd
14362 *
14363 * @return true if the padding is relative or false if it is not.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014364 */
14365 public boolean isPaddingRelative() {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014366 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014367 }
14368
14369 /**
Philip Milne1557fd72012-04-04 23:41:34 -070014370 * @hide
14371 */
Philip Milne7a23b492012-04-24 22:12:36 -070014372 public Insets getOpticalInsets() {
Philip Milne1557fd72012-04-04 23:41:34 -070014373 if (mLayoutInsets == null) {
Philip Milnebbd51f12012-04-18 15:09:05 -070014374 mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
Philip Milne1557fd72012-04-04 23:41:34 -070014375 }
14376 return mLayoutInsets;
14377 }
14378
14379 /**
14380 * @hide
14381 */
14382 public void setLayoutInsets(Insets layoutInsets) {
14383 mLayoutInsets = layoutInsets;
14384 }
14385
14386 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014387 * Changes the selection state of this view. A view can be selected or not.
14388 * Note that selection is not the same as focus. Views are typically
14389 * selected in the context of an AdapterView like ListView or GridView;
14390 * the selected view is the view that is highlighted.
14391 *
14392 * @param selected true if the view must be selected, false otherwise
14393 */
14394 public void setSelected(boolean selected) {
14395 if (((mPrivateFlags & SELECTED) != 0) != selected) {
14396 mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
Romain Guya2431d02009-04-30 16:30:00 -070014397 if (!selected) resetPressedState();
Romain Guy0fd89bf2011-01-26 15:41:30 -080014398 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014399 refreshDrawableState();
14400 dispatchSetSelected(selected);
Svetoslav Ganov42138042012-03-20 11:51:39 -070014401 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
14402 notifyAccessibilityStateChanged();
14403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014404 }
14405 }
14406
14407 /**
14408 * Dispatch setSelected to all of this View's children.
14409 *
14410 * @see #setSelected(boolean)
14411 *
14412 * @param selected The new selected state
14413 */
14414 protected void dispatchSetSelected(boolean selected) {
14415 }
14416
14417 /**
14418 * Indicates the selection state of this view.
14419 *
14420 * @return true if the view is selected, false otherwise
14421 */
14422 @ViewDebug.ExportedProperty
14423 public boolean isSelected() {
14424 return (mPrivateFlags & SELECTED) != 0;
14425 }
14426
14427 /**
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014428 * Changes the activated state of this view. A view can be activated or not.
14429 * Note that activation is not the same as selection. Selection is
14430 * a transient property, representing the view (hierarchy) the user is
14431 * currently interacting with. Activation is a longer-term state that the
14432 * user can move views in and out of. For example, in a list view with
14433 * single or multiple selection enabled, the views in the current selection
14434 * set are activated. (Um, yeah, we are deeply sorry about the terminology
14435 * here.) The activated state is propagated down to children of the view it
14436 * is set on.
14437 *
14438 * @param activated true if the view must be activated, false otherwise
14439 */
14440 public void setActivated(boolean activated) {
14441 if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
14442 mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
Romain Guy0fd89bf2011-01-26 15:41:30 -080014443 invalidate(true);
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014444 refreshDrawableState();
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070014445 dispatchSetActivated(activated);
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014446 }
14447 }
14448
14449 /**
14450 * Dispatch setActivated to all of this View's children.
14451 *
14452 * @see #setActivated(boolean)
14453 *
14454 * @param activated The new activated state
14455 */
14456 protected void dispatchSetActivated(boolean activated) {
14457 }
14458
14459 /**
14460 * Indicates the activation state of this view.
14461 *
14462 * @return true if the view is activated, false otherwise
14463 */
14464 @ViewDebug.ExportedProperty
14465 public boolean isActivated() {
14466 return (mPrivateFlags & ACTIVATED) != 0;
14467 }
14468
14469 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014470 * Returns the ViewTreeObserver for this view's hierarchy. The view tree
14471 * observer can be used to get notifications when global events, like
14472 * layout, happen.
14473 *
14474 * The returned ViewTreeObserver observer is not guaranteed to remain
14475 * valid for the lifetime of this View. If the caller of this method keeps
14476 * a long-lived reference to ViewTreeObserver, it should always check for
14477 * the return value of {@link ViewTreeObserver#isAlive()}.
14478 *
14479 * @return The ViewTreeObserver for this view's hierarchy.
14480 */
14481 public ViewTreeObserver getViewTreeObserver() {
14482 if (mAttachInfo != null) {
14483 return mAttachInfo.mTreeObserver;
14484 }
14485 if (mFloatingTreeObserver == null) {
14486 mFloatingTreeObserver = new ViewTreeObserver();
14487 }
14488 return mFloatingTreeObserver;
14489 }
14490
14491 /**
14492 * <p>Finds the topmost view in the current view hierarchy.</p>
14493 *
14494 * @return the topmost view containing this view
14495 */
14496 public View getRootView() {
14497 if (mAttachInfo != null) {
14498 final View v = mAttachInfo.mRootView;
14499 if (v != null) {
14500 return v;
14501 }
14502 }
Romain Guy8506ab42009-06-11 17:35:47 -070014503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014504 View parent = this;
14505
14506 while (parent.mParent != null && parent.mParent instanceof View) {
14507 parent = (View) parent.mParent;
14508 }
14509
14510 return parent;
14511 }
14512
14513 /**
14514 * <p>Computes the coordinates of this view on the screen. The argument
14515 * must be an array of two integers. After the method returns, the array
14516 * contains the x and y location in that order.</p>
14517 *
14518 * @param location an array of two integers in which to hold the coordinates
14519 */
14520 public void getLocationOnScreen(int[] location) {
14521 getLocationInWindow(location);
14522
14523 final AttachInfo info = mAttachInfo;
Romain Guy779398e2009-06-16 13:17:50 -070014524 if (info != null) {
14525 location[0] += info.mWindowLeft;
14526 location[1] += info.mWindowTop;
14527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014528 }
14529
14530 /**
14531 * <p>Computes the coordinates of this view in its window. The argument
14532 * must be an array of two integers. After the method returns, the array
14533 * contains the x and y location in that order.</p>
14534 *
14535 * @param location an array of two integers in which to hold the coordinates
14536 */
14537 public void getLocationInWindow(int[] location) {
14538 if (location == null || location.length < 2) {
Gilles Debunnecea45132011-11-24 02:19:27 +010014539 throw new IllegalArgumentException("location must be an array of two integers");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014540 }
14541
Gilles Debunne6583ce52011-12-06 18:09:02 -080014542 if (mAttachInfo == null) {
14543 // When the view is not attached to a window, this method does not make sense
14544 location[0] = location[1] = 0;
14545 return;
14546 }
14547
Gilles Debunnecea45132011-11-24 02:19:27 +010014548 float[] position = mAttachInfo.mTmpTransformLocation;
14549 position[0] = position[1] = 0.0f;
14550
14551 if (!hasIdentityMatrix()) {
14552 getMatrix().mapPoints(position);
Dianne Hackbornddb715b2011-09-09 14:43:39 -070014553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014554
Gilles Debunnecea45132011-11-24 02:19:27 +010014555 position[0] += mLeft;
14556 position[1] += mTop;
14557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014558 ViewParent viewParent = mParent;
14559 while (viewParent instanceof View) {
Gilles Debunnecea45132011-11-24 02:19:27 +010014560 final View view = (View) viewParent;
14561
14562 position[0] -= view.mScrollX;
14563 position[1] -= view.mScrollY;
14564
14565 if (!view.hasIdentityMatrix()) {
14566 view.getMatrix().mapPoints(position);
Dianne Hackbornddb715b2011-09-09 14:43:39 -070014567 }
Gilles Debunnecea45132011-11-24 02:19:27 +010014568
14569 position[0] += view.mLeft;
14570 position[1] += view.mTop;
14571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014572 viewParent = view.mParent;
Svetoslav Ganov42138042012-03-20 11:51:39 -070014573 }
Romain Guy8506ab42009-06-11 17:35:47 -070014574
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070014575 if (viewParent instanceof ViewRootImpl) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014576 // *cough*
Gilles Debunnecea45132011-11-24 02:19:27 +010014577 final ViewRootImpl vr = (ViewRootImpl) viewParent;
14578 position[1] -= vr.mCurScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014579 }
Gilles Debunnecea45132011-11-24 02:19:27 +010014580
14581 location[0] = (int) (position[0] + 0.5f);
14582 location[1] = (int) (position[1] + 0.5f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014583 }
14584
14585 /**
14586 * {@hide}
14587 * @param id the id of the view to be found
14588 * @return the view of the specified id, null if cannot be found
14589 */
14590 protected View findViewTraversal(int id) {
14591 if (id == mID) {
14592 return this;
14593 }
14594 return null;
14595 }
14596
14597 /**
14598 * {@hide}
14599 * @param tag the tag of the view to be found
14600 * @return the view of specified tag, null if cannot be found
14601 */
14602 protected View findViewWithTagTraversal(Object tag) {
14603 if (tag != null && tag.equals(mTag)) {
14604 return this;
14605 }
14606 return null;
14607 }
14608
14609 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -080014610 * {@hide}
14611 * @param predicate The predicate to evaluate.
Jeff Brown4dfbec22011-08-15 14:55:37 -070014612 * @param childToSkip If not null, ignores this child during the recursive traversal.
Jeff Brown4e6319b2010-12-13 10:36:51 -080014613 * @return The first view that matches the predicate or null.
14614 */
Jeff Brown4dfbec22011-08-15 14:55:37 -070014615 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
Jeff Brown4e6319b2010-12-13 10:36:51 -080014616 if (predicate.apply(this)) {
14617 return this;
14618 }
14619 return null;
14620 }
14621
14622 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014623 * Look for a child view with the given id. If this view has the given
14624 * id, return this view.
14625 *
14626 * @param id The id to search for.
14627 * @return The view that has the given id in the hierarchy or null
14628 */
14629 public final View findViewById(int id) {
14630 if (id < 0) {
14631 return null;
14632 }
14633 return findViewTraversal(id);
14634 }
14635
14636 /**
Svetoslav Ganov2cdedff2011-10-03 14:18:42 -070014637 * Finds a view by its unuque and stable accessibility id.
14638 *
14639 * @param accessibilityId The searched accessibility id.
14640 * @return The found view.
14641 */
14642 final View findViewByAccessibilityId(int accessibilityId) {
14643 if (accessibilityId < 0) {
14644 return null;
14645 }
14646 return findViewByAccessibilityIdTraversal(accessibilityId);
14647 }
14648
14649 /**
14650 * Performs the traversal to find a view by its unuque and stable accessibility id.
14651 *
14652 * <strong>Note:</strong>This method does not stop at the root namespace
14653 * boundary since the user can touch the screen at an arbitrary location
14654 * potentially crossing the root namespace bounday which will send an
14655 * accessibility event to accessibility services and they should be able
14656 * to obtain the event source. Also accessibility ids are guaranteed to be
14657 * unique in the window.
14658 *
14659 * @param accessibilityId The accessibility id.
14660 * @return The found view.
14661 */
14662 View findViewByAccessibilityIdTraversal(int accessibilityId) {
14663 if (getAccessibilityViewId() == accessibilityId) {
14664 return this;
14665 }
14666 return null;
14667 }
14668
14669 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014670 * Look for a child view with the given tag. If this view has the given
14671 * tag, return this view.
14672 *
14673 * @param tag The tag to search for, using "tag.equals(getTag())".
14674 * @return The View that has the given tag in the hierarchy or null
14675 */
14676 public final View findViewWithTag(Object tag) {
14677 if (tag == null) {
14678 return null;
14679 }
14680 return findViewWithTagTraversal(tag);
14681 }
14682
14683 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -080014684 * {@hide}
14685 * Look for a child view that matches the specified predicate.
14686 * If this view matches the predicate, return this view.
14687 *
14688 * @param predicate The predicate to evaluate.
14689 * @return The first view that matches the predicate or null.
14690 */
14691 public final View findViewByPredicate(Predicate<View> predicate) {
Jeff Brown4dfbec22011-08-15 14:55:37 -070014692 return findViewByPredicateTraversal(predicate, null);
14693 }
14694
14695 /**
14696 * {@hide}
14697 * Look for a child view that matches the specified predicate,
14698 * starting with the specified view and its descendents and then
14699 * recusively searching the ancestors and siblings of that view
14700 * until this view is reached.
14701 *
14702 * This method is useful in cases where the predicate does not match
14703 * a single unique view (perhaps multiple views use the same id)
14704 * and we are trying to find the view that is "closest" in scope to the
14705 * starting view.
14706 *
14707 * @param start The view to start from.
14708 * @param predicate The predicate to evaluate.
14709 * @return The first view that matches the predicate or null.
14710 */
14711 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
14712 View childToSkip = null;
14713 for (;;) {
14714 View view = start.findViewByPredicateTraversal(predicate, childToSkip);
14715 if (view != null || start == this) {
14716 return view;
14717 }
14718
14719 ViewParent parent = start.getParent();
14720 if (parent == null || !(parent instanceof View)) {
14721 return null;
14722 }
14723
14724 childToSkip = start;
14725 start = (View) parent;
14726 }
Jeff Brown4e6319b2010-12-13 10:36:51 -080014727 }
14728
14729 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014730 * Sets the identifier for this view. The identifier does not have to be
14731 * unique in this view's hierarchy. The identifier should be a positive
14732 * number.
14733 *
14734 * @see #NO_ID
Philip Milne6c8ea062012-04-03 17:38:43 -070014735 * @see #getId()
14736 * @see #findViewById(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014737 *
14738 * @param id a number used to identify the view
14739 *
14740 * @attr ref android.R.styleable#View_id
14741 */
14742 public void setId(int id) {
14743 mID = id;
14744 }
14745
14746 /**
14747 * {@hide}
14748 *
14749 * @param isRoot true if the view belongs to the root namespace, false
14750 * otherwise
14751 */
14752 public void setIsRootNamespace(boolean isRoot) {
14753 if (isRoot) {
14754 mPrivateFlags |= IS_ROOT_NAMESPACE;
14755 } else {
14756 mPrivateFlags &= ~IS_ROOT_NAMESPACE;
14757 }
14758 }
14759
14760 /**
14761 * {@hide}
14762 *
14763 * @return true if the view belongs to the root namespace, false otherwise
14764 */
14765 public boolean isRootNamespace() {
14766 return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
14767 }
14768
14769 /**
14770 * Returns this view's identifier.
14771 *
14772 * @return a positive integer used to identify the view or {@link #NO_ID}
14773 * if the view has no ID
14774 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014775 * @see #setId(int)
14776 * @see #findViewById(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014777 * @attr ref android.R.styleable#View_id
14778 */
14779 @ViewDebug.CapturedViewProperty
14780 public int getId() {
14781 return mID;
14782 }
14783
14784 /**
14785 * Returns this view's tag.
14786 *
14787 * @return the Object stored in this view as a tag
Romain Guyd90a3312009-05-06 14:54:28 -070014788 *
14789 * @see #setTag(Object)
14790 * @see #getTag(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014791 */
14792 @ViewDebug.ExportedProperty
14793 public Object getTag() {
14794 return mTag;
14795 }
14796
14797 /**
14798 * Sets the tag associated with this view. A tag can be used to mark
14799 * a view in its hierarchy and does not have to be unique within the
14800 * hierarchy. Tags can also be used to store data within a view without
14801 * resorting to another data structure.
14802 *
14803 * @param tag an Object to tag the view with
Romain Guyd90a3312009-05-06 14:54:28 -070014804 *
14805 * @see #getTag()
14806 * @see #setTag(int, Object)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014807 */
14808 public void setTag(final Object tag) {
14809 mTag = tag;
14810 }
14811
14812 /**
Romain Guyd90a3312009-05-06 14:54:28 -070014813 * Returns the tag associated with this view and the specified key.
14814 *
14815 * @param key The key identifying the tag
14816 *
14817 * @return the Object stored in this view as a tag
14818 *
14819 * @see #setTag(int, Object)
Romain Guy8506ab42009-06-11 17:35:47 -070014820 * @see #getTag()
Romain Guyd90a3312009-05-06 14:54:28 -070014821 */
14822 public Object getTag(int key) {
Adam Powell7db82ac2011-09-22 19:44:04 -070014823 if (mKeyedTags != null) return mKeyedTags.get(key);
Romain Guyd90a3312009-05-06 14:54:28 -070014824 return null;
14825 }
14826
14827 /**
14828 * Sets a tag associated with this view and a key. A tag can be used
14829 * to mark a view in its hierarchy and does not have to be unique within
14830 * the hierarchy. Tags can also be used to store data within a view
14831 * without resorting to another data structure.
14832 *
14833 * The specified key should be an id declared in the resources of the
Scott Maindfe5c202010-06-08 15:54:52 -070014834 * application to ensure it is unique (see the <a
14835 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
14836 * Keys identified as belonging to
Romain Guyd90a3312009-05-06 14:54:28 -070014837 * the Android framework or not associated with any package will cause
14838 * an {@link IllegalArgumentException} to be thrown.
14839 *
14840 * @param key The key identifying the tag
14841 * @param tag An Object to tag the view with
14842 *
14843 * @throws IllegalArgumentException If they specified key is not valid
14844 *
14845 * @see #setTag(Object)
14846 * @see #getTag(int)
14847 */
14848 public void setTag(int key, final Object tag) {
14849 // If the package id is 0x00 or 0x01, it's either an undefined package
14850 // or a framework id
14851 if ((key >>> 24) < 2) {
14852 throw new IllegalArgumentException("The key must be an application-specific "
14853 + "resource id.");
14854 }
14855
Adam Powell2b2f6d62011-09-23 11:15:39 -070014856 setKeyedTag(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070014857 }
14858
14859 /**
14860 * Variation of {@link #setTag(int, Object)} that enforces the key to be a
14861 * framework id.
14862 *
14863 * @hide
14864 */
14865 public void setTagInternal(int key, Object tag) {
14866 if ((key >>> 24) != 0x1) {
14867 throw new IllegalArgumentException("The key must be a framework-specific "
14868 + "resource id.");
14869 }
14870
Adam Powell2b2f6d62011-09-23 11:15:39 -070014871 setKeyedTag(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070014872 }
14873
Adam Powell2b2f6d62011-09-23 11:15:39 -070014874 private void setKeyedTag(int key, Object tag) {
Adam Powell7db82ac2011-09-22 19:44:04 -070014875 if (mKeyedTags == null) {
14876 mKeyedTags = new SparseArray<Object>();
Romain Guyd90a3312009-05-06 14:54:28 -070014877 }
14878
Adam Powell7db82ac2011-09-22 19:44:04 -070014879 mKeyedTags.put(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070014880 }
14881
14882 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014883 * Prints information about this view in the log output, with the tag
14884 * {@link #VIEW_LOG_TAG}.
14885 *
14886 * @hide
14887 */
14888 public void debug() {
14889 debug(0);
14890 }
14891
14892 /**
14893 * Prints information about this view in the log output, with the tag
14894 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
14895 * indentation defined by the <code>depth</code>.
14896 *
14897 * @param depth the indentation level
14898 *
14899 * @hide
14900 */
14901 protected void debug(int depth) {
14902 String output = debugIndent(depth - 1);
14903
14904 output += "+ " + this;
14905 int id = getId();
14906 if (id != -1) {
14907 output += " (id=" + id + ")";
14908 }
14909 Object tag = getTag();
14910 if (tag != null) {
14911 output += " (tag=" + tag + ")";
14912 }
14913 Log.d(VIEW_LOG_TAG, output);
14914
14915 if ((mPrivateFlags & FOCUSED) != 0) {
14916 output = debugIndent(depth) + " FOCUSED";
14917 Log.d(VIEW_LOG_TAG, output);
14918 }
14919
14920 output = debugIndent(depth);
14921 output += "frame={" + mLeft + ", " + mTop + ", " + mRight
14922 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
14923 + "} ";
14924 Log.d(VIEW_LOG_TAG, output);
14925
14926 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
14927 || mPaddingBottom != 0) {
14928 output = debugIndent(depth);
14929 output += "padding={" + mPaddingLeft + ", " + mPaddingTop
14930 + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
14931 Log.d(VIEW_LOG_TAG, output);
14932 }
14933
14934 output = debugIndent(depth);
14935 output += "mMeasureWidth=" + mMeasuredWidth +
14936 " mMeasureHeight=" + mMeasuredHeight;
14937 Log.d(VIEW_LOG_TAG, output);
14938
14939 output = debugIndent(depth);
14940 if (mLayoutParams == null) {
14941 output += "BAD! no layout params";
14942 } else {
14943 output = mLayoutParams.debug(output);
14944 }
14945 Log.d(VIEW_LOG_TAG, output);
14946
14947 output = debugIndent(depth);
14948 output += "flags={";
14949 output += View.printFlags(mViewFlags);
14950 output += "}";
14951 Log.d(VIEW_LOG_TAG, output);
14952
14953 output = debugIndent(depth);
14954 output += "privateFlags={";
14955 output += View.printPrivateFlags(mPrivateFlags);
14956 output += "}";
14957 Log.d(VIEW_LOG_TAG, output);
14958 }
14959
14960 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090014961 * Creates a string of whitespaces used for indentation.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014962 *
14963 * @param depth the indentation level
14964 * @return a String containing (depth * 2 + 3) * 2 white spaces
14965 *
14966 * @hide
14967 */
14968 protected static String debugIndent(int depth) {
14969 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
14970 for (int i = 0; i < (depth * 2) + 3; i++) {
14971 spaces.append(' ').append(' ');
14972 }
14973 return spaces.toString();
14974 }
14975
14976 /**
14977 * <p>Return the offset of the widget's text baseline from the widget's top
14978 * boundary. If this widget does not support baseline alignment, this
14979 * method returns -1. </p>
14980 *
14981 * @return the offset of the baseline within the widget's bounds or -1
14982 * if baseline alignment is not supported
14983 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070014984 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014985 public int getBaseline() {
14986 return -1;
14987 }
14988
14989 /**
14990 * Call this when something has changed which has invalidated the
14991 * layout of this view. This will schedule a layout pass of the view
14992 * tree.
14993 */
14994 public void requestLayout() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014995 mPrivateFlags |= FORCE_LAYOUT;
Chet Haase5af048c2011-01-24 17:00:32 -080014996 mPrivateFlags |= INVALIDATED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014997
Fabrice Di Meglio4a5268852012-03-30 15:56:48 -070014998 if (mParent != null && !mParent.isLayoutRequested()) {
14999 mParent.requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015000 }
15001 }
15002
15003 /**
15004 * Forces this view to be laid out during the next layout pass.
15005 * This method does not call requestLayout() or forceLayout()
15006 * on the parent.
15007 */
15008 public void forceLayout() {
15009 mPrivateFlags |= FORCE_LAYOUT;
Chet Haase5af048c2011-01-24 17:00:32 -080015010 mPrivateFlags |= INVALIDATED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015011 }
15012
15013 /**
15014 * <p>
15015 * This is called to find out how big a view should be. The parent
15016 * supplies constraint information in the width and height parameters.
15017 * </p>
15018 *
15019 * <p>
Romain Guy967e2bf2012-02-07 17:04:34 -080015020 * The actual measurement work of a view is performed in
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015021 * {@link #onMeasure(int, int)}, called by this method. Therefore, only
Romain Guy967e2bf2012-02-07 17:04:34 -080015022 * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015023 * </p>
15024 *
15025 *
15026 * @param widthMeasureSpec Horizontal space requirements as imposed by the
15027 * parent
15028 * @param heightMeasureSpec Vertical space requirements as imposed by the
15029 * parent
15030 *
15031 * @see #onMeasure(int, int)
15032 */
15033 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
15034 if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
15035 widthMeasureSpec != mOldWidthMeasureSpec ||
15036 heightMeasureSpec != mOldHeightMeasureSpec) {
15037
15038 // first clears the measured dimension flag
15039 mPrivateFlags &= ~MEASURED_DIMENSION_SET;
15040
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070015041 if (!isPaddingResolved()) {
Adam Powell0090f202012-08-07 17:15:30 -070015042 resolvePadding();
15043 }
15044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015045 // measure ourselves, this should set the measured dimension flag back
15046 onMeasure(widthMeasureSpec, heightMeasureSpec);
15047
15048 // flag not set, setMeasuredDimension() was not invoked, we raise
15049 // an exception to warn the developer
15050 if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
15051 throw new IllegalStateException("onMeasure() did not set the"
15052 + " measured dimension by calling"
15053 + " setMeasuredDimension()");
15054 }
15055
15056 mPrivateFlags |= LAYOUT_REQUIRED;
15057 }
15058
15059 mOldWidthMeasureSpec = widthMeasureSpec;
15060 mOldHeightMeasureSpec = heightMeasureSpec;
15061 }
15062
15063 /**
15064 * <p>
15065 * Measure the view and its content to determine the measured width and the
15066 * measured height. This method is invoked by {@link #measure(int, int)} and
15067 * should be overriden by subclasses to provide accurate and efficient
15068 * measurement of their contents.
15069 * </p>
15070 *
15071 * <p>
15072 * <strong>CONTRACT:</strong> When overriding this method, you
15073 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
15074 * measured width and height of this view. Failure to do so will trigger an
15075 * <code>IllegalStateException</code>, thrown by
15076 * {@link #measure(int, int)}. Calling the superclass'
15077 * {@link #onMeasure(int, int)} is a valid use.
15078 * </p>
15079 *
15080 * <p>
15081 * The base class implementation of measure defaults to the background size,
15082 * unless a larger size is allowed by the MeasureSpec. Subclasses should
15083 * override {@link #onMeasure(int, int)} to provide better measurements of
15084 * their content.
15085 * </p>
15086 *
15087 * <p>
15088 * If this method is overridden, it is the subclass's responsibility to make
15089 * sure the measured height and width are at least the view's minimum height
15090 * and width ({@link #getSuggestedMinimumHeight()} and
15091 * {@link #getSuggestedMinimumWidth()}).
15092 * </p>
15093 *
15094 * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
15095 * The requirements are encoded with
15096 * {@link android.view.View.MeasureSpec}.
15097 * @param heightMeasureSpec vertical space requirements as imposed by the parent.
15098 * The requirements are encoded with
15099 * {@link android.view.View.MeasureSpec}.
15100 *
15101 * @see #getMeasuredWidth()
15102 * @see #getMeasuredHeight()
15103 * @see #setMeasuredDimension(int, int)
15104 * @see #getSuggestedMinimumHeight()
15105 * @see #getSuggestedMinimumWidth()
15106 * @see android.view.View.MeasureSpec#getMode(int)
15107 * @see android.view.View.MeasureSpec#getSize(int)
15108 */
15109 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
15110 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15111 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
15112 }
15113
15114 /**
15115 * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
15116 * measured width and measured height. Failing to do so will trigger an
15117 * exception at measurement time.</p>
15118 *
Dianne Hackborn189ee182010-12-02 21:48:53 -080015119 * @param measuredWidth The measured width of this view. May be a complex
15120 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15121 * {@link #MEASURED_STATE_TOO_SMALL}.
15122 * @param measuredHeight The measured height of this view. May be a complex
15123 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15124 * {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015125 */
15126 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
15127 mMeasuredWidth = measuredWidth;
15128 mMeasuredHeight = measuredHeight;
15129
15130 mPrivateFlags |= MEASURED_DIMENSION_SET;
15131 }
15132
15133 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -080015134 * Merge two states as returned by {@link #getMeasuredState()}.
15135 * @param curState The current state as returned from a view or the result
15136 * of combining multiple views.
15137 * @param newState The new view state to combine.
15138 * @return Returns a new integer reflecting the combination of the two
15139 * states.
15140 */
15141 public static int combineMeasuredStates(int curState, int newState) {
15142 return curState | newState;
15143 }
15144
15145 /**
15146 * Version of {@link #resolveSizeAndState(int, int, int)}
15147 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
15148 */
15149 public static int resolveSize(int size, int measureSpec) {
15150 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
15151 }
15152
15153 /**
15154 * Utility to reconcile a desired size and state, with constraints imposed
15155 * by a MeasureSpec. Will take the desired size, unless a different size
15156 * is imposed by the constraints. The returned value is a compound integer,
15157 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
15158 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
15159 * size is smaller than the size the view wants to be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015160 *
15161 * @param size How big the view wants to be
15162 * @param measureSpec Constraints imposed by the parent
Dianne Hackborn189ee182010-12-02 21:48:53 -080015163 * @return Size information bit mask as defined by
15164 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015165 */
Dianne Hackborn189ee182010-12-02 21:48:53 -080015166 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015167 int result = size;
15168 int specMode = MeasureSpec.getMode(measureSpec);
15169 int specSize = MeasureSpec.getSize(measureSpec);
15170 switch (specMode) {
15171 case MeasureSpec.UNSPECIFIED:
15172 result = size;
15173 break;
15174 case MeasureSpec.AT_MOST:
Dianne Hackborn189ee182010-12-02 21:48:53 -080015175 if (specSize < size) {
15176 result = specSize | MEASURED_STATE_TOO_SMALL;
15177 } else {
15178 result = size;
15179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015180 break;
15181 case MeasureSpec.EXACTLY:
15182 result = specSize;
15183 break;
15184 }
Dianne Hackborn189ee182010-12-02 21:48:53 -080015185 return result | (childMeasuredState&MEASURED_STATE_MASK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015186 }
15187
15188 /**
15189 * Utility to return a default size. Uses the supplied size if the
Romain Guy98029c82011-06-17 15:47:07 -070015190 * MeasureSpec imposed no constraints. Will get larger if allowed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015191 * by the MeasureSpec.
15192 *
15193 * @param size Default size for this view
15194 * @param measureSpec Constraints imposed by the parent
15195 * @return The size this view should be.
15196 */
15197 public static int getDefaultSize(int size, int measureSpec) {
15198 int result = size;
15199 int specMode = MeasureSpec.getMode(measureSpec);
Romain Guy98029c82011-06-17 15:47:07 -070015200 int specSize = MeasureSpec.getSize(measureSpec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015201
15202 switch (specMode) {
15203 case MeasureSpec.UNSPECIFIED:
15204 result = size;
15205 break;
15206 case MeasureSpec.AT_MOST:
15207 case MeasureSpec.EXACTLY:
15208 result = specSize;
15209 break;
15210 }
15211 return result;
15212 }
15213
15214 /**
15215 * Returns the suggested minimum height that the view should use. This
15216 * returns the maximum of the view's minimum height
15217 * and the background's minimum height
15218 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
15219 * <p>
15220 * When being used in {@link #onMeasure(int, int)}, the caller should still
15221 * ensure the returned height is within the requirements of the parent.
15222 *
15223 * @return The suggested minimum height of the view.
15224 */
15225 protected int getSuggestedMinimumHeight() {
Philip Milne6c8ea062012-04-03 17:38:43 -070015226 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015228 }
15229
15230 /**
15231 * Returns the suggested minimum width that the view should use. This
15232 * returns the maximum of the view's minimum width)
15233 * and the background's minimum width
15234 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
15235 * <p>
15236 * When being used in {@link #onMeasure(int, int)}, the caller should still
15237 * ensure the returned width is within the requirements of the parent.
15238 *
15239 * @return The suggested minimum width of the view.
15240 */
15241 protected int getSuggestedMinimumWidth() {
Philip Milne6c8ea062012-04-03 17:38:43 -070015242 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
15243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015244
Philip Milne6c8ea062012-04-03 17:38:43 -070015245 /**
15246 * Returns the minimum height of the view.
15247 *
15248 * @return the minimum height the view will try to be.
15249 *
15250 * @see #setMinimumHeight(int)
15251 *
15252 * @attr ref android.R.styleable#View_minHeight
15253 */
15254 public int getMinimumHeight() {
15255 return mMinHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015256 }
15257
15258 /**
15259 * Sets the minimum height of the view. It is not guaranteed the view will
15260 * be able to achieve this minimum height (for example, if its parent layout
15261 * constrains it with less available height).
15262 *
15263 * @param minHeight The minimum height the view will try to be.
Philip Milne6c8ea062012-04-03 17:38:43 -070015264 *
15265 * @see #getMinimumHeight()
15266 *
15267 * @attr ref android.R.styleable#View_minHeight
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015268 */
15269 public void setMinimumHeight(int minHeight) {
15270 mMinHeight = minHeight;
Philip Milne6c8ea062012-04-03 17:38:43 -070015271 requestLayout();
15272 }
15273
15274 /**
15275 * Returns the minimum width of the view.
15276 *
15277 * @return the minimum width the view will try to be.
15278 *
15279 * @see #setMinimumWidth(int)
15280 *
15281 * @attr ref android.R.styleable#View_minWidth
15282 */
15283 public int getMinimumWidth() {
15284 return mMinWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015285 }
15286
15287 /**
15288 * Sets the minimum width of the view. It is not guaranteed the view will
15289 * be able to achieve this minimum width (for example, if its parent layout
15290 * constrains it with less available width).
15291 *
15292 * @param minWidth The minimum width the view will try to be.
Philip Milne6c8ea062012-04-03 17:38:43 -070015293 *
15294 * @see #getMinimumWidth()
15295 *
15296 * @attr ref android.R.styleable#View_minWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015297 */
15298 public void setMinimumWidth(int minWidth) {
15299 mMinWidth = minWidth;
Philip Milne6c8ea062012-04-03 17:38:43 -070015300 requestLayout();
15301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015302 }
15303
15304 /**
15305 * Get the animation currently associated with this view.
15306 *
15307 * @return The animation that is currently playing or
15308 * scheduled to play for this view.
15309 */
15310 public Animation getAnimation() {
15311 return mCurrentAnimation;
15312 }
15313
15314 /**
15315 * Start the specified animation now.
15316 *
15317 * @param animation the animation to start now
15318 */
15319 public void startAnimation(Animation animation) {
15320 animation.setStartTime(Animation.START_ON_FIRST_FRAME);
15321 setAnimation(animation);
Romain Guy0fd89bf2011-01-26 15:41:30 -080015322 invalidateParentCaches();
15323 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015324 }
15325
15326 /**
15327 * Cancels any animations for this view.
15328 */
15329 public void clearAnimation() {
Romain Guy305a2eb2010-02-09 11:30:44 -080015330 if (mCurrentAnimation != null) {
Romain Guyb4a107d2010-02-09 18:50:08 -080015331 mCurrentAnimation.detach();
Romain Guy305a2eb2010-02-09 11:30:44 -080015332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015333 mCurrentAnimation = null;
Romain Guy0fd89bf2011-01-26 15:41:30 -080015334 invalidateParentIfNeeded();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015335 }
15336
15337 /**
15338 * Sets the next animation to play for this view.
15339 * If you want the animation to play immediately, use
Chet Haase42428932012-05-11 15:39:07 -070015340 * {@link #startAnimation(android.view.animation.Animation)} instead.
15341 * This method provides allows fine-grained
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015342 * control over the start time and invalidation, but you
15343 * must make sure that 1) the animation has a start time set, and
Chet Haase42428932012-05-11 15:39:07 -070015344 * 2) the view's parent (which controls animations on its children)
15345 * will be invalidated when the animation is supposed to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015346 * start.
15347 *
15348 * @param animation The next animation, or null.
15349 */
15350 public void setAnimation(Animation animation) {
15351 mCurrentAnimation = animation;
Romain Guyeb378892012-04-12 11:33:14 -070015352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015353 if (animation != null) {
Romain Guyeb378892012-04-12 11:33:14 -070015354 // If the screen is off assume the animation start time is now instead of
15355 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
15356 // would cause the animation to start when the screen turns back on
15357 if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
15358 animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
15359 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
15360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015361 animation.reset();
15362 }
15363 }
15364
15365 /**
15366 * Invoked by a parent ViewGroup to notify the start of the animation
15367 * currently associated with this view. If you override this method,
15368 * always call super.onAnimationStart();
15369 *
15370 * @see #setAnimation(android.view.animation.Animation)
15371 * @see #getAnimation()
15372 */
15373 protected void onAnimationStart() {
15374 mPrivateFlags |= ANIMATION_STARTED;
15375 }
15376
15377 /**
15378 * Invoked by a parent ViewGroup to notify the end of the animation
15379 * currently associated with this view. If you override this method,
15380 * always call super.onAnimationEnd();
15381 *
15382 * @see #setAnimation(android.view.animation.Animation)
15383 * @see #getAnimation()
15384 */
15385 protected void onAnimationEnd() {
15386 mPrivateFlags &= ~ANIMATION_STARTED;
15387 }
15388
15389 /**
15390 * Invoked if there is a Transform that involves alpha. Subclass that can
15391 * draw themselves with the specified alpha should return true, and then
15392 * respect that alpha when their onDraw() is called. If this returns false
15393 * then the view may be redirected to draw into an offscreen buffer to
15394 * fulfill the request, which will look fine, but may be slower than if the
15395 * subclass handles it internally. The default implementation returns false.
15396 *
15397 * @param alpha The alpha (0..255) to apply to the view's drawing
15398 * @return true if the view can draw with the specified alpha.
15399 */
15400 protected boolean onSetAlpha(int alpha) {
15401 return false;
15402 }
15403
15404 /**
15405 * This is used by the RootView to perform an optimization when
15406 * the view hierarchy contains one or several SurfaceView.
15407 * SurfaceView is always considered transparent, but its children are not,
15408 * therefore all View objects remove themselves from the global transparent
15409 * region (passed as a parameter to this function).
15410 *
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070015411 * @param region The transparent region for this ViewAncestor (window).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015412 *
15413 * @return Returns true if the effective visibility of the view at this
15414 * point is opaque, regardless of the transparent region; returns false
15415 * if it is possible for underlying windows to be seen behind the view.
15416 *
15417 * {@hide}
15418 */
15419 public boolean gatherTransparentRegion(Region region) {
15420 final AttachInfo attachInfo = mAttachInfo;
15421 if (region != null && attachInfo != null) {
15422 final int pflags = mPrivateFlags;
15423 if ((pflags & SKIP_DRAW) == 0) {
15424 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
15425 // remove it from the transparent region.
15426 final int[] location = attachInfo.mTransparentLocation;
15427 getLocationInWindow(location);
15428 region.op(location[0], location[1], location[0] + mRight - mLeft,
15429 location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
Philip Milne6c8ea062012-04-03 17:38:43 -070015430 } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015431 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
15432 // exists, so we remove the background drawable's non-transparent
15433 // parts from this transparent region.
Philip Milne6c8ea062012-04-03 17:38:43 -070015434 applyDrawableToTransparentRegion(mBackground, region);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015435 }
15436 }
15437 return true;
15438 }
15439
15440 /**
15441 * Play a sound effect for this view.
15442 *
15443 * <p>The framework will play sound effects for some built in actions, such as
15444 * clicking, but you may wish to play these effects in your widget,
15445 * for instance, for internal navigation.
15446 *
15447 * <p>The sound effect will only be played if sound effects are enabled by the user, and
15448 * {@link #isSoundEffectsEnabled()} is true.
15449 *
15450 * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
15451 */
15452 public void playSoundEffect(int soundConstant) {
15453 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
15454 return;
15455 }
15456 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
15457 }
15458
15459 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015460 * BZZZTT!!1!
Romain Guy8506ab42009-06-11 17:35:47 -070015461 *
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015462 * <p>Provide haptic feedback to the user for this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015463 *
15464 * <p>The framework will provide haptic feedback for some built in actions,
15465 * such as long presses, but you may wish to provide feedback for your
15466 * own widget.
15467 *
15468 * <p>The feedback will only be performed if
15469 * {@link #isHapticFeedbackEnabled()} is true.
15470 *
15471 * @param feedbackConstant One of the constants defined in
15472 * {@link HapticFeedbackConstants}
15473 */
15474 public boolean performHapticFeedback(int feedbackConstant) {
15475 return performHapticFeedback(feedbackConstant, 0);
15476 }
15477
15478 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015479 * BZZZTT!!1!
Romain Guy8506ab42009-06-11 17:35:47 -070015480 *
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015481 * <p>Like {@link #performHapticFeedback(int)}, with additional options.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015482 *
15483 * @param feedbackConstant One of the constants defined in
15484 * {@link HapticFeedbackConstants}
15485 * @param flags Additional flags as per {@link HapticFeedbackConstants}.
15486 */
15487 public boolean performHapticFeedback(int feedbackConstant, int flags) {
15488 if (mAttachInfo == null) {
15489 return false;
15490 }
Romain Guyf607bdc2010-09-10 19:20:06 -070015491 //noinspection SimplifiableIfStatement
Romain Guy812ccbe2010-06-01 14:07:24 -070015492 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015493 && !isHapticFeedbackEnabled()) {
15494 return false;
15495 }
Romain Guy812ccbe2010-06-01 14:07:24 -070015496 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
15497 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015498 }
15499
15500 /**
Dianne Hackborn98014352012-04-05 18:31:41 -070015501 * Request that the visibility of the status bar or other screen/window
15502 * decorations be changed.
15503 *
15504 * <p>This method is used to put the over device UI into temporary modes
15505 * where the user's attention is focused more on the application content,
15506 * by dimming or hiding surrounding system affordances. This is typically
15507 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
15508 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
15509 * to be placed behind the action bar (and with these flags other system
15510 * affordances) so that smooth transitions between hiding and showing them
15511 * can be done.
15512 *
15513 * <p>Two representative examples of the use of system UI visibility is
15514 * implementing a content browsing application (like a magazine reader)
15515 * and a video playing application.
15516 *
15517 * <p>The first code shows a typical implementation of a View in a content
15518 * browsing application. In this implementation, the application goes
15519 * into a content-oriented mode by hiding the status bar and action bar,
15520 * and putting the navigation elements into lights out mode. The user can
15521 * then interact with content while in this mode. Such an application should
15522 * provide an easy way for the user to toggle out of the mode (such as to
15523 * check information in the status bar or access notifications). In the
15524 * implementation here, this is done simply by tapping on the content.
15525 *
15526 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
15527 * content}
15528 *
15529 * <p>This second code sample shows a typical implementation of a View
15530 * in a video playing application. In this situation, while the video is
15531 * playing the application would like to go into a complete full-screen mode,
15532 * to use as much of the display as possible for the video. When in this state
15533 * the user can not interact with the application; the system intercepts
Dianne Hackborncf675782012-05-10 15:07:24 -070015534 * touching on the screen to pop the UI out of full screen mode. See
15535 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
Dianne Hackborn98014352012-04-05 18:31:41 -070015536 *
15537 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
15538 * content}
15539 *
15540 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15541 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15542 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15543 * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
Joe Onorato664644d2011-01-23 17:53:23 -080015544 */
15545 public void setSystemUiVisibility(int visibility) {
Daniel Sandler70524062011-09-21 00:30:47 -040015546 if (visibility != mSystemUiVisibility) {
15547 mSystemUiVisibility = visibility;
15548 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15549 mParent.recomputeViewAttributes(this);
15550 }
Joe Onorato664644d2011-01-23 17:53:23 -080015551 }
15552 }
15553
15554 /**
Dianne Hackborn98014352012-04-05 18:31:41 -070015555 * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
15556 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15557 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15558 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15559 * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
Joe Onorato664644d2011-01-23 17:53:23 -080015560 */
Joe Onoratoe595cad2011-01-24 09:22:12 -080015561 public int getSystemUiVisibility() {
Joe Onorato664644d2011-01-23 17:53:23 -080015562 return mSystemUiVisibility;
15563 }
15564
Scott Mainec6331b2011-05-24 16:55:56 -070015565 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070015566 * Returns the current system UI visibility that is currently set for
15567 * the entire window. This is the combination of the
15568 * {@link #setSystemUiVisibility(int)} values supplied by all of the
15569 * views in the window.
15570 */
15571 public int getWindowSystemUiVisibility() {
15572 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
15573 }
15574
15575 /**
15576 * Override to find out when the window's requested system UI visibility
15577 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
15578 * This is different from the callbacks recieved through
15579 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
15580 * in that this is only telling you about the local request of the window,
15581 * not the actual values applied by the system.
15582 */
15583 public void onWindowSystemUiVisibilityChanged(int visible) {
15584 }
15585
15586 /**
15587 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
15588 * the view hierarchy.
15589 */
15590 public void dispatchWindowSystemUiVisiblityChanged(int visible) {
15591 onWindowSystemUiVisibilityChanged(visible);
15592 }
15593
15594 /**
Scott Mainec6331b2011-05-24 16:55:56 -070015595 * Set a listener to receive callbacks when the visibility of the system bar changes.
15596 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
15597 */
Joe Onorato664644d2011-01-23 17:53:23 -080015598 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015599 getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
Joe Onorato664644d2011-01-23 17:53:23 -080015600 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15601 mParent.recomputeViewAttributes(this);
15602 }
15603 }
15604
15605 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015606 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
15607 * the view hierarchy.
Joe Onorato664644d2011-01-23 17:53:23 -080015608 */
15609 public void dispatchSystemUiVisibilityChanged(int visibility) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015610 ListenerInfo li = mListenerInfo;
15611 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
15612 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
Joe Onorato6ab77bd2011-01-31 11:21:10 -080015613 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
Joe Onorato664644d2011-01-23 17:53:23 -080015614 }
15615 }
15616
Dianne Hackborncf675782012-05-10 15:07:24 -070015617 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015618 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
15619 if (val != mSystemUiVisibility) {
15620 setSystemUiVisibility(val);
Dianne Hackborncf675782012-05-10 15:07:24 -070015621 return true;
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015622 }
Dianne Hackborncf675782012-05-10 15:07:24 -070015623 return false;
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015624 }
15625
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070015626 /** @hide */
15627 public void setDisabledSystemUiVisibility(int flags) {
15628 if (mAttachInfo != null) {
15629 if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
15630 mAttachInfo.mDisabledSystemUiVisibility = flags;
15631 if (mParent != null) {
15632 mParent.recomputeViewAttributes(this);
15633 }
15634 }
15635 }
15636 }
15637
Joe Onorato664644d2011-01-23 17:53:23 -080015638 /**
Joe Malin32736f02011-01-19 16:14:20 -080015639 * Creates an image that the system displays during the drag and drop
15640 * operation. This is called a &quot;drag shadow&quot;. The default implementation
15641 * for a DragShadowBuilder based on a View returns an image that has exactly the same
15642 * appearance as the given View. The default also positions the center of the drag shadow
15643 * directly under the touch point. If no View is provided (the constructor with no parameters
15644 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
15645 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
15646 * default is an invisible drag shadow.
15647 * <p>
15648 * You are not required to use the View you provide to the constructor as the basis of the
15649 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
15650 * anything you want as the drag shadow.
15651 * </p>
15652 * <p>
15653 * You pass a DragShadowBuilder object to the system when you start the drag. The system
15654 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
15655 * size and position of the drag shadow. It uses this data to construct a
15656 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
15657 * so that your application can draw the shadow image in the Canvas.
15658 * </p>
Joe Fernandez558459f2011-10-13 16:47:36 -070015659 *
15660 * <div class="special reference">
15661 * <h3>Developer Guides</h3>
15662 * <p>For a guide to implementing drag and drop features, read the
15663 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
15664 * </div>
Christopher Tate2c095f32010-10-04 14:13:40 -070015665 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015666 public static class DragShadowBuilder {
Christopher Tatea0374192010-10-05 13:06:41 -070015667 private final WeakReference<View> mView;
Christopher Tate2c095f32010-10-04 14:13:40 -070015668
15669 /**
Joe Malin32736f02011-01-19 16:14:20 -080015670 * Constructs a shadow image builder based on a View. By default, the resulting drag
15671 * shadow will have the same appearance and dimensions as the View, with the touch point
15672 * over the center of the View.
15673 * @param view A View. Any View in scope can be used.
Christopher Tate2c095f32010-10-04 14:13:40 -070015674 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015675 public DragShadowBuilder(View view) {
Christopher Tatea0374192010-10-05 13:06:41 -070015676 mView = new WeakReference<View>(view);
Christopher Tate2c095f32010-10-04 14:13:40 -070015677 }
15678
Christopher Tate17ed60c2011-01-18 12:50:26 -080015679 /**
15680 * Construct a shadow builder object with no associated View. This
15681 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
15682 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
15683 * to supply the drag shadow's dimensions and appearance without
Joe Malin32736f02011-01-19 16:14:20 -080015684 * reference to any View object. If they are not overridden, then the result is an
15685 * invisible drag shadow.
Christopher Tate17ed60c2011-01-18 12:50:26 -080015686 */
15687 public DragShadowBuilder() {
15688 mView = new WeakReference<View>(null);
15689 }
15690
15691 /**
15692 * Returns the View object that had been passed to the
15693 * {@link #View.DragShadowBuilder(View)}
15694 * constructor. If that View parameter was {@code null} or if the
15695 * {@link #View.DragShadowBuilder()}
15696 * constructor was used to instantiate the builder object, this method will return
15697 * null.
15698 *
15699 * @return The View object associate with this builder object.
15700 */
Romain Guy5c22a8c2011-05-13 11:48:45 -070015701 @SuppressWarnings({"JavadocReference"})
Chris Tate6b391282010-10-14 15:48:59 -070015702 final public View getView() {
15703 return mView.get();
15704 }
15705
Christopher Tate2c095f32010-10-04 14:13:40 -070015706 /**
Joe Malin32736f02011-01-19 16:14:20 -080015707 * Provides the metrics for the shadow image. These include the dimensions of
15708 * the shadow image, and the point within that shadow that should
Christopher Tate2c095f32010-10-04 14:13:40 -070015709 * be centered under the touch location while dragging.
15710 * <p>
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015711 * The default implementation sets the dimensions of the shadow to be the
Joe Malin32736f02011-01-19 16:14:20 -080015712 * same as the dimensions of the View itself and centers the shadow under
15713 * the touch point.
15714 * </p>
Christopher Tate2c095f32010-10-04 14:13:40 -070015715 *
Joe Malin32736f02011-01-19 16:14:20 -080015716 * @param shadowSize A {@link android.graphics.Point} containing the width and height
15717 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
15718 * desired width and must set {@link android.graphics.Point#y} to the desired height of the
15719 * image.
15720 *
15721 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
15722 * shadow image that should be underneath the touch point during the drag and drop
15723 * operation. Your application must set {@link android.graphics.Point#x} to the
15724 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
Christopher Tate2c095f32010-10-04 14:13:40 -070015725 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015726 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
Christopher Tatea0374192010-10-05 13:06:41 -070015727 final View view = mView.get();
15728 if (view != null) {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015729 shadowSize.set(view.getWidth(), view.getHeight());
15730 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
Christopher Tatea0374192010-10-05 13:06:41 -070015731 } else {
15732 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
15733 }
Christopher Tate2c095f32010-10-04 14:13:40 -070015734 }
15735
15736 /**
Joe Malin32736f02011-01-19 16:14:20 -080015737 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
15738 * based on the dimensions it received from the
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015739 * {@link #onProvideShadowMetrics(Point, Point)} callback.
Christopher Tate2c095f32010-10-04 14:13:40 -070015740 *
Joe Malin32736f02011-01-19 16:14:20 -080015741 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
Christopher Tate2c095f32010-10-04 14:13:40 -070015742 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015743 public void onDrawShadow(Canvas canvas) {
Christopher Tatea0374192010-10-05 13:06:41 -070015744 final View view = mView.get();
15745 if (view != null) {
15746 view.draw(canvas);
15747 } else {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015748 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
Christopher Tatea0374192010-10-05 13:06:41 -070015749 }
Christopher Tate2c095f32010-10-04 14:13:40 -070015750 }
15751 }
15752
15753 /**
Joe Malin32736f02011-01-19 16:14:20 -080015754 * Starts a drag and drop operation. When your application calls this method, it passes a
15755 * {@link android.view.View.DragShadowBuilder} object to the system. The
15756 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
15757 * to get metrics for the drag shadow, and then calls the object's
15758 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
15759 * <p>
15760 * Once the system has the drag shadow, it begins the drag and drop operation by sending
15761 * drag events to all the View objects in your application that are currently visible. It does
15762 * this either by calling the View object's drag listener (an implementation of
15763 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
15764 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
15765 * Both are passed a {@link android.view.DragEvent} object that has a
15766 * {@link android.view.DragEvent#getAction()} value of
15767 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
15768 * </p>
15769 * <p>
15770 * Your application can invoke startDrag() on any attached View object. The View object does not
15771 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
15772 * be related to the View the user selected for dragging.
15773 * </p>
15774 * @param data A {@link android.content.ClipData} object pointing to the data to be
15775 * transferred by the drag and drop operation.
15776 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
15777 * drag shadow.
15778 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
15779 * drop operation. This Object is put into every DragEvent object sent by the system during the
15780 * current drag.
15781 * <p>
15782 * myLocalState is a lightweight mechanism for the sending information from the dragged View
15783 * to the target Views. For example, it can contain flags that differentiate between a
15784 * a copy operation and a move operation.
15785 * </p>
15786 * @param flags Flags that control the drag and drop operation. No flags are currently defined,
15787 * so the parameter should be set to 0.
15788 * @return {@code true} if the method completes successfully, or
15789 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
15790 * do a drag, and so no drag operation is in progress.
Christopher Tatea53146c2010-09-07 11:57:52 -070015791 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015792 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015793 Object myLocalState, int flags) {
Christopher Tate2c095f32010-10-04 14:13:40 -070015794 if (ViewDebug.DEBUG_DRAG) {
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015795 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
Christopher Tatea53146c2010-09-07 11:57:52 -070015796 }
15797 boolean okay = false;
15798
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015799 Point shadowSize = new Point();
15800 Point shadowTouchPoint = new Point();
15801 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
Christopher Tate2c095f32010-10-04 14:13:40 -070015802
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015803 if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
15804 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
15805 throw new IllegalStateException("Drag shadow dimensions must not be negative");
Christopher Tate2c095f32010-10-04 14:13:40 -070015806 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015807
Chris Tatea32dcf72010-10-14 12:13:50 -070015808 if (ViewDebug.DEBUG_DRAG) {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015809 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
15810 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
Chris Tatea32dcf72010-10-14 12:13:50 -070015811 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015812 Surface surface = new Surface();
15813 try {
15814 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015815 flags, shadowSize.x, shadowSize.y, surface);
Christopher Tate2c095f32010-10-04 14:13:40 -070015816 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
Christopher Tatea53146c2010-09-07 11:57:52 -070015817 + " surface=" + surface);
15818 if (token != null) {
15819 Canvas canvas = surface.lockCanvas(null);
Romain Guy0bb56672010-10-01 00:25:02 -070015820 try {
Chris Tate6b391282010-10-14 15:48:59 -070015821 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015822 shadowBuilder.onDrawShadow(canvas);
Romain Guy0bb56672010-10-01 00:25:02 -070015823 } finally {
15824 surface.unlockCanvasAndPost(canvas);
15825 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015826
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070015827 final ViewRootImpl root = getViewRootImpl();
Christopher Tate407b4e92010-11-30 17:14:08 -080015828
15829 // Cache the local state object for delivery with DragEvents
15830 root.setLocalDragState(myLocalState);
15831
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015832 // repurpose 'shadowSize' for the last touch point
15833 root.getLastTouchPoint(shadowSize);
Christopher Tate2c095f32010-10-04 14:13:40 -070015834
Christopher Tatea53146c2010-09-07 11:57:52 -070015835 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015836 shadowSize.x, shadowSize.y,
15837 shadowTouchPoint.x, shadowTouchPoint.y, data);
Christopher Tate2c095f32010-10-04 14:13:40 -070015838 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
Christopher Tate8f73b5d2011-09-12 15:22:12 -070015839
15840 // Off and running! Release our local surface instance; the drag
15841 // shadow surface is now managed by the system process.
15842 surface.release();
Christopher Tatea53146c2010-09-07 11:57:52 -070015843 }
15844 } catch (Exception e) {
15845 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
15846 surface.destroy();
15847 }
15848
15849 return okay;
15850 }
15851
Christopher Tatea53146c2010-09-07 11:57:52 -070015852 /**
Joe Malin32736f02011-01-19 16:14:20 -080015853 * Handles drag events sent by the system following a call to
15854 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
15855 *<p>
15856 * When the system calls this method, it passes a
15857 * {@link android.view.DragEvent} object. A call to
15858 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
15859 * in DragEvent. The method uses these to determine what is happening in the drag and drop
15860 * operation.
15861 * @param event The {@link android.view.DragEvent} sent by the system.
15862 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
15863 * in DragEvent, indicating the type of drag event represented by this object.
15864 * @return {@code true} if the method was successful, otherwise {@code false}.
15865 * <p>
15866 * The method should return {@code true} in response to an action type of
15867 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
15868 * operation.
15869 * </p>
15870 * <p>
15871 * The method should also return {@code true} in response to an action type of
15872 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
15873 * {@code false} if it didn't.
15874 * </p>
Christopher Tatea53146c2010-09-07 11:57:52 -070015875 */
Christopher Tate5ada6cb2010-10-05 14:15:29 -070015876 public boolean onDragEvent(DragEvent event) {
Christopher Tatea53146c2010-09-07 11:57:52 -070015877 return false;
15878 }
15879
15880 /**
Joe Malin32736f02011-01-19 16:14:20 -080015881 * Detects if this View is enabled and has a drag event listener.
15882 * If both are true, then it calls the drag event listener with the
15883 * {@link android.view.DragEvent} it received. If the drag event listener returns
15884 * {@code true}, then dispatchDragEvent() returns {@code true}.
15885 * <p>
15886 * For all other cases, the method calls the
15887 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
15888 * method and returns its result.
15889 * </p>
15890 * <p>
15891 * This ensures that a drag event is always consumed, even if the View does not have a drag
15892 * event listener. However, if the View has a listener and the listener returns true, then
15893 * onDragEvent() is not called.
15894 * </p>
Christopher Tatea53146c2010-09-07 11:57:52 -070015895 */
15896 public boolean dispatchDragEvent(DragEvent event) {
Romain Guy676b1732011-02-14 14:45:33 -080015897 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015898 ListenerInfo li = mListenerInfo;
15899 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
15900 && li.mOnDragListener.onDrag(this, event)) {
Chris Tate32affef2010-10-18 15:29:21 -070015901 return true;
15902 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015903 return onDragEvent(event);
15904 }
15905
Christopher Tate3d4bf172011-03-28 16:16:46 -070015906 boolean canAcceptDrag() {
15907 return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
15908 }
15909
Christopher Tatea53146c2010-09-07 11:57:52 -070015910 /**
Dianne Hackbornffa42482009-09-23 22:20:11 -070015911 * This needs to be a better API (NOT ON VIEW) before it is exposed. If
15912 * it is ever exposed at all.
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -070015913 * @hide
Dianne Hackbornffa42482009-09-23 22:20:11 -070015914 */
15915 public void onCloseSystemDialogs(String reason) {
15916 }
Joe Malin32736f02011-01-19 16:14:20 -080015917
Dianne Hackbornffa42482009-09-23 22:20:11 -070015918 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015919 * Given a Drawable whose bounds have been set to draw into this view,
Romain Guy5c22a8c2011-05-13 11:48:45 -070015920 * update a Region being computed for
15921 * {@link #gatherTransparentRegion(android.graphics.Region)} so
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015922 * that any non-transparent parts of the Drawable are removed from the
15923 * given transparent region.
15924 *
15925 * @param dr The Drawable whose transparency is to be applied to the region.
15926 * @param region A Region holding the current transparency information,
15927 * where any parts of the region that are set are considered to be
15928 * transparent. On return, this region will be modified to have the
15929 * transparency information reduced by the corresponding parts of the
15930 * Drawable that are not transparent.
15931 * {@hide}
15932 */
15933 public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
15934 if (DBG) {
15935 Log.i("View", "Getting transparent region for: " + this);
15936 }
15937 final Region r = dr.getTransparentRegion();
15938 final Rect db = dr.getBounds();
15939 final AttachInfo attachInfo = mAttachInfo;
15940 if (r != null && attachInfo != null) {
15941 final int w = getRight()-getLeft();
15942 final int h = getBottom()-getTop();
15943 if (db.left > 0) {
15944 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
15945 r.op(0, 0, db.left, h, Region.Op.UNION);
15946 }
15947 if (db.right < w) {
15948 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
15949 r.op(db.right, 0, w, h, Region.Op.UNION);
15950 }
15951 if (db.top > 0) {
15952 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
15953 r.op(0, 0, w, db.top, Region.Op.UNION);
15954 }
15955 if (db.bottom < h) {
15956 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
15957 r.op(0, db.bottom, w, h, Region.Op.UNION);
15958 }
15959 final int[] location = attachInfo.mTransparentLocation;
15960 getLocationInWindow(location);
15961 r.translate(location[0], location[1]);
15962 region.op(r, Region.Op.INTERSECT);
15963 } else {
15964 region.op(db, Region.Op.DIFFERENCE);
15965 }
15966 }
15967
Patrick Dubroye0a799a2011-05-04 16:19:22 -070015968 private void checkForLongClick(int delayOffset) {
15969 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
15970 mHasPerformedLongPress = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015971
Patrick Dubroye0a799a2011-05-04 16:19:22 -070015972 if (mPendingCheckForLongPress == null) {
15973 mPendingCheckForLongPress = new CheckForLongPress();
15974 }
15975 mPendingCheckForLongPress.rememberWindowAttachCount();
15976 postDelayed(mPendingCheckForLongPress,
15977 ViewConfiguration.getLongPressTimeout() - delayOffset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015979 }
15980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015981 /**
15982 * Inflate a view from an XML resource. This convenience method wraps the {@link
15983 * LayoutInflater} class, which provides a full range of options for view inflation.
15984 *
15985 * @param context The Context object for your activity or application.
15986 * @param resource The resource ID to inflate
15987 * @param root A view group that will be the parent. Used to properly inflate the
15988 * layout_* parameters.
15989 * @see LayoutInflater
15990 */
15991 public static View inflate(Context context, int resource, ViewGroup root) {
15992 LayoutInflater factory = LayoutInflater.from(context);
15993 return factory.inflate(resource, root);
15994 }
Romain Guy33e72ae2010-07-17 12:40:29 -070015995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015996 /**
Adam Powell637d3372010-08-25 14:37:03 -070015997 * Scroll the view with standard behavior for scrolling beyond the normal
15998 * content boundaries. Views that call this method should override
15999 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
16000 * results of an over-scroll operation.
16001 *
16002 * Views can use this method to handle any touch or fling-based scrolling.
16003 *
16004 * @param deltaX Change in X in pixels
16005 * @param deltaY Change in Y in pixels
16006 * @param scrollX Current X scroll value in pixels before applying deltaX
16007 * @param scrollY Current Y scroll value in pixels before applying deltaY
16008 * @param scrollRangeX Maximum content scroll range along the X axis
16009 * @param scrollRangeY Maximum content scroll range along the Y axis
16010 * @param maxOverScrollX Number of pixels to overscroll by in either direction
16011 * along the X axis.
16012 * @param maxOverScrollY Number of pixels to overscroll by in either direction
16013 * along the Y axis.
16014 * @param isTouchEvent true if this scroll operation is the result of a touch event.
16015 * @return true if scrolling was clamped to an over-scroll boundary along either
16016 * axis, false otherwise.
16017 */
Romain Guy7b5b6ab2011-03-14 18:05:08 -070016018 @SuppressWarnings({"UnusedParameters"})
Adam Powell637d3372010-08-25 14:37:03 -070016019 protected boolean overScrollBy(int deltaX, int deltaY,
16020 int scrollX, int scrollY,
16021 int scrollRangeX, int scrollRangeY,
16022 int maxOverScrollX, int maxOverScrollY,
16023 boolean isTouchEvent) {
16024 final int overScrollMode = mOverScrollMode;
16025 final boolean canScrollHorizontal =
16026 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
16027 final boolean canScrollVertical =
16028 computeVerticalScrollRange() > computeVerticalScrollExtent();
16029 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
16030 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
16031 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
16032 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
16033
16034 int newScrollX = scrollX + deltaX;
16035 if (!overScrollHorizontal) {
16036 maxOverScrollX = 0;
16037 }
16038
16039 int newScrollY = scrollY + deltaY;
16040 if (!overScrollVertical) {
16041 maxOverScrollY = 0;
16042 }
16043
16044 // Clamp values if at the limits and record
16045 final int left = -maxOverScrollX;
16046 final int right = maxOverScrollX + scrollRangeX;
16047 final int top = -maxOverScrollY;
16048 final int bottom = maxOverScrollY + scrollRangeY;
16049
16050 boolean clampedX = false;
16051 if (newScrollX > right) {
16052 newScrollX = right;
16053 clampedX = true;
16054 } else if (newScrollX < left) {
16055 newScrollX = left;
16056 clampedX = true;
16057 }
16058
16059 boolean clampedY = false;
16060 if (newScrollY > bottom) {
16061 newScrollY = bottom;
16062 clampedY = true;
16063 } else if (newScrollY < top) {
16064 newScrollY = top;
16065 clampedY = true;
16066 }
16067
16068 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
16069
16070 return clampedX || clampedY;
16071 }
16072
16073 /**
16074 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
16075 * respond to the results of an over-scroll operation.
16076 *
16077 * @param scrollX New X scroll value in pixels
16078 * @param scrollY New Y scroll value in pixels
16079 * @param clampedX True if scrollX was clamped to an over-scroll boundary
16080 * @param clampedY True if scrollY was clamped to an over-scroll boundary
16081 */
16082 protected void onOverScrolled(int scrollX, int scrollY,
16083 boolean clampedX, boolean clampedY) {
16084 // Intentionally empty.
16085 }
16086
16087 /**
16088 * Returns the over-scroll mode for this view. The result will be
16089 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16090 * (allow over-scrolling only if the view content is larger than the container),
16091 * or {@link #OVER_SCROLL_NEVER}.
16092 *
16093 * @return This view's over-scroll mode.
16094 */
16095 public int getOverScrollMode() {
16096 return mOverScrollMode;
16097 }
16098
16099 /**
16100 * Set the over-scroll mode for this view. Valid over-scroll modes are
16101 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16102 * (allow over-scrolling only if the view content is larger than the container),
16103 * or {@link #OVER_SCROLL_NEVER}.
16104 *
16105 * Setting the over-scroll mode of a view will have an effect only if the
16106 * view is capable of scrolling.
16107 *
16108 * @param overScrollMode The new over-scroll mode for this view.
16109 */
16110 public void setOverScrollMode(int overScrollMode) {
16111 if (overScrollMode != OVER_SCROLL_ALWAYS &&
16112 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
16113 overScrollMode != OVER_SCROLL_NEVER) {
16114 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
16115 }
16116 mOverScrollMode = overScrollMode;
16117 }
16118
16119 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -080016120 * Gets a scale factor that determines the distance the view should scroll
16121 * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
16122 * @return The vertical scroll scale factor.
16123 * @hide
16124 */
16125 protected float getVerticalScrollFactor() {
16126 if (mVerticalScrollFactor == 0) {
16127 TypedValue outValue = new TypedValue();
16128 if (!mContext.getTheme().resolveAttribute(
16129 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
16130 throw new IllegalStateException(
16131 "Expected theme to define listPreferredItemHeight.");
16132 }
16133 mVerticalScrollFactor = outValue.getDimension(
16134 mContext.getResources().getDisplayMetrics());
16135 }
16136 return mVerticalScrollFactor;
16137 }
16138
16139 /**
16140 * Gets a scale factor that determines the distance the view should scroll
16141 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
16142 * @return The horizontal scroll scale factor.
16143 * @hide
16144 */
16145 protected float getHorizontalScrollFactor() {
16146 // TODO: Should use something else.
16147 return getVerticalScrollFactor();
16148 }
16149
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016150 /**
16151 * Return the value specifying the text direction or policy that was set with
16152 * {@link #setTextDirection(int)}.
16153 *
16154 * @return the defined text direction. It can be one of:
16155 *
16156 * {@link #TEXT_DIRECTION_INHERIT},
16157 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16158 * {@link #TEXT_DIRECTION_ANY_RTL},
16159 * {@link #TEXT_DIRECTION_LTR},
16160 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016161 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016162 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016163 @ViewDebug.ExportedProperty(category = "text", mapping = {
16164 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
16165 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
16166 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
16167 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
16168 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
16169 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
16170 })
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016171 public int getTextDirection() {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016172 return (mPrivateFlags2 & TEXT_DIRECTION_MASK) >> TEXT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016173 }
16174
16175 /**
16176 * Set the text direction.
16177 *
16178 * @param textDirection the direction to set. Should be one of:
16179 *
16180 * {@link #TEXT_DIRECTION_INHERIT},
16181 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16182 * {@link #TEXT_DIRECTION_ANY_RTL},
16183 * {@link #TEXT_DIRECTION_LTR},
16184 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016185 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016186 */
16187 public void setTextDirection(int textDirection) {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016188 if (getTextDirection() != textDirection) {
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016189 // Reset the current text direction and the resolved one
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016190 mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016191 resetResolvedTextDirection();
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016192 // Set the new text direction
16193 mPrivateFlags2 |= ((textDirection << TEXT_DIRECTION_MASK_SHIFT) & TEXT_DIRECTION_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016194 // Refresh
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016195 requestLayout();
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016196 invalidate(true);
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016197 }
16198 }
16199
16200 /**
16201 * Return the resolved text direction.
16202 *
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016203 * This needs resolution if the value is TEXT_DIRECTION_INHERIT. The resolution matches
16204 * {@link #getTextDirection()}if it is not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds
16205 * up the parent chain of the view. if there is no parent, then it will return the default
16206 * {@link #TEXT_DIRECTION_FIRST_STRONG}.
16207 *
16208 * @return the resolved text direction. Returns one of:
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016209 *
Doug Feltcb3791202011-07-07 11:57:48 -070016210 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16211 * {@link #TEXT_DIRECTION_ANY_RTL},
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016212 * {@link #TEXT_DIRECTION_LTR},
16213 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016214 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016215 */
16216 public int getResolvedTextDirection() {
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070016217 // The text direction will be resolved only if needed
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016218 if ((mPrivateFlags2 & TEXT_DIRECTION_RESOLVED) != TEXT_DIRECTION_RESOLVED) {
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016219 resolveTextDirection();
16220 }
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016221 return (mPrivateFlags2 & TEXT_DIRECTION_RESOLVED_MASK) >> TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016222 }
16223
16224 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016225 * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
16226 * resolution is done.
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016227 */
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016228 public void resolveTextDirection() {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016229 // Reset any previous text direction resolution
16230 mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
16231
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016232 if (hasRtlSupport()) {
16233 // Set resolved text direction flag depending on text direction flag
16234 final int textDirection = getTextDirection();
16235 switch(textDirection) {
16236 case TEXT_DIRECTION_INHERIT:
16237 if (canResolveTextDirection()) {
16238 ViewGroup viewGroup = ((ViewGroup) mParent);
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016239
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016240 // Set current resolved direction to the same value as the parent's one
16241 final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
16242 switch (parentResolvedDirection) {
16243 case TEXT_DIRECTION_FIRST_STRONG:
16244 case TEXT_DIRECTION_ANY_RTL:
16245 case TEXT_DIRECTION_LTR:
16246 case TEXT_DIRECTION_RTL:
16247 case TEXT_DIRECTION_LOCALE:
16248 mPrivateFlags2 |=
16249 (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16250 break;
16251 default:
16252 // Default resolved direction is "first strong" heuristic
16253 mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
16254 }
16255 } else {
16256 // We cannot do the resolution if there is no parent, so use the default one
16257 mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016258 }
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016259 break;
16260 case TEXT_DIRECTION_FIRST_STRONG:
16261 case TEXT_DIRECTION_ANY_RTL:
16262 case TEXT_DIRECTION_LTR:
16263 case TEXT_DIRECTION_RTL:
16264 case TEXT_DIRECTION_LOCALE:
16265 // Resolved direction is the same as text direction
16266 mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16267 break;
16268 default:
16269 // Default resolved direction is "first strong" heuristic
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016270 mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016271 }
16272 } else {
16273 // Default resolved direction is "first strong" heuristic
16274 mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016275 }
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016276
16277 // Set to resolved
16278 mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016279 onResolvedTextDirectionChanged();
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016280 }
16281
16282 /**
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016283 * Called when text direction has been resolved. Subclasses that care about text direction
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016284 * resolution should override this method.
16285 *
16286 * The default implementation does nothing.
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016287 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016288 public void onResolvedTextDirectionChanged() {
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016289 }
16290
16291 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016292 * Check if text direction resolution can be done.
16293 *
16294 * @return true if text direction resolution can be done otherwise return false.
16295 */
16296 public boolean canResolveTextDirection() {
16297 switch (getTextDirection()) {
16298 case TEXT_DIRECTION_INHERIT:
16299 return (mParent != null) && (mParent instanceof ViewGroup);
16300 default:
16301 return true;
16302 }
16303 }
16304
16305 /**
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016306 * Reset resolved text direction. Text direction can be resolved with a call to
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016307 * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016308 * reset is done.
16309 */
16310 public void resetResolvedTextDirection() {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016311 mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016312 onResolvedTextDirectionReset();
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016313 }
16314
16315 /**
16316 * Called when text direction is reset. Subclasses that care about text direction reset should
16317 * override this method and do a reset of the text direction of their children. The default
16318 * implementation does nothing.
16319 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016320 public void onResolvedTextDirectionReset() {
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016321 }
16322
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016323 /**
16324 * Return the value specifying the text alignment or policy that was set with
16325 * {@link #setTextAlignment(int)}.
16326 *
16327 * @return the defined text alignment. It can be one of:
16328 *
16329 * {@link #TEXT_ALIGNMENT_INHERIT},
16330 * {@link #TEXT_ALIGNMENT_GRAVITY},
16331 * {@link #TEXT_ALIGNMENT_CENTER},
16332 * {@link #TEXT_ALIGNMENT_TEXT_START},
16333 * {@link #TEXT_ALIGNMENT_TEXT_END},
16334 * {@link #TEXT_ALIGNMENT_VIEW_START},
16335 * {@link #TEXT_ALIGNMENT_VIEW_END}
16336 */
16337 @ViewDebug.ExportedProperty(category = "text", mapping = {
16338 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16339 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16340 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16341 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16342 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16343 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16344 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16345 })
16346 public int getTextAlignment() {
16347 return (mPrivateFlags2 & TEXT_ALIGNMENT_MASK) >> TEXT_ALIGNMENT_MASK_SHIFT;
16348 }
16349
16350 /**
16351 * Set the text alignment.
16352 *
16353 * @param textAlignment The text alignment to set. Should be one of
16354 *
16355 * {@link #TEXT_ALIGNMENT_INHERIT},
16356 * {@link #TEXT_ALIGNMENT_GRAVITY},
16357 * {@link #TEXT_ALIGNMENT_CENTER},
16358 * {@link #TEXT_ALIGNMENT_TEXT_START},
16359 * {@link #TEXT_ALIGNMENT_TEXT_END},
16360 * {@link #TEXT_ALIGNMENT_VIEW_START},
16361 * {@link #TEXT_ALIGNMENT_VIEW_END}
16362 *
16363 * @attr ref android.R.styleable#View_textAlignment
16364 */
16365 public void setTextAlignment(int textAlignment) {
16366 if (textAlignment != getTextAlignment()) {
16367 // Reset the current and resolved text alignment
16368 mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
16369 resetResolvedTextAlignment();
16370 // Set the new text alignment
16371 mPrivateFlags2 |= ((textAlignment << TEXT_ALIGNMENT_MASK_SHIFT) & TEXT_ALIGNMENT_MASK);
16372 // Refresh
16373 requestLayout();
16374 invalidate(true);
16375 }
16376 }
16377
16378 /**
16379 * Return the resolved text alignment.
16380 *
16381 * The resolved text alignment. This needs resolution if the value is
16382 * TEXT_ALIGNMENT_INHERIT. The resolution matches {@link #setTextAlignment(int)} if it is
16383 * not TEXT_ALIGNMENT_INHERIT, otherwise resolution proceeds up the parent chain of the view.
16384 *
16385 * @return the resolved text alignment. Returns one of:
16386 *
16387 * {@link #TEXT_ALIGNMENT_GRAVITY},
16388 * {@link #TEXT_ALIGNMENT_CENTER},
16389 * {@link #TEXT_ALIGNMENT_TEXT_START},
16390 * {@link #TEXT_ALIGNMENT_TEXT_END},
16391 * {@link #TEXT_ALIGNMENT_VIEW_START},
16392 * {@link #TEXT_ALIGNMENT_VIEW_END}
16393 */
16394 @ViewDebug.ExportedProperty(category = "text", mapping = {
16395 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16396 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16397 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16398 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16399 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16400 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16401 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16402 })
16403 public int getResolvedTextAlignment() {
16404 // If text alignment is not resolved, then resolve it
16405 if ((mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED) != TEXT_ALIGNMENT_RESOLVED) {
16406 resolveTextAlignment();
16407 }
16408 return (mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED_MASK) >> TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
16409 }
16410
16411 /**
16412 * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
16413 * resolution is done.
16414 */
16415 public void resolveTextAlignment() {
16416 // Reset any previous text alignment resolution
16417 mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
16418
16419 if (hasRtlSupport()) {
16420 // Set resolved text alignment flag depending on text alignment flag
16421 final int textAlignment = getTextAlignment();
16422 switch (textAlignment) {
16423 case TEXT_ALIGNMENT_INHERIT:
16424 // Check if we can resolve the text alignment
16425 if (canResolveLayoutDirection() && mParent instanceof View) {
16426 View view = (View) mParent;
16427
16428 final int parentResolvedTextAlignment = view.getResolvedTextAlignment();
16429 switch (parentResolvedTextAlignment) {
16430 case TEXT_ALIGNMENT_GRAVITY:
16431 case TEXT_ALIGNMENT_TEXT_START:
16432 case TEXT_ALIGNMENT_TEXT_END:
16433 case TEXT_ALIGNMENT_CENTER:
16434 case TEXT_ALIGNMENT_VIEW_START:
16435 case TEXT_ALIGNMENT_VIEW_END:
16436 // Resolved text alignment is the same as the parent resolved
16437 // text alignment
16438 mPrivateFlags2 |=
16439 (parentResolvedTextAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16440 break;
16441 default:
16442 // Use default resolved text alignment
16443 mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16444 }
16445 }
16446 else {
16447 // We cannot do the resolution if there is no parent so use the default
16448 mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16449 }
16450 break;
16451 case TEXT_ALIGNMENT_GRAVITY:
16452 case TEXT_ALIGNMENT_TEXT_START:
16453 case TEXT_ALIGNMENT_TEXT_END:
16454 case TEXT_ALIGNMENT_CENTER:
16455 case TEXT_ALIGNMENT_VIEW_START:
16456 case TEXT_ALIGNMENT_VIEW_END:
16457 // Resolved text alignment is the same as text alignment
16458 mPrivateFlags2 |= (textAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16459 break;
16460 default:
16461 // Use default resolved text alignment
16462 mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16463 }
16464 } else {
16465 // Use default resolved text alignment
16466 mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16467 }
16468
16469 // Set the resolved
16470 mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED;
16471 onResolvedTextAlignmentChanged();
16472 }
16473
16474 /**
16475 * Check if text alignment resolution can be done.
16476 *
16477 * @return true if text alignment resolution can be done otherwise return false.
16478 */
16479 public boolean canResolveTextAlignment() {
16480 switch (getTextAlignment()) {
16481 case TEXT_DIRECTION_INHERIT:
16482 return (mParent != null);
16483 default:
16484 return true;
16485 }
16486 }
16487
16488 /**
16489 * Called when text alignment has been resolved. Subclasses that care about text alignment
16490 * resolution should override this method.
16491 *
16492 * The default implementation does nothing.
16493 */
16494 public void onResolvedTextAlignmentChanged() {
16495 }
16496
16497 /**
16498 * Reset resolved text alignment. Text alignment can be resolved with a call to
16499 * getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
16500 * reset is done.
16501 */
16502 public void resetResolvedTextAlignment() {
16503 // Reset any previous text alignment resolution
16504 mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
16505 onResolvedTextAlignmentReset();
16506 }
16507
16508 /**
16509 * Called when text alignment is reset. Subclasses that care about text alignment reset should
16510 * override this method and do a reset of the text alignment of their children. The default
16511 * implementation does nothing.
16512 */
16513 public void onResolvedTextAlignmentReset() {
16514 }
16515
Adam Powella9108a22012-07-18 11:18:09 -070016516 /**
16517 * Generate a value suitable for use in {@link #setId(int)}.
16518 * This value will not collide with ID values generated at build time by aapt for R.id.
16519 *
16520 * @return a generated ID value
16521 */
16522 public static int generateViewId() {
16523 for (;;) {
16524 final int result = sNextGeneratedId.get();
16525 // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
16526 int newValue = result + 1;
16527 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
16528 if (sNextGeneratedId.compareAndSet(result, newValue)) {
16529 return result;
16530 }
16531 }
16532 }
16533
Chet Haaseb39f0512011-05-24 14:36:40 -070016534 //
16535 // Properties
16536 //
16537 /**
16538 * A Property wrapper around the <code>alpha</code> functionality handled by the
16539 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
16540 */
Chet Haased47f1532011-12-16 11:18:52 -080016541 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016542 @Override
16543 public void setValue(View object, float value) {
16544 object.setAlpha(value);
16545 }
16546
16547 @Override
16548 public Float get(View object) {
16549 return object.getAlpha();
16550 }
16551 };
16552
16553 /**
16554 * A Property wrapper around the <code>translationX</code> functionality handled by the
16555 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
16556 */
Chet Haased47f1532011-12-16 11:18:52 -080016557 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016558 @Override
16559 public void setValue(View object, float value) {
16560 object.setTranslationX(value);
16561 }
16562
16563 @Override
16564 public Float get(View object) {
16565 return object.getTranslationX();
16566 }
16567 };
16568
16569 /**
16570 * A Property wrapper around the <code>translationY</code> functionality handled by the
16571 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
16572 */
Chet Haased47f1532011-12-16 11:18:52 -080016573 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016574 @Override
16575 public void setValue(View object, float value) {
16576 object.setTranslationY(value);
16577 }
16578
16579 @Override
16580 public Float get(View object) {
16581 return object.getTranslationY();
16582 }
16583 };
16584
16585 /**
16586 * A Property wrapper around the <code>x</code> functionality handled by the
16587 * {@link View#setX(float)} and {@link View#getX()} methods.
16588 */
Chet Haased47f1532011-12-16 11:18:52 -080016589 public static final Property<View, Float> X = new FloatProperty<View>("x") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016590 @Override
16591 public void setValue(View object, float value) {
16592 object.setX(value);
16593 }
16594
16595 @Override
16596 public Float get(View object) {
16597 return object.getX();
16598 }
16599 };
16600
16601 /**
16602 * A Property wrapper around the <code>y</code> functionality handled by the
16603 * {@link View#setY(float)} and {@link View#getY()} methods.
16604 */
Chet Haased47f1532011-12-16 11:18:52 -080016605 public static final Property<View, Float> Y = new FloatProperty<View>("y") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016606 @Override
16607 public void setValue(View object, float value) {
16608 object.setY(value);
16609 }
16610
16611 @Override
16612 public Float get(View object) {
16613 return object.getY();
16614 }
16615 };
16616
16617 /**
16618 * A Property wrapper around the <code>rotation</code> functionality handled by the
16619 * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
16620 */
Chet Haased47f1532011-12-16 11:18:52 -080016621 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016622 @Override
16623 public void setValue(View object, float value) {
16624 object.setRotation(value);
16625 }
16626
16627 @Override
16628 public Float get(View object) {
16629 return object.getRotation();
16630 }
16631 };
16632
16633 /**
16634 * A Property wrapper around the <code>rotationX</code> functionality handled by the
16635 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
16636 */
Chet Haased47f1532011-12-16 11:18:52 -080016637 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016638 @Override
16639 public void setValue(View object, float value) {
16640 object.setRotationX(value);
16641 }
16642
16643 @Override
16644 public Float get(View object) {
16645 return object.getRotationX();
16646 }
16647 };
16648
16649 /**
16650 * A Property wrapper around the <code>rotationY</code> functionality handled by the
16651 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
16652 */
Chet Haased47f1532011-12-16 11:18:52 -080016653 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016654 @Override
16655 public void setValue(View object, float value) {
16656 object.setRotationY(value);
16657 }
16658
16659 @Override
16660 public Float get(View object) {
16661 return object.getRotationY();
16662 }
16663 };
16664
16665 /**
16666 * A Property wrapper around the <code>scaleX</code> functionality handled by the
16667 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
16668 */
Chet Haased47f1532011-12-16 11:18:52 -080016669 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016670 @Override
16671 public void setValue(View object, float value) {
16672 object.setScaleX(value);
16673 }
16674
16675 @Override
16676 public Float get(View object) {
16677 return object.getScaleX();
16678 }
16679 };
16680
16681 /**
16682 * A Property wrapper around the <code>scaleY</code> functionality handled by the
16683 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
16684 */
Chet Haased47f1532011-12-16 11:18:52 -080016685 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016686 @Override
16687 public void setValue(View object, float value) {
16688 object.setScaleY(value);
16689 }
16690
16691 @Override
16692 public Float get(View object) {
16693 return object.getScaleY();
16694 }
16695 };
16696
Jeff Brown33bbfd22011-02-24 20:55:35 -080016697 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016698 * A MeasureSpec encapsulates the layout requirements passed from parent to child.
16699 * Each MeasureSpec represents a requirement for either the width or the height.
16700 * A MeasureSpec is comprised of a size and a mode. There are three possible
16701 * modes:
16702 * <dl>
16703 * <dt>UNSPECIFIED</dt>
16704 * <dd>
16705 * The parent has not imposed any constraint on the child. It can be whatever size
16706 * it wants.
16707 * </dd>
16708 *
16709 * <dt>EXACTLY</dt>
16710 * <dd>
16711 * The parent has determined an exact size for the child. The child is going to be
16712 * given those bounds regardless of how big it wants to be.
16713 * </dd>
16714 *
16715 * <dt>AT_MOST</dt>
16716 * <dd>
16717 * The child can be as large as it wants up to the specified size.
16718 * </dd>
16719 * </dl>
16720 *
16721 * MeasureSpecs are implemented as ints to reduce object allocation. This class
16722 * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
16723 */
16724 public static class MeasureSpec {
16725 private static final int MODE_SHIFT = 30;
16726 private static final int MODE_MASK = 0x3 << MODE_SHIFT;
16727
16728 /**
16729 * Measure specification mode: The parent has not imposed any constraint
16730 * on the child. It can be whatever size it wants.
16731 */
16732 public static final int UNSPECIFIED = 0 << MODE_SHIFT;
16733
16734 /**
16735 * Measure specification mode: The parent has determined an exact size
16736 * for the child. The child is going to be given those bounds regardless
16737 * of how big it wants to be.
16738 */
16739 public static final int EXACTLY = 1 << MODE_SHIFT;
16740
16741 /**
16742 * Measure specification mode: The child can be as large as it wants up
16743 * to the specified size.
16744 */
16745 public static final int AT_MOST = 2 << MODE_SHIFT;
16746
16747 /**
16748 * Creates a measure specification based on the supplied size and mode.
16749 *
16750 * The mode must always be one of the following:
16751 * <ul>
16752 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
16753 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
16754 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
16755 * </ul>
16756 *
16757 * @param size the size of the measure specification
16758 * @param mode the mode of the measure specification
16759 * @return the measure specification based on size and mode
16760 */
16761 public static int makeMeasureSpec(int size, int mode) {
16762 return size + mode;
16763 }
16764
16765 /**
16766 * Extracts the mode from the supplied measure specification.
16767 *
16768 * @param measureSpec the measure specification to extract the mode from
16769 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
16770 * {@link android.view.View.MeasureSpec#AT_MOST} or
16771 * {@link android.view.View.MeasureSpec#EXACTLY}
16772 */
16773 public static int getMode(int measureSpec) {
16774 return (measureSpec & MODE_MASK);
16775 }
16776
16777 /**
16778 * Extracts the size from the supplied measure specification.
16779 *
16780 * @param measureSpec the measure specification to extract the size from
16781 * @return the size in pixels defined in the supplied measure specification
16782 */
16783 public static int getSize(int measureSpec) {
16784 return (measureSpec & ~MODE_MASK);
16785 }
16786
16787 /**
16788 * Returns a String representation of the specified measure
16789 * specification.
16790 *
16791 * @param measureSpec the measure specification to convert to a String
16792 * @return a String with the following format: "MeasureSpec: MODE SIZE"
16793 */
16794 public static String toString(int measureSpec) {
16795 int mode = getMode(measureSpec);
16796 int size = getSize(measureSpec);
16797
16798 StringBuilder sb = new StringBuilder("MeasureSpec: ");
16799
16800 if (mode == UNSPECIFIED)
16801 sb.append("UNSPECIFIED ");
16802 else if (mode == EXACTLY)
16803 sb.append("EXACTLY ");
16804 else if (mode == AT_MOST)
16805 sb.append("AT_MOST ");
16806 else
16807 sb.append(mode).append(" ");
16808
16809 sb.append(size);
16810 return sb.toString();
16811 }
16812 }
16813
16814 class CheckForLongPress implements Runnable {
16815
16816 private int mOriginalWindowAttachCount;
16817
16818 public void run() {
The Android Open Source Project10592532009-03-18 17:39:46 -070016819 if (isPressed() && (mParent != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016820 && mOriginalWindowAttachCount == mWindowAttachCount) {
16821 if (performLongClick()) {
16822 mHasPerformedLongPress = true;
16823 }
16824 }
16825 }
16826
16827 public void rememberWindowAttachCount() {
16828 mOriginalWindowAttachCount = mWindowAttachCount;
16829 }
16830 }
Joe Malin32736f02011-01-19 16:14:20 -080016831
Adam Powelle14579b2009-12-16 18:39:52 -080016832 private final class CheckForTap implements Runnable {
16833 public void run() {
16834 mPrivateFlags &= ~PREPRESSED;
Adam Powell4d6f0662012-02-21 15:11:11 -080016835 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -070016836 checkForLongClick(ViewConfiguration.getTapTimeout());
Adam Powelle14579b2009-12-16 18:39:52 -080016837 }
16838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016839
Adam Powella35d7682010-03-12 14:48:13 -080016840 private final class PerformClick implements Runnable {
16841 public void run() {
16842 performClick();
16843 }
16844 }
16845
Dianne Hackborn63042d62011-01-26 18:56:29 -080016846 /** @hide */
16847 public void hackTurnOffWindowResizeAnim(boolean off) {
16848 mAttachInfo.mTurnOffWindowResizeAnim = off;
16849 }
Joe Malin32736f02011-01-19 16:14:20 -080016850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016851 /**
Chet Haasea00f3862011-02-22 06:34:40 -080016852 * This method returns a ViewPropertyAnimator object, which can be used to animate
16853 * specific properties on this View.
16854 *
16855 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
16856 */
16857 public ViewPropertyAnimator animate() {
16858 if (mAnimator == null) {
16859 mAnimator = new ViewPropertyAnimator(this);
16860 }
16861 return mAnimator;
16862 }
16863
16864 /**
Jean Chalard405bc512012-05-29 19:12:34 +090016865 * Interface definition for a callback to be invoked when a hardware key event is
16866 * dispatched to this view. The callback will be invoked before the key event is
16867 * given to the view. This is only useful for hardware keyboards; a software input
16868 * method has no obligation to trigger this listener.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016869 */
16870 public interface OnKeyListener {
16871 /**
Jean Chalard405bc512012-05-29 19:12:34 +090016872 * Called when a hardware key is dispatched to a view. This allows listeners to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016873 * get a chance to respond before the target view.
Jean Chalard405bc512012-05-29 19:12:34 +090016874 * <p>Key presses in software keyboards will generally NOT trigger this method,
16875 * although some may elect to do so in some situations. Do not assume a
16876 * software input method has to be key-based; even if it is, it may use key presses
16877 * in a different way than you expect, so there is no way to reliably catch soft
16878 * input key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016879 *
16880 * @param v The view the key has been dispatched to.
16881 * @param keyCode The code for the physical key that was pressed
16882 * @param event The KeyEvent object containing full information about
16883 * the event.
16884 * @return True if the listener has consumed the event, false otherwise.
16885 */
16886 boolean onKey(View v, int keyCode, KeyEvent event);
16887 }
16888
16889 /**
16890 * Interface definition for a callback to be invoked when a touch event is
16891 * dispatched to this view. The callback will be invoked before the touch
16892 * event is given to the view.
16893 */
16894 public interface OnTouchListener {
16895 /**
16896 * Called when a touch event is dispatched to a view. This allows listeners to
16897 * get a chance to respond before the target view.
16898 *
16899 * @param v The view the touch event has been dispatched to.
16900 * @param event The MotionEvent object containing full information about
16901 * the event.
16902 * @return True if the listener has consumed the event, false otherwise.
16903 */
16904 boolean onTouch(View v, MotionEvent event);
16905 }
16906
16907 /**
Jeff Brown10b62902011-06-20 16:40:37 -070016908 * Interface definition for a callback to be invoked when a hover event is
16909 * dispatched to this view. The callback will be invoked before the hover
16910 * event is given to the view.
16911 */
16912 public interface OnHoverListener {
16913 /**
16914 * Called when a hover event is dispatched to a view. This allows listeners to
16915 * get a chance to respond before the target view.
16916 *
16917 * @param v The view the hover event has been dispatched to.
16918 * @param event The MotionEvent object containing full information about
16919 * the event.
16920 * @return True if the listener has consumed the event, false otherwise.
16921 */
16922 boolean onHover(View v, MotionEvent event);
16923 }
16924
16925 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -080016926 * Interface definition for a callback to be invoked when a generic motion event is
16927 * dispatched to this view. The callback will be invoked before the generic motion
16928 * event is given to the view.
16929 */
16930 public interface OnGenericMotionListener {
16931 /**
16932 * Called when a generic motion event is dispatched to a view. This allows listeners to
16933 * get a chance to respond before the target view.
16934 *
16935 * @param v The view the generic motion event has been dispatched to.
16936 * @param event The MotionEvent object containing full information about
16937 * the event.
16938 * @return True if the listener has consumed the event, false otherwise.
16939 */
16940 boolean onGenericMotion(View v, MotionEvent event);
16941 }
16942
16943 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016944 * Interface definition for a callback to be invoked when a view has been clicked and held.
16945 */
16946 public interface OnLongClickListener {
16947 /**
16948 * Called when a view has been clicked and held.
16949 *
16950 * @param v The view that was clicked and held.
16951 *
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -080016952 * @return true if the callback consumed the long click, false otherwise.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016953 */
16954 boolean onLongClick(View v);
16955 }
16956
16957 /**
Chris Tate32affef2010-10-18 15:29:21 -070016958 * Interface definition for a callback to be invoked when a drag is being dispatched
16959 * to this view. The callback will be invoked before the hosting view's own
16960 * onDrag(event) method. If the listener wants to fall back to the hosting view's
16961 * onDrag(event) behavior, it should return 'false' from this callback.
Joe Fernandez558459f2011-10-13 16:47:36 -070016962 *
16963 * <div class="special reference">
16964 * <h3>Developer Guides</h3>
16965 * <p>For a guide to implementing drag and drop features, read the
16966 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
16967 * </div>
Chris Tate32affef2010-10-18 15:29:21 -070016968 */
16969 public interface OnDragListener {
16970 /**
16971 * Called when a drag event is dispatched to a view. This allows listeners
16972 * to get a chance to override base View behavior.
16973 *
Joe Malin32736f02011-01-19 16:14:20 -080016974 * @param v The View that received the drag event.
16975 * @param event The {@link android.view.DragEvent} object for the drag event.
16976 * @return {@code true} if the drag event was handled successfully, or {@code false}
16977 * if the drag event was not handled. Note that {@code false} will trigger the View
16978 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
Chris Tate32affef2010-10-18 15:29:21 -070016979 */
16980 boolean onDrag(View v, DragEvent event);
16981 }
16982
16983 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016984 * Interface definition for a callback to be invoked when the focus state of
16985 * a view changed.
16986 */
16987 public interface OnFocusChangeListener {
16988 /**
16989 * Called when the focus state of a view has changed.
16990 *
16991 * @param v The view whose state has changed.
16992 * @param hasFocus The new focus state of v.
16993 */
16994 void onFocusChange(View v, boolean hasFocus);
16995 }
16996
16997 /**
16998 * Interface definition for a callback to be invoked when a view is clicked.
16999 */
17000 public interface OnClickListener {
17001 /**
17002 * Called when a view has been clicked.
17003 *
17004 * @param v The view that was clicked.
17005 */
17006 void onClick(View v);
17007 }
17008
17009 /**
17010 * Interface definition for a callback to be invoked when the context menu
17011 * for this view is being built.
17012 */
17013 public interface OnCreateContextMenuListener {
17014 /**
17015 * Called when the context menu for this view is being built. It is not
17016 * safe to hold onto the menu after this method returns.
17017 *
17018 * @param menu The context menu that is being built
17019 * @param v The view for which the context menu is being built
17020 * @param menuInfo Extra information about the item for which the
17021 * context menu should be shown. This information will vary
17022 * depending on the class of v.
17023 */
17024 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
17025 }
17026
Joe Onorato664644d2011-01-23 17:53:23 -080017027 /**
17028 * Interface definition for a callback to be invoked when the status bar changes
Dianne Hackborn9a230e02011-10-06 11:51:27 -070017029 * visibility. This reports <strong>global</strong> changes to the system UI
Dianne Hackborncf675782012-05-10 15:07:24 -070017030 * state, not what the application is requesting.
Joe Onorato664644d2011-01-23 17:53:23 -080017031 *
Philip Milne6c8ea062012-04-03 17:38:43 -070017032 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
Joe Onorato664644d2011-01-23 17:53:23 -080017033 */
17034 public interface OnSystemUiVisibilityChangeListener {
17035 /**
17036 * Called when the status bar changes visibility because of a call to
Romain Guy5c22a8c2011-05-13 11:48:45 -070017037 * {@link View#setSystemUiVisibility(int)}.
Joe Onorato664644d2011-01-23 17:53:23 -080017038 *
Dianne Hackborncf675782012-05-10 15:07:24 -070017039 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17040 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
17041 * This tells you the <strong>global</strong> state of these UI visibility
17042 * flags, not what your app is currently applying.
Joe Onorato664644d2011-01-23 17:53:23 -080017043 */
17044 public void onSystemUiVisibilityChange(int visibility);
17045 }
17046
Adam Powell4afd62b2011-02-18 15:02:18 -080017047 /**
17048 * Interface definition for a callback to be invoked when this view is attached
17049 * or detached from its window.
17050 */
17051 public interface OnAttachStateChangeListener {
17052 /**
17053 * Called when the view is attached to a window.
17054 * @param v The view that was attached
17055 */
17056 public void onViewAttachedToWindow(View v);
17057 /**
17058 * Called when the view is detached from a window.
17059 * @param v The view that was detached
17060 */
17061 public void onViewDetachedFromWindow(View v);
17062 }
17063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017064 private final class UnsetPressedState implements Runnable {
17065 public void run() {
17066 setPressed(false);
17067 }
17068 }
17069
17070 /**
17071 * Base class for derived classes that want to save and restore their own
17072 * state in {@link android.view.View#onSaveInstanceState()}.
17073 */
17074 public static class BaseSavedState extends AbsSavedState {
17075 /**
17076 * Constructor used when reading from a parcel. Reads the state of the superclass.
17077 *
17078 * @param source
17079 */
17080 public BaseSavedState(Parcel source) {
17081 super(source);
17082 }
17083
17084 /**
17085 * Constructor called by derived classes when creating their SavedState objects
17086 *
17087 * @param superState The state of the superclass of this view
17088 */
17089 public BaseSavedState(Parcelable superState) {
17090 super(superState);
17091 }
17092
17093 public static final Parcelable.Creator<BaseSavedState> CREATOR =
17094 new Parcelable.Creator<BaseSavedState>() {
17095 public BaseSavedState createFromParcel(Parcel in) {
17096 return new BaseSavedState(in);
17097 }
17098
17099 public BaseSavedState[] newArray(int size) {
17100 return new BaseSavedState[size];
17101 }
17102 };
17103 }
17104
17105 /**
17106 * A set of information given to a view when it is attached to its parent
17107 * window.
17108 */
17109 static class AttachInfo {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017110 interface Callbacks {
17111 void playSoundEffect(int effectId);
17112 boolean performHapticFeedback(int effectId, boolean always);
17113 }
17114
17115 /**
17116 * InvalidateInfo is used to post invalidate(int, int, int, int) messages
17117 * to a Handler. This class contains the target (View) to invalidate and
17118 * the coordinates of the dirty rectangle.
17119 *
17120 * For performance purposes, this class also implements a pool of up to
17121 * POOL_LIMIT objects that get reused. This reduces memory allocations
17122 * whenever possible.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017123 */
Romain Guyd928d682009-03-31 17:52:16 -070017124 static class InvalidateInfo implements Poolable<InvalidateInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017125 private static final int POOL_LIMIT = 10;
Romain Guy2e9bbce2009-04-01 10:40:10 -070017126 private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
17127 Pools.finitePool(new PoolableManager<InvalidateInfo>() {
Romain Guyd928d682009-03-31 17:52:16 -070017128 public InvalidateInfo newInstance() {
17129 return new InvalidateInfo();
17130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017131
Romain Guyd928d682009-03-31 17:52:16 -070017132 public void onAcquired(InvalidateInfo element) {
17133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017134
Romain Guyd928d682009-03-31 17:52:16 -070017135 public void onReleased(InvalidateInfo element) {
Romain Guy40c18f52011-09-01 17:01:18 -070017136 element.target = null;
Romain Guyd928d682009-03-31 17:52:16 -070017137 }
17138 }, POOL_LIMIT)
17139 );
17140
17141 private InvalidateInfo mNext;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017142 private boolean mIsPooled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017143
17144 View target;
17145
17146 int left;
17147 int top;
17148 int right;
17149 int bottom;
17150
Romain Guyd928d682009-03-31 17:52:16 -070017151 public void setNextPoolable(InvalidateInfo element) {
17152 mNext = element;
17153 }
17154
17155 public InvalidateInfo getNextPoolable() {
17156 return mNext;
17157 }
17158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017159 static InvalidateInfo acquire() {
Romain Guyd928d682009-03-31 17:52:16 -070017160 return sPool.acquire();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017161 }
17162
17163 void release() {
Romain Guyd928d682009-03-31 17:52:16 -070017164 sPool.release(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017165 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017166
17167 public boolean isPooled() {
17168 return mIsPooled;
17169 }
17170
17171 public void setPooled(boolean isPooled) {
17172 mIsPooled = isPooled;
17173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017174 }
17175
17176 final IWindowSession mSession;
17177
17178 final IWindow mWindow;
17179
17180 final IBinder mWindowToken;
17181
17182 final Callbacks mRootCallbacks;
17183
Romain Guy59a12ca2011-06-09 17:48:21 -070017184 HardwareCanvas mHardwareCanvas;
Chet Haasedaf98e92011-01-10 14:10:36 -080017185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017186 /**
17187 * The top view of the hierarchy.
17188 */
17189 View mRootView;
Romain Guy8506ab42009-06-11 17:35:47 -070017190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017191 IBinder mPanelParentWindowToken;
17192 Surface mSurface;
17193
Romain Guyb051e892010-09-28 19:09:36 -070017194 boolean mHardwareAccelerated;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080017195 boolean mHardwareAccelerationRequested;
Romain Guyb051e892010-09-28 19:09:36 -070017196 HardwareRenderer mHardwareRenderer;
Joe Malin32736f02011-01-19 16:14:20 -080017197
Romain Guy7e4e5612012-03-05 14:37:29 -080017198 boolean mScreenOn;
17199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017200 /**
Romain Guy8506ab42009-06-11 17:35:47 -070017201 * Scale factor used by the compatibility mode
17202 */
17203 float mApplicationScale;
17204
17205 /**
17206 * Indicates whether the application is in compatibility mode
17207 */
17208 boolean mScalingRequired;
17209
17210 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070017211 * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
Dianne Hackborn63042d62011-01-26 18:56:29 -080017212 */
17213 boolean mTurnOffWindowResizeAnim;
Joe Malin32736f02011-01-19 16:14:20 -080017214
Dianne Hackborn63042d62011-01-26 18:56:29 -080017215 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017216 * Left position of this view's window
17217 */
17218 int mWindowLeft;
17219
17220 /**
17221 * Top position of this view's window
17222 */
17223 int mWindowTop;
17224
17225 /**
Adam Powell26153a32010-11-08 15:22:27 -080017226 * Indicates whether views need to use 32-bit drawing caches
Romain Guy35b38ce2009-10-07 13:38:55 -070017227 */
Adam Powell26153a32010-11-08 15:22:27 -080017228 boolean mUse32BitDrawingCache;
Romain Guy35b38ce2009-10-07 13:38:55 -070017229
17230 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017231 * For windows that are full-screen but using insets to layout inside
17232 * of the screen decorations, these are the current insets for the
17233 * content of the window.
17234 */
17235 final Rect mContentInsets = new Rect();
17236
17237 /**
17238 * For windows that are full-screen but using insets to layout inside
17239 * of the screen decorations, these are the current insets for the
17240 * actual visible parts of the window.
17241 */
17242 final Rect mVisibleInsets = new Rect();
17243
17244 /**
17245 * The internal insets given by this window. This value is
17246 * supplied by the client (through
17247 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
17248 * be given to the window manager when changed to be used in laying
17249 * out windows behind it.
17250 */
17251 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
17252 = new ViewTreeObserver.InternalInsetsInfo();
17253
17254 /**
17255 * All views in the window's hierarchy that serve as scroll containers,
17256 * used to determine if the window can be resized or must be panned
17257 * to adjust for a soft input area.
17258 */
17259 final ArrayList<View> mScrollContainers = new ArrayList<View>();
17260
Dianne Hackborn83fe3f52009-09-12 23:38:30 -070017261 final KeyEvent.DispatcherState mKeyDispatchState
17262 = new KeyEvent.DispatcherState();
17263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017264 /**
17265 * Indicates whether the view's window currently has the focus.
17266 */
17267 boolean mHasWindowFocus;
17268
17269 /**
17270 * The current visibility of the window.
17271 */
17272 int mWindowVisibility;
17273
17274 /**
17275 * Indicates the time at which drawing started to occur.
17276 */
17277 long mDrawingTime;
17278
17279 /**
Romain Guy5bcdff42009-05-14 21:27:18 -070017280 * Indicates whether or not ignoring the DIRTY_MASK flags.
17281 */
17282 boolean mIgnoreDirtyState;
17283
17284 /**
Romain Guy02ccac62011-06-24 13:20:23 -070017285 * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
17286 * to avoid clearing that flag prematurely.
17287 */
17288 boolean mSetIgnoreDirtyState = false;
17289
17290 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017291 * Indicates whether the view's window is currently in touch mode.
17292 */
17293 boolean mInTouchMode;
17294
17295 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070017296 * Indicates that ViewAncestor should trigger a global layout change
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017297 * the next time it performs a traversal
17298 */
17299 boolean mRecomputeGlobalAttributes;
17300
17301 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -070017302 * Always report new attributes at next traversal.
17303 */
17304 boolean mForceReportNewAttributes;
17305
17306 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017307 * Set during a traveral if any views want to keep the screen on.
17308 */
17309 boolean mKeepScreenOn;
17310
17311 /**
Joe Onorato664644d2011-01-23 17:53:23 -080017312 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
17313 */
17314 int mSystemUiVisibility;
17315
17316 /**
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070017317 * Hack to force certain system UI visibility flags to be cleared.
17318 */
17319 int mDisabledSystemUiVisibility;
17320
17321 /**
Dianne Hackborncf675782012-05-10 15:07:24 -070017322 * Last global system UI visibility reported by the window manager.
17323 */
17324 int mGlobalSystemUiVisibility;
17325
17326 /**
Joe Onorato664644d2011-01-23 17:53:23 -080017327 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
17328 * attached.
17329 */
17330 boolean mHasSystemUiListeners;
17331
17332 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017333 * Set if the visibility of any views has changed.
17334 */
17335 boolean mViewVisibilityChanged;
17336
17337 /**
17338 * Set to true if a view has been scrolled.
17339 */
17340 boolean mViewScrollChanged;
17341
17342 /**
17343 * Global to the view hierarchy used as a temporary for dealing with
17344 * x/y points in the transparent region computations.
17345 */
17346 final int[] mTransparentLocation = new int[2];
17347
17348 /**
17349 * Global to the view hierarchy used as a temporary for dealing with
17350 * x/y points in the ViewGroup.invalidateChild implementation.
17351 */
17352 final int[] mInvalidateChildLocation = new int[2];
17353
Chet Haasec3aa3612010-06-17 08:50:37 -070017354
17355 /**
17356 * Global to the view hierarchy used as a temporary for dealing with
17357 * x/y location when view is transformed.
17358 */
17359 final float[] mTmpTransformLocation = new float[2];
17360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017361 /**
17362 * The view tree observer used to dispatch global events like
17363 * layout, pre-draw, touch mode change, etc.
17364 */
17365 final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
17366
17367 /**
17368 * A Canvas used by the view hierarchy to perform bitmap caching.
17369 */
17370 Canvas mCanvas;
17371
17372 /**
Jeff Browna175a5b2012-02-15 19:18:31 -080017373 * The view root impl.
17374 */
17375 final ViewRootImpl mViewRootImpl;
17376
17377 /**
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070017378 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017379 * handler can be used to pump events in the UI events queue.
17380 */
17381 final Handler mHandler;
17382
17383 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017384 * Temporary for use in computing invalidate rectangles while
17385 * calling up the hierarchy.
17386 */
17387 final Rect mTmpInvalRect = new Rect();
svetoslavganov75986cf2009-05-14 22:28:01 -070017388
17389 /**
Chet Haasec3aa3612010-06-17 08:50:37 -070017390 * Temporary for use in computing hit areas with transformed views
17391 */
17392 final RectF mTmpTransformRect = new RectF();
17393
17394 /**
Chet Haase599913d2012-07-23 16:22:05 -070017395 * Temporary for use in transforming invalidation rect
17396 */
17397 final Matrix mTmpMatrix = new Matrix();
17398
17399 /**
17400 * Temporary for use in transforming invalidation rect
17401 */
17402 final Transformation mTmpTransformation = new Transformation();
17403
17404 /**
svetoslavganov75986cf2009-05-14 22:28:01 -070017405 * Temporary list for use in collecting focusable descendents of a view.
17406 */
Svetoslav Ganov42138042012-03-20 11:51:39 -070017407 final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
svetoslavganov75986cf2009-05-14 22:28:01 -070017408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017409 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017410 * The id of the window for accessibility purposes.
17411 */
17412 int mAccessibilityWindowId = View.NO_ID;
17413
17414 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -070017415 * Whether to ingore not exposed for accessibility Views when
17416 * reporting the view tree to accessibility services.
17417 */
17418 boolean mIncludeNotImportantViews;
17419
17420 /**
17421 * The drawable for highlighting accessibility focus.
17422 */
17423 Drawable mAccessibilityFocusDrawable;
17424
17425 /**
Philip Milne10ca24a2012-04-23 15:38:27 -070017426 * Show where the margins, bounds and layout bounds are for each view.
17427 */
Dianne Hackborna53de062012-05-08 18:53:51 -070017428 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
Philip Milne10ca24a2012-04-23 15:38:27 -070017429
17430 /**
Romain Guyab4c4f4f2012-05-06 13:11:24 -070017431 * Point used to compute visible regions.
17432 */
17433 final Point mPoint = new Point();
17434
17435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017436 * Creates a new set of attachment information with the specified
17437 * events handler and thread.
17438 *
17439 * @param handler the events handler the view must use
17440 */
17441 AttachInfo(IWindowSession session, IWindow window,
Jeff Browna175a5b2012-02-15 19:18:31 -080017442 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017443 mSession = session;
17444 mWindow = window;
17445 mWindowToken = window.asBinder();
Jeff Browna175a5b2012-02-15 19:18:31 -080017446 mViewRootImpl = viewRootImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017447 mHandler = handler;
17448 mRootCallbacks = effectPlayer;
17449 }
17450 }
17451
17452 /**
17453 * <p>ScrollabilityCache holds various fields used by a View when scrolling
17454 * is supported. This avoids keeping too many unused fields in most
17455 * instances of View.</p>
17456 */
Mike Cleronf116bf82009-09-27 19:14:12 -070017457 private static class ScrollabilityCache implements Runnable {
Joe Malin32736f02011-01-19 16:14:20 -080017458
Mike Cleronf116bf82009-09-27 19:14:12 -070017459 /**
17460 * Scrollbars are not visible
17461 */
17462 public static final int OFF = 0;
17463
17464 /**
17465 * Scrollbars are visible
17466 */
17467 public static final int ON = 1;
17468
17469 /**
17470 * Scrollbars are fading away
17471 */
17472 public static final int FADING = 2;
17473
17474 public boolean fadeScrollBars;
Joe Malin32736f02011-01-19 16:14:20 -080017475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017476 public int fadingEdgeLength;
Mike Cleronf116bf82009-09-27 19:14:12 -070017477 public int scrollBarDefaultDelayBeforeFade;
17478 public int scrollBarFadeDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017479
17480 public int scrollBarSize;
17481 public ScrollBarDrawable scrollBar;
Mike Cleronf116bf82009-09-27 19:14:12 -070017482 public float[] interpolatorValues;
17483 public View host;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017484
17485 public final Paint paint;
17486 public final Matrix matrix;
17487 public Shader shader;
17488
Mike Cleronf116bf82009-09-27 19:14:12 -070017489 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
17490
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017491 private static final float[] OPAQUE = { 255 };
17492 private static final float[] TRANSPARENT = { 0.0f };
Joe Malin32736f02011-01-19 16:14:20 -080017493
Mike Cleronf116bf82009-09-27 19:14:12 -070017494 /**
17495 * When fading should start. This time moves into the future every time
17496 * a new scroll happens. Measured based on SystemClock.uptimeMillis()
17497 */
17498 public long fadeStartTime;
17499
17500
17501 /**
17502 * The current state of the scrollbars: ON, OFF, or FADING
17503 */
17504 public int state = OFF;
17505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017506 private int mLastColor;
17507
Mike Cleronf116bf82009-09-27 19:14:12 -070017508 public ScrollabilityCache(ViewConfiguration configuration, View host) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017509 fadingEdgeLength = configuration.getScaledFadingEdgeLength();
17510 scrollBarSize = configuration.getScaledScrollBarSize();
Romain Guy35b38ce2009-10-07 13:38:55 -070017511 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
17512 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017513
17514 paint = new Paint();
17515 matrix = new Matrix();
17516 // use use a height of 1, and then wack the matrix each time we
17517 // actually use it.
17518 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
Romain Guy8506ab42009-06-11 17:35:47 -070017519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017520 paint.setShader(shader);
17521 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
Mike Cleronf116bf82009-09-27 19:14:12 -070017522 this.host = host;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017523 }
Romain Guy8506ab42009-06-11 17:35:47 -070017524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017525 public void setFadeColor(int color) {
17526 if (color != 0 && color != mLastColor) {
17527 mLastColor = color;
17528 color |= 0xFF000000;
Romain Guy8506ab42009-06-11 17:35:47 -070017529
Romain Guye55e1a72009-08-27 10:42:26 -070017530 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
17531 color & 0x00FFFFFF, Shader.TileMode.CLAMP);
Romain Guy8506ab42009-06-11 17:35:47 -070017532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017533 paint.setShader(shader);
17534 // Restore the default transfer mode (src_over)
17535 paint.setXfermode(null);
17536 }
17537 }
Joe Malin32736f02011-01-19 16:14:20 -080017538
Mike Cleronf116bf82009-09-27 19:14:12 -070017539 public void run() {
Mike Cleron3ecd58c2009-09-28 11:39:02 -070017540 long now = AnimationUtils.currentAnimationTimeMillis();
Mike Cleronf116bf82009-09-27 19:14:12 -070017541 if (now >= fadeStartTime) {
17542
17543 // the animation fades the scrollbars out by changing
17544 // the opacity (alpha) from fully opaque to fully
17545 // transparent
17546 int nextFrame = (int) now;
17547 int framesCount = 0;
17548
17549 Interpolator interpolator = scrollBarInterpolator;
17550
17551 // Start opaque
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017552 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
Mike Cleronf116bf82009-09-27 19:14:12 -070017553
17554 // End transparent
17555 nextFrame += scrollBarFadeDuration;
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017556 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
Mike Cleronf116bf82009-09-27 19:14:12 -070017557
17558 state = FADING;
17559
17560 // Kick off the fade animation
Romain Guy0fd89bf2011-01-26 15:41:30 -080017561 host.invalidate(true);
Mike Cleronf116bf82009-09-27 19:14:12 -070017562 }
17563 }
Svetoslav Ganova0156172011-06-26 17:55:44 -070017564 }
Mike Cleronf116bf82009-09-27 19:14:12 -070017565
Svetoslav Ganova0156172011-06-26 17:55:44 -070017566 /**
17567 * Resuable callback for sending
17568 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
17569 */
17570 private class SendViewScrolledAccessibilityEvent implements Runnable {
17571 public volatile boolean mIsPending;
17572
17573 public void run() {
17574 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
17575 mIsPending = false;
17576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017577 }
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017578
17579 /**
17580 * <p>
17581 * This class represents a delegate that can be registered in a {@link View}
17582 * to enhance accessibility support via composition rather via inheritance.
17583 * It is specifically targeted to widget developers that extend basic View
17584 * classes i.e. classes in package android.view, that would like their
17585 * applications to be backwards compatible.
17586 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080017587 * <div class="special reference">
17588 * <h3>Developer Guides</h3>
17589 * <p>For more information about making applications accessible, read the
17590 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
17591 * developer guide.</p>
17592 * </div>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017593 * <p>
17594 * A scenario in which a developer would like to use an accessibility delegate
17595 * is overriding a method introduced in a later API version then the minimal API
17596 * version supported by the application. For example, the method
17597 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
17598 * in API version 4 when the accessibility APIs were first introduced. If a
17599 * developer would like his application to run on API version 4 devices (assuming
17600 * all other APIs used by the application are version 4 or lower) and take advantage
17601 * of this method, instead of overriding the method which would break the application's
17602 * backwards compatibility, he can override the corresponding method in this
17603 * delegate and register the delegate in the target View if the API version of
17604 * the system is high enough i.e. the API version is same or higher to the API
17605 * version that introduced
17606 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
17607 * </p>
17608 * <p>
17609 * Here is an example implementation:
17610 * </p>
17611 * <code><pre><p>
17612 * if (Build.VERSION.SDK_INT >= 14) {
17613 * // If the API version is equal of higher than the version in
17614 * // which onInitializeAccessibilityNodeInfo was introduced we
17615 * // register a delegate with a customized implementation.
17616 * View view = findViewById(R.id.view_id);
17617 * view.setAccessibilityDelegate(new AccessibilityDelegate() {
17618 * public void onInitializeAccessibilityNodeInfo(View host,
17619 * AccessibilityNodeInfo info) {
17620 * // Let the default implementation populate the info.
17621 * super.onInitializeAccessibilityNodeInfo(host, info);
17622 * // Set some other information.
17623 * info.setEnabled(host.isEnabled());
17624 * }
17625 * });
17626 * }
17627 * </code></pre></p>
17628 * <p>
17629 * This delegate contains methods that correspond to the accessibility methods
17630 * in View. If a delegate has been specified the implementation in View hands
17631 * off handling to the corresponding method in this delegate. The default
17632 * implementation the delegate methods behaves exactly as the corresponding
17633 * method in View for the case of no accessibility delegate been set. Hence,
17634 * to customize the behavior of a View method, clients can override only the
17635 * corresponding delegate method without altering the behavior of the rest
17636 * accessibility related methods of the host view.
17637 * </p>
17638 */
17639 public static class AccessibilityDelegate {
17640
17641 /**
17642 * Sends an accessibility event of the given type. If accessibility is not
17643 * enabled this method has no effect.
17644 * <p>
17645 * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
17646 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
17647 * been set.
17648 * </p>
17649 *
17650 * @param host The View hosting the delegate.
17651 * @param eventType The type of the event to send.
17652 *
17653 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
17654 */
17655 public void sendAccessibilityEvent(View host, int eventType) {
17656 host.sendAccessibilityEventInternal(eventType);
17657 }
17658
17659 /**
alanv8eeefef2012-05-07 16:57:53 -070017660 * Performs the specified accessibility action on the view. For
17661 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
17662 * <p>
17663 * The default implementation behaves as
17664 * {@link View#performAccessibilityAction(int, Bundle)
17665 * View#performAccessibilityAction(int, Bundle)} for the case of
17666 * no accessibility delegate been set.
17667 * </p>
17668 *
17669 * @param action The action to perform.
17670 * @return Whether the action was performed.
17671 *
17672 * @see View#performAccessibilityAction(int, Bundle)
17673 * View#performAccessibilityAction(int, Bundle)
17674 */
17675 public boolean performAccessibilityAction(View host, int action, Bundle args) {
17676 return host.performAccessibilityActionInternal(action, args);
17677 }
17678
17679 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017680 * Sends an accessibility event. This method behaves exactly as
17681 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
17682 * empty {@link AccessibilityEvent} and does not perform a check whether
17683 * accessibility is enabled.
17684 * <p>
17685 * The default implementation behaves as
17686 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17687 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
17688 * the case of no accessibility delegate been set.
17689 * </p>
17690 *
17691 * @param host The View hosting the delegate.
17692 * @param event The event to send.
17693 *
17694 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17695 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17696 */
17697 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
17698 host.sendAccessibilityEventUncheckedInternal(event);
17699 }
17700
17701 /**
17702 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
17703 * to its children for adding their text content to the event.
17704 * <p>
17705 * The default implementation behaves as
17706 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17707 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
17708 * the case of no accessibility delegate been set.
17709 * </p>
17710 *
17711 * @param host The View hosting the delegate.
17712 * @param event The event.
17713 * @return True if the event population was completed.
17714 *
17715 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17716 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17717 */
17718 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17719 return host.dispatchPopulateAccessibilityEventInternal(event);
17720 }
17721
17722 /**
17723 * Gives a chance to the host View to populate the accessibility event with its
17724 * text content.
17725 * <p>
17726 * The default implementation behaves as
17727 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
17728 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
17729 * the case of no accessibility delegate been set.
17730 * </p>
17731 *
17732 * @param host The View hosting the delegate.
17733 * @param event The accessibility event which to populate.
17734 *
17735 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
17736 * View#onPopulateAccessibilityEvent(AccessibilityEvent)
17737 */
17738 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17739 host.onPopulateAccessibilityEventInternal(event);
17740 }
17741
17742 /**
17743 * Initializes an {@link AccessibilityEvent} with information about the
17744 * the host View which is the event source.
17745 * <p>
17746 * The default implementation behaves as
17747 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
17748 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
17749 * the case of no accessibility delegate been set.
17750 * </p>
17751 *
17752 * @param host The View hosting the delegate.
17753 * @param event The event to initialize.
17754 *
17755 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
17756 * View#onInitializeAccessibilityEvent(AccessibilityEvent)
17757 */
17758 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
17759 host.onInitializeAccessibilityEventInternal(event);
17760 }
17761
17762 /**
17763 * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
17764 * <p>
17765 * The default implementation behaves as
17766 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17767 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
17768 * the case of no accessibility delegate been set.
17769 * </p>
17770 *
17771 * @param host The View hosting the delegate.
17772 * @param info The instance to initialize.
17773 *
17774 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17775 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17776 */
17777 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
17778 host.onInitializeAccessibilityNodeInfoInternal(info);
17779 }
17780
17781 /**
17782 * Called when a child of the host View has requested sending an
17783 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
17784 * to augment the event.
17785 * <p>
17786 * The default implementation behaves as
17787 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17788 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
17789 * the case of no accessibility delegate been set.
17790 * </p>
17791 *
17792 * @param host The View hosting the delegate.
17793 * @param child The child which requests sending the event.
17794 * @param event The event to be sent.
17795 * @return True if the event should be sent
17796 *
17797 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17798 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17799 */
17800 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
17801 AccessibilityEvent event) {
17802 return host.onRequestSendAccessibilityEventInternal(child, event);
17803 }
Svetoslav Ganov02107852011-10-03 17:06:56 -070017804
17805 /**
17806 * Gets the provider for managing a virtual view hierarchy rooted at this View
17807 * and reported to {@link android.accessibilityservice.AccessibilityService}s
17808 * that explore the window content.
17809 * <p>
17810 * The default implementation behaves as
17811 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
17812 * the case of no accessibility delegate been set.
17813 * </p>
17814 *
17815 * @return The provider.
17816 *
17817 * @see AccessibilityNodeProvider
17818 */
17819 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
17820 return null;
17821 }
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017823}