I have to implement action mode in fragment, but its gets nullpointer exception in action mode. I have tried so much but not gets any results, Please help me I am new in android. I have also tried startActionMode but not impact. I have wasted my time & searched lot of code not found any solution. Please help me
public class GalleryFragment extends Fragment {
private GalleryViewModel galleryViewModel;
private ActionModeCallback actionModeCallback;
private ActionMode actionMode;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
galleryViewModel =
ViewModelProviders.of(this).get(GalleryViewModel.class);
View root = inflater.inflate(R.layout.fragment_gallery, container, false);
final TextView textView = root.findViewById(R.id.text_gallery);
galleryViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
final Button btnLoad = root.findViewById(R.id.load);
btnLoad.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
enableActionMode(1, true );
}
});
return root;
}
public void enableActionMode(int position, boolean bool) {
int count = 4;
if(actionMode == null) {
actionMode = ((AppCompatActivity)getActivity()).startSupportActionMode(actionModeCallback);
}
if (count == 0) {
actionMode.finish();
actionMode = null;
} else {
actionMode.setTitle(String.valueOf(count));
actionMode.invalidate();
}
}
private class ActionModeCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.actionbar_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// getSupportActionBar().hide();
menu.findItem(R.id.action_delete).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Log.d("API123", ""+item.getItemId());
switch (item.getItemId()) {
case R.id.action_delete:
// delete all the selected rows
//mode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
//clear selections
mode.finish();
actionMode = null;
}
}
}
This is mycode, null pointer in actionmode. please help me i wasting my time. searching lot of, no result found
Related
I need Add SearchBar in ActionBar handle with more Fragments like whatsApp
when Search in Tab chats get data and when Search in Tab Status get another data
How do This?This is My Code there is 3 tabs i need every tab there is SearchView
This Activity which there is on Fragments
public class ActivityForIncludeFragments extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_for_include_fragments);
ViewPager viewPager = (ViewPager)findViewById(R.id.viewPager);
CategoryAdapter adapter = new CategoryAdapter(this,getSupportFragmentManager());
viewPager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
invalidateOptionsMenu();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem menuItemAddData = menu.findItem(R.id.add_data);
MenuItem menuItemActionSearch = menu.findItem(R.id.action_search);
menuItemAddData.setVisible(false);
menuItemActionSearch.setVisible(false);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.add_stocking_warehouse:
Intent intent = new Intent(ActivityForIncludeFragments.this,StockingWarehouse.class);
startActivity(intent);
break;
case R.id.add_reportes:
Intent intentReport = new Intent(ActivityForIncludeFragments.this,TableDaliyMovmentes.class);
startActivity(intentReport);
break;
}
return super.onOptionsItemSelected(item);
}
}
and This Fragment there is the data
public class AddPremissionFragment extends Fragment implements
LoaderManager.LoaderCallbacks<ArrayList<ItemsStore>>
,SearchView.OnQueryTextListener {
public AddPremissionFragment() {
// Required empty public constructor
}
public static final String ID_PERMISSION = "id";
public static final String NAME_PERMISION = "namePErmission";
public static final String NOTES_PERMISSION = "notes";
public static final String DIALOG_PERMISSION = "dialogPermission";
FloatingActionButton fab_add_permission;
ListView mListView;
public static AdapterAddPermission adapterAddPermission;
TaskDbHelper dbHelper;
ArrayList<ItemsStore> itemsPermissions = new ArrayList<ItemsStore>();
private ProgressBar progressBarPermission;
//Identifier for the category dataloader;
public static final int PERMISSION_LOADER = 2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_add_premission, container, false);
TextView namePremission = (TextView)view.findViewById(R.id.ETTypeStore);
dbHelper = new TaskDbHelper(getActivity());
mListView = (ListView) view.findViewById(R.id.listViewAddPermission);
progressBarPermission =(ProgressBar)view.findViewById(R.id.progressBarPermission);
adapterAddPermission = new AdapterAddPermission(getContext(), itemsPermissions);
View emptyView = view.findViewById(R.id.empty_view_permission);
mListView.setEmptyView(emptyView);
mListView.setAdapter(adapterAddPermission);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Toast.makeText(getContext(), "Click :"+ position, Toast.LENGTH_SHORT).show();
ItemsStore itemSPermision = itemsPermissions.get(position);
Bundle bundle = new Bundle();
bundle.putInt(ID_PERMISSION, itemSPermision.getId());
bundle.putString(NAME_PERMISION, itemSPermision.getNamePermission());
bundle.putString(NOTES_PERMISSION, itemSPermision.getNotes());
// startActivity(intent);
// long id = cursor.getLong(cursor.getColumnIndex(TaskContract.TaskEntry._ID));
EditPermissionFragment f = new EditPermissionFragment();
f.setArguments(bundle);
f.show(getFragmentManager(),DIALOG_PERMISSION);}});
// namePremission.setText("Name Permission");
fab_add_permission = (FloatingActionButton)view.findViewById(R.id.fab_add_permission);
fab_add_permission.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new EditPermissionFragment().show(getFragmentManager(),DIALOG_PERMISSION);
}
});
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//Kick off the loader
getActivity().getSupportLoaderManager().initLoader(PERMISSION_LOADER, null, this);
}
#Override
public Loader<ArrayList<ItemsStore>> onCreateLoader(int id, Bundle args) {
return new LoaderPErmission(getContext().getApplicationContext(),itemsPermissions,dbHelper);
}
#Override
public void onLoadFinished(Loader<ArrayList<ItemsStore>> loader, ArrayList<ItemsStore> data) {
progressBarPermission.setVisibility(View.GONE);
mListView.setVisibility(View.VISIBLE);
adapterAddPermission.swapData(data);
}
#Override
public void onLoaderReset(Loader<ArrayList<ItemsStore>> loader) {
adapterAddPermission.swapData(Collections.<ItemsStore>emptyList());
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
// Inflate the menu; this adds items to the action bar if it is present.
getActivity().getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem menuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem);
searchView.setOnQueryTextListener(this);
super.onCreateContextMenu(menu, v, menuInfo);
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
itemsPermissions = dbHelper.getAllItemsPermissionBySearch(newText);
if (itemsPermissions !=null){
adapterAddPermission.setFilter(itemsPermissions);
// getSupportLoaderManager().restartLoader(Daily_LOADER,null,this);
}
return false;
}
}
Please check which fragment is visible using this
Fragment fragment = getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (fragment != null && fragment.isVisible()) {
if (fragment instanceof ChatFragment) {
....
}
else { }
}
Hello hoping someone can see what the problem is. Trying to grab data from firebase database and show it in a using FirebaseRecyclerAdapter but it only shows the data after I click on the searchview in the actionbar. Just can't figure out why.
public class CustomerFragment extends Fragment{
private FirebaseRecyclerAdapter<Customer,CustomerViewHolder> customerAdapter;
final String TAG = "CustomerFrag: ";
private EventBus eventBus = EventBus.getDefault();
private DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
private DatabaseReference customerRef = rootRef.child("customers");
private RecyclerView rvCustomer;
public CustomerFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
((AppStart)getActivity()).getSupportActionBar().setSubtitle("Customer List");
setHasOptionsMenu(true);
Log.d(TAG," onCreate");
}
// Inflate the menu; this adds items to the action bar if it is present.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu,inflater);
menu.clear();
inflater.inflate(R.menu.toolbar_customermenu, menu);
MenuItem searchItem = menu.findItem(R.id.customerSearch);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setQueryHint("Search Customer");
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
Log.d(TAG," onCreateOptionsMenu");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_customer, container, false);
rvCustomer = (RecyclerView)rootView.findViewById(R.id.rvCustomer);
rvCustomer.setHasFixedSize(true);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
rvCustomer.setLayoutManager(manager);
Log.d(TAG," onCreateView");
customerAdapter = new FirebaseRecyclerAdapter<Customer,CustomerViewHolder>(Customer.class, R.layout.customer_cardview, CustomerViewHolder.class, customerRef) {
#Override
protected void populateViewHolder(CustomerViewHolder viewHolder, final Customer customer, final int position) {
Log.d(TAG," populateViewHolder");
viewHolder.tvCustomerName.setText(customer.getCustomerName());
viewHolder.tvCustomerAddress.setText(customer.getCustomerAddress());
viewHolder.tvCustomerTel.setText(customer.getCustomerTel());
}
};
rvCustomer.setAdapter(customerAdapter);
return rootView;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
AppCompatActivity activity = (AppCompatActivity) getContext();
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
Log.d(TAG," onOptionsItemsSelected");
switch (item.getItemId()) {
case R.id.customerSearch:
Log.d(TAG,"Search icon pressed");
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
static class CustomerViewHolder extends RecyclerView.ViewHolder{
private TextView tvCustomerName;
private TextView tvCustomerAddress;
private TextView tvCustomerTel;
private CardView cvCustomer;
public CustomerViewHolder(View itemView) {
super(itemView);
tvCustomerName = (TextView)itemView.findViewById(R.id.tvCustomerName);
tvCustomerAddress = (TextView)itemView.findViewById(R.id.tvCustomerAddress);
tvCustomerTel = (TextView)itemView.findViewById(R.id.tvCustomerTel);
cvCustomer = (CardView)itemView.findViewById(R.id.cvCustomer);
Log.d("CustFragment"," CustomerViewHolder");
}
}
}
after days of hitting my head I figured it was the recyclerView layout height was not set to match_parent both the height and the width have to be match_parent.
Hope this helps someone.
Whenever I move from DetailsActivity to MainActivity the RecyclerView is reset and list is always shown from the top position.
Full source code can be seen here. The code is still largely a work in progress.
MainActivityFragment is as follows.
public class MainActivityFragment extends Fragment {
private ArrayList<Movie> mMovieArrayList = new ArrayList<Movie>();
private static final String PAGE = "1";
private RecyclerView mRecyclerView;
private SharedPreferences mSettings;
private SharedPreferences.Editor mEditor;
private static final String LOG = MainActivityFragment.class.getSimpleName();
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_movie_list, container, false);
// Set column size to 2 for default and portrait
// and 3 for landscape orientations
int column = Integer.parseInt(getString(R.string.grid_portrait));
if (getResources().getConfiguration().orientation == 1) {
column = Integer.parseInt(getString(R.string.grid_portrait));
} else if (getResources().getConfiguration().orientation == 2) {
column = Integer.parseInt(getString(R.string.grid_landscape));
}
if (getActivity().findViewById(R.id.movie_detail_container) != null) {
column = Integer.parseInt("2");
}
mSettings = PreferenceManager.getDefaultSharedPreferences(getActivity());
mEditor = mSettings.edit();
mEditor.apply();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), column));
mRecyclerView.setAdapter(new MovieAdapter(getActivity(), mMovieArrayList));
return rootView;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onStart() {
super.onStart();
updateMovieList();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main_fragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.popularity:
mEditor.putString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_popularity));
mEditor.apply();
updateMovieList();
item.setChecked(true);
Log.d(LOG, "onOptionsItemSelected: popularity");
return true;
case R.id.rating:
mEditor.putString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_top_rated));
mEditor.apply();
updateMovieList();
item.setChecked(true);
Log.d(LOG, "onOptionsItemSelected: rating");
return true;
case R.id.favorite:
mEditor.putString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_favorite));
mEditor.apply();
updateMovieList();
item.setChecked(true);
Log.d(LOG, "onOptionsItemSelected: favorite");
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
String sortBy = mSettings.getString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_popularity));
if (sortBy.equals(getResources().getString(R.string.url_popularity))) {
menu.findItem(R.id.popularity).setChecked(true);
} else if (sortBy.equals(getResources().getString(R.string.url_top_rated))) {
menu.findItem(R.id.rating).setChecked(true);
} else if (sortBy.equals(getResources().getString(R.string.url_favorite))) {
menu.findItem(R.id.favorite).setChecked(true);
}
}
private void updateMovieList() {
mMovieArrayList = new ArrayList<>();
String sortBy = mSettings.getString(getResources().getString(R.string.perf_sort),
getResources().getString(R.string.url_popularity));
if (sortBy.equals(getResources().getString(R.string.url_popularity)) ||
sortBy.equals(getResources().getString(R.string.url_top_rated))) {
try {
mMovieArrayList =
new FetchMoviesTask().execute(sortBy, PAGE).get();
} catch (ExecutionException | InterruptedException ei) {
ei.printStackTrace();
}
} else if (sortBy.equals(getResources().getString(R.string.url_favorite))) {
ContentResolver resolver = getActivity().getContentResolver();
Cursor cursor =
resolver.query(MovieContract.MovieEntry.CONTENT_URI,
null,
null,
null,
null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
String title = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.TITLE));
String movie_id = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.MOVIE_ID));
String poster = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.POSTER));
String backdrop = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.BACKDROP));
String overview = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.OVERVIEW));
String vote_average = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.VOTE_AVERAGE));
String release_date = cursor.getString(cursor.getColumnIndex(MovieContract.MovieEntry.DATE));
Movie movie = new Movie(title, release_date, poster,
vote_average, overview, backdrop, movie_id);
mMovieArrayList.add(movie);
} while (cursor.moveToNext());
}
}
if (cursor != null)
cursor.close();
}
mRecyclerView.setAdapter(new MovieAdapter(getActivity(), mMovieArrayList));
mRecyclerView.getAdapter().notifyDataSetChanged();
}
}
MainActivity is as follows.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#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_main, menu);
return 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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
// if (id == android.R.id.home) {
// onBackPressed();
// return true;
// }
return super.onOptionsItemSelected(item);
}
}
I have tried setting saving up RecyclerView's state like shown in this post.
I have also tried saving the mArrayList in onSaveInstanceState and restoring it in onActivityCreated or onViewCreated like in this post.
Both of these have not worked for me. As soon as I return back from the DetailsActivity to MainActivity the position is gone.
Thanks.
You're calling a method to update movies list in onStart callback of fragment life cycle. Which means when your main activity is shown back, you're resetting your list. You shouldn't.
You set a new instance of adapter at the end of update list method. That redraws the entire list. You should rethink your life cycles. Call update movie list only in onCreate or onCreateView and always check if adapter opject is null and only then use setAdapter method on recycler view. If adapter is not null, just call notifyDataSetChanged or whatever is needed to update your items.
Maybe this could help. Eventhough it will scroll all the way to the selected item each time.
I've implemented a ListView in the sense of a master detail view:onItemClick() calls new Activity with details according to the list item.
onItemLongClick calls ActionMode.Callback to provide the selection of multiple list items. I already solved the problem to avoid calling onItemClick() when an item should be selected by returning true in onItemLongClick().
The problem is the selection is made/is visualized after I clicked an item and returned from the activity.
Please not the standard listSelector. I'm not sure if this is the correct way/solution. I tried to implement a custom listSelector but it did not work properly.
Any suggestions?
XML of the ListView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ResultFragment" >
<!-- standard list_selector_background -->
<ListView
android:id="#+id/fragment_ergebnis_listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="multipleChoice"
android:divider="#color/gray_3"
android:dividerHeight="1dp"
android:listSelector="#android:drawable/list_selector_background"
android:saveEnabled="true" >
</ListView>
</LinearLayout>
Code of the Fragment
public class ResultPOJOFragment extends Fragment implements OnItemClickListener, OnItemLongClickListener {
private Activity mActivity;
private ActionModeCallback mActionModeCallback;
private ActionMode mActionMode;
private ListView mListView;
private ResultAdapter mAdapter;
private ResultDAO mResultDAO;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mActivity = getActivity();
mResultDAO = new ResultDAO(mActivity);
View fragmentView = inflater.inflate(R.layout.fragment_result, container, false);
mAdapter = new ResultAdapter(mActivity);
mListView = (ListView) fragmentView.findViewById(R.id.fragment_result_listView);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener((OnItemClickListener) this);
mListView.setOnItemLongClickListener((OnItemLongClickListener) this);
mActionModeCallback = new ActionModeCallback();
return fragmentView;
}
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
ResultPOJO result = new ResultPOJO();
result = mAdapter.getItem(position);
/* Show activity with details */
Intent resultDetailsIntent = new Intent(getActivity(), ResultPOJODetailsActivity.class);
if (resultDetailsIntent != null) {
resultDetailsIntent.putExtra(AppConstants.TAG_RESULT, result);
startActivity(resultDetailsIntent);
}
}
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (mActionMode != null) {
/* true: to avoid calling onItemClick() */
return true;
} else {
mActionMode = mActivity.startActionMode(mActionModeCallback);
view.setSelected(true);
}
mActionMode = mActivity.startActionMode(new ActionModeCallback());
return true;
}
private void selectAllEntries() {
for (int i = 0; i < mListView.getChildCount(); i++) {
mListView.setItemChecked(i, true);
}
}
private void deselectAllEntries() {
for (int i = 0; i < mListView.getChildCount(); i++) {
mListView.setItemChecked(i, false);
}
}
private void refreshView() {
mAdapter.notifyDataSetChanged();
}
private class ActionModeCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.result_fragment_cab, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_cab_result_fragment_select_all:
selectAllEntries();
break;
case R.id.menu_item_cab_result_fragment_deselect_all:
deselectAllEntries();
break;
default:
break;
}
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
}
}
I'm having a strange problem using an ActionView in my Actionbar (specifically ActionbarSherlock). This issue is only happening in devices below SDK 3.0 (basically Gingerbread devices is all I'm testing on).
My app has a ViewPager and I am animating one of my menu items while an AsyncTask is running. If I touch the ActionView before swiping everything is ok, if I swipe to any of the views, then go back to the first view, which is the only view to have the ActionView, and touch the ActionView the icon is doubling up on itself, like so:
I had this same issue previously, before I implemented a ViewPager, and I fixed it by stopping and starting the animation in onCreateOptionsMenu and calling invalidateMenuOptions, which is why I have ActivityCompat.invalidateOptionsMenu(this); in onResume of the Activity. I was hoping, by calling that, the menu would refresh itself and fix the duplicating, but it isn't.
UPDATE Using getSherlock().dispatchInvalidateOptionsMenu(); seems to, at least, get the menu to refresh itself, but it causing the ActionView to go nuts.
ViewPager:
public class Main extends SherlockFragmentActivity
{
private static List<Integer> mIds;
private static SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>();
#Override
public void onCreate(final Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
mViewPager = (ViewPager)findViewById(R.id.viewpager);
mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mMyFragmentPagerAdapter);
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
GetListingFragment().StopAnimation(); //needed to add this because the ActionView was showing on the other views when swiping
}
#Override
public void onPageScrolled(int position, float offset, int offsetPixel) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
mIds = new ArrayList<Integer>();
mIds.add(0);
mIds.add(1);
mIds.add(2);
}
#Override
public void onResume()
{
super.onResume();
ActivityCompat.invalidateOptionsMenu(this);
}
private ListingFragment GetKeywordsFragment()
{
ListingFragment lf = (ListingFragment)getSupportFragmentManager().findFragmentById(R.id.fragmentListing);
if (lf == null)
{
final MyFragmentPagerAdapter fpa = (MyFragmentPagerAdapter)mViewPager.getAdapter();
lf = (ListingFragment)fpa.getFragment(0);
}
return lf;
}
private static class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
if (index == 0)
{
final ListingFragment lf = ListingFragment.newInstance();
mPageReferenceMap.put(index, lf);
return lf;
}
else
{
final DetailFragment df = DetailFragment.newInstance(mIds.get(index));
mPageReferenceMap.put(index, df);
return df;
}
}
public Fragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
#Override
public int getCount() {
return 3;
}
}
}
Fragment:
public class ListFragment extends SherlockListFragment
{
private int mId;
private MenuItem refreshItem;
private AsyncTask<Void, String, Void> gi;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public static ListingFragment newInstance(int id) {
ListingFragment lf = new ListingFragment();
Bundle bundle = new Bundle();
bundle.putInt("id", id);
lf.setArguments(bundle);
return lf;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (getArguments() != null)
mId = getArguments().getInt("id");
return inflater.inflate(R.layout.listing, container, false);
}
private class GetItems extends AsyncTask<Void, String, Void> {
#Override
protected void onPreExecute()
{
StartAnimation();
}
#Override
protected Void doInBackground(Void... unused)
{
//background process to get items
}
protected void onPostExecute(final Void unused)
{
StopAnimation();
}
}
#Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.keyword_menu, menu);
StopAnimation();
refreshItem = menu.findItem(R.id.refresh);
if (fi != null && fi.getStatus() == AsyncTask.Status.RUNNING)
StartAnimation();
super.onCreateOptionsMenu(menu, inflater);
}
private void StartAnimation() {
if (refreshItem != null && refreshItem.getActionView() == null)
{
final LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ImageView ivRefresh = (ImageView)inflater.inflate(R.layout.refresh_view, null);
final Animation rotation = AnimationUtils.loadAnimation(activity, R.anim.refresh);
ivRefresh.startAnimation(rotation);
refreshItem.setActionView(ivRefresh);
}
}
public void StopAnimation()
{
if (refreshItem != null && refreshItem.getActionView() != null)
{
refreshItem.getActionView().clearAnimation();
refreshItem.setActionView(null);
}
}
#Override
public boolean onOptionsItemSelected(final MenuItem item)
{
if (item.getItemId() == R.id.getitems) {
gi = new GetItems(getActivity(), null);
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
}
Looks like this is a known bug in ABS:
https://github.com/JakeWharton/ActionBarSherlock/issues/331