I am trying use the actionbarcompat (with the android support library) following the android developer's blog entry.
Basically, I am trying create a Fragment extending the ListFragment. I am using an ArrayAdapter for the listview. I was able to successfully integrate the actionbar compat with a search menu item and could get the search working as well.
I now want to retain the state of the fragment on orientation change as well. I haven't set the setRetainInstance(true) in my fragment. Inorder to retain the state of the search view, i tried the following:
save the text in the SearchView in onSaveInstanceState()
in onCreateView, retrieve the searchText if available
in onCreateOptionsMenu (which would be invoked on every orientation change), I am trying to set the search query to the SearchView instance mSearchView.setQuery(mSearchText, false);
There are 2 issues that I see with this approach:
the onQueryTextChange() is called twice on orientation change - once with the searchText that has been retained (because of mSearchView.setQuery(mSearchText, false);) and again, with an empty String value. This second call with the empty String value updates the list adapater to have all the items without any filtering. I am also not really sure why this is happening.
mSearchView.setQuery(mSearchText, false); isn't setting the query in the SearchView and is not visible in the UI as well (on orientation change, the search view is expanded by default and is focused without any text value though I have set the query).
Outline of my Fragment is as follows:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create and initialize list adapter
....
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.plainlist, container, false);
if (savedInstanceState != null) {
mSearchText = savedInstanceState.getString(RetainDataKeySearchText, null);
}
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
if (isAdded()) {
if (mSearchView != null) {
String searchText = mSearchView.getQuery().toString();
if (!TextUtils.isEmpty(searchText))
outState.putString(RetainDataKeySearchText, searchText);
}
}
super.onSaveInstanceState(outState);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.search_item_list, menu);
MenuItem searchItem = menu.findItem(R.id.menu_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
mSearchView.setOnQueryTextListener(this);
if (!TextUtils.isEmpty(mSearchText))
mSearchView.setQuery(mSearchText, false);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed.
searchItems(newText);
return true;
}
#Override
public boolean onQueryTextSubmit(String searchText) {
return true;
}
private void searchItems(String searchText) {
// filter results and update the list adapter
}
The menu xml (search_item_list) file is as follows:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sprinklr="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/menu_search"
android:icon="#android:drawable/ic_menu_search"
android:title="#string/search"
android:orderInCategory="0"
sprinklr:showAsAction="ifRoom|collapseActionView"
sprinklr:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
I would like to know if there is anything that I am missing or if there is a better alternate to retain the state of the SearchView (android.support.v7.widget.SearchView) on orientation change in a ListFragment with actionbarcompat.
As a workaround, replace your
mSearchView.setQuery(mSearchText, false);
with:
final String s = mSearchText;
mSearchView.post(new Runnable() {
#Override
public void run() {
mSearchView.setQuery(s, false);
}
});
It will set the saved string after the system has set the empty string.
I did it with AppCompatActivity rather than with Fragment. I used the equivalent solution as above but the search text wasn't visible even with the post on the search view. I added the menu item expansion before:
mSearchView.post(() -> {
searchItem.expandActionView();
mSearchView.setQuery(mSearchText, false);
mSearchView.clearFocus();
});
Related
I am use data from web using XML parser and setting data using custom adapter for this use asyncTask .
My problem is that some devices like Samsang duos,gallaxy work perfectly but on micromax devices it will not work properly.
My adapter is
public class HallBookingAdapter extends ArrayAdapter<MyHall> {
private Context context;
private ArrayList<MCCIAHall> halls;
private int resource;
MyHall objHall;
public int count;
View view;
public static Boolean isScrollingHalls=true;
LayoutInflater inflater;
static class HallBookingHolder
{
public TextView txtTitle,txtLocation,txtCapacity,txtCapacityTitle;
public ImageView imgHall;
public LinearLayout hallBookingLayout;
}
public HallBookingAdapter(Context context, int resource, ArrayList<MyHall> halls) {
super(context, resource, halls);
this.context=context;
this.halls=halls;
this.resource=resource;
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
count=halls.size();
return halls.size();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
view=convertView;
objHall=halls.get(position);
HallBookingHolder holder=new HallBookingHolder();
if (convertView==null) {
view = inflater.inflate(resource, null);
holder.txtTitle=(TextView)view.findViewById(R.id.txtListHallTitle);
holder.txtLocation=(TextView)view.findViewById(R.id.txtListHallLocation);
holder.txtCapacity=(TextView)view.findViewById(R.id.txtListHallCapacity);
holder.txtCapacityTitle=(TextView)view.findViewById(R.id.txtListHallCapacityHeadding);
holder.imgHall=(ImageView)view.findViewById(R.id.imgListHall);
view.setTag(holder);
}
else
{
holder = (HallBookingHolder)convertView.getTag();
}
//Creating the Font to the text
Typeface tfLight = Typeface.createFromAsset(context.getAssets(),"OpenSans-Light.ttf");
Typeface tfRegular = Typeface.createFromAsset(context.getAssets(),"OpenSans-Regular.ttf");
Typeface tfsemiBold = Typeface.createFromAsset(context.getAssets(),"OpenSans-Semibold.ttf");
//Setting the font
holder.txtTitle.setTypeface(tfRegular);
holder.txtLocation.setTypeface(tfLight);
holder.txtCapacity.setTypeface(tfsemiBold);
holder.txtCapacityTitle.setTypeface(tfLight);
//Setting data to textview and image
holder.txtTitle.setText(objHall.hallName);
holder.txtLocation.setText(objHall.location);
holder.txtCapacity.setText(objHall.capacity);
//Using Guild Library Image Load using image web url
String imgurl=objHall.getImageUrl();
Glide.load(imgurl).centerCrop().into(holder.imgHall);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(context, HallDetailsActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
}
});
return view;
}
}
read it listview smooth-scrolling
Using a background thread ("worker thread") removes strain from the
main thread so it can focus on drawing the UI. In many cases, using
AsyncTask provides a simple way to perform your work outside the main
thread. AsyncTask automatically queues up all the execute() requests
and performs them serially. This behavior is global to a particular
process and means you don’t need to worry about creating your own
thread pool.
check this too http://www.itworld.com/development/380008/how-make-smooth-scrolling-listviews-android
Put all your font styles in the if (convertView==null) {} block to set them only once. Now you are setting them every time a new row is created.
Here is a list of quick tips to help you.
Reduce the number of conditions used in the getView of your adapter.
Check and reduce the number of garbage collection warnings that you get in the logs
If you're loading images while scrolling, get rid of them.
Set scrollingCache and animateCache to false (more on this later)
Simplify the hierarchy of the list view row layout
Use the view holder pattern
Here is a link to help you implement these tips. Link
The Context
I have a HomeActivity that contains a NewsFragment. The NewsFragment contains a ListView to display news items in a list. I have a ViewPager that is added as a header-view to the ListView. This ViewPager appears as a header to the list and contains a DateFragment to display the date. The first time the user opens the HomeActivity, I want "TODAY" to be the date. When the user swipes the DateFragment to the left, I want the date text to show "TOMORROW". Swipe again and it should show the day after tomorrow. Similarly, when the user swipes in the other direction, I want to display "YESTERDAY", the day before yesterday etc. The ViewPager should support swiping infinitely (or a very large number) in both directions.
Here's how they are nested - http://tinypic.com/r/31623qw/8. (I don't have the reputation to post images yet, but this diagram is super useful for understanding this question).
The Problem
For simplicity, I'm displaying the index of the fragment as the date. When I first open the app, I see "Date: 0" being displayed as the date in the DateFragment. When I swipe the fragment to the left (to go to the next day), I can see the next fragment appear with "Date: 1" being displayed, but almost immediately, the fragment disappears. Once the fragment disappears, nothing reappears, and I just see an empty container. I can swipe to bring back the "Date: 0" Fragment, but I can't see any other Fragments. (I'm using the - Infinite View Pager by Antony T. - https://github.com/antonyt/InfiniteViewPager)
The Gory Details
I have a HomeActivity that contains a NewsFragment. The NewsFragment contains a ListView to display news items as a list. Here is the layout.xml for the NewsFragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
I have a ViewPager that is dynamically added as a header to this list. So inside NewsFragment, I first initialize the ListView:
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.home_news_fragment, container, false);
list = (ListView) view.findViewById(android.R.id.list);
emptyView = view.findViewById(android.R.id.empty);
list.setEmptyView(emptyView);
return view;
}
Next, in onActivityCreated(), I initialize and load the header for the ListView, and then load the news feed items:
#Override
public void onActivityCreated(final Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
loadHeader();
loadNewsFeed();
}
In the loadHeader() method, I then dynamically create a LinearLayout container to contain my ViewPager. I create a PagerAdapter for the ViewPager and I wrap it with an InfiniteViewPager to allow infinite swiping in both directions. I then create a ViewPager and I add it to the LinearLayout container. I then add the container as a Header View to the ListView:
private void loadHeader()
{
final LinearLayout headerContainer = new LinearLayout(getActivity());
headerContainer.setId(R.id.header_container_id);
headerContainer.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
headerContainer.setOrientation(LinearLayout.VERTICAL);
// initialize the pager adapter for the view pager
PagerAdapter pagerAdapter = new HeaderPagerAdapter(getActivity().getSupportFragmentManager());
// Create a view pager. I use a custom implementation of a view pager I found from another Stackoverflow answer - WrapContentHeightViewPager - that allows ViewPager's layout.height to wrap content. The original ViewPager does not allow wrapping of content.
WrapContentHeightViewPager mViewPager = new WrapContentHeightViewPager(getActivity());
mViewPager.setId(R.id.view_pager_header);
mViewPager.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
// wrap pager to provide infinite paging with wrap-around
PagerAdapter wrappedAdapter = new InfinitePagerAdapter(pagerAdapter);
mViewPager.setAdapter(wrappedAdapter);
// Add the view pager to the header container
headerContainer.addView(mViewPager);
// add the container as a header view to the list
list.addHeaderView(headerContainer);
}
In the loadNewsFeed() method, I do an async fetch of the news feed items and populate the list by adding the items into the footer view. I won't go into the implementation details for this - outside the scope of this question.
The NewsFragment contains my pager adapter, which contains the getItem method that initializes the Fragment to be displayed by the ViewPager:
private class HeaderPagerAdapter extends FragmentPagerAdapter
{
public HeaderPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
return DateFragment.newInstance(i);
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
}
And here is the actual Fragment to be displayed inside the ViewPager:
public class DateFragment extends Fragment
{
private int index;
TextView date;
public static final DateFragment newInstance(int index) {
DateFragment fragment = new DateFragment();
final Bundle args = new Bundle(1);
args.putInt(Constants.Extras.PAGE_INDEX, index);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
index = getArguments() != null ? getArguments().getInt(Constants.Extras.PAGE_INDEX) : 1;
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
{
View v = (ViewGroup) inflater.inflate(R.layout.summary_fragment, container, false);
date = (TextView) v.findViewById(R.id.tvDate);
return v;
}
#Override
public void onActivityCreated(final Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
date.setText("Date: " + index);
}
}
For now I am simply using the index to be displayed as the date. I want to replace this with the actual date. Why does the fragment disappear on swipe?
Considerations:
Is there a refresh/redraw event that gets called?
Does it have to do with extending FragmentPagerAdapter vs. FragmentStatePagerAdapter
Override destroyItem() or instantiateItem()?
Set up a onPageScrolled listener on the ViewPager and then handle the page scroll events? I tried thehayro.blogspot.com/2012/12/enable-infinite-paging-with-android.html and that causes my fragments to disappear and then appear after a while.
Is it because I am adding the ViewPager as a header to the list view? The list view scrolls up and down and the view pager left and right. I've added this to my ViewPager implementation to tell the list view to stop intercepting our touch events:
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
// Tell our parent to stop intercepting our events!
boolean ret = super.onInterceptTouchEvent(ev);
if (ret)
{
getParent().requestDisallowInterceptTouchEvent(true);
}
return ret;
}
I'm sorry about the length of this post. I felt this much detail might be necessary. Thoughts?
I'm trying to implement a viewpager with a PagerSlidingTabStrip instead of a TabView. The viewpager has three tabs in which each listview displays a list of events. The three tabs are called Past, Tonight and Future.
I've set up the slider as the github page suggests:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.all_events_main_strip, container, false);
// Set up the ViewPager, attaching the adapter and setting up a listener for when the
// user swipes between sections.
pager = (ViewPager) v .findViewById(R.id.pager_main);
tabs = (PagerSlidingTabStrip) v.findViewById(R.id.tabs);
adapter = new MyPagerAdapter(getFragmentManager());
pager.setAdapter(adapter);
tabs.setViewPager(pager);
// Set Present tab as default
pager.setCurrentItem(1);
return v;
}
When the app starts the Main Activity adds for the first time this fragment and everything works great. 3 swipeable tabs with 3 listviews. (c.f. code section)
Here is the problem:
I've noticed that when I press the back button and replace the fragment again, in order to reopen the viewpager, the tab in the middle doesn't show any listview. If I swype left or right the content in the other tabs is loaded and displayed but the Present Tab remains empty.
When I debug the ToNightEvents ListFragment isn't called at all.
Do you guys have any suggestions to solve the problem?
The code:
The code is structured as follows: After the onCreateView I've added an OnDestroyView method to remove the fragment but it didn't work... Then in the fragmentPagerAdapter each page is called as a fragment in the getItem method. Finally at the end of the code you can see the three ListFragment classes in which a listview is populated through an AsyncTask
public class FragmentAllEvents extends Fragment
{
private static final String TAG_UID = "uid";
private static final String TAG_LOGO = "logo";
private static final String TAG_POKUID = "pokuid";
static ArrayList<HashMap<String, String>> userList;
ArrayList<HashMap<String, String>> userListTotal;
private final Handler handler = new Handler();
HashMap<String, String> userSelected;
EventsFunctions eventsFunctions;
UserFunctions userFunctions;
static ListView lv;
ActionBar actionBar;
MyPagerAdapter adapter;
ViewPager pager;
PagerSlidingTabStrip tabs;
private Drawable oldBackground = null;
private int currentColor = 0xFF666666;
//Context context = this;
#Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Set up the action bar.
actionBar = getActivity().getActionBar();
actionBar.setHomeButtonEnabled(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.all_events_main_strip, container, false);
pager = (ViewPager) v .findViewById(R.id.pager_main);
tabs = (PagerSlidingTabStrip) v.findViewById(R.id.tabs);
adapter = new MyPagerAdapter(getFragmentManager());
pager.setAdapter(adapter);
tabs.setViewPager(pager);
pager.setCurrentItem(1);
return v;
}
#Override
public void onDestroyView()
{
super.onDestroyView();
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
}
public static class MyPagerAdapter extends FragmentPagerAdapter
{
public MyPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int i)
{
switch (i)
{
case 0:
return new PastEvents();
case 1:
return new ToNightEvents();
case 2:
return new FutureEvents();
/*default:
// The other sections of the app are dummy placeholders.
return new ToNightEvents();
*/
}
return null;
}
/**
* A fragment that launches past events list.
*/
public static class PastEvents extends ListFragment implements
PullToRefreshAttacher.OnRefreshListener
{
private ListView pastList;
private PullToRefreshAttacher mPullToRefreshAttacher;
ProgressBar progress;
String tabTime;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View pastView = inflater.inflate(R.layout.pastlist, container, false);
progress = (ProgressBar) pastView.findViewById(R.id.loading_spinner_past);
tabTime="past";
pastList = (ListView) pastView.findViewById(android.R.id.list);
// Now get the PullToRefresh attacher from the Activity. An exercise to the reader
// is to create an implicit interface instead of casting to the concrete Activity
mPullToRefreshAttacher = ((Home) getActivity()).getPullToRefreshAttacher();
// Now set the ScrollView as the refreshable view, and the refresh listener (this)
mPullToRefreshAttacher.addRefreshableView(pastList, this);
new AsyncLoadEvents(getActivity(), progress, pastList, mPullToRefreshAttacher).execute(tabTime);
return pastView;
}
#SuppressWarnings("unchecked")
#Override
public void onListItemClick(ListView listView, View view, int position, long id)
{
super.onListItemClick (listView, view, position, id);
HashMap<String, String> map = (HashMap<String, String>) getListView().getItemAtPosition(position);
//Log.e("AttendList Report", "Clicked list item: " + position +" Content: \n" + map.get(TAG_ID).toString());
Log.e("PastList Report", "Clicked list item: " + position +" Event's content: \n" + map.get(TAG_UID).toString());
Intent intent = new Intent(getActivity(), SingleEventActivity.class);
intent.putExtra("pokuid",map.get(TAG_POKUID)); // Maybe remove attribute toString();
intent.putExtra("uid", map.get(TAG_UID));
intent.putExtra("logo",map.get(TAG_LOGO));
getActivity().startActivity(intent);
}
#Override
public void onRefreshStarted(View view)
{
new AsyncLoadEvents(getActivity(), progress, pastList, mPullToRefreshAttacher).execute(tabTime);
}
}
/**
* A fragment that launches future event list.
*/
public static class FutureEvents extends ListFragment implements
PullToRefreshAttacher.OnRefreshListener
{
private ListView futureList;
private PullToRefreshAttacher mPullToRefreshAttacher;
ProgressBar progress;
String tabTime;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View futureView = inflater.inflate(R.layout.futurelist, container, false);
progress = (ProgressBar) futureView.findViewById(R.id.loading_spinner_future);
tabTime = "future";
futureList = (ListView) futureView.findViewById(android.R.id.list); //change to attendlist if needed
// Now get the PullToRefresh attacher from the Activity. An exercise to the reader
// is to create an implicit interface instead of casting to the concrete Activity
mPullToRefreshAttacher = ((Home) getActivity()).getPullToRefreshAttacher();
// Now set the ScrollView as the refreshable view, and the refresh listener (this)
mPullToRefreshAttacher.addRefreshableView(futureList, this);
new AsyncLoadEvents(getActivity(), progress, futureList, mPullToRefreshAttacher).execute(tabTime);
return futureView;
}
#SuppressWarnings("unchecked")
#Override
public void onListItemClick(ListView listView, View view, int position, long id)
{
super.onListItemClick (listView, view, position, id);
HashMap<String, String> map = (HashMap<String, String>) getListView().getItemAtPosition(position);
Log.e("PastList Report", "Clicked list item: " + position +" Event's content: \n" + map.get(TAG_UID).toString());
Intent intent = new Intent(getActivity(), SingleEventActivity.class);
intent.putExtra("pokuid",map.get(TAG_POKUID)); // Maybe remove attribute toString();
intent.putExtra("uid", map.get(TAG_UID));
intent.putExtra("logo",map.get(TAG_LOGO));
getActivity().startActivity(intent);
}
#Override
public void onRefreshStarted(View view)
{
new AsyncLoadEvents(getActivity(), progress, futureList, mPullToRefreshAttacher).execute(tabTime);
}
}
/**
* A fragment that launches future event list.
*/
public static class ToNightEvents extends ListFragment implements
PullToRefreshAttacher.OnRefreshListener
{
private ListView tonightList;
private PullToRefreshAttacher mPullToRefreshAttacher;
ProgressBar progress;
String tabTime;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View tonightView = inflater.inflate(R.layout.tonightlist, container, false);
progress = (ProgressBar) tonightView.findViewById(R.id.loading_spinner_tonight);
tabTime = "tonight";
tonightList = (ListView) tonightView.findViewById(android.R.id.list); //change to attendlist if needed
// Now get the PullToRefresh attacher from the Activity. An exercise to the reader
// is to create an implicit interface instead of casting to the concrete Activity
mPullToRefreshAttacher = ((Home) getActivity()).getPullToRefreshAttacher();
// Now set the ScrollView as the refreshable view, and the refresh listener (this)
mPullToRefreshAttacher.addRefreshableView(tonightList, this);
new AsyncLoadEvents(getActivity(), progress, tonightList, mPullToRefreshAttacher).execute(tabTime);
return tonightView;
}
#SuppressWarnings("unchecked")
#Override
public void onListItemClick(ListView listView, View view, int position, long id)
{
super.onListItemClick (listView, view, position, id);
HashMap<String, String> map = (HashMap<String, String>) getListView().getItemAtPosition(position);
Log.e("PastList Report", "Clicked list item: " + position +" Event's content: \n" + map.get(TAG_UID).toString());
Intent intent = new Intent(getActivity(), SingleEventActivity.class);
intent.putExtra("pokuid",map.get(TAG_POKUID)); // Maybe remove attribute toString();
intent.putExtra("uid", map.get(TAG_UID));
intent.putExtra("logo",map.get(TAG_LOGO));
getActivity().startActivity(intent);
}
#Override
public void onRefreshStarted(View view)
{
new AsyncLoadEvents(getActivity(), progress, tonightList, mPullToRefreshAttacher).execute(tabTime);
}
}
public String[] titles=
{
"Past",
"Tonight",
"Future"
};
#Override
public int getCount()
{
return titles.length;
}
#Override
public CharSequence getPageTitle(int position)
{
return titles[position];
}
}
}
This would normally work if you were in an Activity, however I guess you are in a Fragment since the code you posted is the method onCreateView(). The problem is that you are trying to use the FragmentManager of the Activity and you should be using the Fragment's FragmentManager. This FragmentManager is not what you need. Try this instead:
adapter = new MyPagerAdapter(getChildFragmentManager());
I think I'm a little bit late but if anyone happens to have the same error here is the solution =)
Q.
The following fixed it for me:
Add an OnBackStackChangedListener to the fragment manager.
In the onBackStackChanged method, get references to both the ViewPager and the PagerSlidingTabStrip (pager and tabs in your example). If the appropriate fragment is currently active, do the following:
pager.invalidate();
tabs.invalidate();
pager.setAdapter(new MyPagerAdapter(getFragmentManager()));
tabs.setViewPager(pager);
I'm writing an android application (Min API 14) which consists of 3 tabs that hold a fragment each.
One of the fragments holds a list view (with a list view item defined as simple_list_item_2) and a search view. Now, I'm trying to filter the data in the list view by a room's name (Room is my model)
protected SearchView searchView;
protected ListView view;
protected List<Room> rooms;
protected ArrayAdapter<Room> roomAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(getLayoutId(), container, false);
view = (ListView)rootView.findViewById(getListViewId());
searchView = (SearchView)rootView.findViewById(R.id.rooms_search_view);
view.setTextFilterEnabled(true);
....
roomAdapter = new ArrayAdapter<Room>(this.getActivity(), android.R.layout.simple_list_item_2, rooms){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if(convertView == null){
LayoutInflater inflater =
(LayoutInflater)getActivity().getApplicationContext().
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = (View)inflater.inflate(android.R.layout.simple_list_item_2, null);
}else{
row = (View)convertView;
}
Room data = rooms.get(position);
TextView v = (TextView) row.findViewById(android.R.id.text1);
v.setText(data.getName());
v = (TextView) row.findViewById(android.R.id.text2);
v.setText(data.getPhone());
return row;
}
};
view.setAdapter(roomAdapter);
....
return rootView;
}
#Override
public boolean onQueryTextChange(String newText) {
roomAdapter.getFilter().filter(newText);
return true;
}
The problem is that the search results are in no way relevant to the input entered in the search view. When I replace *android.R.layout.simple_list_item_2* with *android.R.layout.simple_list_item* everything work as expected.
I also read that overriding the toString() method in my model(Room) would solve such a problem,
but that didn't work either.
Any help figuring out how to filter by title(android.R.id.text1) would be highly appreciated.
Well, After I couldn't find any solution with the 'standard' android adapters, I ended up writing a custom adapter that extends BaseAdapter and implements Filterable.
You can find some hints in here if you encounter the same problem.
I use Spinner in Dialog Mode.
I set SimpleCursorAdapter for the Spinner with setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
That works fine.
Now instead of simple_spinner_dropdown_item I'm trying to pass my custom layout it does work well too.
But there is a but... it does not have radio button that original simple_spinner_dropdown_item does.
Is it possible to add radio button inside of my custom spinner_dropdown_item that would be selected when spinner dialog is shown?
yes its possible but you have to define a another class for spinner.Just look at this
you have one more option to get your requirement. that is Alert dialog
just check out this Alert Dialog Window with radio buttons in Android and How to create custom and drop down type dialog and Dialog in android
Well I have found solution. ListView (what is inside of the spinners dialog) will check if your View is Checkable and call setChecked. Since android.R.layout.simple_spinner_dropdown_item is checkable it works.
So for my custom List item i have created LinearLayout that implements Checkable
public class CheckableLinearLayout extends LinearLayout implements Checkable
{
private boolean _isChecked = false;
public CheckableLinearLayout(Context context)
{
super(context);
}
public CheckableLinearLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
#Override
public void setChecked(boolean checked)
{
_isChecked = checked;
for (int i = 0; i < getChildCount(); i++)
{
View child = getChildAt(i);
if (child instanceof Checkable)
{
((Checkable) child).setChecked(_isChecked);
}
}
}
#Override
public boolean isChecked()
{
return _isChecked;
}
#Override
public void toggle()
{
_isChecked = !_isChecked;
}
}
So ListView calls setChecked and I propagate that down to children views and my CheckBox / RadioButton will get checked / unchecked correctly.