2929import android .content .res .ColorStateList ;
3030import android .content .res .Resources ;
3131import android .content .res .TypedArray ;
32+ import android .graphics .Outline ;
3233import android .graphics .RadialGradient ;
3334import android .graphics .Rect ;
3435import android .graphics .RectF ;
3940import android .util .AttributeSet ;
4041import android .util .DisplayMetrics ;
4142import android .util .SparseArray ;
43+ import android .view .KeyEvent ;
4244import android .view .LayoutInflater ;
4345import android .view .MotionEvent ;
4446import android .view .View ;
47+ import android .view .ViewOutlineProvider ;
4548import android .view .ViewTreeObserver .OnPreDrawListener ;
4649import android .view .accessibility .AccessibilityNodeInfo ;
4750import android .widget .TextView ;
@@ -92,6 +95,8 @@ class ClockFaceView extends RadialViewGroup implements OnRotateListener {
9295
9396 private final ColorStateList textColor ;
9497
98+ private OnEnterKeyPressedListener onEnterKeyPressedListener ;
99+
95100 public ClockFaceView (@ NonNull Context context ) {
96101 this (context , null );
97102 }
@@ -150,8 +155,18 @@ public boolean onPreDraw() {
150155 }
151156 });
152157
153- setFocusable (false );
154158 a .recycle ();
159+
160+ setOutlineProvider (
161+ new ViewOutlineProvider () {
162+ @ Override
163+ public void getOutline (View view , Outline outline ) {
164+ outline .setOval (0 , 0 , view .getWidth (), view .getHeight ());
165+ }
166+ });
167+ setFocusable (true );
168+ setClipToOutline (true );
169+
155170 valueAccessibilityDelegate =
156171 new AccessibilityDelegateCompat () {
157172 @ Override
@@ -167,7 +182,7 @@ public void onInitializeAccessibilityNodeInfo(
167182 CollectionItemInfoCompat .obtain (
168183 /* rowIndex= */ 0 ,
169184 /* rowSpan= */ 1 ,
170- /* columnIndex = */ index ,
185+ /* columnIndex= */ index ,
171186 /* columnSpan= */ 1 ,
172187 /* heading= */ false ,
173188 /* selected= */ host .isSelected ()));
@@ -375,6 +390,57 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
375390 super .onMeasure (spec , spec );
376391 }
377392
393+ private int getSelectedIndex () {
394+ for (int i = 0 ; i < textViewPool .size (); i ++) {
395+ TextView textView = textViewPool .valueAt (i );
396+ if (textView .isSelected ()) {
397+ return (int ) textView .getTag (R .id .material_value_index );
398+ }
399+ }
400+ return -1 ;
401+ }
402+
403+ @ Override
404+ public boolean onKeyDown (int keyCode , KeyEvent event ) {
405+ int selectedIndex = getSelectedIndex ();
406+ if (!isShown () || selectedIndex == -1 ) {
407+ return super .onKeyDown (keyCode , event );
408+ }
409+
410+ int nextIndex ;
411+ switch (keyCode ) {
412+ case KeyEvent .KEYCODE_DPAD_RIGHT :
413+ case KeyEvent .KEYCODE_DPAD_UP :
414+ nextIndex = (selectedIndex + 1 ) % values .length ;
415+ break ;
416+ case KeyEvent .KEYCODE_DPAD_LEFT :
417+ case KeyEvent .KEYCODE_DPAD_DOWN :
418+ nextIndex = (selectedIndex - 1 + values .length ) % values .length ;
419+ break ;
420+ case KeyEvent .KEYCODE_ENTER :
421+ case KeyEvent .KEYCODE_DPAD_CENTER :
422+ if (onEnterKeyPressedListener != null ) {
423+ onEnterKeyPressedListener .onEnterKeyPressed ();
424+ }
425+ return true ;
426+ default :
427+ return super .onKeyDown (keyCode , event );
428+ }
429+
430+ if (nextIndex != selectedIndex ) {
431+ int level = (nextIndex / INITIAL_CAPACITY ) + LEVEL_1 ;
432+ if (level != getCurrentLevel ()) {
433+ setCurrentLevel (level );
434+ }
435+
436+ float rotation = (nextIndex % INITIAL_CAPACITY ) * (360f / INITIAL_CAPACITY );
437+ setHandRotation (rotation );
438+ return true ;
439+ }
440+
441+ return super .onKeyDown (keyCode , event );
442+ }
443+
378444 private static float max3 (float a , float b , float c ) {
379445 return max (max (a , b ), c );
380446 }
@@ -387,4 +453,14 @@ int getCurrentLevel() {
387453 void setCurrentLevel (@ Level int level ) {
388454 clockHandView .setCurrentLevel (level );
389455 }
456+
457+ public void setOnEnterKeyPressedListener (OnEnterKeyPressedListener onEnterKeyPressedListener ) {
458+ this .onEnterKeyPressedListener = onEnterKeyPressedListener ;
459+ }
460+
461+ /** Listener interface for enter key press events on the clock face. */
462+ interface OnEnterKeyPressedListener {
463+ /** Called when the enter key is pressed. */
464+ void onEnterKeyPressed ();
465+ }
390466}
0 commit comments