Add support for seconds hand to AnalogClock
Bug: 177997338 Test: manual - wrote app to use runtime apis Change-Id: I05b3ebb19598a4f1d605f9ba62005aaab733666d Merged-In: I05b3ebb19598a4f1d605f9ba62005aaab733666d
This commit is contained in:
@@ -722,6 +722,7 @@ package android {
|
||||
field public static final int gwpAsanMode = 16844310; // 0x1010616
|
||||
field public static final int hand_hour = 16843011; // 0x1010103
|
||||
field public static final int hand_minute = 16843012; // 0x1010104
|
||||
field public static final int hand_second = 16844323; // 0x1010623
|
||||
field public static final int handle = 16843354; // 0x101025a
|
||||
field public static final int handleProfiling = 16842786; // 0x1010022
|
||||
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
|
||||
@@ -53058,6 +53059,10 @@ package android.widget {
|
||||
ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet);
|
||||
ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet, int);
|
||||
ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet, int, int);
|
||||
method @Deprecated public void setDial(@NonNull android.graphics.drawable.Icon);
|
||||
method @Deprecated public void setHourHand(@NonNull android.graphics.drawable.Icon);
|
||||
method @Deprecated public void setMinuteHand(@NonNull android.graphics.drawable.Icon);
|
||||
method @Deprecated public void setSecondHand(@Nullable android.graphics.drawable.Icon);
|
||||
}
|
||||
|
||||
public class ArrayAdapter<T> extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.widget;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -25,8 +27,10 @@ import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.RemotableViewMethod;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews.RemoteView;
|
||||
|
||||
@@ -42,25 +46,32 @@ import java.time.ZoneId;
|
||||
* @attr ref android.R.styleable#AnalogClock_dial
|
||||
* @attr ref android.R.styleable#AnalogClock_hand_hour
|
||||
* @attr ref android.R.styleable#AnalogClock_hand_minute
|
||||
* @attr ref android.R.styleable#AnalogClock_hand_second
|
||||
* @deprecated This widget is no longer supported.
|
||||
*/
|
||||
@RemoteView
|
||||
@Deprecated
|
||||
public class AnalogClock extends View {
|
||||
/** How often the clock should refresh to make the seconds hand advance at ~15 FPS. */
|
||||
private static final long SECONDS_TICK_FREQUENCY_MS = 1000 / 15;
|
||||
|
||||
private Clock mClock;
|
||||
|
||||
@UnsupportedAppUsage
|
||||
private Drawable mHourHand;
|
||||
@UnsupportedAppUsage
|
||||
private Drawable mMinuteHand;
|
||||
@Nullable
|
||||
private Drawable mSecondHand;
|
||||
@UnsupportedAppUsage
|
||||
private Drawable mDial;
|
||||
|
||||
private int mDialWidth;
|
||||
private int mDialHeight;
|
||||
|
||||
private boolean mAttached;
|
||||
private boolean mVisible;
|
||||
|
||||
private float mSeconds;
|
||||
private float mMinutes;
|
||||
private float mHour;
|
||||
private boolean mChanged;
|
||||
@@ -101,18 +112,70 @@ public class AnalogClock extends View {
|
||||
mMinuteHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_minute);
|
||||
}
|
||||
|
||||
mSecondHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_second);
|
||||
|
||||
mClock = Clock.systemDefaultZone();
|
||||
|
||||
mDialWidth = mDial.getIntrinsicWidth();
|
||||
mDialHeight = mDial.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
/** Sets the dial of the clock to the specified Icon. */
|
||||
@RemotableViewMethod
|
||||
public void setDial(@NonNull Icon icon) {
|
||||
mDial = icon.loadDrawable(getContext());
|
||||
mDialWidth = mDial.getIntrinsicWidth();
|
||||
mDialHeight = mDial.getIntrinsicHeight();
|
||||
|
||||
if (!mAttached) {
|
||||
mAttached = true;
|
||||
mChanged = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/** Sets the hour hand of the clock to the specified Icon. */
|
||||
@RemotableViewMethod
|
||||
public void setHourHand(@NonNull Icon icon) {
|
||||
mHourHand = icon.loadDrawable(getContext());
|
||||
|
||||
mChanged = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/** Sets the minute hand of the clock to the specified Icon. */
|
||||
@RemotableViewMethod
|
||||
public void setMinuteHand(@NonNull Icon icon) {
|
||||
mMinuteHand = icon.loadDrawable(getContext());
|
||||
|
||||
mChanged = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the second hand of the clock to the specified Icon, or hides the second hand if it is
|
||||
* null.
|
||||
*/
|
||||
@RemotableViewMethod
|
||||
public void setSecondHand(@Nullable Icon icon) {
|
||||
mSecondHand = icon == null ? null : icon.loadDrawable(getContext());
|
||||
mSecondsTick.run();
|
||||
|
||||
mChanged = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibilityAggregated(boolean isVisible) {
|
||||
super.onVisibilityAggregated(isVisible);
|
||||
|
||||
if (isVisible) {
|
||||
onVisible();
|
||||
} else {
|
||||
onInvisible();
|
||||
}
|
||||
}
|
||||
|
||||
private void onVisible() {
|
||||
if (!mVisible) {
|
||||
mVisible = true;
|
||||
IntentFilter filter = new IntentFilter();
|
||||
|
||||
filter.addAction(Intent.ACTION_TIME_TICK);
|
||||
@@ -128,6 +191,8 @@ public class AnalogClock extends View {
|
||||
// user not the one the context is for.
|
||||
getContext().registerReceiverAsUser(mIntentReceiver,
|
||||
android.os.Process.myUserHandle(), filter, null, getHandler());
|
||||
|
||||
mSecondsTick.run();
|
||||
}
|
||||
|
||||
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
|
||||
@@ -140,12 +205,11 @@ public class AnalogClock extends View {
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
if (mAttached) {
|
||||
private void onInvisible() {
|
||||
if (mVisible) {
|
||||
getContext().unregisterReceiver(mIntentReceiver);
|
||||
mAttached = false;
|
||||
removeCallbacks(mSecondsTick);
|
||||
mVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +301,20 @@ public class AnalogClock extends View {
|
||||
minuteHand.draw(canvas);
|
||||
canvas.restore();
|
||||
|
||||
final Drawable secondHand = mSecondHand;
|
||||
if (secondHand != null) {
|
||||
canvas.save();
|
||||
canvas.rotate(mSeconds / 60.0f * 360.0f, x, y);
|
||||
|
||||
if (changed) {
|
||||
w = secondHand.getIntrinsicWidth();
|
||||
h = secondHand.getIntrinsicHeight();
|
||||
secondHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
|
||||
}
|
||||
secondHand.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
if (scaled) {
|
||||
canvas.restore();
|
||||
}
|
||||
@@ -250,6 +328,7 @@ public class AnalogClock extends View {
|
||||
int minute = localDateTime.getMinute();
|
||||
int second = localDateTime.getSecond();
|
||||
|
||||
mSeconds = second + localDateTime.getNano() / 1_000_000_000f;
|
||||
mMinutes = minute + second / 60.0f;
|
||||
mHour = hour + mMinutes / 60.0f;
|
||||
mChanged = true;
|
||||
@@ -271,6 +350,21 @@ public class AnalogClock extends View {
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mSecondsTick = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!mVisible || mSecondHand == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
onTimeChanged();
|
||||
|
||||
invalidate();
|
||||
|
||||
postDelayed(this, SECONDS_TICK_FREQUENCY_MS);
|
||||
}
|
||||
};
|
||||
|
||||
private void updateContentDescription(long timeMillis) {
|
||||
final int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR;
|
||||
String contentDescription = DateUtils.formatDateTime(mContext, timeMillis, flags);
|
||||
|
||||
@@ -4069,6 +4069,7 @@
|
||||
<attr name="dial" format="reference"/>
|
||||
<attr name="hand_hour" format="reference"/>
|
||||
<attr name="hand_minute" format="reference"/>
|
||||
<attr name="hand_second" format="reference"/>
|
||||
</declare-styleable>
|
||||
<declare-styleable name="Button">
|
||||
</declare-styleable>
|
||||
|
||||
@@ -3059,6 +3059,7 @@
|
||||
<public name="pathAdvancedPattern" />
|
||||
<public name="sspAdvancedPattern" />
|
||||
<public name="fontProviderSystemFontFamily" />
|
||||
<public name="hand_second" />
|
||||
</public-group>
|
||||
|
||||
<public-group type="drawable" first-id="0x010800b5">
|
||||
|
||||
Reference in New Issue
Block a user