Skip to content

Commit

Permalink
Make Back button/gesture not instantly collapse the MainActivity's se…
Browse files Browse the repository at this point in the history
…arch view (#2030)
  • Loading branch information
unbiaseduser-github authored Aug 14, 2024
1 parent 7c7a05f commit 80e4701
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 4 deletions.
16 changes: 15 additions & 1 deletion .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ env:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
api-level: [ 21, 34 ]
steps:
- uses: actions/[email protected]
- name: Fail on bad translations
Expand All @@ -44,11 +47,22 @@ jobs:
run: ./gradlew lintRelease
- name: Run unit tests
run: timeout 5m ./gradlew testReleaseUnitTest || { ./gradlew --stop && timeout 5m ./gradlew testReleaseUnitTest; }
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Run instrumented tests
uses: ReactiveCircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
arch: x86_64
script: ./gradlew connectedCheck
- name: SpotBugs
run: ./gradlew spotbugsRelease
- name: Archive test results
if: always()
uses: actions/[email protected]
with:
name: test-results
name: test-results-api${{ matrix.api-level }}
path: app/build/reports
15 changes: 13 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ android {
multiDexEnabled = true

resourceConfigurations += listOf("ar", "bg", "bn", "bn-rIN", "bs", "cs", "da", "de", "el-rGR", "en", "eo", "es", "es-rAR", "et", "fi", "fr", "he-rIL", "hi", "hr", "hu", "in-rID", "is", "it", "ja", "ko", "lt", "lv", "nb-rNO", "nl", "oc", "pl", "pt-rBR", "pt-rPT", "ro-rRO", "ru", "sk", "sl", "sr", "sv", "tr", "uk", "vi", "zh-rCN", "zh-rTW")

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
Expand Down Expand Up @@ -110,9 +112,18 @@ dependencies {
implementation("io.wcm.tooling.spotbugs:io.wcm.tooling.spotbugs.annotations:1.0.0")

// Testing
testImplementation("androidx.test:core:1.6.1")
testImplementation("junit:junit:4.13.2")
val androidXTestVersion = "1.6.1"
val junitVersion = "4.13.2"
testImplementation("androidx.test:core:$androidXTestVersion")
testImplementation("junit:junit:$junitVersion")
testImplementation("org.robolectric:robolectric:4.13")

androidTestImplementation("androidx.test:core:$androidXTestVersion")
androidTestImplementation("junit:junit:$junitVersion")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test:runner:$androidXTestVersion")
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
}

tasks.withType<SpotBugsTask>().configureEach {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package protect.card_locker;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.typeText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withChild;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;

import androidx.appcompat.widget.Toolbar;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class MainActivitySearchViewTest {

@Test
public void whenSearchViewIsExpandedAndBackIsPressedThenMenuItemShouldNotBeCollapsed() {
String query = "random arbitrary text";
try (ActivityScenario<MainActivity> mainActivityScenario = ActivityScenario.launch(MainActivity.class)) {
mainActivityScenario.onActivity(this::makeSearchMenuItemVisible);
onView(withId(R.id.action_search)).perform(click());
onView(withId(androidx.appcompat.R.id.search_src_text)).perform(typeText(query));

pressBack();

onView(withId(androidx.appcompat.R.id.search_src_text)).check(matches(withText(query)));
mainActivityScenario.onActivity(activity -> assertEquals(query, activity.mFilter));
}
}

@Test
public void whenSearchViewIsExpandedThenItShouldOnlyBeCollapsedWhenBackIsPressedTwice() {
try (ActivityScenario<MainActivity> mainActivityScenario = ActivityScenario.launch(MainActivity.class)) {
mainActivityScenario.onActivity(this::makeSearchMenuItemVisible);
onView(withId(R.id.action_search)).perform(click());

pressBack();

onView(withId(androidx.appcompat.R.id.search_src_text)).check(matches(isDisplayed()));

pressBack();

onView(withId(android.R.id.content)).check(matches(is(not(withChild(withId(androidx.appcompat.R.id.search_src_text))))));
}
}

private void makeSearchMenuItemVisible(MainActivity activity) {
Toolbar toolbar = activity.findViewById(R.id.toolbar);
toolbar.getMenu().findItem(R.id.action_search).setVisible(true);
}

private void pressBack() {
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressBack();
}

}
29 changes: 28 additions & 1 deletion app/src/main/java/protect/card_locker/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.content.SharedPreferences;
import android.database.CursorIndexOutOfBoundsException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
Expand All @@ -21,6 +22,7 @@
import androidx.activity.OnBackPressedCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
Expand Down Expand Up @@ -511,7 +513,8 @@ public boolean onCreateOptionsMenu(Menu inputMenu) {

SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null) {
mSearchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
MenuItem searchMenuItem = inputMenu.findItem(R.id.action_search);
mSearchView = (SearchView) searchMenuItem.getActionView();
mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
mSearchView.setSubmitButtonEnabled(false);

Expand All @@ -520,6 +523,30 @@ public boolean onCreateOptionsMenu(Menu inputMenu) {
return false;
});

/*
* On Android 13 and later, pressing Back while the search view is open hides the keyboard
* and collapses the search view at the same time.
* This brings back the old behavior on Android 12 and lower: pressing Back once
* hides the keyboard, press again while keyboard is hidden to collapse the search view.
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
searchMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(@NonNull MenuItem item) {
return true;
}

@Override
public boolean onMenuItemActionCollapse(@NonNull MenuItem item) {
if (mSearchView.hasFocus()) {
mSearchView.clearFocus();
return false;
}
return true;
}
});
}

mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
Expand Down

0 comments on commit 80e4701

Please sign in to comment.