From acc4c506236dac0b67b4d7dd0994fde965dfea67 Mon Sep 17 00:00:00 2001 From: FongMi Date: Sat, 3 Sep 2022 00:30:03 +0800 Subject: [PATCH] Update Search UI --- .../tv/ui/activity/SearchActivity.java | 71 +++----------- .../tv/ui/adapter/KeyboardAdapter.java | 2 +- .../android/tv/ui/custom/CustomKeyDown.java | 10 +- .../android/tv/ui/custom/CustomKeyboard.java | 10 +- .../android/tv/ui/custom/CustomMic.java | 71 ++++++++++++++ .../android/tv/ui/custom/CustomTitleView.java | 6 +- .../res/drawable/ic_keyboard_space.xml | 10 ++ .../{ic_keyboard_voice.xml => ic_mic.xml} | 4 +- .../leanback/res/drawable/selector_mic.xml | 5 - .../res/drawable/shape_mic_focused.xml | 11 --- .../res/drawable/shape_mic_normal.xml | 7 -- .../leanback/res/layout/activity_search.xml | 96 +++++++++---------- .../leanback/res/values-zh-rCN/strings.xml | 6 +- .../leanback/res/values-zh-rTW/strings.xml | 6 +- .../com/fongmi/android/tv/utils/Utils.java | 4 + 15 files changed, 166 insertions(+), 153 deletions(-) create mode 100644 app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomMic.java create mode 100644 app/src/leanback/res/drawable/ic_keyboard_space.xml rename app/src/leanback/res/drawable/{ic_keyboard_voice.xml => ic_mic.xml} (94%) delete mode 100644 app/src/leanback/res/drawable/selector_mic.xml delete mode 100644 app/src/leanback/res/drawable/shape_mic_focused.xml delete mode 100644 app/src/leanback/res/drawable/shape_mic_normal.xml diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SearchActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SearchActivity.java index 95633471e..d3890c9c3 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SearchActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SearchActivity.java @@ -6,15 +6,11 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.os.Handler; import android.os.Looper; -import android.speech.RecognizerIntent; -import android.speech.SpeechRecognizer; import android.text.Editable; import android.text.TextUtils; import android.view.View; -import android.view.animation.Animation; import android.view.inputmethod.EditorInfo; -import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; @@ -31,7 +27,6 @@ import com.fongmi.android.tv.ui.adapter.WordAdapter; import com.fongmi.android.tv.ui.custom.CustomKeyboard; import com.fongmi.android.tv.ui.custom.CustomListener; import com.fongmi.android.tv.ui.custom.SpaceItemDecoration; -import com.fongmi.android.tv.utils.ResUtil; import com.fongmi.android.tv.utils.Utils; import java.io.IOException; @@ -42,13 +37,9 @@ import okhttp3.Response; public class SearchActivity extends BaseActivity implements WordAdapter.OnClickListener, HistoryAdapter.OnClickListener, CustomKeyboard.Callback { - private final ActivityResultLauncher launcher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> startListening()); - private ActivitySearchBinding mBinding; - private SpeechRecognizer mRecognizer; private HistoryAdapter mHistoryAdapter; private WordAdapter mWordAdapter; - private Animation mFlicker; private Handler mHandler; public static void start(Activity activity) { @@ -62,9 +53,7 @@ public class SearchActivity extends BaseActivity implements WordAdapter.OnClickL @Override protected void initView() { - mFlicker = ResUtil.getAnim(R.anim.flicker); mHandler = new Handler(Looper.getMainLooper()); - mRecognizer = SpeechRecognizer.createSpeechRecognizer(this); CustomKeyboard.init(this, mBinding); setRecyclerView(); getHot(); @@ -72,6 +61,7 @@ public class SearchActivity extends BaseActivity implements WordAdapter.OnClickL @Override protected void initEvent() { + mBinding.mic.setOnClickListener(view -> onMic()); mBinding.keyword.setOnEditorActionListener((textView, actionId, event) -> { if (actionId == EditorInfo.IME_ACTION_DONE) onSearch(); return true; @@ -83,10 +73,10 @@ public class SearchActivity extends BaseActivity implements WordAdapter.OnClickL else getSuggest(s.toString()); } }); - mRecognizer.setRecognitionListener(new CustomListener() { + mBinding.mic.setListener(new CustomListener() { @Override public void onResults(String result) { - stopListening(); + mBinding.mic.stop(); mBinding.keyword.setText(result); mBinding.keyword.setSelection(mBinding.keyword.length()); } @@ -124,6 +114,14 @@ public class SearchActivity extends BaseActivity implements WordAdapter.OnClickL }); } + public void onMic() { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> mBinding.mic.start()).launch(Manifest.permission.RECORD_AUDIO); + } else { + mBinding.mic.start(); + } + } + @Override public void onItemClick(String text) { mBinding.keyword.setText(text); @@ -150,56 +148,9 @@ public class SearchActivity extends BaseActivity implements WordAdapter.OnClickL PushActivity.start(this); } - @Override - public void onVoice() { - if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { - launcher.launch(Manifest.permission.RECORD_AUDIO); - } else { - startListening(); - } - } - - private void startListening() { - Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); - intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); - mBinding.keyboard.setVisibility(View.INVISIBLE); - mBinding.voice.setVisibility(View.VISIBLE); - mBinding.voice.startAnimation(mFlicker); - mRecognizer.startListening(intent); - } - - private void stopListening() { - mBinding.keyboard.setVisibility(View.VISIBLE); - mBinding.voice.setVisibility(View.GONE); - mBinding.voice.clearAnimation(); - mRecognizer.stopListening(); - } - - private void destroyRecognizer() { - try { - mRecognizer.destroy(); - } catch (Exception ignored) { - } - } - @Override protected void onResume() { super.onResume(); mBinding.keyword.requestFocus(); } - - @Override - public void onBackPressed() { - if (mBinding.voice.getVisibility() == View.VISIBLE) { - stopListening(); - } else { - super.onBackPressed(); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - destroyRecognizer(); - } } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/adapter/KeyboardAdapter.java b/app/src/leanback/java/com/fongmi/android/tv/ui/adapter/KeyboardAdapter.java index a563d8d26..450bd78c6 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/adapter/KeyboardAdapter.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/adapter/KeyboardAdapter.java @@ -20,7 +20,7 @@ public class KeyboardAdapter extends RecyclerView.Adapter mItems; public KeyboardAdapter(OnClickListener listener) { - this.mItems = Arrays.asList(R.drawable.ic_keyboard_remote, R.drawable.ic_keyboard_voice, R.drawable.ic_keyboard_left, R.drawable.ic_keyboard_right, R.drawable.ic_keyboard_back, R.drawable.ic_keyboard_search, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); + this.mItems = Arrays.asList(R.drawable.ic_keyboard_remote, R.drawable.ic_keyboard_left, R.drawable.ic_keyboard_space, R.drawable.ic_keyboard_right, R.drawable.ic_keyboard_back, R.drawable.ic_keyboard_search, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); this.mListener = listener; } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyDown.java b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyDown.java index 9d89dcc92..d5102a3b6 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyDown.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyDown.java @@ -7,7 +7,7 @@ import com.fongmi.android.tv.utils.Utils; public class CustomKeyDown { private final Listener mListener; - private int mHoldTime; + private int holdTime; public static CustomKeyDown create(Listener listener) { return new CustomKeyDown(listener); @@ -21,7 +21,7 @@ public class CustomKeyDown { if (event.getAction() == KeyEvent.ACTION_DOWN && (Utils.isLeftKey(event) || Utils.isRightKey(event))) { mListener.onSeeking(Utils.isRightKey(event) ? addTime() : subTime()); } else if (event.getAction() == KeyEvent.ACTION_UP && (Utils.isLeftKey(event) || Utils.isRightKey(event))) { - mListener.onSeekTo(mHoldTime); + mListener.onSeekTo(holdTime); } else if (event.getAction() == KeyEvent.ACTION_UP && Utils.isDownKey(event)) { mListener.onKeyDown(); } else if (event.getAction() == KeyEvent.ACTION_UP && Utils.isEnterKey(event)) { @@ -31,15 +31,15 @@ public class CustomKeyDown { } private int addTime() { - return mHoldTime = mHoldTime + 10000; + return holdTime = holdTime + 10000; } private int subTime() { - return mHoldTime = mHoldTime - 10000; + return holdTime = holdTime - 10000; } public void resetTime() { - mHoldTime = 0; + holdTime = 0; } public boolean hasEvent(KeyEvent event) { diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyboard.java b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyboard.java index 012b2b7c4..243e85dda 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyboard.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomKeyboard.java @@ -42,6 +42,11 @@ public class CustomKeyboard implements KeyboardAdapter.OnClickListener { StringBuilder sb = new StringBuilder(binding.keyword.getText().toString()); int cursor = binding.keyword.getSelectionStart(); switch (resId) { + case R.drawable.ic_keyboard_space: + sb.insert(cursor, " "); + binding.keyword.setText(sb.toString()); + binding.keyword.setSelection(cursor + 1); + break; case R.drawable.ic_keyboard_left: binding.keyword.setSelection(--cursor < 0 ? 0 : cursor); break; @@ -54,9 +59,6 @@ public class CustomKeyboard implements KeyboardAdapter.OnClickListener { binding.keyword.setText(sb.toString()); binding.keyword.setSelection(cursor - 1); break; - case R.drawable.ic_keyboard_voice: - callback.onVoice(); - break; case R.drawable.ic_keyboard_remote: callback.onRemote(); break; @@ -75,8 +77,6 @@ public class CustomKeyboard implements KeyboardAdapter.OnClickListener { public interface Callback { - void onVoice(); - void onRemote(); void onSearch(); diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomMic.java b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomMic.java new file mode 100644 index 000000000..da45cccff --- /dev/null +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomMic.java @@ -0,0 +1,71 @@ +package com.fongmi.android.tv.ui.custom; + +import android.content.Context; +import android.content.Intent; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.speech.RecognizerIntent; +import android.speech.SpeechRecognizer; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.animation.Animation; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + +import com.fongmi.android.tv.R; +import com.fongmi.android.tv.utils.ResUtil; +import com.fongmi.android.tv.utils.Utils; +import com.github.bassaer.library.MDColor; + +public class CustomMic extends AppCompatImageView { + + private SpeechRecognizer recognizer; + private Animation flicker; + + public CustomMic(@NonNull Context context) { + super(context); + } + + public CustomMic(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + private void initView(Context context) { + flicker = ResUtil.getAnim(R.anim.flicker); + recognizer = SpeechRecognizer.createSpeechRecognizer(context); + } + + public void setListener(CustomListener listener) { + recognizer.setRecognitionListener(listener); + } + + public void start() { + Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + setColorFilter(MDColor.RED_500, PorterDuff.Mode.SRC_IN); + recognizer.startListening(intent); + } + + public boolean stop() { + setColorFilter(MDColor.WHITE, PorterDuff.Mode.SRC_IN); + recognizer.stopListening(); + clearAnimation(); + return true; + } + + @Override + protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) { + super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); + if (gainFocus) startAnimation(flicker); + else stop(); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (Utils.isBackKey(event) && event.getAction() == KeyEvent.ACTION_UP) return stop(); + else return super.dispatchKeyEvent(event); + } +} diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomTitleView.java b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomTitleView.java index d366324f1..d6793c59c 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomTitleView.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/custom/CustomTitleView.java @@ -22,7 +22,7 @@ import java.util.List; public class CustomTitleView extends AppCompatTextView { private Listener mListener; - private Animation mFlicker; + private Animation flicker; public CustomTitleView(@NonNull Context context) { super(context); @@ -30,7 +30,7 @@ public class CustomTitleView extends AppCompatTextView { public CustomTitleView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - mFlicker = ResUtil.getAnim(R.anim.flicker); + flicker = ResUtil.getAnim(R.anim.flicker); } public void setListener(Listener listener) { @@ -40,7 +40,7 @@ public class CustomTitleView extends AppCompatTextView { @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(focused, direction, previouslyFocusedRect); - if (focused) startAnimation(mFlicker); + if (focused) startAnimation(flicker); else clearAnimation(); } diff --git a/app/src/leanback/res/drawable/ic_keyboard_space.xml b/app/src/leanback/res/drawable/ic_keyboard_space.xml new file mode 100644 index 000000000..7dbdbe636 --- /dev/null +++ b/app/src/leanback/res/drawable/ic_keyboard_space.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/leanback/res/drawable/ic_keyboard_voice.xml b/app/src/leanback/res/drawable/ic_mic.xml similarity index 94% rename from app/src/leanback/res/drawable/ic_keyboard_voice.xml rename to app/src/leanback/res/drawable/ic_mic.xml index a0c349844..448243a30 100644 --- a/app/src/leanback/res/drawable/ic_keyboard_voice.xml +++ b/app/src/leanback/res/drawable/ic_mic.xml @@ -1,6 +1,6 @@ diff --git a/app/src/leanback/res/drawable/selector_mic.xml b/app/src/leanback/res/drawable/selector_mic.xml deleted file mode 100644 index 1831bdc4c..000000000 --- a/app/src/leanback/res/drawable/selector_mic.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/leanback/res/drawable/shape_mic_focused.xml b/app/src/leanback/res/drawable/shape_mic_focused.xml deleted file mode 100644 index d401aa080..000000000 --- a/app/src/leanback/res/drawable/shape_mic_focused.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/leanback/res/drawable/shape_mic_normal.xml b/app/src/leanback/res/drawable/shape_mic_normal.xml deleted file mode 100644 index 28c38c1da..000000000 --- a/app/src/leanback/res/drawable/shape_mic_normal.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/leanback/res/layout/activity_search.xml b/app/src/leanback/res/layout/activity_search.xml index f9359d34f..1cccdf073 100644 --- a/app/src/leanback/res/layout/activity_search.xml +++ b/app/src/leanback/res/layout/activity_search.xml @@ -11,58 +11,11 @@ android:paddingTop="24dp" android:paddingEnd="24dp"> - - - - - - - - - - - - - + + + + + + + + + + 关键字… - 历史纪录 - 建议搜索 - 热门搜索 + 历史 + 建议 + 热搜 %s”的搜索结果 diff --git a/app/src/leanback/res/values-zh-rTW/strings.xml b/app/src/leanback/res/values-zh-rTW/strings.xml index 6fe9588f6..23132b0b8 100644 --- a/app/src/leanback/res/values-zh-rTW/strings.xml +++ b/app/src/leanback/res/values-zh-rTW/strings.xml @@ -11,9 +11,9 @@ 關鍵字… - 歷史紀錄 - 建議搜尋 - 熱門搜尋 + 歷史 + 建議 + 熱搜 %s」的搜尋結果 diff --git a/app/src/main/java/com/fongmi/android/tv/utils/Utils.java b/app/src/main/java/com/fongmi/android/tv/utils/Utils.java index f05875246..19df93a70 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/Utils.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/Utils.java @@ -36,6 +36,10 @@ public class Utils { return event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT; } + public static boolean isBackKey(KeyEvent event) { + return event.getKeyCode() == KeyEvent.KEYCODE_BACK; + } + public static void hideSystemUI(Activity activity) { int flags = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; activity.getWindow().getDecorView().setSystemUiVisibility(flags);