Search code examples
androidsearchandroid-actionbaractionbarsherlock

Go back after Searching with setActionView in Android using ActionBarSherlock


With this code (taken from ABS examples) I'm able to add a "Search" icon in my ActionBar which will display an EditText when clicked (to search in a list):

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(Menu.NONE, searchId, Menu.NONE, R.string.menu_search)
     .setIcon(android.R.drawable.ic_menu_search)
     .setActionView(R.layout.collapsible_edittext)
     .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
    return true;
}

With this code I'm able to show a different layout after tapping the "Search" icon:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case searchId:
        search = (EditText) item.getActionView();
        search.addTextChangedListener(filterTextWatcher);
        search.requestFocus();
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

        setContentView(R.layout.search);

        this.allSongs = data.getSongs();
        ListView list = (ListView) findViewById(R.id.songList);
        list.setAdapter(new SongAdapter(this, this.allSongs));
    }
    return true;
}

With this code I'm able to handle my search:

private TextWatcher filterTextWatcher = new TextWatcher() {
    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before, int count) {

        List<Song> results = new ArrayList<Song>();

        Locale locale = Locale.getDefault();

        for (Song song : allSongs) {
            if (song.getTitle().toLowerCase(locale).contains(s.toString().toLowerCase(locale)))
                results.add(song);
        }

        ListView list = (ListView) findViewById(R.id.songList);
        list.setAdapter(new SongAdapter(ctx, results));
    }
};

When the user taps the "Search" icon, the EditText appears in ActionBar and the App Icon gains the "back" left arrow. If the user taps "Back" button or taps the ActionBar icon (with left arrow), the EditText disappears. I'd like to intercept this event (no, onOptionsItemSelected() doesn't fire this time) and show the previous layout, in addition to hiding the EditText.

Note: I need API8 (Android 2.2) compatibility!

Thank you!


Solution

  • When using an ActionView, tapping "up" or "back" doesn't result in an Ancestral Navigation (which can be handled by onOptionsItemSelected) but results in a Collapsible Action event.

    Found here on Android Developers.

    Handling collapsible action views

    If you need to update your activity based on the visibility of your action view, you can receive callbacks when it's expanded and collapsed by defining an OnActionExpandListener and registering it with setOnActionExpandListener(). For example:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.options, menu);
        MenuItem menuItem = menu.findItem(R.id.actionItem);
        ...
    
        menuItem.setOnActionExpandListener(new OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                // Do something when collapsed
                return true;  // Return true to collapse action view
            }
    
            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                // Do something when expanded
                return true;  // Return true to expand action view
            }
        });
    }
    

    So, to answer to my question, I was searching for onMenuItemActionCollapse event.

    PS: for better consistency I should move my case searchId: from onOptionsItemSelected to onMenuItemActionExpand