1 package androidx.leanback.widget; 2 3 import android.content.Context; 4 import android.content.res.Resources; 5 import android.graphics.Color; 6 import android.util.AttributeSet; 7 8 import androidx.leanback.R; 9 10 /** 11 * A subclass of {@link SearchOrbView} that visualizes the state of an ongoing speech recognition. 12 */ 13 public class SpeechOrbView extends SearchOrbView { 14 private final float mSoundLevelMaxZoom; 15 private Colors mListeningOrbColors; 16 private Colors mNotListeningOrbColors; 17 18 private int mCurrentLevel = 0; 19 private boolean mListening = false; 20 21 public SpeechOrbView(Context context) { 22 this(context, null); 23 } 24 25 public SpeechOrbView(Context context, AttributeSet attrs) { 26 this(context, attrs, 0); 27 } 28 29 public SpeechOrbView(Context context, AttributeSet attrs, int defStyle) { 30 super(context, attrs, defStyle); 31 32 Resources resources = context.getResources(); 33 mSoundLevelMaxZoom = 34 resources.getFraction(R.fraction.lb_search_bar_speech_orb_max_level_zoom, 1, 1); 35 36 mNotListeningOrbColors = new Colors(resources.getColor(R.color.lb_speech_orb_not_recording), 37 resources.getColor(R.color.lb_speech_orb_not_recording_pulsed), 38 resources.getColor(R.color.lb_speech_orb_not_recording_icon)); 39 mListeningOrbColors = new Colors(resources.getColor(R.color.lb_speech_orb_recording), 40 resources.getColor(R.color.lb_speech_orb_recording), 41 Color.TRANSPARENT); 42 43 showNotListening(); 44 } 45 46 @Override 47 int getLayoutResourceId() { 48 return R.layout.lb_speech_orb; 49 } 50 51 /** 52 * Sets default listening state orb color. 53 * 54 * @param colors SearchOrbView.Colors. 55 */ 56 public void setListeningOrbColors(Colors colors) { 57 mListeningOrbColors = colors; 58 } 59 60 /** 61 * Sets default not-listening state orb color. 62 * 63 * @param colors SearchOrbView.Colors. 64 */ 65 public void setNotListeningOrbColors(Colors colors) { 66 mNotListeningOrbColors = colors; 67 } 68 69 /** 70 * Sets the view to display listening state. 71 */ 72 public void showListening() { 73 setOrbColors(mListeningOrbColors); 74 setOrbIcon(getResources().getDrawable(R.drawable.lb_ic_search_mic)); 75 // Assume focused 76 animateOnFocus(true); 77 enableOrbColorAnimation(false); 78 scaleOrbViewOnly(1f); 79 mCurrentLevel = 0; 80 mListening = true; 81 } 82 83 /** 84 * Sets the view to display the not-listening state. 85 */ 86 public void showNotListening() { 87 setOrbColors(mNotListeningOrbColors); 88 setOrbIcon(getResources().getDrawable(R.drawable.lb_ic_search_mic_out)); 89 animateOnFocus(hasFocus()); 90 scaleOrbViewOnly(1f); 91 mListening = false; 92 } 93 94 /** 95 * Sets the sound level while listening to speech. 96 */ 97 public void setSoundLevel(int level) { 98 if (!mListening) return; 99 100 // Either ease towards the target level, or decay away from it depending on whether 101 // its higher or lower than the current. 102 if (level > mCurrentLevel) { 103 mCurrentLevel = mCurrentLevel + ((level - mCurrentLevel) / 2); 104 } else { 105 mCurrentLevel = (int) (mCurrentLevel * 0.7f); 106 } 107 108 float zoom = 1f + (mSoundLevelMaxZoom - getFocusedZoom()) * mCurrentLevel / 100; 109 110 scaleOrbViewOnly(zoom); 111 } 112 } 113