diff options
Diffstat (limited to 'core/java')
21 files changed, 534 insertions, 633 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 394175a..fcfeddd 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6077,9 +6077,9 @@ public class Activity extends ContextThemeWrapper * * If {@link DevicePolicyManager#isLockTaskPermitted(String)} returns false * then the system will prompt the user with a dialog requesting permission to enter - * this mode. When entered through this method the user can exit at any time by - * swiping down twice from the top of the screen. Calling stopLockTask will also - * exit the mode. + * this mode. When entered through this method the user can exit at any time through + * an action described by the request dialog. Calling stopLockTask will also exit the + * mode. */ public void startLockTask() { try { diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java index d7fb707..a78b137 100644 --- a/core/java/android/app/DatePickerDialog.java +++ b/core/java/android/app/DatePickerDialog.java @@ -112,15 +112,14 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener, Context themeContext = getContext(); - LayoutInflater inflater = - (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = inflater.inflate(R.layout.date_picker_dialog, null); + final LayoutInflater inflater = (LayoutInflater) themeContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + final View view = inflater.inflate(R.layout.date_picker_dialog, null); setView(view); setButtonPanelLayoutHint(LAYOUT_HINT_SIDE); - mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); // Initialize state - mDatePicker.setLegacyMode(false, null); + mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); mDatePicker.setShowDoneButton(true); mDatePicker.setDismissCallback(new DatePicker.DatePickerDismissCallback() { @Override diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index f4eb558..2ce6018 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -117,7 +117,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { setTransitionAlpha(mTransitioningViews, 1); setTransitionAlpha(mSharedElements, 1); mIsHidden = true; - if (getDecor() != null) { + if (!mIsReturning && getDecor() != null) { getDecor().suppressLayout(false); } clearState(); @@ -357,7 +357,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { mExitNotified = true; mResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null); mResultReceiver = null; // done talking - if (getDecor() != null) { + if (!mIsReturning && getDecor() != null) { getDecor().suppressLayout(false); } finishIfNecessary(); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index b84eca2..0e6f86e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2328,7 +2328,7 @@ public class DevicePolicyManager { } /** - * Sets a list of features to enable for a TrustAgentService component. This is meant to be + * Sets a list of features to enable for a TrustAgent component. This is meant to be * used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which will disable all * trust agents but those with features enabled by this function call. * @@ -2353,7 +2353,7 @@ public class DevicePolicyManager { } /** - * Gets list of enabled features for the given {@link TrustAgentService} agent. If admin is + * Gets list of enabled features for the given TrustAgent component. If admin is * null, this will return the intersection of all features enabled for the given agent by all * admins. * diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index 70f6966..936e205 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -266,6 +266,11 @@ public class JobInfo implements Parcelable { } }; + @Override + public String toString() { + return "(job:" + jobId + "/" + service.flattenToShortString() + ")"; + } + /** Builder class for constructing {@link JobInfo} objects. */ public static final class Builder { private int mJobId; diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 3f01dd2..900b41d 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -331,6 +331,46 @@ public class ColorStateList implements Parcelable { return mColors; } + /** + * If the color state list does not already have an entry matching the + * specified state, prepends a state set and color pair to a color state + * list. + * <p> + * This is a workaround used in TimePicker and DatePicker until we can + * add support for theme attributes in ColorStateList. + * + * @param colorStateList the source color state list + * @param state the state to prepend + * @param color the color to use for the given state + * @return a new color state list, or the source color state list if there + * was already a matching state set + * + * @hide Remove when we can support theme attributes. + */ + public static ColorStateList addFirstIfMissing( + ColorStateList colorStateList, int state, int color) { + final int[][] inputStates = colorStateList.getStates(); + for (int i = 0; i < inputStates.length; i++) { + final int[] inputState = inputStates[i]; + for (int j = 0; j < inputState.length; j++) { + if (inputState[i] == state) { + return colorStateList; + } + } + } + + final int[][] outputStates = new int[inputStates.length + 1][]; + System.arraycopy(inputStates, 0, outputStates, 1, inputStates.length); + outputStates[0] = new int[] { state }; + + final int[] inputColors = colorStateList.getColors(); + final int[] outputColors = new int[inputColors.length + 1]; + System.arraycopy(inputColors, 0, outputColors, 1, inputColors.length); + outputColors[0] = color; + + return new ColorStateList(outputStates, outputColors); + } + @Override public String toString() { return "ColorStateList{" + diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index 645f7df..8607bbc 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -400,6 +400,8 @@ public class TypedArray { return csl.getDefaultColor(); } return defValue; + } else if (type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to color: type=0x" @@ -422,6 +424,9 @@ public class TypedArray { final TypedValue value = mValue; if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { + if (value.type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); + } return mResources.loadColorStateList(value, value.resourceId); } return null; @@ -449,6 +454,8 @@ public class TypedArray { } else if (type >= TypedValue.TYPE_FIRST_INT && type <= TypedValue.TYPE_LAST_INT) { return data[index+AssetManager.STYLE_DATA]; + } else if (type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to integer: type=0x" @@ -484,6 +491,8 @@ public class TypedArray { } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimension( data[index+AssetManager.STYLE_DATA], mMetrics); + } else if (type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to dimension: type=0x" @@ -520,6 +529,8 @@ public class TypedArray { } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelOffset( data[index+AssetManager.STYLE_DATA], mMetrics); + } else if (type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to dimension: type=0x" @@ -557,6 +568,8 @@ public class TypedArray { } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelSize( data[index+AssetManager.STYLE_DATA], mMetrics); + } else if (type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to dimension: type=0x" @@ -589,6 +602,8 @@ public class TypedArray { } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelSize( data[index+AssetManager.STYLE_DATA], mMetrics); + } else if (type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } throw new RuntimeException(getPositionDescription() @@ -655,6 +670,8 @@ public class TypedArray { } else if (type == TypedValue.TYPE_FRACTION) { return TypedValue.complexToFraction( data[index+AssetManager.STYLE_DATA], base, pbase); + } else if (type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to fraction: type=0x" @@ -731,14 +748,8 @@ public class TypedArray { final TypedValue value = mValue; if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { - if (false) { - System.out.println("******************************************************************"); - System.out.println("Got drawable resource: type=" - + value.type - + " str=" + value.string - + " int=0x" + Integer.toHexString(value.data) - + " cookie=" + value.assetCookie); - System.out.println("******************************************************************"); + if (value.type == TypedValue.TYPE_ATTRIBUTE) { + throw new RuntimeException("Failed to resolve attribute at index " + index); } return mResources.loadDrawable(value, value.resourceId, mTheme); } @@ -762,15 +773,6 @@ public class TypedArray { final TypedValue value = mValue; if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { - if (false) { - System.out.println("******************************************************************"); - System.out.println("Got drawable resource: type=" - + value.type - + " str=" + value.string - + " int=0x" + Integer.toHexString(value.data) - + " cookie=" + value.assetCookie); - System.out.println("******************************************************************"); - } return mResources.getTextArray(value.resourceId); } return null; diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 5397d49..d4e6df5 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -198,10 +198,14 @@ public final class DisplayManager { * VIRTUAL_DISPLAY_FLAG_PRIVATE. Other flags are not allowed (especially * not VIRTUAL_DISPLAY_FLAG_PUBLIC or PRESENTATION). * + * <p> * Requires screen share permission for use. + * </p> * + * <p> * While a display of this type exists, the system will show some sort of * notification to the user indicating that the screen is being shared. + * </p> * * @see #createVirtualDisplay */ diff --git a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl index 0bf4f25..b1a02c1 100644 --- a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl +++ b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl @@ -26,10 +26,8 @@ oneway interface IRecognitionStatusCallback { * Called when the keyphrase is spoken. * * @param data Optional trigger audio data, if it was requested and is available. - * TODO: See if the data being passed in works well, if not use shared memory. - * This *MUST* not exceed 100K. */ - void onDetected(in SoundTrigger.RecognitionEvent recognitionEvent); + void onDetected(in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent); /** * Called when the detection for the associated keyphrase stops. */ diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl index 9adc6bc..e16ea71 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl @@ -18,8 +18,8 @@ package android.hardware.soundtrigger; parcelable SoundTrigger.ConfidenceLevel; parcelable SoundTrigger.Keyphrase; +parcelable SoundTrigger.KeyphraseRecognitionEvent; parcelable SoundTrigger.KeyphraseRecognitionExtra; parcelable SoundTrigger.KeyphraseSoundModel; parcelable SoundTrigger.ModuleProperties; parcelable SoundTrigger.RecognitionConfig; -parcelable SoundTrigger.RecognitionEvent;
\ No newline at end of file diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index 3e84368..4498789 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.java +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java @@ -361,13 +361,13 @@ public class SoundTrigger { public void writeToParcel(Parcel dest, int flags) { dest.writeString(uuid.toString()); dest.writeBlob(data); - dest.writeTypedArray(keyphrases, 0); + dest.writeTypedArray(keyphrases, flags); } @Override public String toString() { return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases) + ", uuid=" - + uuid + ", type=" + type + ", data? " + (data != null) + "]"; + + uuid + ", type=" + type + ", data=" + (data == null ? 0 : data.length) + "]"; } } @@ -504,6 +504,15 @@ public class SoundTrigger { return false; return true; } + + @Override + public String toString() { + return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle + + ", captureAvailable=" + captureAvailable + ", captureSession=" + + captureSession + ", captureDelayMs=" + captureDelayMs + + ", capturePreambleMs=" + capturePreambleMs + + ", data=" + (data == null ? 0 : data.length) + "]"; + } } /** @@ -551,7 +560,7 @@ public class SoundTrigger { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByte((byte) (captureRequested ? 1 : 0)); - dest.writeTypedArray(keyphrases, 0); + dest.writeTypedArray(keyphrases, flags); dest.writeBlob(data); } @@ -563,7 +572,8 @@ public class SoundTrigger { @Override public String toString() { return "RecognitionConfig [captureRequested=" + captureRequested + ", keyphrases=" - + Arrays.toString(keyphrases) + ", data? " + (data != null) + "]"; + + Arrays.toString(keyphrases) + + ", data=" + (data == null ? 0 : data.length) + "]"; } } @@ -611,6 +621,37 @@ public class SoundTrigger { public int describeContents() { return 0; } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + confidenceLevel; + result = prime * result + userId; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ConfidenceLevel other = (ConfidenceLevel) obj; + if (confidenceLevel != other.confidenceLevel) + return false; + if (userId != other.userId) + return false; + return true; + } + + @Override + public String toString() { + return "ConfidenceLevel [userId=" + userId + + ", confidenceLevel=" + confidenceLevel + "]"; + } } /** @@ -657,13 +698,47 @@ public class SoundTrigger { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); dest.writeInt(recognitionModes); - dest.writeTypedArray(confidenceLevels, 0); + dest.writeTypedArray(confidenceLevels, flags); } @Override public int describeContents() { return 0; } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(confidenceLevels); + result = prime * result + id; + result = prime * result + recognitionModes; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj; + if (!Arrays.equals(confidenceLevels, other.confidenceLevels)) + return false; + if (id != other.id) + return false; + if (recognitionModes != other.recognitionModes) + return false; + return true; + } + + @Override + public String toString() { + return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes + + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]"; + } } /** @@ -676,7 +751,7 @@ public class SoundTrigger { /** Additional data available for each recognized key phrases in the model */ public final boolean keyphraseInCapture; - KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable, + public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable, int captureSession, int captureDelayMs, int capturePreambleMs, byte[] data, boolean keyphraseInCapture, KeyphraseRecognitionExtra[] keyphraseExtras) { super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs, @@ -684,6 +759,86 @@ public class SoundTrigger { this.keyphraseInCapture = keyphraseInCapture; this.keyphraseExtras = keyphraseExtras; } + + public static final Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR + = new Parcelable.Creator<KeyphraseRecognitionEvent>() { + public KeyphraseRecognitionEvent createFromParcel(Parcel in) { + return KeyphraseRecognitionEvent.fromParcel(in); + } + + public KeyphraseRecognitionEvent[] newArray(int size) { + return new KeyphraseRecognitionEvent[size]; + } + }; + + private static KeyphraseRecognitionEvent fromParcel(Parcel in) { + int status = in.readInt(); + int soundModelHandle = in.readInt(); + boolean captureAvailable = in.readByte() == 1; + int captureSession = in.readInt(); + int captureDelayMs = in.readInt(); + int capturePreambleMs = in.readInt(); + byte[] data = in.readBlob(); + boolean keyphraseInCapture = in.readByte() == 1; + KeyphraseRecognitionExtra[] keyphraseExtras = + in.createTypedArray(KeyphraseRecognitionExtra.CREATOR); + return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable, + captureSession, captureDelayMs, capturePreambleMs, data, keyphraseInCapture, + keyphraseExtras); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(status); + dest.writeInt(soundModelHandle); + dest.writeByte((byte) (captureAvailable ? 1 : 0)); + dest.writeInt(captureSession); + dest.writeInt(captureDelayMs); + dest.writeInt(capturePreambleMs); + dest.writeBlob(data); + dest.writeByte((byte) (keyphraseInCapture ? 1 : 0)); + dest.writeTypedArray(keyphraseExtras, flags); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Arrays.hashCode(keyphraseExtras); + result = prime * result + (keyphraseInCapture ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj; + if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras)) + return false; + if (keyphraseInCapture != other.keyphraseInCapture) + return false; + return true; + } + + @Override + public String toString() { + return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras) + + ", keyphraseInCapture=" + keyphraseInCapture + ", status=" + status + + ", soundModelHandle=" + soundModelHandle + ", captureAvailable=" + + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs=" + + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs + + ", data=" + (data == null ? 0 : data.length) + "]"; + } } /** diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index a8c08d55..e40ece3 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -23,6 +23,7 @@ import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.SoundTrigger; import android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel; import android.hardware.soundtrigger.SoundTrigger.Keyphrase; +import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent; import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra; import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; import android.hardware.soundtrigger.SoundTrigger.ModuleProperties; @@ -133,11 +134,6 @@ public class AlwaysOnHotwordDetector { private final Object mLock = new Object(); private final Handler mHandler; - /** - * Indicates if there is a sound model enrolled for the keyphrase, - * derived from the model management service (IVoiceInteractionManagerService). - */ - private boolean mIsEnrolledForDetection; private int mAvailability = STATE_NOT_READY; /** @@ -381,10 +377,10 @@ public class AlwaysOnHotwordDetector { } @Override - public void onDetected(RecognitionEvent recognitionEvent) { + public void onDetected(KeyphraseRecognitionEvent event) { Slog.i(TAG, "onDetected"); Message message = Message.obtain(mHandler, MSG_HOTWORD_DETECTED); - message.obj = recognitionEvent.data; + message.obj = event.data; message.sendToTarget(); } @@ -436,7 +432,6 @@ public class AlwaysOnHotwordDetector { Slog.d(TAG, "Hotword availability changed from " + mAvailability + " -> " + availability); } - mIsEnrolledForDetection = enrolled; mAvailability = availability; notifyStateChangedLocked(); } diff --git a/core/java/android/transition/Explode.java b/core/java/android/transition/Explode.java index 995702e..0ccdf15 100644 --- a/core/java/android/transition/Explode.java +++ b/core/java/android/transition/Explode.java @@ -52,6 +52,7 @@ public class Explode extends Visibility { public Explode(Context context, AttributeSet attrs) { super(context, attrs); + setPropagation(new CircularPropagation()); } private void captureValues(TransitionValues transitionValues) { diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java new file mode 100644 index 0000000..1aa8d99 --- /dev/null +++ b/core/java/android/view/GhostView.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2014 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. + */ +package android.view; + +import android.graphics.Canvas; +import android.graphics.Matrix; + +/** + * This view draws another View in an Overlay without changing the parent. It will not be drawn + * by its parent because its visibility is set to INVISIBLE, but will be drawn + * here using its render node. When the GhostView is set to INVISIBLE, the View it is + * shadowing will become VISIBLE and when the GhostView becomes VISIBLE, the shadowed + * view becomes INVISIBLE. + * @hide + */ +public class GhostView extends View { + private final Matrix mMatrix = new Matrix(); + private final View mView; + + private GhostView(View view, ViewGroup host) { + super(view.getContext()); + mView = view; + setMatrix(host); + mView.mGhostView = this; + final ViewGroup parent = (ViewGroup) mView.getParent(); + setLeft(0); + setTop(0); + setRight(host.getWidth()); + setBottom(host.getHeight()); + setGhostedVisibility(View.INVISIBLE); + parent.mRecreateDisplayList = true; + parent.getDisplayList(); + } + + @Override + protected void onDraw(Canvas canvas) { + if (canvas instanceof HardwareCanvas) { + HardwareCanvas hwCanvas = (HardwareCanvas) canvas; + int saveCount = hwCanvas.save(Canvas.MATRIX_SAVE_FLAG); + canvas.concat(mMatrix); + mView.mRecreateDisplayList = true; + RenderNode renderNode = mView.getDisplayList(); + if (renderNode.isValid()) { + hwCanvas.drawRenderNode(renderNode); + } + hwCanvas.restoreToCount(saveCount); + } + } + + @Override + public void setVisibility(@Visibility int visibility) { + super.setVisibility(visibility); + if (mView.mGhostView == this) { + int inverseVisibility = (visibility == View.VISIBLE) ? View.INVISIBLE : View.VISIBLE; + setGhostedVisibility(inverseVisibility); + } + } + + private void setGhostedVisibility(int visibility) { + mView.mViewFlags = (mView.mViewFlags & ~View.VISIBILITY_MASK) | visibility; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + setGhostedVisibility(View.VISIBLE); + mView.mGhostView = null; + final ViewGroup parent = (ViewGroup) mView.getParent(); + parent.mRecreateDisplayList = true; + parent.getDisplayList(); + } + + private void setMatrix(ViewGroup host) { + host.transformMatrixToLocal(mMatrix); + ViewGroup parent = (ViewGroup) mView.getParent(); + parent.transformMatrixToGlobal(mMatrix); + mMatrix.postTranslate(-parent.getScrollX(), -parent.getScrollY()); + } + + public static GhostView addGhost(View view, ViewGroup viewGroup) { + if (!(view.getParent() instanceof ViewGroup)) { + throw new IllegalArgumentException("Ghosted views must be parented by a ViewGroup"); + } + ViewGroupOverlay overlay = viewGroup.getOverlay(); + ViewOverlay.OverlayViewGroup overlayViewGroup = overlay.mOverlayViewGroup; + GhostView ghostView = view.mGhostView; + if (ghostView != null) { + ViewGroup oldParent = (ViewGroup) ghostView.getParent(); + if (oldParent != overlayViewGroup) { + oldParent.removeView(ghostView); + ghostView = null; + } + } + if (ghostView == null) { + ghostView = new GhostView(view, (ViewGroup) overlayViewGroup.mHostView); + overlay.add(ghostView); + } + return ghostView; + } + + public static void removeGhost(View view) { + GhostView ghostView = view.mGhostView; + if (ghostView != null) { + ViewGroup parent = (ViewGroup) ghostView.getParent(); + parent.removeView(ghostView); + } + } + + public static GhostView getGhost(View view) { + return view.mGhostView; + } +} diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a9b3ec1..16a161b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -17,9 +17,7 @@ package android.view; import android.animation.AnimatorInflater; -import android.animation.RevealAnimator; import android.animation.StateListAnimator; -import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -3520,6 +3518,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private int[] mTempNestedScrollConsumed; /** + * An overlay is going to draw this View instead of being drawn as part of this + * View's parent. mGhostView is the View in the Overlay that must be invalidated + * when this view is invalidated. + */ + GhostView mGhostView; + + /** * Simple constructor to use when creating a view from code. * * @param context The Context the view is running in, through which it can @@ -10284,6 +10289,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @hide */ + @ViewDebug.ExportedProperty(category = "drawing") public float getTransitionAlpha() { return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; } @@ -11371,6 +11377,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate) { + if (mGhostView != null) { + mGhostView.invalidate(invalidateCache); + return; + } + if (skipInvalidate()) { return; } @@ -11408,7 +11419,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } - // Damage the entire IsolatedZVolume recieving this view's shadow. + // Damage the entire IsolatedZVolume receiving this view's shadow. if (isHardwareAccelerated() && getZ() != 0) { damageShadowReceiver(); } @@ -19410,6 +19421,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return The name used of the View to be used to identify Views in Transitions or null * if no name has been given. */ + @ViewDebug.ExportedProperty public String getTransitionName() { return mTransitionName; } diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index 8f49fb8..74c66c8 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -17,9 +17,7 @@ package android.widget; import android.annotation.Widget; -import android.app.UiModeManager; import android.content.Context; -import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.TypedArray; import android.os.Parcel; @@ -51,8 +49,6 @@ import java.util.TimeZone; import libcore.icu.ICU; -import static android.os.Build.VERSION_CODES.L; - /** * This class is a widget for selecting a date. The date can be selected by a * year, month, and day spinners or a {@link CalendarView}. The set of spinners @@ -74,26 +70,21 @@ import static android.os.Build.VERSION_CODES.L; * @attr ref android.R.styleable#DatePicker_minDate * @attr ref android.R.styleable#DatePicker_spinnersShown * @attr ref android.R.styleable#DatePicker_calendarViewShown - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekBackgroundColor - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekTextAppearance - * @attr ref android.R.styleable#DatePicker_dateSelectorBackgroundColor - * @attr ref android.R.styleable#DatePicker_dateSelectorMonthTextAppearance - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfMonthTextAppearance - * @attr ref android.R.styleable#DatePicker_dateSelectorYearTextAppearance - * @attr ref android.R.styleable#DatePicker_dateSelectorYearListItemTextAppearance - * @attr ref android.R.styleable#DatePicker_dateSelectorYearListSelectedCircleColor + * @attr ref android.R.styleable#DatePicker_dayOfWeekBackgroundColor + * @attr ref android.R.styleable#DatePicker_dayOfWeekTextAppearance + * @attr ref android.R.styleable#DatePicker_headerBackgroundColor + * @attr ref android.R.styleable#DatePicker_headerMonthTextAppearance + * @attr ref android.R.styleable#DatePicker_headerDayOfMonthTextAppearance + * @attr ref android.R.styleable#DatePicker_headerYearTextAppearance + * @attr ref android.R.styleable#DatePicker_yearListItemTextAppearance + * @attr ref android.R.styleable#DatePicker_yearListSelectorColor * @attr ref android.R.styleable#DatePicker_calendarTextColor */ @Widget public class DatePicker extends FrameLayout { - private static final String LOG_TAG = DatePicker.class.getSimpleName(); - private DatePickerDelegate mDelegate; - - private int mDefStyleAttr; - private int mDefStyleRes; - private Context mContext; + private final DatePickerDelegate mDelegate; /** * The callback used to indicate the user changes\d the date. @@ -127,30 +118,16 @@ public class DatePicker extends FrameLayout { public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - mContext = context; - mDefStyleAttr = defStyleAttr; - mDefStyleRes = defStyleRes; - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, - mDefStyleAttr, mDefStyleRes); - - // Create the correct UI delegate. Default is the legacy one. - final boolean isLegacyMode = a.getBoolean(R.styleable.DatePicker_legacyMode, - isLegacyMode()); - + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, + defStyleAttr, defStyleRes); + final boolean legacyMode = a.getBoolean(R.styleable.DatePicker_legacyMode, true); a.recycle(); - setLegacyMode(isLegacyMode, attrs); - } - - private boolean isLegacyMode() { - UiModeManager uiModeManager = - (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); - if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) { - return true; + if (legacyMode) { + mDelegate = createLegacyUIDelegate(context, attrs, defStyleAttr, defStyleRes); + } else { + mDelegate = createNewUIDelegate(context, attrs, defStyleAttr, defStyleRes); } - final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; - return targetSdkVersion < L; } private DatePickerDelegate createLegacyUIDelegate(Context context, AttributeSet attrs, @@ -167,16 +144,6 @@ public class DatePicker extends FrameLayout { /** * @hide */ - public void setLegacyMode(boolean isLegacyMode, AttributeSet attrs) { - removeAllViewsInLayout(); - mDelegate = isLegacyMode ? - createLegacyUIDelegate(mContext, attrs, mDefStyleAttr, mDefStyleRes) : - createNewUIDelegate(mContext, attrs, mDefStyleAttr, mDefStyleRes); - } - - /** - * @hide - */ public void setShowDoneButton(boolean showDoneButton) { mDelegate.setShowDoneButton(showDoneButton); } @@ -375,182 +342,6 @@ public class DatePicker extends FrameLayout { mDelegate.setSpinnersShown(shown); } - /** - * Sets the background color for the date selector's day of week. - * - * @param color The background color. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekBackgroundColor - */ - public void setDateSelectorDayOfWeekBackgroundColor(int color) { - mDelegate.setDateSelectorDayOfWeekBackgroundColor(color); - } - - /** - * Gets the background color for the date selector's day of week. - * - * @return The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekBackgroundColor - */ - public int getDateSelectorDayOfWeekBackgroundColor() { - return mDelegate.getDateSelectorDayOfWeekBackgroundColor(); - } - - /** - * Sets the text appearance for the date selector's day of week. - * - * @param resId The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekTextAppearance - */ - public void setDateSelectorDayOfWeekTextAppearance(int resId) { - mDelegate.setDateSelectorDayOfWeekTextAppearance(resId); - } - - /** - * Gets the text appearance for the date selector's day of week. - * - * @return The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekTextAppearance - */ - public int getDateSelectorDayOfWeekTextAppearance() { - return mDelegate.getDateSelectorDayOfWeekTextAppearance(); - } - - /** - * Sets the background color for the date selector's. - * - * @param color The background color. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorBackgroundColor - */ - public void setDateSelectorBackgroundColor(int color) { - mDelegate.setDateSelectorBackgroundColor(color); - } - - /** - * Gets the background color for the date selector's. - * - * @return The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorBackgroundColor - */ - public int getDateSelectorBackgroundColor() { - return mDelegate.getDateSelectorBackgroundColor(); - } - - /** - * Sets the text appearance for the date selector's month. - * - * @param resId The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorMonthTextAppearance - */ - public void setDateSelectorMonthTextAppearance(int resId) { - mDelegate.setDateSelectorMonthTextAppearance(resId); - } - - /** - * Gets the text appearance for the date selector's month. - * - * @return The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorMonthTextAppearance - */ - public int getDateSelectorMonthTextAppearance() { - return mDelegate.getDateSelectorMonthTextAppearance(); - } - - /** - * Sets the text appearance for the date selector's day of month. - * - * @param resId The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfMonthTextAppearance - */ - public void setDateSelectorDayOfMonthTextAppearance(int resId) { - mDelegate.setDateSelectorDayOfMonthTextAppearance(resId); - } - - /** - * Gets the text appearance for the date selector's day of month. - * - * @return The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfMonthTextAppearance - */ - public int getDateSelectorDayOfMonthTextAppearance() { - return mDelegate.getDateSelectorDayOfMonthTextAppearance(); - } - - /** - * Sets the text appearance for the date selector's year. - * - * @param resId The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorYearTextAppearance - */ - public void setDateSelectorYearTextAppearance(int resId) { - mDelegate.setDateSelectorYearTextAppearance(resId); - } - - /** - * Gets the text appearance for the date selector's year. - * - * @return The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorYearTextAppearance - */ - public int getDateSelectorYearTextAppearance() { - return mDelegate.getDateSelectorYearTextAppearance(); - } - - /** - * Sets the text appearance for the year list item. - * - * @param resId The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorYearListItemTextAppearance - */ - public void setDateSelectorYearListItemTextAppearance(int resId) { - mDelegate.setDateSelectorYearListItemTextAppearance(resId); - } - - /** - * Gets the text appearance for the year list item. - * - * @return The text appearance resource id. - * - * @attr ref android.R.styleable#DatePicker_dateSelectorYearListItemTextAppearance - */ - public int getDateSelectorYearListItemTextAppearance() { - return mDelegate.getDateSelectorYearListItemTextAppearance(); - } - - /** - * Sets the text color state list for the calendar. - * - * @param colors The text color state list. - * - * @attr ref android.R.styleable#DatePicker_calendarTextColor - */ - public void setCalendarTextColor(ColorStateList colors) { - mDelegate.setCalendarTextColor(colors); - } - - /** - * Gets the text color state list for the calendar. - * - * @return The text color state list for the calendar. - * - * @attr ref android.R.styleable#DatePicker_calendarTextColor - */ - public ColorStateList getCalendarTextColor() { - return mDelegate.getCalendarTextColors(); - } - // Override so we are in complete control of save / restore for this widget. @Override protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { @@ -596,33 +387,6 @@ public class DatePicker extends FrameLayout { void setEnabled(boolean enabled); boolean isEnabled(); - void setDateSelectorDayOfWeekBackgroundColor(int color); - int getDateSelectorDayOfWeekBackgroundColor(); - - void setDateSelectorDayOfWeekTextAppearance(int resId); - int getDateSelectorDayOfWeekTextAppearance(); - - void setDateSelectorBackgroundColor(int color); - int getDateSelectorBackgroundColor(); - - void setDateSelectorMonthTextAppearance(int resId); - int getDateSelectorMonthTextAppearance(); - - void setDateSelectorDayOfMonthTextAppearance(int resId); - int getDateSelectorDayOfMonthTextAppearance(); - - void setDateSelectorYearTextAppearance(int resId); - int getDateSelectorYearTextAppearance(); - - void setDateSelectorYearListItemTextAppearance(int resId); - int getDateSelectorYearListItemTextAppearance(); - - void setDateSelectorYearListSelectedCircleColor(int color); - int getDateSelectorYearListSelectedCircleColor(); - - void setCalendarTextColor(ColorStateList colors); - ColorStateList getCalendarTextColors(); - CalendarView getCalendarView(); void setCalendarViewShown(boolean shown); @@ -979,87 +743,6 @@ public class DatePicker extends FrameLayout { } @Override - public void setDateSelectorDayOfWeekBackgroundColor(int color) { - } - - @Override - public int getDateSelectorDayOfWeekBackgroundColor() { - return 0; - } - - @Override - public void setDateSelectorDayOfWeekTextAppearance(int resId) { - } - - @Override - public int getDateSelectorDayOfWeekTextAppearance() { - return 0; - } - - @Override - public void setDateSelectorBackgroundColor(int color) { - } - - @Override - public int getDateSelectorBackgroundColor() { - return 0; - } - - @Override - public void setDateSelectorMonthTextAppearance(int resId) { - } - - @Override - public int getDateSelectorMonthTextAppearance() { - return 0; - } - - @Override - public void setDateSelectorDayOfMonthTextAppearance(int resId) { - } - - @Override - public int getDateSelectorDayOfMonthTextAppearance() { - return 0; - } - - @Override - public void setDateSelectorYearTextAppearance(int resId) { - } - - @Override - public int getDateSelectorYearTextAppearance() { - return 0; - } - - @Override - public void setDateSelectorYearListItemTextAppearance(int resId) { - } - - @Override - public int getDateSelectorYearListItemTextAppearance() { - return 0; - } - - @Override - public void setDateSelectorYearListSelectedCircleColor(int color) { - } - - @Override - public int getDateSelectorYearListSelectedCircleColor() { - return 0; - } - - @Override - public void setCalendarTextColor(ColorStateList colors) { - } - - @Override - public ColorStateList getCalendarTextColors() { - return ColorStateList.valueOf(0); - } - - @Override public CalendarView getCalendarView() { return mCalendarView; } diff --git a/core/java/android/widget/DatePickerDelegate.java b/core/java/android/widget/DatePickerDelegate.java index 31044d4..ddc565d 100644 --- a/core/java/android/widget/DatePickerDelegate.java +++ b/core/java/android/widget/DatePickerDelegate.java @@ -24,12 +24,14 @@ import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.Color; import android.os.Parcel; import android.os.Parcelable; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.AttributeSet; import android.util.SparseArray; +import android.util.StateSet; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.View; @@ -45,7 +47,6 @@ import com.android.internal.widget.AccessibleDateAnimator; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashSet; -import java.util.Iterator; import java.util.Locale; /** @@ -76,9 +77,9 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement private TextView mDayOfWeekView; private LinearLayout mDateLayout; private LinearLayout mMonthAndDayLayout; - private TextView mSelectedMonthTextView; - private TextView mSelectedDayTextView; - private TextView mSelectedYearView; + private TextView mHeaderMonthTextView; + private TextView mHeaderDayOfMonthTextView; + private TextView mHeaderYearTextView; private DayPickerView mDayPickerView; private YearPickerView mYearPickerView; @@ -112,21 +113,8 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>(); - private int mDayOfWeekTextAppearanceResId; - private int mMonthTextAppearanceResId; - private int mDayOfMonthTextAppearanceResId; - private int mYearTextAppearanceResId; - - private int mYearListItemTextAppearanceResId; - - private int mDayOfWeekBackgroundColor; - private int mMonthAndDayBackgroundColor; - - private ColorStateList mCalendarTextColors; - public DatePickerDelegate(DatePicker delegator, Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(delegator, context); final Locale locale = Locale.getDefault(); @@ -139,17 +127,14 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement mMinDate.set(DEFAULT_START_YEAR, 1, 1); mMaxDate.set(DEFAULT_END_YEAR, 12, 31); - // process style attributes + final Resources res = mDelegator.getResources(); final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.DatePicker, defStyleAttr, defStyleRes); - final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); - final int layoutResourceId = a.getResourceId( R.styleable.DatePicker_internalLayout, R.layout.date_picker_holo); - - View mainView = inflater.inflate(layoutResourceId, null); + final View mainView = inflater.inflate(layoutResourceId, null); mDelegator.addView(mainView); mDayOfWeekView = (TextView) mainView.findViewById(R.id.date_picker_header); @@ -157,54 +142,68 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement mMonthAndDayLayout = (LinearLayout) mainView.findViewById( R.id.date_picker_month_and_day_layout); mMonthAndDayLayout.setOnClickListener(this); - mSelectedMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_month); - mSelectedDayTextView = (TextView) mainView.findViewById(R.id.date_picker_day); - mSelectedYearView = (TextView) mainView.findViewById(R.id.date_picker_year); - mSelectedYearView.setOnClickListener(this); + mHeaderMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_month); + mHeaderDayOfMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_day); + mHeaderYearTextView = (TextView) mainView.findViewById(R.id.date_picker_year); + mHeaderYearTextView.setOnClickListener(this); + + // Obtain default highlight color from the theme. + final int defaultHighlightColor = mHeaderYearTextView.getHighlightColor(); // Use Theme attributes if possible - mDayOfWeekTextAppearanceResId = a.getResourceId( - R.styleable.DatePicker_dateSelectorDayOfWeekTextAppearance, -1); - if (mDayOfWeekTextAppearanceResId != -1) { - mDayOfWeekView.setTextAppearance(context, mDayOfWeekTextAppearanceResId); + final int dayOfWeekTextAppearanceResId = a.getResourceId( + R.styleable.DatePicker_dayOfWeekTextAppearance, -1); + if (dayOfWeekTextAppearanceResId != -1) { + mDayOfWeekView.setTextAppearance(context, dayOfWeekTextAppearanceResId); } - mMonthTextAppearanceResId = a.getResourceId( - R.styleable.DatePicker_dateSelectorMonthTextAppearance, -1); - if (mMonthTextAppearanceResId != -1) { - mSelectedMonthTextView.setTextAppearance(context, mMonthTextAppearanceResId); - } + final int dayOfWeekBackgroundColor = a.getColor( + R.styleable.DatePicker_dayOfWeekBackgroundColor, Color.TRANSPARENT); + mDayOfWeekView.setBackgroundColor(dayOfWeekBackgroundColor); - mDayOfMonthTextAppearanceResId = a.getResourceId( - R.styleable.DatePicker_dateSelectorDayOfMonthTextAppearance, -1); - if (mDayOfMonthTextAppearanceResId != -1) { - mSelectedDayTextView.setTextAppearance(context, mDayOfMonthTextAppearanceResId); - } + final int headerSelectedTextColor = a.getColor( + R.styleable.DatePicker_headerSelectedTextColor, defaultHighlightColor); + final int headerBackgroundColor = a.getColor(R.styleable.DatePicker_headerBackgroundColor, + Color.TRANSPARENT); + mMonthAndDayLayout.setBackgroundColor(headerBackgroundColor); - mYearTextAppearanceResId = a.getResourceId( - R.styleable.DatePicker_dateSelectorYearTextAppearance, -1); - if (mYearTextAppearanceResId != -1) { - mSelectedYearView.setTextAppearance(context, mYearTextAppearanceResId); + final int monthTextAppearanceResId = a.getResourceId( + R.styleable.DatePicker_headerMonthTextAppearance, -1); + if (monthTextAppearanceResId != -1) { + mHeaderMonthTextView.setTextAppearance(context, monthTextAppearanceResId); } + mHeaderMonthTextView.setTextColor(ColorStateList.addFirstIfMissing( + mHeaderMonthTextView.getTextColors(), R.attr.state_selected, + headerSelectedTextColor)); - Resources res = mDelegator.getResources(); - - mDayOfWeekBackgroundColor = a.getColor( - R.styleable.DatePicker_dateSelectorDayOfWeekBackgroundColor, - res.getColor( - R.color.datepicker_default_header_dayofweek_background_color_holo_light)); - mDayOfWeekView.setBackgroundColor(mDayOfWeekBackgroundColor); + final int dayOfMonthTextAppearanceResId = a.getResourceId( + R.styleable.DatePicker_headerDayOfMonthTextAppearance, -1); + if (dayOfMonthTextAppearanceResId != -1) { + mHeaderDayOfMonthTextView.setTextAppearance(context, dayOfMonthTextAppearanceResId); + } + mHeaderDayOfMonthTextView.setTextColor(ColorStateList.addFirstIfMissing( + mHeaderDayOfMonthTextView.getTextColors(), R.attr.state_selected, + headerSelectedTextColor)); - mMonthAndDayBackgroundColor = a.getColor(R.styleable.DatePicker_dateSelectorBackgroundColor, - res.getColor(R.color.datepicker_default_header_selector_background_holo_light)); - mMonthAndDayLayout.setBackgroundColor(mMonthAndDayBackgroundColor); + final int yearTextAppearanceResId = a.getResourceId( + R.styleable.DatePicker_headerYearTextAppearance, -1); + if (yearTextAppearanceResId != -1) { + mHeaderYearTextView.setTextAppearance(context, yearTextAppearanceResId); + } + mHeaderYearTextView.setTextColor(ColorStateList.addFirstIfMissing( + mHeaderYearTextView.getTextColors(), R.attr.state_selected, + headerSelectedTextColor)); mDayPickerView = new DayPickerView(mContext, this); mYearPickerView = new YearPickerView(mContext); mYearPickerView.init(this); - ColorStateList colors = a.getColorStateList(R.styleable.DatePicker_calendarTextColor); - setCalendarTextColor(colors); + final ColorStateList calendarTextColor = a.getColorStateList( + R.styleable.DatePicker_calendarTextColor); + final int calendarSelectedTextColor = a.getColor( + R.styleable.DatePicker_calendarSelectedTextColor, defaultHighlightColor); + mDayPickerView.setCalendarTextColor(ColorStateList.addFirstIfMissing( + calendarTextColor, R.attr.state_selected, calendarSelectedTextColor)); mDayPickerDescription = res.getString(R.string.day_picker_description); mSelectDay = res.getString(R.string.select_day); @@ -308,30 +307,30 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement // Restart from a clean state mMonthAndDayLayout.removeAllViews(); - mDateLayout.removeView(mSelectedYearView); + mDateLayout.removeView(mHeaderYearTextView); // Position the Year View at the correct location if (viewIndices[YEAR_INDEX] == 0) { - mDateLayout.addView(mSelectedYearView, 0); + mDateLayout.addView(mHeaderYearTextView, 0); } else { - mDateLayout.addView(mSelectedYearView, 1); + mDateLayout.addView(mHeaderYearTextView, 1); } // Position Day and Month Views if (viewIndices[MONTH_INDEX] > viewIndices[DAY_INDEX]) { // Day View is first - mMonthAndDayLayout.addView(mSelectedDayTextView); - mMonthAndDayLayout.addView(mSelectedMonthTextView); + mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView); + mMonthAndDayLayout.addView(mHeaderMonthTextView); } else { // Month View is first - mMonthAndDayLayout.addView(mSelectedMonthTextView); - mMonthAndDayLayout.addView(mSelectedDayTextView); + mMonthAndDayLayout.addView(mHeaderMonthTextView); + mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView); } - mSelectedMonthTextView.setText(mCurrentDate.getDisplayName(Calendar.MONTH, Calendar.SHORT, + mHeaderMonthTextView.setText(mCurrentDate.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault()).toUpperCase(Locale.getDefault())); - mSelectedDayTextView.setText(mDayFormat.format(mCurrentDate.getTime())); - mSelectedYearView.setText(mYearFormat.format(mCurrentDate.getTime())); + mHeaderDayOfMonthTextView.setText(mDayFormat.format(mCurrentDate.getTime())); + mHeaderYearTextView.setText(mYearFormat.format(mCurrentDate.getTime())); // Accessibility. long millis = mCurrentDate.getTimeInMillis(); @@ -362,7 +361,7 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement mDayPickerView.onDateChanged(); if (mCurrentView != viewIndex) { mMonthAndDayLayout.setSelected(true); - mSelectedYearView.setSelected(false); + mHeaderYearTextView.setSelected(false); mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW); mCurrentView = viewIndex; } @@ -374,7 +373,7 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement mAnimator.announceForAccessibility(mSelectDay); break; case YEAR_VIEW: - pulseAnimator = getPulseAnimator(mSelectedYearView, 0.85f, 1.1f); + pulseAnimator = getPulseAnimator(mHeaderYearTextView, 0.85f, 1.1f); if (mDelayAnimation) { pulseAnimator.setStartDelay(ANIMATION_DELAY); mDelayAnimation = false; @@ -382,7 +381,7 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement mYearPickerView.onDateChanged(); if (mCurrentView != viewIndex) { mMonthAndDayLayout.setSelected(false); - mSelectedYearView.setSelected(true); + mHeaderYearTextView.setSelected(true); mAnimator.setDisplayedChild(YEAR_VIEW); mCurrentView = viewIndex; } @@ -509,7 +508,7 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement @Override public void setEnabled(boolean enabled) { mMonthAndDayLayout.setEnabled(enabled); - mSelectedYearView.setEnabled(enabled); + mHeaderYearTextView.setEnabled(enabled); mAnimator.setEnabled(enabled); mIsEnabled = enabled; } @@ -520,123 +519,6 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement } @Override - public void setDateSelectorDayOfWeekBackgroundColor(int color) { - if (mDayOfWeekBackgroundColor != color) { - mDayOfWeekBackgroundColor = color; - mDayOfWeekView.setBackgroundColor(color); - } - } - - @Override - public int getDateSelectorDayOfWeekBackgroundColor() { - return mDayOfWeekBackgroundColor; - } - - @Override - public void setDateSelectorDayOfWeekTextAppearance(int resId) { - if (mDayOfWeekTextAppearanceResId != resId && resId > 0) { - mDayOfWeekTextAppearanceResId = resId; - mDayOfWeekView.setTextAppearance(mContext, resId); - } - } - - @Override - public int getDateSelectorDayOfWeekTextAppearance() { - return mDayOfWeekTextAppearanceResId; - } - - @Override - public void setDateSelectorBackgroundColor(int color) { - if (mMonthAndDayBackgroundColor != color) { - mMonthAndDayBackgroundColor = color; - mMonthAndDayLayout.setBackgroundColor(color); - } - } - - @Override - public int getDateSelectorBackgroundColor() { - return mMonthAndDayBackgroundColor; - } - - @Override - public void setDateSelectorMonthTextAppearance(int resId) { - if (mMonthTextAppearanceResId != resId && resId > 0) { - mMonthTextAppearanceResId = resId; - mSelectedMonthTextView.setTextAppearance(mContext, resId); - } - } - - @Override - public int getDateSelectorMonthTextAppearance() { - return mMonthTextAppearanceResId; - } - - @Override - public void setDateSelectorDayOfMonthTextAppearance(int resId) { - if (mDayOfMonthTextAppearanceResId != resId && resId > 0) { - mDayOfMonthTextAppearanceResId = resId; - mSelectedDayTextView.setTextAppearance(mContext, resId); - } - } - - @Override - public int getDateSelectorDayOfMonthTextAppearance() { - return mDayOfMonthTextAppearanceResId; - } - - @Override - public void setDateSelectorYearTextAppearance(int resId) { - if (mYearTextAppearanceResId != resId && resId > 0) { - mYearTextAppearanceResId = resId; - mSelectedYearView.setTextAppearance(mContext, resId); - } - } - - @Override - public int getDateSelectorYearTextAppearance() { - return mYearTextAppearanceResId; - } - - @Override - public void setDateSelectorYearListItemTextAppearance(int resId) { - if (mYearListItemTextAppearanceResId != resId) { - mYearListItemTextAppearanceResId = resId; - mYearPickerView.setItemTextAppearance(resId); - } - } - - @Override - public int getDateSelectorYearListItemTextAppearance() { - return mYearListItemTextAppearanceResId; - } - - @Override - public void setDateSelectorYearListSelectedCircleColor(int color) { - mYearPickerView.setYearSelectedCircleColor(color); - } - - @Override - public int getDateSelectorYearListSelectedCircleColor() { - return mYearPickerView.getYearSelectedCircleColor(); - } - - @Override - public void setCalendarTextColor(ColorStateList colors) { - if (colors == null) { - return; - } - if (mCalendarTextColors == null || !mCalendarTextColors.equals(colors)) { - mCalendarTextColors = colors; - mDayPickerView.setCalendarTextColor(colors); - } - } - - @Override - public ColorStateList getCalendarTextColors() { - return mCalendarTextColors; - } - - @Override public CalendarView getCalendarView() { throw new UnsupportedOperationException( "CalendarView does not exists for the new DatePicker"); @@ -815,9 +697,8 @@ class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implement } private void updatePickers() { - Iterator<OnDateChangedListener> iterator = mListeners.iterator(); - while (iterator.hasNext()) { - iterator.next().onDateChanged(); + for (OnDateChangedListener listener : mListeners) { + listener.onDateChanged(); } } diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java index 1e30bfa..3d2f67f 100644 --- a/core/java/android/widget/RadialTimePickerView.java +++ b/core/java/android/widget/RadialTimePickerView.java @@ -24,6 +24,7 @@ import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; @@ -104,6 +105,8 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { private static final int CENTER_RADIUS = 2; + private static final int[] STATE_SET_SELECTED = new int[] { R.attr.state_selected }; + private static int[] sSnapPrefer30sMap = new int[361]; private final String[] mHours12Texts = new String[12]; @@ -323,10 +326,20 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimePicker, defStyle, 0); - mAmPmUnselectedColor = a.getColor(R.styleable.TimePicker_amPmUnselectedBackgroundColor, - res.getColor(R.color.timepicker_default_ampm_unselected_background_color_material)); - mAmPmSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor, + ColorStateList amPmBackgroundColor = a.getColorStateList( + R.styleable.TimePicker_amPmBackgroundColor); + if (amPmBackgroundColor == null) { + amPmBackgroundColor = res.getColorStateList( + R.color.timepicker_default_ampm_unselected_background_color_material); + } + + // Obtain the backup selected color. If the background color state + // list doesn't have a state for selected, we'll use this color. + final int amPmSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor, res.getColor(R.color.timepicker_default_ampm_selected_background_color_material)); + mAmPmSelectedColor = amPmBackgroundColor.getColorForState( + STATE_SET_SELECTED, amPmSelectedColor); + mAmPmUnselectedColor = amPmBackgroundColor.getDefaultColor(); mAmPmTextColor = a.getColor(R.styleable.TimePicker_amPmTextColor, res.getColor(R.color.timepicker_default_text_color_material)); diff --git a/core/java/android/widget/TextViewWithCircularIndicator.java b/core/java/android/widget/TextViewWithCircularIndicator.java index 22d770c..43c0843 100644 --- a/core/java/android/widget/TextViewWithCircularIndicator.java +++ b/core/java/android/widget/TextViewWithCircularIndicator.java @@ -50,20 +50,18 @@ class TextViewWithCircularIndicator extends TextView { public TextViewWithCircularIndicator(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs); - Resources res = context.getResources(); + // Use Theme attributes if possible final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.DatePicker, defStyleAttr, defStyleRes); - - final int resId = a.getResourceId( - R.styleable.DatePicker_dateSelectorYearListItemTextAppearance, -1); + final int resId = a.getResourceId(R.styleable.DatePicker_yearListItemTextAppearance, -1); if (resId != -1) { setTextAppearance(context, resId); } + final Resources res = context.getResources(); mItemIsSelectedText = res.getString(R.string.item_is_selected); a.recycle(); diff --git a/core/java/android/widget/TimePickerDelegate.java b/core/java/android/widget/TimePickerDelegate.java index 45be637..c68619c 100644 --- a/core/java/android/widget/TimePickerDelegate.java +++ b/core/java/android/widget/TimePickerDelegate.java @@ -20,6 +20,7 @@ import android.animation.Keyframe; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -79,7 +80,6 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement // Duration in ms of the pulse animation private static final int PULSE_ANIMATOR_DURATION = 544; - private final View mMainView; private TextView mHourView; private TextView mMinuteView; private TextView mAmPmTextView; @@ -88,8 +88,6 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement private ViewGroup mLayoutButtons; - private int mHeaderSelectedColor; - private int mHeaderUnselectedColor; private String mAmText; private String mPmText; @@ -128,7 +126,8 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement // process style attributes final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes); - + final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); final Resources res = mContext.getResources(); mHourPickerDescription = res.getString(R.string.hour_picker_description); @@ -136,53 +135,52 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement mMinutePickerDescription = res.getString(R.string.minute_picker_description); mSelectMinutes = res.getString(R.string.select_minutes); - mHeaderSelectedColor = a.getColor(R.styleable.TimePicker_headerSelectedTextColor, - res.getColor(R.color.timepicker_default_selector_color_material)); - - final int headerTimeTextAppearance = a.getResourceId( - R.styleable.TimePicker_headerTimeTextAppearance, 0); - final int headerAmPmTextAppearance = a.getResourceId( - R.styleable.TimePicker_headerAmPmTextAppearance, 0); - final int headerBackgroundColor = a.getColor( - R.styleable.TimePicker_headerBackgroundColor, Color.TRANSPARENT); - final int layoutResourceId = a.getResourceId( - R.styleable.TimePicker_internalLayout, R.layout.time_picker_holo); - - a.recycle(); - - final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - - mMainView = inflater.inflate(layoutResourceId, null); - mDelegator.addView(mMainView); + final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout, + R.layout.time_picker_holo); + final View mainView = inflater.inflate(layoutResourceId, null); + mDelegator.addView(mainView); - mHourView = (TextView) mMainView.findViewById(R.id.hours); - mSeparatorView = (TextView) mMainView.findViewById(R.id.separator); - mMinuteView = (TextView) mMainView.findViewById(R.id.minutes); - mAmPmTextView = (TextView) mMainView.findViewById(R.id.ampm_label); - mLayoutButtons = (ViewGroup) mMainView.findViewById(R.id.layout_buttons); + mHourView = (TextView) mainView.findViewById(R.id.hours); + mSeparatorView = (TextView) mainView.findViewById(R.id.separator); + mMinuteView = (TextView) mainView.findViewById(R.id.minutes); + mAmPmTextView = (TextView) mainView.findViewById(R.id.ampm_label); + mLayoutButtons = (ViewGroup) mainView.findViewById(R.id.layout_buttons); // Set up text appearances from style. + final int headerTimeTextAppearance = a.getResourceId( + R.styleable.TimePicker_headerTimeTextAppearance, 0); if (headerTimeTextAppearance != 0) { mHourView.setTextAppearance(context, headerTimeTextAppearance); mSeparatorView.setTextAppearance(context, headerTimeTextAppearance); mMinuteView.setTextAppearance(context, headerTimeTextAppearance); } + final int headerSelectedTextColor = a.getColor( + R.styleable.TimePicker_headerSelectedTextColor, + res.getColor(R.color.timepicker_default_selector_color_material)); + mHourView.setTextColor(ColorStateList.addFirstIfMissing(mHourView.getTextColors(), + R.attr.state_selected, headerSelectedTextColor)); + mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(), + R.attr.state_selected, headerSelectedTextColor)); + + final int headerAmPmTextAppearance = a.getResourceId( + R.styleable.TimePicker_headerAmPmTextAppearance, 0); if (headerAmPmTextAppearance != 0) { mAmPmTextView.setTextAppearance(context, headerAmPmTextAppearance); } + final int headerBackgroundColor = a.getColor( + R.styleable.TimePicker_headerBackgroundColor, Color.TRANSPARENT); if (headerBackgroundColor != Color.TRANSPARENT) { mLayoutButtons.setBackgroundColor(headerBackgroundColor); - mMainView.findViewById(R.id.time_header).setBackgroundColor(headerBackgroundColor); + mainView.findViewById(R.id.time_header).setBackgroundColor(headerBackgroundColor); } - // Load unselected header color from current state. - mHeaderUnselectedColor = mHourView.getCurrentTextColor(); + a.recycle(); - mRadialTimePickerView = (RadialTimePickerView) mMainView.findViewById(R.id.radial_picker); - mDoneButton = (Button) mMainView.findViewById(R.id.done_button); + mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById( + R.id.radial_picker); + mDoneButton = (Button) mainView.findViewById(R.id.done_button); String[] amPmTexts = new DateFormatSymbols().getAmPmStrings(); mAmText = amPmTexts[0]; @@ -785,7 +783,6 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1)); } mSeparatorView.setText(separatorText); - mSeparatorView.setTextColor(mHeaderUnselectedColor); } static private int lastIndexOfAny(String str, char[] any) { @@ -839,10 +836,8 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement labelToAnimate = mMinuteView; } - int hourColor = (index == HOUR_INDEX) ? mHeaderSelectedColor : mHeaderUnselectedColor; - int minuteColor = (index == MINUTE_INDEX) ? mHeaderSelectedColor : mHeaderUnselectedColor; - mHourView.setTextColor(hourColor); - mMinuteView.setTextColor(minuteColor); + mHourView.setSelected(index == HOUR_INDEX); + mMinuteView.setSelected(index == MINUTE_INDEX); ObjectAnimator pulseAnimator = getPulseAnimator(labelToAnimate, 0.85f, 1.1f); if (delayLabelAnimate) { @@ -1064,9 +1059,9 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement String minuteStr = (values[1] == -1) ? mDoublePlaceholderText : String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText); mHourView.setText(hourStr); - mHourView.setTextColor(mHeaderUnselectedColor); + mHourView.setSelected(false); mMinuteView.setText(minuteStr); - mMinuteView.setTextColor(mHeaderUnselectedColor); + mMinuteView.setSelected(false); if (!mIs24HourView) { updateAmPmDisplay(values[2]); } @@ -1143,8 +1138,7 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement } } - int[] ret = {hour, minute, amOrPm}; - return ret; + return new int[] { hour, minute, amOrPm }; } /** diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java index bac9320..b67fa55 100644 --- a/core/java/android/widget/YearPickerView.java +++ b/core/java/android/widget/YearPickerView.java @@ -33,8 +33,6 @@ import com.android.internal.R; */ class YearPickerView extends ListView implements AdapterView.OnItemClickListener, OnDateChangedListener { - private static final String TAG = "YearPickerView"; - private DatePickerController mController; private YearAdapter mAdapter; private int mViewSize; @@ -57,11 +55,11 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - ViewGroup.LayoutParams frame = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.WRAP_CONTENT); + final LayoutParams frame = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); setLayoutParams(frame); - Resources res = context.getResources(); + final Resources res = context.getResources(); mViewSize = res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height); mChildSize = res.getDimensionPixelOffset(R.dimen.datepicker_year_label_height); @@ -73,11 +71,9 @@ class YearPickerView extends ListView implements AdapterView.OnItemClickListener setPadding(0, paddingTop, 0, 0); // Use Theme attributes if possible - final TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.DatePicker, defStyleAttr, defStyleRes); - - final int colorResId = a.getResourceId( - R.styleable.DatePicker_dateSelectorYearListSelectedCircleColor, + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.DatePicker, defStyleAttr, defStyleRes); + final int colorResId = a.getResourceId(R.styleable.DatePicker_yearListSelectorColor, R.color.datepicker_default_circle_background_color_holo_light); mYearSelectedCircleColor = res.getColor(colorResId); |