I have a searchview and a button i my actionbar,but the button gets displayed only in the landscape mode and however I try it wont get displayed in the portrait mode.
Landscape Mode
Portrait Mode
this is my menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_item_search"
android:title="Search"
android:showAsAction="ifRoom"
android:icon="#android:drawable/ic_menu_search"
android:actionViewClass="android.widget.SearchView" />
<item
android:id="#+id/submit"
android:title="submit"
android:showAsAction="always" />
</menu>
This is my main activity
public class Myclass extends Activity implements OnQueryTextListener,OnItemClickListener {
GroupAdapter grpAdapter;
public static ArrayList<GroupsModel> arrayOfList;
public static ListView listView;
public static String base_url = "myurl";
private SeekBar volumeControl = null;
private TextView year;
private int progressChanged = 0;
private Menu menu_data;
MenuItem submitBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.two);
ActionBar actionBar = getActionBar();
//actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setHomeButtonEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
volumeControl = (SeekBar) findViewById(R.id.volume_bar);
year = (TextView)findViewById(R.id.year_level);
volumeControl.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
progressChanged = progress;
year.setText(Integer.toString(progressChanged+7));
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
arrayOfList = new ArrayList<GroupsModel>();
listView = (ListView) findViewById(R.id.group_listview);
listView.setOnItemClickListener(this);
listView.setTextFilterEnabled(true);
new ProgressTask(two.this).execute();
}
private class ProgressTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
#SuppressWarnings("unused")
private two activity;
public ProgressTask(two two) {
this.activity = two;
context = two;
dialog = new ProgressDialog(context);
}
private Context context;
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
protected Boolean doInBackground(final String... args) {
//arrayOfList = new ArrayList<GroupsModel>();
List<NameValuePair> params = new ArrayList<NameValuePair>();
//params.add(new BasicNameValuePair("",""));
JSONParser jp = new JSONParser();
JSONArray groups_obj = jp.makeHttpRequest(base_url + "groups/all", "GET", params);
for (int i = 0; i < groups_obj.length(); i++) {
GroupsModel group = new GroupsModel();
try {
JSONObject grp = groups_obj.getJSONObject(i);
group.setGroupId(grp.getInt("id"));
group.setGroupname(grp.getString("name"));
arrayOfList.add(group);
}
catch (JSONException e) {
e.printStackTrace();
}
}
two.this.runOnUiThread(new Runnable() {
#Override
public void run() {
grpAdapter = new GroupAdapter(two.this, R.layout.two_row,arrayOfList);
listView.setAdapter(grpAdapter);
}
});
return null;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu_data = menu;
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
SearchManager searchManager = (SearchManager) getSystemService( Context.SEARCH_SERVICE );
SearchView searchView = (SearchView) menu.findItem(R.id.menu_item_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(false);
searchView.setOnQueryTextListener(this);
searchView.setQueryHint("My text");
searchView.setIconifiedByDefault(false);
submitBtn = (MenuItem)menu_data.findItem(R.id.submit);
submitBtn.setIcon(R.drawable.button22);
submitBtn.setEnabled(false);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.submit:
if(submitBtn.isVisible())
Toast.makeText(getApplicationContext(), Integer.toString(progressChanged+7),Toast.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onQueryTextChange(String newText)
{
// this is your adapter that will be filtered
if (TextUtils.isEmpty(newText))
{
listView.clearTextFilter();
}
grpAdapter.getFilter().filter(newText.toString());
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
// TODO Auto-generated method stub
submitBtn.setIcon(R.drawable.button111);
submitBtn.setEnabled(true);
for (GroupsModel s : arrayOfList)
s.setChecked(false);
final boolean isChecked = GroupAdapter.items.get(position).getChecked();
if(isChecked==false){
GroupAdapter.items.get(position).setChecked(!isChecked);
grpAdapter.notifyDataSetChanged();
}
else{
GroupAdapter.items.get(position).setChecked(isChecked);
grpAdapter.notifyDataSetChanged();
}
} }
Please help me.
If it doesn't concern you that the SearchView is collapsed at the start, try configuring the SearchView like this:
android:showAsAction="collapseActionView|ifRoom"
This should make the actionbar show both, the SearchView and your Button. Plus the SearchView will only take up the remaining space to the left, when it gets expanded.
According to developer.android.com
If your app is using the Support Library for compatibility on versions as low as Android 2.1, the showAsAction attribute is not available from the android: namespace. Instead this attribute is provided by the Support Library and you must define your own XML namespace and use that namespace as the attribute prefix. (A custom XML namespace should be based on your app name, but it can be any name you want and is only accessible within the scope of the file in which you declare it.) For example:
res/menu/main_activity_actions.xml >>>>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
<!-- Search, should appear as action button -->
<item android:id="#+id/action_search"
android:icon="#drawable/ic_action_search"
android:title="#string/action_search"
yourapp:showAsAction="ifRoom" />
...
</menu>
A SearchView will default to taking up a majority of, if not all of the action bar in portrait mode. Try decreasing the size of the SearchView in menu.xml and see if the button is displayed.
Related
I have just implemented the "android.support.v7.widget.SearchView" in my Actionbar to search for some pdf files.
When i insert multiple characters for search, the list of suggestions is shown perferctly. But when i'm only entering one single character, there are no proposals shown, although the function to populate the suggestions is called.
Do you have an idea how to change that behavior, to get the proposals shown when entering only one character?
This is where i simply define the searchview inside a menu.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/pdf_menu_search_item"
android:icon="#mipmap/ic_search_white_24dp"
android:title="Suche"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/></menu>
In my Activity, the following code is implemented:
private static final String[] SUGGESTIONS = {
"Amsterdam","Berlin","Rome"
};
private SimpleCursorAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_contextual_actionbar, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
final SearchView mSearchView;
mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.pdf_menu_search_item));
final String[] from = new String[] {"cityName"};
final int[] to = new int[] {android.R.id.text1};
mAdapter = new SimpleCursorAdapter(Startseite.this,
android.R.layout.simple_list_item_1,
null,
from,
to,
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
mSearchView.setSuggestionsAdapter(mAdapter);
mSearchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
#Override
public boolean onSuggestionClick(int position) {
return true;
}
#Override
public boolean onSuggestionSelect(int position) {
return true;
}
});
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
populateAdapter(newText);
return true;
}
});
return super.onPrepareOptionsMenu(menu);
}
// You must implements your logic to get data using OrmLite
private void populateAdapter(String query) {
final MatrixCursor c = new MatrixCursor(new String[]{ BaseColumns._ID, "cityName" });
for (int i=0; i<SUGGESTIONS.length; i++) {
if (SUGGESTIONS[i].toLowerCase().startsWith(query.toLowerCase()))
{ c.addRow(new Object[] {i, SUGGESTIONS[i]}); }
}
mAdapter.changeCursor(c);
mAdapter.notifyDataSetChanged();
}
Working with more than one characters:
Not working with only one character:
Please has anyone an idea how to fix that?
I have just found the answer.
If you are using AppCompatActivity (like me), you can set the searchview threshold like that:
AutoCompleteTextView searchAutoCompleteTextView = (AutoCompleteTextView) mSearchView.findViewById(getResources().getIdentifier("search_src_text", "id", getPackageName()));
searchAutoCompleteTextView.setThreshold(1);
Now the search-suggestions will be shown from the first character on.
Maybe it is helpful for others :)
I was following this article. Unfortunatelly, badge isn't drawn. Of course I changed invalidateOptionsMenu method to supportInvalidateOptionsMenu method.
I was checking the log, step by step and found out that draw method in custom Drawable named BadgeDrawable is never called. Why is that?
I'm trying to use it in AppCompatActivity using Support Design Library version 23.0.1
I saw this answer but it seems to be out of date.
Is there anyone who managed to implement badger counter for MenuItem icon inside android.support.v7.widget.Toolbar?
If the way shown in the article is wrong then could you suggest other way to achieve the result as in example below?:
Here is a setup inside my application:
LayerDrawable XML ic_filter_notifications.xml:
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/ic_filter_notification"
android:drawable="#drawable/ic_filter_grey600_18dp"
android:gravity="center"/>
<!-- set a place holder Drawable so android:drawable isn't null -->
<item android:id="#+id/ic_filter_badge"
android:drawable="#drawable/ic_filter_grey600_18dp">
</item>
</layer-list>
Menu that I use in the Toolbar menu_activity_main.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cobytu="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/menu_settings"
android:orderInCategory="100"
android:title="#string/menu_settings"
cobytu:showAsAction="never"/>
<item
android:id="#+id/menu_logout"
android:orderInCategory="1000000"
android:title="#string/menu_logout"
cobytu:showAsAction="never"/>
<item
android:id="#+id/action_filter"
android:title="#string/filters"
android:icon="#drawable/ic_filter_notifications"
cobytu:showAsAction="always"/>
<item
android:id="#+id/action_location"
android:icon="#drawable/ic_map_marker_radius_grey600_18dp"
android:title="#string/location"
cobytu:showAsAction="always"/>
</menu>
This is function sets the count int for new BadgeDrawable inside UsefulFunctions class - UsefulFunctions.java:
public class UsefulFunctions {
private Context ctx;
public UsefulFunctions(Context context){
ctx = context;
}
public static void setBadgeCount(Context context, LayerDrawable icon,
int count) {
BadgeDrawable badge;
// Reuse drawable if possible
Drawable reuse = icon.findDrawableByLayerId(R.id.ic_filter_badge);
if (reuse != null && reuse instanceof BadgeDrawable) {
badge = (BadgeDrawable) reuse;
} else {
Log.d("mTAG", UsefulFunctions.class.getName()
+ " I'm creating new BadgeDrawable!");
badge = new BadgeDrawable(context);
}
badge.setCount(count);
icon.mutate();
Log.d("mTAG",
UsefulFunctions.class.getName() + " badge: " + badge.toString()
+ " count: " + count);
icon.setDrawableByLayerId(R.id.ic_filter_badge, badge);
}
}
This is the important scrap of my MainActivity where I invoke BadgeDrawable creation. I also show what's inside onCreate and in onOptionsItemSelected, may be needed - MainActivity.java:
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, DialogFragmentFilters.FiltersRefreshInterface{
public String username;
//CollapsingToolbarLayout
private CollapsingToolbarLayout mCollapsingToolbarLayout;
//Toolbar
private Toolbar mToolbar;
//TabLayout
private TabLayout mTabLayout;
private ViewPager mPager;
private MyPagerAdapter mAdapter;
//NavigationDraver
private static final String SELECTED_ITEM_ID = "selected_item_id";
private static final String FIRST_TIME = "first_time";
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private NavigationView mNavigationView;
private int mSelectedId;
private boolean mUserSawDrawer = false;
private TextView mNavHeaderNameText;
private TextView mNavHeaderEmailText;
private DatabaseHandler db;
private UserFunctions userFunctions;
private AlertDialog.Builder dialogBuilder;
private AlertDialog alertDialog;
private JSONObject jsonLocation = new JSONObject();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userFunctions = new UserFunctions();
db = new DatabaseHandler(getApplicationContext());
username = db.getUserDetails().get(DatabaseHandler.getKEY_USER_LOGIN());
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
setupToolbar();
setupTablayout();
mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
mNavigationView.setNavigationItemSelectedListener(this);
View header = LayoutInflater.from(MainActivity.this).inflate(R.layout.nav_header, null);
mNavHeaderNameText = (TextView) header.findViewById(R.id.tv_nav_header_name);
mNavHeaderNameText.setText("Siema "+username+"!");
mNavHeaderEmailText = (TextView) header.findViewById(R.id.tv_nav_header_email);
mNavHeaderEmailText.setText(db.getUserDetails().get(DatabaseHandler.getKEY_USER_EMAIL()));
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,mToolbar, R.string.drawer_open, R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
if (!didUserSeeDrawer()) {
showDrawer();
markDrawerSeen();
} else {
hideDrawer();
}
mSelectedId = savedInstanceState == null ? R.id.navigation_item_4 : savedInstanceState.getInt(SELECTED_ITEM_ID);
navigate(mSelectedId);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
showActionDialog(id);
//noinspection SimplifiableIfStatement
switch (id) {
case R.id.menu_settings:
return true;
case R.id.menu_logout:
dialogBuilder = new AlertDialog.Builder(new ContextThemeWrapper(
MainActivity.this, R.style.Theme_AppCompat_Light_Dialog));
dialogBuilder
.setTitle(getResources().getString(R.string.logoutAlertTitle))
.setIcon(R.drawable.ic_logout).setMessage(getResources().getString(R.string.logoutAlertMessage)).setPositiveButton(getResources().getString(R.string.logoutAlertYesButton),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
((RelativeLayout) findViewById(R.id.fl_mainContent))
.animate()
.alpha(0f)
.setListener(
new AnimatorListenerAdapter() {
public void onAnimationEnd(
Animator animation) {
mDrawerLayout
.setVisibility(View.INVISIBLE);
mDrawerLayout
.setAlpha(1f);
mDrawerLayout
.animate()
.setListener(null);
}
});
userFunctions.logoutUser(getApplicationContext());
Intent i = new Intent(MainActivity.this, LoginActivity.class);
// MainActivity.this.deleteDatabase("cobytu_db");
startActivity(i);
finish();
}
})
.setNegativeButton(getResources().getString(R.string.logoutAlertNoButton),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
}
});
alertDialog = dialogBuilder.create();
alertDialog.show();
return true;
}
return false;
}
public int filterCounter = 0;
class FetchCountTask extends AsyncTask<Void, Void, Integer> {
#Override
protected Integer doInBackground(Void... params) {
// example count. This is where you'd
// query your data store for the actual count.
return 5;
}
#Override
public void onPostExecute(Integer count) {
setNotifCount(count);
}
}
private void setNotifCount(int count){
filterCounter = count;
supportInvalidateOptionsMenu();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_activity_main, menu);
MenuItem item = menu.findItem(R.id.action_filter);
LayerDrawable icon = (LayerDrawable) item.getIcon();
// Update LayerDrawable's BadgeDrawable
Log.d("mTag", "onCreateOptionsMenu: this: " + this.toString());
UsefulFunctions.setBadgeCount(this, icon, filterCounter);
return true;
}
#Override
public void onRefreshFilters(int counter) {
setupTablayout();
Toast.makeText(MainActivity.this, "List has been refreshed! " + counter, Toast.LENGTH_SHORT).show();
filterCounter = counter;
new FetchCountTask.execute();
}
}
I have a search action item associated with an AppCompatActivity. The search icon appears but when I click on it, it doesn't show the edit control allowing me to put in the search text. I've tried all the obvious issues but I just can't seem to get this to work.
This app loads a PDF a switches out the Toolbar based on user choices. The first toolbar shows a search item. Once this is selected it adds the searchNext and searchPrev buttons. All this worked until I switched to Material Design. I think the problem has something to do with replacing the menu but I'm not sure.
Here is the manifest:
<activity
android:name="com.mupdf.MuPDFActivity"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="#string/app_name" >
</activity>
Here is the menu resources:
MAIN MENU:
<item android:id="#+id/pdf_action_search"
android:title="#string/pdf_action_search"
android:icon="#drawable/ic_pdf_action_search"
android:orderInCategory="100"
app:showAsAction="ifRoom"/>
<item android:id="#+id/pdf_action_export"
android:title="#string/pdf_action_export"
android:icon="#drawable/ic_pdf_action_export"
android:orderInCategory="100"
app:showAsAction="ifRoom">
<menu>
<item
android:id="#+id/pdf_action_share"
android:title="#string/pdf_action_share"
app:showAsAction="ifRoom"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
<item
android:id="#+id/pdf_action_print"
android:title="#string/pdf_action_print"
app:showAsAction="always|withText"/>
</menu>
</item>
<item android:id="#+id/pdf_action_tools"
android:title="#string/pdf_action_tools"
android:icon="#drawable/ic_pdf_action_tools"
android:orderInCategory="100"
app:showAsAction="ifRoom">
<menu>
<item
android:id="#+id/pdf_action_highlight"
android:title="#string/pdf_action_highlight"
app:showAsAction="always|withText"/>
<item
android:id="#+id/pdf_action_underline"
android:title="#string/pdf_action_underline"
app:showAsAction="always|withText"/>
<item
android:id="#+id/pdf_action_strikeout"
android:title="#string/pdf_action_strikeout"
app:showAsAction="always|withText"/>
<item
android:id="#+id/pdf_action_pen"
android:title="#string/pdf_action_pen"
app:showAsAction="always|withText"/>
</menu>
</item>
REPLACEMENT MENU:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/pdf_menu_search_item"
android:title="#string/search"
android:icon="#drawable/ic_pdf_action_search"
app:showAsAction="always|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
<item
android:id="#+id/pdf_menu_search_prev"
android:title="#string/search_prev"
android:icon="#drawable/ic_pdf_action_search_prev"
app:showAsAction="always" />
<item
android:id="#+id/pdf_menu_search_next"
android:title="#string/search_next"
android:icon="#drawable/ic_pdf_action_search_next"
app:showAsAction="always" />
</group>
This is activity:
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.text.method.PasswordTransformationMethod;
import android.view.Menu;
import android.view.MenuItem;
public class MuPDFActivity extends AppCompatActivity implements FilePicker.FilePickerSupport
{
/* The core rendering instance */
enum TopBarMode {Main, Search, Annot, Delete, More, Accept};
enum AcceptMode {Highlight, Underline, StrikeOut, Ink, CopyText};
private TopBarMode mTopBarMode = TopBarMode.Main;
private AcceptMode mAcceptMode;
private SearchTask mSearchTask;
private SearchView mSearchView;
private MenuItem mSearchMenuPrev;
private MenuItem mSearchMenuNext;
private String mSearchString;
private ActionBar mActionBar;
private Toolbar toolbar;
// ***************************************************************************************************
//
// onCreate
//
// ***************************************************************************************************
#Override
public void onCreate(Bundle savedInstanceState)
{
/** Called when the activity is first created. */
getWindow().requestFeature(Window.FEATURE_ACTION_BAR | Window.FEATURE_ACTION_BAR_OVERLAY);
super.onCreate(savedInstanceState);
createUI(savedInstanceState);
}
// ***************************************************************************************************
//
// setupToolbar
//
// ***************************************************************************************************
private void setupToolbar()
{
//toolbar = (Toolbar) findViewById(R.id.toolbar);
if(toolbar != null)
{
setSupportActionBar(toolbar);
mActionBar = getSupportActionBar();
if(mActionBar != null)
{
mActionBar.setDisplayHomeAsUpEnabled(true);
mActionBar.setHomeButtonEnabled(true);
mActionBar.setDisplayShowHomeEnabled(false);
mActionBar.setDisplayUseLogoEnabled(false);
mActionBar.setIcon(null);
mActionBar.setBackgroundDrawable(new ColorDrawable(MINAppConfiguration.getSharedInstance().getCurrentVisualElements().tbTopBackgroundColor));
mActionBar.setTitle(pdfName);
}
}
if (Build.VERSION.SDK_INT >= 21)
{
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(MINAppConfiguration.getSharedInstance().getCurrentVisualElements().tbStatusBarBackgroundColor);
}
}
// ***************************************************************************************************
//
// onCreateOptionsMenu
//
// ***************************************************************************************************
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.pdf_menu_main, menu);
MenuItem shareMenuItem = menu.findItem(R.id.pdf_action_share);
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareMenuItem);
setShareIntent();
return true;
}
// ***************************************************************************************************
//
// onOptionsItemSelected
//
// ***************************************************************************************************
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
boolean bHandledEvent = false;
int id = item.getItemId();
switch (id)
{
case R.id.pdf_action_search:
bHandledEvent = true;
mActionModeSearch = this.startSupportActionMode(mActionModeSearchCallback);
break;
}
if(!bHandledEvent)
{
return super.onOptionsItemSelected(item);
}
else
{
return bHandledEvent;
}
}
// ***************************************************************************************************
//
// mActionModeEditCallback
//
// ***************************************************************************************************
protected ActionMode mActionModeSearch;
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback()
{
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
mSearchMenuPrev = (MenuItem) menu.findItem(R.id.pdf_menu_search_prev);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = (MenuItem) menu.findItem(R.id.pdf_menu_search_next);
mSearchMenuNext.setEnabled(false);
//mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.pdf_menu_search_item));
// TODO this search functionality still isn't working
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
mSearchView=(SearchView)MenuItemCompat.getActionView(searchItem);
if(mSearchView != null)
{
mSearchView.setIconifiedByDefault(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
}
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.pdf_menu_search_prev:
mSearchView.clearFocus();
hideKeyboard();
search(-1);
return true;
case R.id.pdf_menu_search_next:
mSearchView.clearFocus();
hideKeyboard();
search(1);
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode)
{
searchModeOff();
bPopoverLoaded = false;
mActionModeEdit = null;
mActionModeSearch = null;
resetHideToolbarsTimer();
}
};
// ***************************************************************************************************
//
// createUI
//
// ***************************************************************************************************
public void createUI(Bundle savedInstanceState)
{
if (core == null)
return;
// Now create the UI.
// First create the document view
mDocView = new MuPDFReaderView(this) {
#Override
protected void onMoveToChild(int i) {
if (core == null)
return;
mPageNumberView.setText(String.format("%d / %d", i + 1,
core.countPages()));
mPageSlider.setMax((core.countPages() - 1) * mPageSliderRes);
mPageSlider.setProgress(i * mPageSliderRes);
super.onMoveToChild(i);
}
#Override
protected void onTapMainDocArea()
{
// Hide/Show action bar
if(isToolbarsVisible())
{
setToolbarsVisible(false);
}
else
{
setToolbarsVisible(true);
}
}
#Override
protected void onDocMotion() {
hideButtons();
}
#Override
protected void onHit(Hit item) {
switch (mTopBarMode) {
case Annot:
if (item == Hit.Annotation) {
showButtons();
mTopBarMode = TopBarMode.Delete;
//mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
break;
case Delete:
mTopBarMode = TopBarMode.Annot;
default:
// Not in annotation editing mode, but the pageview will
// still select and highlight hit annotations, so
// deselect just in case.
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
if (pageView != null)
pageView.deselectAnnotation();
break;
}
}
};
mDocView.setAdapter(new MuPDFPageAdapter(this, this, core));
mSearchTask = new SearchTask(this, core)
{
#Override
protected void onTextFound(SearchTaskResult result)
{
SearchTaskResult.set(result);
// Ask the ReaderView to move to the resulting page
mDocView.setDisplayedViewIndex(result.pageNumber);
// Make the ReaderView act on the change to SearchTaskResult
// via overridden onChildSetup method.
mDocView.resetupChildren();
}
};
// Make the buttons overlay, and store all its
// controls in variables
makeButtonsView();
// Set up the page slider
int smax = Math.max(core.countPages()-1,1);
mPageSliderRes = ((10 + smax - 1)/smax) * 2;
// Activate the seekbar
mPageSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
public void onStopTrackingTouch(SeekBar seekBar)
{
mDocView.setDisplayedViewIndex((seekBar.getProgress()+mPageSliderRes/2)/mPageSliderRes);
}
public void onStartTrackingTouch(SeekBar seekBar)
{
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
updatePageNumView((progress+mPageSliderRes/2)/mPageSliderRes);
}
});
if (savedInstanceState == null || !savedInstanceState.getBoolean("ButtonsHidden", false))
showButtons();
// Stick the document view and the buttons overlay into a parent view
RelativeLayout layout = new RelativeLayout(this);
layout.addView(mDocView);
layout.addView(mButtonsView);
toolbar = new Toolbar(this);
//toolbar.setMinimumWidth(android.app.ActionBar.LayoutParams.MATCH_PARENT);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
toolbar.setLayoutParams(layoutParams);
layout.addView(toolbar);
//RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layout.getLayoutParams();
//params.width = android.app.ActionBar.LayoutParams.MATCH_PARENT;
setContentView(layout);
// Setup New Toolbar implementation
setupToolbar();
// Set up custom colors, etc...
setCustomAttributes();
}
// ***************************************************************************************************
//
// onResume
//
// ***************************************************************************************************
#Override
public void onResume()
{
super.onResume();
// Start timer to hide toolbars.
bPopoverLoaded = false;
resetHideToolbarsTimer();
}
private void showButtons()
{
if (core == null)
return;
if (!mButtonsVisible)
{
mButtonsVisible = true;
// Update page number text and slider
int index = mDocView.getDisplayedViewIndex();
updatePageNumView(index);
mPageSlider.setMax((core.countPages()-1)*mPageSliderRes);
mPageSlider.setProgress(index*mPageSliderRes);
if (mTopBarMode == TopBarMode.Search)
{
//mSearchText.requestFocus();
showKeyboard();
}
Animation anim = new TranslateAnimation(0, 0, mPageSlider.getHeight(), 0);
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationStart(Animation animation) {
mPageSlider.setVisibility(View.VISIBLE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mPageNumberView.setVisibility(View.VISIBLE);
}
});
mPageSlider.startAnimation(anim);
}
}
private void hideButtons()
{
if (mButtonsVisible)
{
mButtonsVisible = false;
hideKeyboard();
Animation anim = new TranslateAnimation(0, 0, 0, mPageSlider.getHeight());
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationStart(Animation animation)
{
mPageNumberView.setVisibility(View.INVISIBLE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation)
{
mPageSlider.setVisibility(View.INVISIBLE);
}
});
mPageSlider.startAnimation(anim);
}
}
private void searchModeOn()
{
if (mTopBarMode != TopBarMode.Search)
{
mTopBarMode = TopBarMode.Search;
//Focus on EditTextWidget
showKeyboard();
}
}
private void searchModeOff()
{
if (mTopBarMode == TopBarMode.Search)
{
mTopBarMode = TopBarMode.Main;
hideKeyboard();
SearchTaskResult.set(null);
// Make the ReaderView act on the change to mSearchTaskResult
// via overridden onChildSetup method.
mDocView.resetupChildren();
}
}
private void makeButtonsView()
{
mButtonsView = getLayoutInflater().inflate(R.layout.buttons,null);
mPageNumberView = (TextView)mButtonsView.findViewById(R.id.pageNumber);
mPageNumberView.setVisibility(View.INVISIBLE);
mInfoView = (TextView)mButtonsView.findViewById(R.id.info);
mInfoView.setVisibility(View.INVISIBLE);
mPageSlider = (SeekBar)mButtonsView.findViewById(R.id.pageSlider);
mPageSlider.setVisibility(View.INVISIBLE);
}
private void search(int direction)
{
hideKeyboard();
int displayPage = mDocView.getDisplayedViewIndex();
SearchTaskResult r = SearchTaskResult.get();
int searchPage = r != null ? r.pageNumber : -1;
mSearchTask.go(mSearchString, direction, displayPage, searchPage);
}
#Override
public boolean onSearchRequested()
{
if (mButtonsVisible && mTopBarMode == TopBarMode.Search)
{
hideButtons();
}
else
{
showButtons();
searchModeOn();
}
return super.onSearchRequested();
}
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
if (mButtonsVisible && mTopBarMode != TopBarMode.Search) {
hideButtons();
} else {
showButtons();
searchModeOff();
}
return super.onPrepareOptionsMenu(menu);
}
}
EDIT
One item of note: the call get getActionView on the search item is returning null. I think this might have something to do with the problem. I then try and force it but I'm not sure that's right either. Here is the code in question:
protected ActionMode mActionModeSearch;
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback()
{
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
mSearchMenuPrev = (MenuItem) menu.findItem(R.id.pdf_menu_search_prev);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = (MenuItem) menu.findItem(R.id.pdf_menu_search_next);
mSearchMenuNext.setEnabled(false);
mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.pdf_menu_search_item));
// TODO this search functionality still isn't working
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
mSearchView=(SearchView)MenuItemCompat.getActionView(searchItem); // ALWAYS COMES BACK AS NULL
if(mSearchView==null)
{
//MenuItemCompat.setShowAsAction(searchItem,MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW|MenuItem.SHOW_AS_ACTION_ALWAYS);
MenuItemCompat.setShowAsAction(searchItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchView = new SearchView(MuPDFActivity.this);
MenuItemCompat.setActionView(searchItem, mSearchView);
}
if(mSearchView != null)
{
mSearchView.setIconifiedByDefault(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
}
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.pdf_menu_search_prev:
mSearchView.clearFocus();
hideKeyboard();
search(-1);
return true;
case R.id.pdf_menu_search_next:
mSearchView.clearFocus();
hideKeyboard();
search(1);
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode)
{
searchModeOff();
bPopoverLoaded = false;
mActionModeEdit = null;
mActionModeSearch = null;
resetHideToolbarsTimer();
}
};
EDIT 2:
I got the control to come up but now the "next" and "prev" menu items are gone. Also, the control is not left aligned. And, I still have to expand the search control.
Screenshot:
Here is the updated code that got me here:
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
mSearchMenuPrev = menu.findItem(R.id.pdf_menu_search_prev);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = menu.findItem(R.id.pdf_menu_search_next);
mSearchMenuNext.setEnabled(false);
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
MenuItemCompat.setShowAsAction(searchItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchView = new SearchView(MuPDFActivity.this);
MenuItemCompat.setActionView(searchItem, mSearchView);
//mSearchView.setIconifiedByDefault(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
return true;
}
If I call mSearchView.setIconified(false), I get the following screenshots. The menu items are all there but they are in overflow. If I expand overflow, I see the search menu but when I click on it, it goes back to my original problem of no edit box to enter search string. In other words, it looks like the first screenshot below when I click on "Search":
I finally had to build it manually. I changed the menu xml file to:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/pdf_menu_search_item"
android:title="#string/search"
android:icon="#drawable/ic_pdf_action_search"
app:showAsAction="ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</group>
I then changed the code in the ActionMode.Callback to manually build the menu and force the search control open. I think it might be overkill but it works:
private static final int PREV_MENU_ITEM_ID = 1;
private static final int NEXT_MENU_ITEM_ID = 2;
protected ActionMode mActionModeSearch;
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback()
{
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
// Load search action
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
MenuItemCompat.setShowAsAction(searchItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchView = new SearchView(MuPDFActivity.this);
MenuItemCompat.setActionView(searchItem, mSearchView);
MenuItemCompat.expandActionView(searchItem);
mSearchView.setIconifiedByDefault(false);
mSearchView.setIconified(false);
// Load prev and next menu items
mSearchMenuPrev = menu.add(0, PREV_MENU_ITEM_ID, 1, R.string.search_prev);
mSearchMenuPrev.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = menu.add(0, NEXT_MENU_ITEM_ID, 1, R.string.search_next);
mSearchMenuNext.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchMenuNext.setEnabled(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
search(1);
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case PREV_MENU_ITEM_ID:
mSearchView.clearFocus();
hideKeyboard();
search(-1);
return true;
case NEXT_MENU_ITEM_ID:
mSearchView.clearFocus();
hideKeyboard();
search(1);
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode)
{
searchModeOff();
bPopoverLoaded = false;
mActionModeEdit = null;
mActionModeSearch = null;
resetHideToolbarsTimer();
}
};
I hope this helps someone out there. What a pain!
How to check that the action overflow PopupMenu is now showing?
It is need for me when I trying to auto-hide ActionBar, and don't need to hide when ActionBar's overflow popup is showing.
You can override Activity.onMenuOpened and Activity.onPanelClosed to determine when the overflow menu or other sub-menus are showing, such as the ShareActionProvider. Here's an example:
/** True if an options menu has been opened, false otherwise */
private boolean mMenuOpened;
#Override
public boolean onMenuOpened(int featureId, Menu menu) {
mMenuOpened = true;
return super.onMenuOpened(featureId, menu);
}
#Override
public void onPanelClosed(int featureId, Menu menu) {
super.onPanelClosed(featureId, menu);
mMenuOpened = false;
}
Alternatively
ActionBarView subclasses AbsActionBarView which contains AbsActionBarView.isOverflowMenuShowing. Since these class are internal and hidden, you'll need to access it via reflection.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final int actionBarViewId = getResources().getIdentifier("action_bar", "id", "android");
final View actionBarView = findViewById(actionBarViewId);
actionBarView.postDelayed(new Runnable() {
#Override
public void run() {
System.out.println(isOverflowMenuShowing(actionBarView));
}
}, 2500);
}
private static boolean isOverflowMenuShowing(View actionBarView) {
try {
final Class<?> abv = Class.forName("com.android.internal.widget.ActionBarView");
final Method isOverflowShowing = abv.getMethod("isOverflowMenuShowing", new Class[] {});
return (boolean) isOverflowShowing.invoke(actionBarView, new Object[] {});
} catch (final Exception ignored) {
// Nothing to do
}
return false;
}
I am using the the SearchView in the ActionBar of the ListView. The magnifying glass can be touched, the SearchView shows its edit box, and the user can enter the text for filtering the content of the list. It almost works. However, when the user presses the Up button, the SearchView collapses back to the icon, the text inside the widget is cleared, and the filtering is reset. The effect (in my case) is that the list can be filtered only when the SearchView is not iconified. The wanted behaviour is to keep the filter text also after the SearchView was collapsed.
Attention: The behaviour probably changed in Android 4.3. With 4.2.2 it worked as wanted. See the observations below.
Details: To be more specific, the menu contains the following item:
<item android:id="#+id/menu_search_customers"
android:title="#string/menu_search_text"
android:icon="#android:drawable/ic_menu_search"
android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.widget.SearchView" />
Notice the icon and the android:showAsAction. I belive the Up button appears by default when the SearchView is expanded (by Up I mean the < plus the icon -- see the right image with the blue book from the official Navigation with Back and Up). It seems that the default handler implementation just collapses the expanded SearchView (returns back to the icon state).
When debugging, I have found that the onQueryTextChange() is fired with the empty text when the Up is used. (I believe this was not the case with Android 4.2.2, because it worked as wanted before the OS update.) This is the reason why the filtering of the list items is also reset -- see my onQueryTextChange() below. I want the SearchView collapsed, and the filter text displayed as subtitle in the action bar.
So far, my code related to the SearchView looks like this:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater adds the magnifying glass icon for the SearchView
// to the ActionBar as the always visible menu item.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.customers_menu, menu);
// Get the related SearchView widget.
SearchView sv = (SearchView) menu.findItem(R.id.menu_search_customers)
.getActionView();
// Get the changes immediately.
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
// I am not sure whether the onQueryTextSubmit() is important
// for the purpose.
#Override
public boolean onQueryTextSubmit(String query) {
getActionBar().setSubtitle(mCurFilter);
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
// The newText is stored into a member variable that
// is used when the new CursorLoader is created.
mCurFilter = newText;
getActionBar().setSubtitle(mCurFilter);
getLoaderManager().restartLoader(0, null,
CustomersOverviewActivity.this);
return true;
}
});
return true;
}
The restarted loader calls the onCreateLoader. Notice the mCurFilter is used for building the SQL query:
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { CustomerTable._ID,
CustomerTable.CODE,
CustomerTable.NAME,
CustomerTable.STREET,
CustomerTable.TOWN };
String selection = null; // init
String[] selectionArgs = null; // init
if ( ! mCurFilter.isEmpty()) {
selection = CustomerTable.NAME + " like ?";
selectionArgs = new String[]{ "%" + mCurFilter +"%" };
}
CursorLoader cursorLoader = new CursorLoader(this,
DemoContentProvider.CUSTOMERS_CONTENT_URI, projection,
selection, selectionArgs,
orderInfo);
return cursorLoader;
}
I would like to detect the situation when the Up is pressed before the onQueryTextChange() is called. This way (say) I could set a flag and block the mCurFilter assignment by the emptied SearchView content. Also, when the search icon is expanded again, I would like to initialize the text in the expanded SearchView from the mCurFilter before it is shown (i.e. the expanded view is preset with the filter text). How that can be done?
Update: The earlier implementation of the SearchView had...
#Override
public void onActionViewCollapsed() {
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
Now, it contains...
#Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
Do you know what could be the reason for setting the query to the empty string? Should I override the new implementation by the old code? Or is there a better way?
I have written a StatefulSearchView which retains the text:
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
public class StatefulSearchView extends SearchView implements android.view.View.OnLayoutChangeListener, OnQueryTextListener,android.widget.SearchView.OnCloseListener{
private boolean mSaveText=true;
private OnQueryTextListener mQueryListener;
private String mQuery;
private OnCloseListener mCloseListener;
private boolean fromIconify = true;
public StatefulSearchView(Context context, AttributeSet attrs) {
super(context, attrs);
addOnLayoutChangeListener(this);
super.setOnCloseListener(this);
}
public StatefulSearchView(Context context) {
super(context);
// TODO Auto-generated constructor stub
addOnLayoutChangeListener(this);
super.setOnCloseListener(this);
}
public void setSaveSearchTextState(boolean save){
this.mSaveText = save;
this.setSaveEnabled(mSaveText);
}
public void setOnStatefulQueryTextListener(OnQueryTextListener listener) {
mQueryListener = listener;
super.setOnQueryTextListener(this);
}
#Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if(super.isIconfiedByDefault() || !super.isIconified() && !TextUtils.isEmpty(mQuery) && mSaveText){
setSavedText(mQuery);
}
Log.i("onLayoutChanged()",""+mQuery);
}
#Override
public void setIconified(boolean iconify) {
mQuery = getQuery().toString();
Log.i("setIconified()",""+mQuery);
super.setOnCloseListener(null);
super.setIconified(iconify);
super.setIconified(iconify);
super.setOnCloseListener(this);
fromIconify = true;
}
#Override
public void setOnCloseListener(OnCloseListener listener) {
mCloseListener = listener;
super.setOnCloseListener(this);
}
#Override
protected Parcelable onSaveInstanceState() {
Parcelable state = super.onSaveInstanceState();
return new SearchQueryState(state, mQuery, mSaveText);
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
SearchQueryState sqs = (SearchQueryState)state;
super.onRestoreInstanceState(sqs.getSuperState());
mQuery = sqs.getSavedQuery();
mSaveText = sqs.getSaveText();
}
#Override
public boolean onQueryTextChange(String arg0) {
mQuery = arg0;
return mQueryListener.onQueryTextChange(mQuery);
}
#Override
public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
return mQueryListener.onQueryTextSubmit(arg0);
}
private TextView getTextView(){
int searchTextViewId = getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
return (TextView) this.findViewById(searchTextViewId);
}
private void setSavedText(String s){
super.setOnQueryTextListener(null);
Log.i("setSavedText()",""+s);
TextView t = getTextView();
t.setText(s);
if(!TextUtils.isEmpty(s))
((EditText)t).setSelection(s.length());
super.setOnQueryTextListener(mQueryListener);
}
private class SearchQueryState extends BaseSavedState{
private boolean mSaveText;
private String mQueryText;
public SearchQueryState(Parcel arg0) {
super(arg0);
this.mQueryText = arg0.readString();
this.mSaveText = arg0.readInt() == 1;
}
public SearchQueryState(Parcelable superState, String queryText, boolean saveText) {
super(superState);
this.mQueryText = queryText;
this.mSaveText = saveText;
}
public boolean getSaveText(){
return this.mSaveText;
}
public String getSavedQuery(){
return mQueryText;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
super.writeToParcel(dest, flags);
dest.writeString(mQueryText);
dest.writeInt(mSaveText? 1: 0);
}
}
#Override
public boolean onClose() {
Log.i("onClose()", "Is from setIconified(): "+fromIconify);
if(!fromIconify){
mQuery = null;
fromIconify = false;
}
return mCloseListener == null ? false : mCloseListener.onClose();
}
}
In demonstration activity:
public class MainActivity extends Activity{
private StatefulSearchView mSearchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().setHomeButtonEnabled(true);
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if(item.getItemId()==android.R.id.home) {
mSearchView.setIconified(true);
return true;
}
return super.onMenuItemSelected(featureId, item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem item = menu.findItem(R.id.action_search);
mSearchView =(StatefulSearchView)item.getActionView();
mSearchView.setSaveSearchTextState(true);
mSearchView.setOnStatefulQueryTextListener(new OnQueryTextListener(){
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}});
return true;
}
In menu xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_search"
android:orderInCategory="100"
android:showAsAction="always"
android:actionViewClass="com.nikola.despotoski.saveablesearchview.StatefulSearchView"
android:title="#string/action_settings"/>
</menu>
In the source of the SearchView, it clearly says that they change the text to "":
#Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
/**
* {#inheritDoc}
*/
#Override
public void onActionViewExpanded() {
if (mExpandedInActionView) return;
mExpandedInActionView = true;
mCollapsedImeOptions = mQueryTextView.getImeOptions();
mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
mQueryTextView.setText("");
setIconified(false);
}
Let me know if you have issues.
I'm not sure I understand your problem but you can just detect when up is clicked like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
doSOmething();
return true;
}
return super.onOptionsItemSelected(item);
}
If you intercept the up click, you can presumably do anything you want here. Returning true will consume the event and that should prevent any default action from taking place. This way you can do whatever you want the up button to do while at the same time consuming the up event to prevent clearing of your filters.
I struggle with this a little until I found the solution.
Declare your menuItem like this, check the showAsAction attribute, type only ifRoom, if you set collapseActionView the widget will collapse and show the back button on the actionbar
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/search"
android:actionViewClass="android.widget.SearchView"
android:icon="#drawable/ic_2_action_search"
android:showAsAction="ifRoom"
android:title="#null"/>
</menu>
Set up your SearchView as usual, remember to Add setIconifiedByDefault this will make the icon to start up as an icon
SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setIconifiedByDefault(true);
searchView.setOnQueryTextListener(new SearchViewOnQueryListener());
searchView.setOnCloseListener(new SearchViewOnCloseListener());
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
On your QueryListener is where you handle the end of your search like so, here is where you use onActionViewCollapse() which collapse back the ViewSearch
#Override
public boolean onQueryTextSubmit(String query) {
makeSearchRequest(SEARCH_TYPE_KEYWORD, query);
searchView.setQuery("", false);
searchView.clearFocus();
searchView.onActionViewCollapsed();
buttonClearSearchResults.setVisibility(View.VISIBLE);
return false;
}