Merge change 26714 into eclair

* changes:
  Update RotarySelector to support vertical orientation, and add resolution specific assets (removing old ones).
This commit is contained in:
Android (Google) Code Review
2009-09-24 13:19:15 -04:00
35 changed files with 338 additions and 87 deletions

View File

@@ -18,7 +18,12 @@ package com.android.internal.widget;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Vibrator;
import android.util.AttributeSet;
@@ -38,6 +43,9 @@ import com.android.internal.R;
* security pattern is set.
*/
public class RotarySelector extends View {
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private static final String LOG_TAG = "RotarySelector";
private static final boolean DBG = false;
@@ -47,15 +55,15 @@ public class RotarySelector extends View {
private float mDensity;
// UI elements
private Drawable mBackground;
private Bitmap mBackground;
private Drawable mDimple;
private Drawable mLeftHandleIcon;
private Drawable mRightHandleIcon;
private Drawable mArrowShortLeftAndRight;
private Drawable mArrowLongLeft; // Long arrow starting on the left, pointing clockwise
private Drawable mArrowLongRight; // Long arrow starting on the right, pointing CCW
private Bitmap mArrowShortLeftAndRight;
private Bitmap mArrowLongLeft; // Long arrow starting on the left, pointing clockwise
private Bitmap mArrowLongRight; // Long arrow starting on the right, pointing CCW
// positions of the left and right handle
private int mLeftHandleX;
@@ -74,6 +82,12 @@ public class RotarySelector extends View {
private DecelerateInterpolator mInterpolator;
private Paint mPaint = new Paint();
// used to rotate the background and arrow assets depending on orientation
final Matrix mBgMatrix = new Matrix();
final Matrix mArrowMatrix = new Matrix();
/**
* If the user is currently dragging something.
*/
@@ -117,7 +131,6 @@ public class RotarySelector extends View {
static final int SNAP_BACK_ANIMATION_DURATION_MILLIS = 300;
static final int SPIN_ANIMATION_DURATION_MILLIS = 800;
private static final boolean DRAW_CENTER_DIMPLE = true;
private int mEdgeTriggerThresh;
private int mDimpleWidth;
private int mBackgroundWidth;
@@ -137,6 +150,10 @@ public class RotarySelector extends View {
*/
private int mDimplesOfFling = 0;
/**
* Either {@link #HORIZONTAL} or {@link #VERTICAL}.
*/
private int mOrientation;
public RotarySelector(Context context) {
@@ -148,28 +165,23 @@ public class RotarySelector extends View {
*/
public RotarySelector(Context context, AttributeSet attrs) {
super(context, attrs);
if (DBG) log("IncomingCallDialWidget constructor...");
TypedArray a =
context.obtainStyledAttributes(attrs, R.styleable.RotarySelector);
mOrientation = a.getInt(R.styleable.RotarySelector_orientation, HORIZONTAL);
a.recycle();
Resources r = getResources();
mDensity = r.getDisplayMetrics().density;
if (DBG) log("- Density: " + mDensity);
// Assets (all are BitmapDrawables).
mBackground = r.getDrawable(R.drawable.jog_dial_bg_cropped);
mBackground = getBitmapFor(R.drawable.jog_dial_bg);
mDimple = r.getDrawable(R.drawable.jog_dial_dimple);
mArrowLongLeft = r.getDrawable(R.drawable.jog_dial_arrow_long_left_green);
mArrowLongRight = r.getDrawable(R.drawable.jog_dial_arrow_long_right_red);
mArrowShortLeftAndRight = r.getDrawable(R.drawable.jog_dial_arrow_short_left_and_right);
// Arrows:
// All arrow assets are the same size (they're the full width of
// the screen) regardless of which arrows are actually visible.
int arrowW = mArrowShortLeftAndRight.getIntrinsicWidth();
int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight();
mArrowShortLeftAndRight.setBounds(0, 0, arrowW, arrowH);
mArrowLongLeft.setBounds(0, 0, arrowW, arrowH);
mArrowLongRight.setBounds(0, 0, arrowW, arrowH);
mArrowLongLeft = getBitmapFor(R.drawable.jog_dial_arrow_long_left_green);
mArrowLongRight = getBitmapFor(R.drawable.jog_dial_arrow_long_right_red);
mArrowShortLeftAndRight = getBitmapFor(R.drawable.jog_dial_arrow_short_left_and_right);
mInterpolator = new DecelerateInterpolator(1f);
@@ -177,8 +189,8 @@ public class RotarySelector extends View {
mDimpleWidth = mDimple.getIntrinsicWidth();
mBackgroundWidth = mBackground.getIntrinsicWidth();
mBackgroundHeight = mBackground.getIntrinsicHeight();
mBackgroundWidth = mBackground.getWidth();
mBackgroundHeight = mBackground.getHeight();
mOuterRadius = (int) (mDensity * OUTER_ROTARY_RADIUS_DIP);
mInnerRadius = (int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity);
@@ -187,15 +199,35 @@ public class RotarySelector extends View {
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
private Bitmap getBitmapFor(int resId) {
return BitmapFactory.decodeResource(getContext().getResources(), resId);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mLeftHandleX = (int) (EDGE_PADDING_DIP * mDensity) + mDimpleWidth / 2;
mRightHandleX =
getWidth() - (int) (EDGE_PADDING_DIP * mDensity) - mDimpleWidth / 2;
final int edgePadding = (int) (EDGE_PADDING_DIP * mDensity);
mLeftHandleX = edgePadding + mDimpleWidth / 2;
final int length = isHoriz() ? w : h;
mRightHandleX = length - edgePadding - mDimpleWidth / 2;
mDimpleSpacing = (length / 2) - mLeftHandleX;
mDimpleSpacing = (getWidth() / 2) - mLeftHandleX;
// bg matrix only needs to be calculated once
mBgMatrix.setTranslate(0, 0);
if (!isHoriz()) {
// set up matrix for translating drawing of background and arrow assets
final int left = w - mBackgroundHeight;
mBgMatrix.preRotate(-90, 0, 0);
mBgMatrix.postTranslate(left, h);
} else {
mBgMatrix.postTranslate(0, h - mBackgroundHeight);
}
}
private boolean isHoriz() {
return mOrientation == HORIZONTAL;
}
/**
@@ -252,28 +284,35 @@ public class RotarySelector extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = MeasureSpec.getSize(widthMeasureSpec); // screen width
final int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight();
final int backgroundH = mBackgroundHeight;
final int length = isHoriz() ?
MeasureSpec.getSize(widthMeasureSpec) :
MeasureSpec.getSize(heightMeasureSpec);
final int arrowScrunch = (int) (ARROW_SCRUNCH_DIP * mDensity);
final int arrowH = mArrowShortLeftAndRight.getHeight();
// by making the height less than arrow + bg, arrow and bg will be scrunched together,
// overlaying somewhat (though on transparent portions of the drawable).
// this works because the arrows are drawn from the top, and the rotary bg is drawn
// from the bottom.
final int arrowScrunch = (int) (ARROW_SCRUNCH_DIP * mDensity);
setMeasuredDimension(width, backgroundH + arrowH - arrowScrunch);
}
final int height = mBackgroundHeight + arrowH - arrowScrunch;
// private Paint mPaint = new Paint();
if (isHoriz()) {
setMeasuredDimension(length, height);
} else {
setMeasuredDimension(height, length);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (DBG) {
log(String.format("onDraw: mAnimating=%s, mRotaryOffsetX=%d, mGrabbedState=%d",
mAnimating, mRotaryOffsetX, mGrabbedState));
}
final int width = getWidth();
// DEBUG: draw bounding box around widget
// mPaint.setColor(Color.RED);
// mPaint.setStyle(Paint.Style.STROKE);
// canvas.drawRect(0, 0, width, getHeight(), mPaint);
final int height = getHeight();
@@ -283,76 +322,113 @@ public class RotarySelector extends View {
}
// Background:
final int backgroundW = mBackgroundWidth;
final int backgroundH = mBackgroundHeight;
final int backgroundY = height - backgroundH;
if (DBG) log("- Background INTRINSIC: " + backgroundW + " x " + backgroundH);
mBackground.setBounds(0, backgroundY,
backgroundW, backgroundY + backgroundH);
if (DBG) log(" Background BOUNDS: " + mBackground.getBounds());
mBackground.draw(canvas);
canvas.drawBitmap(mBackground, mBgMatrix, mPaint);
// Draw the correct arrow(s) depending on the current state:
Drawable currentArrow;
mArrowMatrix.reset();
switch (mGrabbedState) {
case NOTHING_GRABBED:
currentArrow = null; //mArrowShortLeftAndRight;
//mArrowShortLeftAndRight;
break;
case LEFT_HANDLE_GRABBED:
currentArrow = mArrowLongLeft;
mArrowMatrix.setTranslate(0, 0);
if (!isHoriz()) {
mArrowMatrix.preRotate(-90, 0, 0);
mArrowMatrix.postTranslate(0, height);
}
canvas.drawBitmap(mArrowLongLeft, mArrowMatrix, mPaint);
break;
case RIGHT_HANDLE_GRABBED:
currentArrow = mArrowLongRight;
mArrowMatrix.setTranslate(0, 0);
if (!isHoriz()) {
mArrowMatrix.preRotate(-90, 0, 0);
// since bg width is > height of screen in landscape mode...
mArrowMatrix.postTranslate(0, height + (mBackgroundWidth - height));
}
canvas.drawBitmap(mArrowLongRight, mArrowMatrix, mPaint);
break;
default:
throw new IllegalStateException("invalid mGrabbedState: " + mGrabbedState);
}
if (currentArrow != null) currentArrow.draw(canvas);
// debug: draw circle that should match the outer arc (good sanity check)
// mPaint.setColor(Color.RED);
// mPaint.setStyle(Paint.Style.STROKE);
final int bgHeight = mBackgroundHeight;
final int bgTop = isHoriz() ?
height - bgHeight:
width - bgHeight;
// DEBUG: draw circle bounding arc drawable: good sanity check we're doing the math
// correctly
// float or = OUTER_ROTARY_RADIUS_DIP * mDensity;
// canvas.drawCircle(getWidth() / 2, or + mBackground.getBounds().top, or, mPaint);
// final int vOffset = mBackgroundWidth - height;
// final int midX = isHoriz() ?
// width / 2 :
// mBackgroundWidth / 2 - vOffset;
// if (isHoriz()) {
// canvas.drawCircle(midX, or + bgTop, or, mPaint);
// } else {
// canvas.drawCircle(or + bgTop, midX, or, mPaint);
// }
final int bgTop = mBackground.getBounds().top;
// left dimple / icon
{
final int xOffset = mLeftHandleX + mRotaryOffsetX;
final int drawableY = getYOnArc(
mBackground,
mBackgroundWidth,
mInnerRadius,
mOuterRadius,
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
if (mGrabbedState != RIGHT_HANDLE_GRABBED) {
drawCentered(mLeftHandleIcon, canvas, xOffset, drawableY + bgTop);
if (isHoriz()) {
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
if (mGrabbedState != RIGHT_HANDLE_GRABBED) {
drawCentered(mLeftHandleIcon, canvas, xOffset, drawableY + bgTop);
}
} else {
// vertical
drawCentered(mDimple, canvas, drawableY + bgTop, height - xOffset);
if (mGrabbedState != RIGHT_HANDLE_GRABBED) {
drawCentered(mLeftHandleIcon, canvas, drawableY + bgTop, height - xOffset);
}
}
}
if (DRAW_CENTER_DIMPLE) {
final int xOffset = getWidth() / 2 + mRotaryOffsetX;
// center dimple
{
final int xOffset = isHoriz() ?
width / 2 + mRotaryOffsetX:
height / 2 + mRotaryOffsetX;
final int drawableY = getYOnArc(
mBackground,
mBackgroundWidth,
mInnerRadius,
mOuterRadius,
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
if (isHoriz()) {
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
} else {
// vertical
drawCentered(mDimple, canvas, drawableY + bgTop, height - xOffset);
}
}
// right dimple / icon
{
final int xOffset = mRightHandleX + mRotaryOffsetX;
final int drawableY = getYOnArc(
mBackground,
mBackgroundWidth,
mInnerRadius,
mOuterRadius,
xOffset);
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
if (mGrabbedState != LEFT_HANDLE_GRABBED) {
drawCentered(mRightHandleIcon, canvas, xOffset, drawableY + bgTop);
if (isHoriz()) {
drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
if (mGrabbedState != LEFT_HANDLE_GRABBED) {
drawCentered(mRightHandleIcon, canvas, xOffset, drawableY + bgTop);
}
} else {
// vertical
drawCentered(mDimple, canvas, drawableY + bgTop, height - xOffset);
if (mGrabbedState != LEFT_HANDLE_GRABBED) {
drawCentered(mRightHandleIcon, canvas, drawableY + bgTop, height - xOffset);
}
}
}
@@ -361,12 +437,16 @@ public class RotarySelector extends View {
final int halfdimple = mDimpleWidth / 2;
while (dimpleLeft > -halfdimple) {
final int drawableY = getYOnArc(
mBackground,
mBackgroundWidth,
mInnerRadius,
mOuterRadius,
dimpleLeft);
drawCentered(mDimple, canvas, dimpleLeft, drawableY + bgTop);
if (isHoriz()) {
drawCentered(mDimple, canvas, dimpleLeft, drawableY + bgTop);
} else {
drawCentered(mDimple, canvas, drawableY + bgTop, height - dimpleLeft);
}
dimpleLeft -= mDimpleSpacing;
}
@@ -375,40 +455,43 @@ public class RotarySelector extends View {
final int rightThresh = mRight + halfdimple;
while (dimpleRight < rightThresh) {
final int drawableY = getYOnArc(
mBackground,
mBackgroundWidth,
mInnerRadius,
mOuterRadius,
dimpleRight);
drawCentered(mDimple, canvas, dimpleRight, drawableY + bgTop);
if (isHoriz()) {
drawCentered(mDimple, canvas, dimpleRight, drawableY + bgTop);
} else {
drawCentered(mDimple, canvas, drawableY + bgTop, height - dimpleRight);
}
dimpleRight += mDimpleSpacing;
}
}
/**
* Assuming drawable is a bounding box around a piece of an arc drawn by two concentric circles
* Assuming bitmap is a bounding box around a piece of an arc drawn by two concentric circles
* (as the background drawable for the rotary widget is), and given an x coordinate along the
* drawable, return the y coordinate of a point on the arc that is between the two concentric
* circles. The resulting y combined with the incoming x is a point along the circle in
* between the two concentric circles.
*
* @param drawable The drawable.
* @param backgroundWidth The width of the asset (the bottom of the box surrounding the arc).
* @param innerRadius The radius of the circle that intersects the drawable at the bottom two
* corders of the drawable (top two corners in terms of drawing coordinates).
* @param outerRadius The radius of the circle who's top most point is the top center of the
* drawable (bottom center in terms of drawing coordinates).
* @param x The distance along the x axis of the desired point.
* @return The y coordinate, in drawing coordinates, that will place (x, y) along the circle
* @param x The distance along the x axis of the desired point. @return The y coordinate, in drawing coordinates, that will place (x, y) along the circle
* in between the two concentric circles.
*/
private int getYOnArc(Drawable drawable, int innerRadius, int outerRadius, int x) {
private int getYOnArc(int backgroundWidth, int innerRadius, int outerRadius, int x) {
// the hypotenuse
final int halfWidth = (outerRadius - innerRadius) / 2;
final int middleRadius = innerRadius + halfWidth;
// the bottom leg of the triangle
final int triangleBottom = (drawable.getIntrinsicWidth() / 2) - x;
final int triangleBottom = (backgroundWidth / 2) - x;
// "Our offense is like the pythagorean theorem: There is no answer!" - Shaquille O'Neal
final int triangleY =
@@ -437,8 +520,11 @@ public class RotarySelector extends View {
}
mVelocityTracker.addMovement(event);
final int height = getHeight();
final int eventX = (int) event.getX();
final int eventX = isHoriz() ?
(int) event.getX():
height - ((int) event.getY());
final int hitWindow = mDimpleWidth;
final int action = event.getAction();
@@ -468,12 +554,16 @@ public class RotarySelector extends View {
if (mGrabbedState == LEFT_HANDLE_GRABBED) {
mRotaryOffsetX = eventX - mLeftHandleX;
invalidate();
if (eventX >= getRight() - mEdgeTriggerThresh && !mTriggered) {
final int rightThresh = isHoriz() ? getRight() : height;
if (eventX >= rightThresh - mEdgeTriggerThresh && !mTriggered) {
mTriggered = true;
dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
final int velocity = Math.max(mMinimumVelocity, (int) velocityTracker.getXVelocity());
final int rawVelocity = isHoriz() ?
(int) velocityTracker.getXVelocity():
-(int) velocityTracker.getYVelocity();
final int velocity = Math.max(mMinimumVelocity, rawVelocity);
mDimplesOfFling = Math.max(
8,
Math.abs(velocity / mDimpleSpacing));
@@ -490,7 +580,10 @@ public class RotarySelector extends View {
dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
final int velocity = Math.min(-mMinimumVelocity, (int) velocityTracker.getXVelocity());
final int rawVelocity = isHoriz() ?
(int) velocityTracker.getXVelocity():
- (int) velocityTracker.getYVelocity();
final int velocity = Math.min(-mMinimumVelocity, rawVelocity);
mDimplesOfFling = Math.max(
8,
Math.abs(velocity / mDimpleSpacing));
@@ -559,6 +652,7 @@ public class RotarySelector extends View {
final long millisSoFar = currentAnimationTimeMillis() - mAnimationStartTime;
final long millisLeft = mAnimationDuration - millisSoFar;
final int totalDeltaX = mAnimatingDeltaXStart - mAnimatingDeltaXEnd;
final boolean goingRight = totalDeltaX < 0;
if (DBG) log("millisleft for animating: " + millisLeft);
if (millisLeft <= 0) {
reset();
@@ -569,13 +663,17 @@ public class RotarySelector extends View {
mInterpolator.getInterpolation((float) millisSoFar / mAnimationDuration);
final int dx = (int) (totalDeltaX * (1 - interpolation));
mRotaryOffsetX = mAnimatingDeltaXEnd + dx;
// once we have gone far enough to animate the current buttons off screen, we start
// wrapping the offset back to the other side so that when the animation is finished,
// the buttons will come back into their original places.
if (mDimplesOfFling > 0) {
if (mRotaryOffsetX < 4 * mDimpleSpacing) {
if (!goingRight && mRotaryOffsetX < 3 * mDimpleSpacing) {
// wrap around on fling left
mRotaryOffsetX += (4 + mDimplesOfFling - 4) * mDimpleSpacing;
} else if (mRotaryOffsetX > 4 * mDimpleSpacing) {
mRotaryOffsetX += mDimplesOfFling * mDimpleSpacing;
} else if (goingRight && mRotaryOffsetX > 3 * mDimpleSpacing) {
// wrap around on fling right
mRotaryOffsetX -= (4 + mDimplesOfFling - 4) * mDimpleSpacing;
mRotaryOffsetX -= mDimplesOfFling * mDimpleSpacing;
}
}
invalidate();

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<!-- This is the general lock screen which shows information about the
state of the device, as well as instructions on how to get past it
depending on the state of the device.-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:rotaryunlock="http://schemas.android.com/apk/res/com.android.rotaryunlock"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/root"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#A0000000"
>
<!-- left side -->
<RelativeLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1.0"
android:gravity="center_horizontal"
>
<TextView
android:id="@+id/carrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary"
/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/carrier"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dip"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="55sp"
/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/time"
android:layout_centerHorizontal="true"
android:layout_marginTop="-12dip"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<View
android:id="@+id/divider"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:layout_marginTop="10dip"
android:layout_below="@id/date"
android:background="@android:drawable/divider_horizontal_dark"
/>
<TextView
android:id="@+id/status1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/divider"
android:layout_centerHorizontal="true"
android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary"
android:drawablePadding="4dip"
/>
<TextView
android:id="@+id/status2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/status1"
android:layout_centerHorizontal="true"
android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary"
android:drawablePadding="4dip"
/>
<TextView
android:id="@+id/screenLocked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/status2"
android:layout_centerHorizontal="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary"
android:gravity="center"
android:layout_marginTop="12dip"
/>
<!-- emergency call button shown when sim is missing or PUKd -->
<Button
android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/screenLocked"
android:layout_centerHorizontal="true"
android:layout_marginTop="24dip"
android:drawableLeft="@drawable/ic_emergency"
android:drawablePadding="8dip"
/>
</RelativeLayout>
<!-- right side -->
<com.android.internal.widget.RotarySelector
android:id="@+id/rotary"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical"
/>
</LinearLayout>
</FrameLayout>

View File

@@ -2295,6 +2295,14 @@
<attr name="layout_scale" format="float" />
</declare-styleable>
<!-- attributes for internal rotary widget used in lock screen and phone app
@hide -->
<declare-styleable name="RotarySelector">
<!-- Use "horizontal" or "vertical". The default is horizontal. -->
<attr name="orientation" />
</declare-styleable>
<!-- ========================= -->
<!-- Drawable class attributes -->
<!-- ========================= -->