I am using the method onRestoreInstanceState of android to get the information when the screen rotates and it works fine except for one thing.
When i try to set visible a menuItem that have initialized in onCreateOptionsMenu, it gets NullPointerException and is very important for the funcionality that the item apearrs
Does anyone know how to fix this?
Thanks a lot for the help
My method to initialize item
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.map, menu);
itemClean = menu.findItem((R.id.map_clear_lines));
return true;
}
My method to recover the info
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mapa.moveCamera(CameraUpdateFactory.newLatLngZoom(
(LatLng)savedInstanceState.getParcelable(MapConstants.MAP_CAMERA_LATLNG),
savedInstanceState.getFloat(MapConstants.MAP_CAMERA_ZOOM)));
if(savedInstanceState.getBoolean(MapConstants.MAP_TYPE)){
stateSatelitalMap();
}
if(savedInstanceState.containsKey(MapConstants.ROUTES_START)){
LatLng starLatLng = savedInstanceState.getParcelable(MapConstants.ROUTES_START);
LatLng finishLatLng = savedInstanceState.getParcelable(MapConstants.ROUTES_END);
markerStart = mapa.addMarker(new MarkerOptions().position(starLatLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_inici_fin))
.title(getResources().getString(R.string.marker_confirm_start)).snippet(getResources().getString(R.string.snippet_confirm_start)));
markerFinish = mapa.addMarker(new MarkerOptions().position(finishLatLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_inici_fin))
.title(getResources().getString(R.string.marker_confirm_end)).snippet(getResources().getString(R.string.snippet_confirm_end)));
getRoute(starLatLng, finishLatLng);
booleanEndConfirmed = true;
booleanStartConfirmed = true;
itemClean.setVisible(true);
}
everything works fine, except the final line, the menuItem don't cause problem when i use it witout rotation the screen
Following the recomendation of Tim Mutton, i created a global variable and setted in the OnCreateMenuOptions
private boolean booleanItemVisible = false;
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
...
booleanItemVisible = true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
...
itemClean.setVisible(booleanItemVisible);
return true;
}
Related
I have SearchView which I want to programmatically expand and set text when the device orientation change. I tried many found solution but nothing work. If I use only setQuery then my list is filtered, but when I use also expandActionView then the search view does not contain the given search text and onQueryTextChange is called twice, first with the given text and the second time with the empty text.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.activity, menu);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
MenuItem searchMenuItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
searchView.setIconifiedByDefault(true);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
searchView.setOnQueryTextListener(this);
MenuItemCompat.setOnActionExpandListener(searchMenuItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
mCurrentQueryString = null;
if (mAdapter != null) {
mAdapter.clearFilter();
mStopSearching = true;
}
return true;
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
if (mAdapter != null) {
mStopSearching = false;
}
return true;
}
});
mSearchView = searchView;
mSearchMenuItem = searchMenuItem;
mSearchView.post(new Runnable() {
#Override
public void run() {
MenuItemCompat.expandActionView(mSearchMenuItem);
mSearchView.setQuery(mCurrentQueryString, true);
}
});
super.onCreateOptionsMenu(menu, inflater);
}
I use the search view in the fragment which is used in the view pager. The fragment is retained. The problem is that onQueryTextChange function is called twice, by the second time with the empty text, but I am not sure why. This function is also called with the empty text when I first time open the search view when the fragment is initialized, but when close the serach view and open it again, this function is not called.
How can I fix it?
I've also faced that issue. The solution I've come up with was via posting with handler.
#Override public boolean onPrepareOptionsMenu(Menu menu) {
...
// SearchView doesn't retain it's state after orientation change
// have to handle it the bad way (╯°□°)╯︵ ┻━┻
boolean isQueryExists = !TextUtils.isEmpty(mSearchQuery);
if (isQueryExists) {
// Calling directly doesn't take effect
// Custom runnable class in order to refrain from context leakage
new Handler(Looper.getMainLooper()).post(new SearchMenuRunnable(mSearchView, mSearchQuery));
}
...
}
SearchMenuRunnable.java
public class SearchMenuRunnable implements Runnable {
private WeakReference<SearchView> mSearchViewWeakReference;
private String mSearchQuery;
public SearchMenuRunnable(SearchView searchView, String searchQuery) {
mSearchViewWeakReference = new WeakReference<>(searchView);
mSearchQuery = searchQuery;
}
#Override public void run() {
if (null != mSearchViewWeakReference.get()) {
SearchView searchView = mSearchViewWeakReference.get();
searchView.setIconified(false);
searchView.setQuery(mSearchQuery, true);
searchView.clearFocus();
}
}
This are source from one of projects in github. You can examine them here, it's pretty simple project.
The text i enter in searchView disappears on config change.
I am already handling the config change but still its not working.
As i have used fragments, so below code is written inside fragment.
Please solve my problem with respect to that.
My problem is i am not able to retrieve savedInstance in onActivityCreated method
Below is my code:
Snippets of useful code
private String searchQuery="";
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(savedInstanceState != null)
searchQuery = savedInstanceState.getString(Tag.SEARCH_QUERY);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(Tag.SEARCH_QUERY, searchQuery);
}
#Override
public void onCreateOptionsMenu(Menu menu,MenuInflater menuInflater) {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_search, menu);
MenuItem menuItem = menu.findItem(R.id.action_search);
SearchView searchView = null;
if (menuItem != null)
searchView = (SearchView) menuItem.getActionView();
if (searchView != null) {
searchView.setQuery(searchQuery,false);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
//searching is done in async task
searchQuery = query;
NetworkUtility.onProgressBarShow(getActivity());
MyAsyncTaskDownloadDetails myAsyncTaskDownloadDetails = new MyAsyncTaskDownloadDetails();
myAsyncTaskDownloadDetails.execute(new String[]{Tag.PLP_URL + query, Tag.PLP,""});
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
}
super.onCreateOptionsMenu(menu, menuInflater);
}
}
First of all you are saving queryText in onQueryTextSubmit callback which means searchQuerywill remain empty unless and until user have submitted query for search, so keep that in mind.
Secondly try following code. It will work I have tested it.
if(searchQuery.length()>0){
//See this commented code
// if(Utils.hasIceCreamSandwich()) {
// searchMenuItem.expandActionView();
// }else {
// MenuItemCompat.expandActionView(searchMenuItem);
// }
MenuItemCompat.expandActionView(menuItem);
searchView.setQuery(searchQuery, false);
}
I'm looking to hide a icons from the ActionBar depending on variables. Is there a simple way to do this?
Will I need to use onPrepareOptionsMenu() and if so how?
To hide menu items you should use the setVisible() method on your menu item inside your activity onPrepareOptionsMenu() override after your menu has been inflated. For example:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.example, menu);
if(showItem) {
menu.findItem(R.id.icon).setVisible(true);
} else {
menu.findItem(R.id.icon).setVisible(false);
}
return true;
}
If you have declared your variable inside onCreate(), it will be limited to the scope of onCreate() and therefore inaccessible inside onPrepareOptionsMenu().
For example, instead of this:
#Override
protected void onCreate(Bundle savedInstanceState) {
boolean showItem = false;
// ...
}
Declare it like this:
public boolean showItem = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
}
Also if you want to change the visibility on button press for example, you will need to call the invalidateOptionsMenu() method to reload the menu.
You need to call invalidateOptionsMenu() depending on your variable.
When you call invalidateOptionsMenu() the onPrepareOptionsMenu will be called , where you can hide/show the option menu like this..
#Override
public boolean onPrepareOptionsMenu(Menu menu){
for(int index = 0 ; index < menu.size() ; index ++){
MenuItem menuItem = menu.getItem(index);
if(menuItem != null) {
// hide the menu items
menuItem.setVisible(false);
}
}
return super.onPrepareOptionsMenu(menu);
}
I have Action Bar in my application. I am adding action items using menu.xml. I am using action bar-compat as my support library. I observed a weird issue where my action items are getting duplicated.
I am finding this issue randomly when leave my device idle or work with other applications. Please find the screen shot and my code below:
private LoginWebActivity mContext;
private final String TAG = "LoginFragment";
// for metrics
private String mPageNameSignIn = "signin";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.webview, container, false);
return mView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mContext = (LoginWebActivity) getActivity();
initFragment();
}
#Override
public void onResume() {
super.onResume();
}
/**
* Initialises the views and variables of the fragment.
*/
#SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
protected void initFragment() {
mWebView = (WebView) mView.findViewById(R.id.webView);
Bundle b = mContext.getIntent().getExtras();
if (b != null) {
mUrl = b.getString(Constants.EXTRA_WEB_LOGIN_URL);
}
super.initFragment();
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.signin, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Navigate
switch (item.getItemId()) {
case R.id.menu_item_signup:
mContext.onSignUpClick();
break;
case android.R.id.home:
if (!goBack())
getActivity().finish();
default:
break;
}
return super.onOptionsItemSelected(item);
}
My XML :
<?xml version="1.0" encoding="utf-8"?>
<item
android:id="#+id/menu_item_signup"
allergy:showAsAction="ifRoom"
android:title="#string/sign_up">
</item>
You must clear your menu object before adding items. I had the same problem and this was the best solution that I've found.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.signin, menu);
super.onCreateOptionsMenu(menu, inflater);
}
Pretty late to this party, but for anyone that comes across this via the Google like I did, here's the real problem.
You didn't post your Activity code that's creating the Fragment, but I will venture to guess that it looks something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Fragment fragment = ...
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
The problem with this is that when the activity goes through its lifecycle (which would happen "when leave my device idle or work with other applications", as you say), the system will save and restore the state of fragments for you. But with this code, you also are adding a new fragment to your Activity, so you end up with multiple fragments running in your activity, each adding an item to the menu.
While the posted workaround will address the duplicate menu entries issue, it would leave these extra fragment instances lying around, which is obviously not what you want.
The correct fix is a simple null check:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
if (savedInstanceState == null) {
Fragment fragment = ...
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
}
Since the system will indicate the activity is being recreated with a non-null Bundle for the savedInstanceState parameter, you check this to determine whether you should be creating and adding a new fragment.
Hope that helps.
i used Renan Bandeira's great solution and i had some error so i changed it a little bit and worked for me too . then I'm sharing my experience : maybe it become helpful again all credit goes to him for great solution .
#Override
public void onCreateOptionsMenu(Menu menu ) {
menu.clear();
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu."your current activity name ", menu);
return true;
}
I facing the same problem and exactly as state by #Szymon "I add menu option from the fragment, I create multiple fragments?" So my solution was look like below.
onCreate :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu, menu);
menu.findItem(R.id.action_one).setVisible(true);
menu.findItem(R.id.action_two).setVisible(false);
super.onCreateOptionsMenu(menu, inflater);
}
onPrepare :
#Override
public void onPrepareOptionsMenu(Menu menu) {
if (isAdded()
&& !isDetached()
&& isVisible()
&& !isRemoving()
)
{
// show the menu
if (menu.findItem(R.id.action_one).isVisible())
menu.findItem(R.id.action_one).setVisible(true);
// hide the menu
if (menu.findItem(R.id.action_two).isVisible())
menu.findItem(R.id.action_two).setVisible(false);
}
}
You should use the following method instead and you will not see the duplicates anymore (notice that it has only a Menu object as argument)
#Override
public boolean onCreateOptionsMenu( Menu menu )
{
getMenuInflater().inflate( R.menu.main_activity_menu, menu );
return true;
}
When I try to call a function from onCreate, the app stops working.
All i am trying to do, it change the text in textview, when the activity loads. Help?
public class BellSchedules extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bell_schedules);
BellSch(null);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.bell_schedules, menu);
return true;
}
public void BellSch(View view)
{
TextView bells = (TextView) findViewById(R.id.textView1);
int date = (Calendar.DAY_OF_WEEK);
String realDate = getString(date);
//bells.setText(realDate);
bells.setText("huehuehuehuehue");
}
getString method's argument is a resId, which needs to point to one of your resource ids. Reference here: http://developer.android.com/reference/android/content/Context.html#getString(int)
Try this instead:
String realDate = ""+date;
You need to put
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// do your work
return true;
}