From 7ba591aebf2d51b6c9eaf203cc676714314dc8fb Mon Sep 17 00:00:00 2001 From: falzonv Date: Mon, 12 Jul 2021 22:11:47 +0200 Subject: [PATCH] Rollback the search to a PopupWindow --- app/src/main/AndroidManifest.xml | 7 - .../discreetlauncher/ActivityMain.java | 8 +- .../discreetlauncher/ActivitySearch.java | 138 --------------- .../core/ApplicationsList.java | 6 + .../discreetlauncher/core/Menu.java | 5 +- .../discreetlauncher/core/Search.java | 167 +++++++++++++++++- app/src/main/res/values-fr/strings_help.xml | 1 + app/src/main/res/values-ru/strings_help.xml | 1 + app/src/main/res/values/strings_help.xml | 1 + 9 files changed, 181 insertions(+), 153 deletions(-) delete mode 100644 app/src/main/java/com/vincent_falzon/discreetlauncher/ActivitySearch.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d2837932..b20d8084 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -74,13 +74,6 @@ android:excludeFromRecents="true"> - - - diff --git a/app/src/main/java/com/vincent_falzon/discreetlauncher/ActivityMain.java b/app/src/main/java/com/vincent_falzon/discreetlauncher/ActivityMain.java index ba01aca8..115985f6 100644 --- a/app/src/main/java/com/vincent_falzon/discreetlauncher/ActivityMain.java +++ b/app/src/main/java/com/vincent_falzon/discreetlauncher/ActivityMain.java @@ -47,13 +47,12 @@ import com.vincent_falzon.discreetlauncher.core.ApplicationsList ; import com.vincent_falzon.discreetlauncher.core.Folder ; import com.vincent_falzon.discreetlauncher.core.Menu ; +import com.vincent_falzon.discreetlauncher.core.Search ; import com.vincent_falzon.discreetlauncher.events.ShortcutLegacyListener ; import com.vincent_falzon.discreetlauncher.events.MinuteListener ; import com.vincent_falzon.discreetlauncher.events.PackagesListener ; import com.vincent_falzon.discreetlauncher.notification.NotificationDisplayer ; import com.vincent_falzon.discreetlauncher.settings.ActivitySettings ; -import com.vincent_falzon.discreetlauncher.storage.InternalFileTXT ; -import java.util.Set ; /** * Main class activity managing the home screen and applications drawer. @@ -666,9 +665,12 @@ public void onPause() // Always show the system bars displaySystemBars(true) ; - // Hide folders if some are still opened + // Hide popups if some are still opened for(Application application : applicationsList.getDrawer()) + { if(application instanceof Folder) ((Folder)application).closePopup() ; + if(application instanceof Search) ((Search)application).closePopup() ; + } } diff --git a/app/src/main/java/com/vincent_falzon/discreetlauncher/ActivitySearch.java b/app/src/main/java/com/vincent_falzon/discreetlauncher/ActivitySearch.java deleted file mode 100644 index c3b63f9d..00000000 --- a/app/src/main/java/com/vincent_falzon/discreetlauncher/ActivitySearch.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.vincent_falzon.discreetlauncher; - -// License -/* - - This file is part of Discreet Launcher. - - Copyright (C) 2019-2021 Vincent Falzon - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - */ - -// Imports -import android.os.Bundle ; -import android.text.Editable ; -import android.text.TextWatcher ; -import android.view.KeyEvent ; -import android.view.View ; -import android.view.inputmethod.EditorInfo ; -import android.widget.EditText ; -import android.widget.TextView ; -import androidx.appcompat.app.AppCompatActivity ; -import androidx.recyclerview.widget.RecyclerView ; - -/** - * Activity called when the notification is clicked. - */ -public class ActivitySearch extends AppCompatActivity -{ - // Attributes - private SearchAdapter adapter ; - - - /** - * Constructor. - * @param savedInstanceState To retrieve the context - */ - @Override - protected void onCreate(Bundle savedInstanceState) - { - // Let the parent actions be performed - super.onCreate(savedInstanceState) ; - - // Initializations related to the interface - setContentView(R.layout.popup) ; - findViewById(R.id.popup_title).setVisibility(View.GONE) ; - findViewById(R.id.close_popup).setOnClickListener(new PopupClickListener()) ; - - // Prepare the search bar - EditText searchBar = findViewById(R.id.search_bar) ; - searchBar.setVisibility(View.VISIBLE) ; - searchBar.addTextChangedListener(new TextChangeListener()) ; - searchBar.setOnEditorActionListener(new TextView.OnEditorActionListener() - { - @Override - public boolean onEditorAction(TextView view, int actionId, KeyEvent event) - { - // Perform an action when the user presses "Enter" - if(actionId == EditorInfo.IME_ACTION_DONE) - { - // If there is only one application remaining, start it - if(adapter.getItemCount() == 1) - { - adapter.getFirstItem().start(view) ; - return true ; - } - } - return false ; - } - }) ; - - // Prepare the recycler with all applications (without folders) - RecyclerView recycler = findViewById(R.id.popup_recycler) ; - adapter = new SearchAdapter(this, ActivityMain.getApplicationsList().getApplications(false)) ; - recycler.setAdapter(adapter) ; - recycler.setLayoutManager(new FlexibleGridLayout(this, ActivityMain.getApplicationWidth())) ; - } - - - /** - * Listen for a click on the popup. - */ - private class PopupClickListener implements View.OnClickListener - { - /** - * Detect a click on a view. - * @param view Target element - */ - @Override - public void onClick(View view) - { - // Close the popup - finish() ; - } - } - - - /** - * Called when the text of an EditText is changed by the user. - */ - private class TextChangeListener implements TextWatcher - { - // Needed to implement TextWatcher - @Override - public void beforeTextChanged(CharSequence text, int start, int count, int after){ } - - - /** - * Called when the text has just been changed. - * @param text New text - * @param start Place of the replacement - * @param before Previous text length - * @param count Number of new characters - */ - @Override - public void onTextChanged(CharSequence text, int start, int before, int count) - { - // Update the display of the RecyclerView - adapter.getFilter().filter(text) ; - } - - // Needed to implement TextWatcher - @Override - public void afterTextChanged(Editable text){ } - } -} diff --git a/app/src/main/java/com/vincent_falzon/discreetlauncher/core/ApplicationsList.java b/app/src/main/java/com/vincent_falzon/discreetlauncher/core/ApplicationsList.java index cc7a4277..10ce01a5 100644 --- a/app/src/main/java/com/vincent_falzon/discreetlauncher/core/ApplicationsList.java +++ b/app/src/main/java/com/vincent_falzon/discreetlauncher/core/ApplicationsList.java @@ -342,7 +342,13 @@ public ArrayList getApplicationsNotInFolders() { ArrayList result = new ArrayList<>() ; for(Application application : drawer) + { + // Skip the search application + if(application instanceof Search) continue ; + + // Add all user applications outside folders if(!(application instanceof Folder)) result.add(application) ; + } return result ; } diff --git a/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Menu.java b/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Menu.java index e4db77dd..cdb9c7fb 100644 --- a/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Menu.java +++ b/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Menu.java @@ -91,9 +91,12 @@ public static void open(View view) @Override public void onClick(DialogInterface dialog, int selection) { - // Hide folders if some are still opened + // Hide popups if some are still opened for(Application application : ActivityMain.getApplicationsList().getDrawer()) + { if(application instanceof Folder) ((Folder)application).closePopup() ; + if(application instanceof Search) ((Search)application).closePopup() ; + } // Check which option has been selected switch(selection) diff --git a/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Search.java b/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Search.java index 008a2175..3c32433f 100644 --- a/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Search.java +++ b/app/src/main/java/com/vincent_falzon/discreetlauncher/core/Search.java @@ -23,18 +23,44 @@ */ // Imports +import android.app.Activity ; import android.content.Context ; -import android.content.Intent ; +import android.graphics.Color ; +import android.graphics.drawable.ColorDrawable ; import android.graphics.drawable.Drawable ; +import android.text.Editable ; +import android.text.TextWatcher ; +import android.view.Gravity ; +import android.view.KeyEvent ; +import android.view.LayoutInflater ; +import android.view.MotionEvent ; import android.view.View ; -import com.vincent_falzon.discreetlauncher.ActivitySearch ; +import android.view.ViewGroup ; +import android.view.inputmethod.EditorInfo ; +import android.view.inputmethod.InputMethod ; +import android.view.inputmethod.InputMethodManager ; +import android.widget.EditText ; +import android.widget.LinearLayout ; +import android.widget.PopupWindow ; +import android.widget.TextView ; +import androidx.recyclerview.widget.RecyclerView ; +import com.vincent_falzon.discreetlauncher.ActivityMain ; import com.vincent_falzon.discreetlauncher.Constants ; +import com.vincent_falzon.discreetlauncher.FlexibleGridLayout ; +import com.vincent_falzon.discreetlauncher.R ; +import com.vincent_falzon.discreetlauncher.SearchAdapter ; +import java.util.ArrayList ; /** * Represent the search application. */ public class Search extends Application { + // Attributes + private PopupWindow popup ; + private SearchAdapter adapter ; + + /** * Constructor to represent the search application. * @param display_name Displayed to the user @@ -43,18 +69,151 @@ public class Search extends Application public Search(String display_name, Drawable icon) { super(display_name, Constants.APK_SEARCH, Constants.APK_SEARCH, icon) ; + popup = null ; } /** - * Start the search application. + * Display the search application as a popup. * @param parent Element from which the event originates * @return Always true */ public boolean start(View parent) { + // Initializations Context context = parent.getContext() ; - context.startActivity(new Intent().setClass(context, ActivitySearch.class)) ; + LayoutInflater inflater = LayoutInflater.from(context) ; + + // Prepare the popup view + View popupView = inflater.inflate(R.layout.popup, (ViewGroup)null) ; + popupView.findViewById(R.id.popup_title).setVisibility(View.GONE) ; + popupView.findViewById(R.id.close_popup).setOnClickListener(new PopupClickListener()) ; + + // Prepare the search bar + EditText searchBar = popupView.findViewById(R.id.search_bar) ; + searchBar.setVisibility(View.VISIBLE) ; + searchBar.addTextChangedListener(new TextChangeListener()) ; + searchBar.setOnEditorActionListener(new TextView.OnEditorActionListener() + { + @Override + public boolean onEditorAction(TextView view, int actionId, KeyEvent event) + { + // Perform an action when the user presses "Enter" + if(actionId == EditorInfo.IME_ACTION_DONE) + { + // If there is only one application remaining, start it + if(adapter.getItemCount() == 1) + { + adapter.getFirstItem().start(view) ; + return true ; + } + } + return false ; + } + }) ; + + // Retrieve all the applications without folders and the search + ArrayList applications = ActivityMain.getApplicationsList().getApplications(false) ; + Application search = null ; + for(Application application : applications) + if(application instanceof Search) search = application ; + if(search != null) applications.remove(search) ; + + // Prepare the popup content + RecyclerView recycler = popupView.findViewById(R.id.popup_recycler) ; + adapter = new SearchAdapter(context, applications) ; + recycler.setAdapter(adapter) ; + recycler.setLayoutManager(new FlexibleGridLayout(context, ActivityMain.getApplicationWidth())) ; + + // Create the popup representing the search application + int popup_height = Math.min(context.getResources().getDisplayMetrics().heightPixels / 2, parent.getRootView().getHeight()) ; + popup = new PopupWindow(popupView, LinearLayout.LayoutParams.MATCH_PARENT, popup_height, true) ; + popupView.setOnTouchListener(new PopupTouchListener()) ; + + // Fix popup not closing on press back with API 21 + popup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)) ; + + // Display the popup and the keyboard + popup.showAtLocation(parent, Gravity.CENTER, 0, 0) ; + ((InputMethodManager)context.getSystemService(Activity.INPUT_METHOD_SERVICE)).toggleSoftInputFromWindow(parent.getWindowToken(), InputMethod.SHOW_EXPLICIT, 0) ; return true ; } + + + /** + * Dismiss the popup if it is currently displayed. + */ + public void closePopup() + { + if(popup != null) popup.dismiss() ; + } + + + /** + * Listen for a click on the popup. + */ + private class PopupClickListener implements View.OnClickListener + { + /** + * Detect a click on a view. + * @param view Target element + */ + @Override + public void onClick(View view) + { + // Close the popup + closePopup() ; + } + } + + + /** + * Dismiss the popup when the user touchs outside of it (needs focusable = true). + */ + private class PopupTouchListener implements View.OnTouchListener + { + /** + * Detect a gesture on a view. + * @param view Target element + * @param event Details about the gesture + * @return true if the event is consumed, false otherwise + */ + @Override + public boolean onTouch(View view, MotionEvent event) + { + view.performClick() ; + closePopup() ; + return true ; + } + } + + + /** + * Called when the text of an EditText is changed by the user. + */ + private class TextChangeListener implements TextWatcher + { + // Needed to implement TextWatcher + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after){ } + + + /** + * Called when the text has just been changed. + * @param text New text + * @param start Place of the replacement + * @param before Previous text length + * @param count Number of new characters + */ + @Override + public void onTextChanged(CharSequence text, int start, int before, int count) + { + // Update the display of the RecyclerView + adapter.getFilter().filter(text) ; + } + + // Needed to implement TextWatcher + @Override + public void afterTextChanged(Editable s){ } + } } diff --git a/app/src/main/res/values-fr/strings_help.xml b/app/src/main/res/values-fr/strings_help.xml index 9b0d41c1..b420cba9 100644 --- a/app/src/main/res/values-fr/strings_help.xml +++ b/app/src/main/res/values-fr/strings_help.xml @@ -56,6 +56,7 @@ L\'icône de recherche permet de trouver une application dans la liste complète. Vous pouvez l\'ajouter aux favoris de façon à y accéder aussi grâce à la notification. + Pour des raisons techniques, il n\'est pas possible de la mettre dans un dossier. \n \nSi vous ne pensez pas l\'utiliser, vous pouvez aussi masquer la recherche comme n\'importe quelle application. \n diff --git a/app/src/main/res/values-ru/strings_help.xml b/app/src/main/res/values-ru/strings_help.xml index 6299e4b7..0ddb7464 100644 --- a/app/src/main/res/values-ru/strings_help.xml +++ b/app/src/main/res/values-ru/strings_help.xml @@ -56,6 +56,7 @@ Значок поиска позволяет найти приложение в полном списке. Вы можете добавить его в избранное, чтобы получить доступ к нему также с помощью уведомления. + По техническим причинам его невозможно добавить в папку. \n \nЕсли вы не планируете им пользоваться, его можно скрыть, как и любое другое приложение. diff --git a/app/src/main/res/values/strings_help.xml b/app/src/main/res/values/strings_help.xml index 89eed4cb..bcafdd4a 100644 --- a/app/src/main/res/values/strings_help.xml +++ b/app/src/main/res/values/strings_help.xml @@ -56,6 +56,7 @@ The search icon allows to find an application in the complete list. You can add it to favorites in order to access it also using the notification. + For technical reasons, it is not possible to add it in a folder. \n \nIf you do not plan to use it, you can also hide the search like any application. \n