Android creating dynamic fragments with dynamic data using gridview and realm DB? - android

I want to load category and products like the image shown:
frag
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Category ctID = mSubCategory.get(position);
int id = ctID.getCategory_id();
return PlaceholderFragment.newInstance(getBaseContext(),id);
}
#Override
public int getCount() {
// Set number of fragments to be created
if(SubCategoriesCount == 0) {
Category ct;
ct = mSubCategory.get(0);
if (ct != null)
return 1;
}
return SubCategoriesCount;
}
}
Creating Fragment using newInstance with different Data.
PlaceholderFragment.java
public class PlaceholderFragment extends Fragment {
private static final String FragmentCategoryID = "CategoryID";
private static Context cTx;
private static String catName;
public PlaceholderFragment() {
}
public static PlaceholderFragment newInstance(Context ctx, int id){
PlaceholderFragment fragment = new PlaceholderFragment();
cTx = ctx;
Log.d("New Fragment Created ", ":" + id );
Bundle args = new Bundle();
args.putInt(FragmentCategoryID, id);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_category_products_view, container, false);
RealmResults<Product> ProductList;
ProductList = GetProducts(getArguments().getInt(FragmentCategoryID));
Log.d("Fragment Arguments", "" + getArguments().getInt(FragmentCategoryID));
GridView gv = (GridView) rootView.findViewById(R.id.gridViewFrg);
gv.setAdapter(new AdapterRealmProduct(getActivity(), R.layout.grid_view_main, ProductList, true));
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(FragmentCategoryID))+ ":::"+catName);
return rootView;
}
private RealmResults<Product> GetProducts(int CategoryID){
RealmConfiguration realmConfigs;
realmConfigs = new RealmConfiguration.Builder(getActivity()).build();
Realm realmtm = Realm.getInstance(realmConfigs);
Category camt = realmtm.where(Category.class).equalTo("category_id", CategoryID).findFirst();
catName = camt.getName();
RealmResults<Product> results = realmtm.where(Product.class).equalTo("category_id", CategoryID).findAll();
try{
if(results != null && results.isValid()) {
return results;
}
}catch (IllegalStateException e){
e.printStackTrace();
}finally {
//realmtm.close();
}
return results;
}
}
It loads creates multiple fragments as value of SubCategoriesCount. But data in all fragments is same. Means All gridViews on all fragments have same grid data.
textView.setText(getString(R.string.section_format, getArguments().getInt(FragmentCategoryID))+ ":::"+catName);
CategoryName and ID displays.. but data does not change...
it might be Realm data. how to handle realm handle in different activitis.

there was repeated data in realm. So there is no problem in above code. I didn't notice what is coming to realm database.

Related

How i can move data from DB to my ViewPager?

Class with DB and realization of Adapter.
public class MainActivity extends AppCompatActivity {//implements
View.OnClickListener{
ArrayList<String> titles = new ArrayList<>();
ArrayAdapter arrayAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = findViewById(R.id.listView);
arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,
titles);
listView.setAdapter(arrayAdapter);
try {
SQLiteDatabase myDatabase = this.openOrCreateDatabase("Places",
MODE_PRIVATE, null);
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS places (name VARCHAR,
time INT(2), solo INT(1), id INTEGER PRIMARY KEY)");
myDatabase.execSQL("INSERT INTO places (name, time, solo) VALUES
('One', 23, 1)");
myDatabase.execSQL("INSERT INTO places (name, time, solo) VALUES
('Two', 24, 2)");
myDatabase.execSQL("INSERT INTO places (name, time, solo) VALUES
('Three', 22, 1)");
myDatabase.execSQL("INSERT INTO places (name, time, solo) VALUES
('Four', 02, 2)");
Cursor c = myDatabase.rawQuery("SELECT * FROM places WHERE solo =
1", null);
int nameIndex = c.getColumnIndex("name");
int timeIndex = c.getColumnIndex("time");
int soloIndex = c.getColumnIndex("solo");
int idIndex = c.getColumnIndex("id");
if (c.moveToFirst()) {
titles.clear();
do {
titles.add(c.getString(nameIndex));
} while (c.moveToNext());
arrayAdapter.notifyDataSetChanged();
}
c.close();
myDatabase.execSQL("DELETE FROM places");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Class with realization Fragment and PagerAdapter:
public class MyGallery extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_gallery);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new
SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_my_gallery,
container, false);
TextView textView = (TextView)
rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format,
getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class
below).
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
}
}
I'm trying to move a field named "name" (nameIndex) from the database to the viewpager screen. I can not move cursor values ​​to a class with the creation of a Fragment. I read about the method of entering data into the List and moved from there, the number of the required position to the FragmentPager, but it did not quite work out. Can someone know a simple and elegant way to solve this problem?
When you instantiate your FragmentPagerAdapter, pass an ArrayList to adapter constructor as argument
mSectionsPagerAdapter = new
SectionsPagerAdapter(getSupportFragmentManager(), titles);
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
In your adapter use a reference, and get string from array, such like
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private ArrayList<String> strings;
public SectionsPagerAdapter(FragmentManager fm, ArrayList<String> strings) {
super(fm);
this.strings = strings;
}
#Override
public Fragment getItem(int position) {
return PlaceholderFragment.newInstance(position + 1, strings.get(position + 1));
}
#Override
public int getCount() {
return strings.size();
}
}
And finally, in your Fragment class, pass it as argument, and get as a global variable from onCreate method
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
private String title;
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber, String title) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
args.putString("key", title);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
title = getArguments().getString("key");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_my_gallery,
container, false);
TextView textView = (TextView)
rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format,
getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
Note. For better control on your code, if you have limited number of fragment, you should make an all cases using switch statement. Calling position + 1 in you adapter may throw nullpointerexception, when an index of your array will be exceeded. You can start any postion using viewPager.setCurrentItem(position);, example of FragmentPagerAdapter with switch statement should looks like
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return PlaceholderFragment.newInstance(position, strings.get(position));
case 1:
return PlaceholderFragment.newInstance(position, strings.get(position));
case 2:
return PlaceholderFragment.newInstance(position, strings.get(position));
default:
return something...
}
}

Unable to get position of selected tab on viewpager

How many tabs will be created it depends on web service. It means I cannot discover how many Tabs are going to be Created until web service is called.
The tabs contain the products which I want to show in grid view.
In my project I have ShopProductsPageFragments.java where tabs get created. Please have look below code :
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CatPosition = getArguments().getInt("CatPosition");
StoreID = getArguments().getString("StoreID");
System.out.println("getStoreID in ShopProductsPageFragments="+ StoreID);
System.out.println("getCatPosition in ShopProductsPageFragments="+ CatPosition);
try {
ShopCategoryData = (GetProductCategoriesByStoreResponsePojo) getArguments().getSerializable("ShopCatNames");
}catch (Exception e){
e.printStackTrace();
}
assert ShopCategoryData != null;
List<Datum> shopcatdata = ShopCategoryData.getData();
for (int i = 0; i < shopcatdata.size(); i++) {
System.out.println("ShopCategoryData in ShopProductsPageFragments "+ shopcatdata.get(i).getCatName());
}
ShopProductsPageView = inflater.inflate(R.layout.activity_product_page_fragment ,container ,false);
viewPager = (ViewPager)ShopProductsPageView.findViewById(R.id.product_viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout)ShopProductsPageView.findViewById(R.id.product_tabs);
tabLayout.setupWithViewPager(viewPager);
return ShopProductsPageView;
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager());
List<Datum> shopcatdata = ShopCategoryData.getData();
for (int i = 0; i < shopcatdata.size(); i++) {
CommanShopProductFragment commanShopProductFragment = CommanShopProductFragment.newInstance(i);
String CatName = shopcatdata.get(i).getCatName();
Bundle bundle = new Bundle();
bundle.putString("StoreID",StoreID);
bundle.putString("CatName",CatName);
commanShopProductFragment.setArguments(bundle);
System.out.println("ShopCategoryData in ShopProductsPageFragments "+ shopcatdata.get(i).getCatName());
adapter.addFrag(commanShopProductFragment, shopcatdata.get(i).getCatName());
}
adapter.notifyDataSetChanged();
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(CatPosition);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
FragmentManager fragmentManager;
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
fragmentManager = manager;
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
Here, you can see how tabs are created. I am using same fragment for showing data in Tabs as follows:
public class CommanShopProductFragment extends Fragment {
private static final String ARG_POSITION = "position";
private int position;
View CategoryTabFragmentView;
GetStoreProductsByCategoriesPresenterImpl presenter;
RestClient service;
GridView gridView;
List<Datum> shopProduct;
ProductByCategoryGridViewAdapter mAdapter;
public CommanShopProductFragment() {
// Required empty public constructor
}
public static CommanShopProductFragment newInstance(int position) {
CommanShopProductFragment f = new CommanShopProductFragment();
Bundle b = new Bundle();
b.putInt(ARG_POSITION, position);
f.setArguments(b);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String CatName = getArguments().getString("CatName");
String StoreID = getArguments().getString("StoreID");
assert CatName != null;
System.out.println("CommanShopProductFragment >>>>>>>> CatName="+CatName);
assert StoreID != null;
System.out.println("CommanShopProductFragment >>>>>>>> StoreID="+StoreID);
CategoryTabFragmentView = inflater.inflate(R.layout.activity_category_tab_fragment ,container ,false);
service = ((LilubiApplication) getActivity().getApplication()).getNetworkService();
presenter = new GetStoreProductsByCategoriesPresenterImpl(this, service);
String page = "1", itemsPerPage = "10";
try {
presenter.GetStoreProductsByCategories(CatName, StoreID, page, itemsPerPage);
}catch (Exception e){
e.printStackTrace();
}
return CategoryTabFragmentView;
}
public void getStoreProductsByCategories(ProductByCategoriesResponsePojo productByCategoriesResponsePojo){
System.out.println("CategoryTabFragment in getMessage="+productByCategoriesResponsePojo.getMessage());
System.out.println("CategoryTabFragment in getStatus="+productByCategoriesResponsePojo.getStatus());
// prepared arraylist and passed it to the Adapter class
shopProduct = productByCategoriesResponsePojo.getData();
mAdapter = new ProductByCategoryGridViewAdapter(getActivity(),shopProduct);
// Set custom adapter to gridview
gridView = (GridView) CategoryTabFragmentView.findViewById(R.id.category_tab_view_grid_view);
gridView.setAdapter(mAdapter);
}
Now what I want is when user selects a tab then list of products should be displayed according to selected category from the tabs.
All product data also comes from web service. Let me know if I missed any thing to explain. Thank you.
I am editing my previous answer
Edit:
you can use viewpager.getCurrentItem() to get current position //include this in your activity with viewpager

Instance of same fragment destroy layout of first one in ViewPager?

I am trying to fetch results from sqllite db in ViewPager using Adapater class
public class AppDetailPagerAdapter extends android.support.v4.app.FragmentStatePagerAdapter {
private List<AppPagingData> mData;
public AppDetailPagerAdapter(FragmentManager fm, List<AppPagingData> data) {
super(fm);
this.mData = data;
}
#Override
public Fragment getItem(int i) {
sCurrentPosition = i;
Fragment fragment = AppDetailFragment.newInstance(mData, i);
return fragment;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
}
And my fragment is
public class AppDetailFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private List<AppPagingData> mData;
private int mCurrentPosition;
private int mToken;
private static final String EXTRA_KEY_APP_DATA = "EXTRA_KEY_APP_DATA";
private static final String EXTRA_KEY_APP_CURR_POSITION = "EXTRA_KEY_APP_CURR_POSITION";
public static AppDetailFragment newInstance(ArrayList<AppPagingData> param1, int currentPosition) {
AppDetailFragment fragment = new AppDetailFragment();
Bundle args = new Bundle();
args.putParcelableArrayList(EXTRA_KEY_APP_DATA, param1);
args.putInt(EXTRA_KEY_APP_CURR_POSITION, currentPosition);
fragment.setArguments(args);
return fragment;
}
public AppDetailFragment() {
// Required empty public constructor
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().restartLoader(mToken, null, this);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (loader.getId() == mToken) {
ViewGroup oocsGroup = (ViewGroup) getActivity().findViewById(R.id.oocsGroup);
// Remove all existing timings (except 1 ie header)
//I think this line remove childs for all fragment????
for (int i = oocsGroup.getChildCount() - 1; i >= 1; i--) {
oocsGroup.removeViewAt(i);
}
} else {
cursor.close();
}
}...
Now, the problem is my fragment linear layout items get deleted, as android call my fragment second instance. for e.g. if i select 1st item second will called automatically.
How to avoid layout of first instance to destry because of second.
As your adapter creates a new instance of fragment at getItem(), you are probably loosing the previous fragment to the garbage collector.
You could keep your fragments in an array (or ArrayList) and return fragment from the array at getItem().
like:
// keep created instances of AppDetailFragments
private AppDetailFragment[] frags;
public AppDetailPagerAdapter(FragmentManager fm, List<AppPagingData> data) {
super(fm);
this.data = data;
frags = new AppDetailFragment[data.size()];
// init all frags
for (int i=0;i<data.size();i++) {
frags[i] = AppDetailFragment.newInstance(data, i);
}
}
#Override
public Fragment getItem(int i) {
sCurrentPosition = i;
return frags[i]; // may want to check for arrayindexoutofboundsEx..
}
This way you will keep a reference to all created fragments.
note:
You no longer need to keep the data as for getCount you can return length of frags-array.

swipe tabs inside a fragment with pages from same class

I created a swipe tab view inside a fragment. I tested this in a FragmentActivity with no issues. I tested with pages that consisted of different fragment classes and fragments all from the same class... again no issues.
Then, I changed the FragmentActivity to a Fragment. I tested again with different Fragment classes representing each page and had no problem. Finally, i repeated the test with fragments of the same class and ran into issues.
There are 3 pages right now representing three weeks. At first week 1 shows up. I swipe to week 2 and there is nothing. I swipe to week 3 and nothing again. When I swipe back to week 1, the only viewable page ends up being the middle page. Is this an issue with fragment life cycles? I'm not sure how to debug this special circumstance. I'm looking for possible causes so I can start solving this issue.
public class WeeklyScrollTab extends Fragment {
private ViewPager my_view_pager;
private View my_layout;
private int my_current_page;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
my_layout = inflater.inflate(R.layout.weekly_scroll_tabs, container, false);
return my_layout;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/** Getting the arguments to the Bundle object */
//Bundle data = getArguments();
/** Getting integer data of the key current_page from the bundle */
//my_current_page = data.getInt("week_val", 0);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
my_view_pager = (ViewPager)my_layout.findViewById(R.id.week_list_pager);
FragmentManager manager = getActivity().getSupportFragmentManager();
//FragmentManager manager = getChildFragmentManager();
my_view_pager.setAdapter(new WeeklyScrollAdapter(manager));
super.onActivityCreated(savedInstanceState);
}
public int getCurrentPage(){
return my_current_page;
}
public class WeeklyScrollAdapter extends FragmentStatePagerAdapter {
public WeeklyScrollAdapter(FragmentManager the_manager){
super(the_manager);
}
#Override
public Fragment getItem(int the_position) {
Fragment fragment1 = null;
if(the_position == 0){
fragment1 = new MyNflPlayerList();
Bundle args1 = new Bundle();
args1.putInt("week_val"+the_position, the_position);
fragment1.setArguments(args1);
}
if(the_position == 1){
fragment1 = new MyNflPlayerList();
Bundle args2 = new Bundle();
args2.putInt("week_val"+the_position, the_position);
fragment1.setArguments(args2);
}
if(the_position == 2){
fragment1 = new MyNflPlayerList();
Bundle args3 = new Bundle();
args3.putInt("week_val"+the_position, the_position);
fragment1.setArguments(args3);
}
return fragment1;
}
/**
*
* #return number of total pages
*/
#Override
public int getCount() {
return 3;
}
/**
* gets title for tab
*/
#Override
public CharSequence getPageTitle(int position) {
if(position ==0){
return "Week 1";
}
if(position == 1){
return "Week 2";
}
if(position == 2){
return "Week 3";
}
return super.getPageTitle(position);
}
public class NflPlayerAdapter extends BaseAdapter {
private ArrayList<NflPlayerModel> my_list;
private Context my_context;
public NflPlayerAdapter(Context c){
my_context = c;
my_list = new ArrayList<NflPlayerModel>();
my_list.add(new NflPlayerModel("T.","Brady","NE","QB",56));
my_list.add(new NflPlayerModel("A.","Peterson","MN","RB",24));
my_list.add(new NflPlayerModel("D.","Bryant","DAL","WR",18));
my_list.add(new NflPlayerModel("M.","Gattica","TB","K",9));
}
#Override
public int getCount() {
return my_list.size();
}
#Override
public NflPlayerModel getItem(int i) {
return my_list.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//getting the data and injecting it into the each row view
View row = convertView;
NflPlayerHolder holder = null;
if(row == null){
LayoutInflater inflater = (LayoutInflater)my_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.my_nfl_player_row,parent, false);
holder = new NflPlayerHolder(row);
row.setTag(holder);
}
else{
holder = (NflPlayerHolder) row.getTag();
}
NflPlayerModel temp = my_list.get(position);
holder.getFname().setText(temp.getFname());
holder.getLname().setText(temp.getLname());
holder.getTeam().setText(temp.getTeam());
holder.getPosition().setText(temp.getPosition());
holder.getPoints().setText(Integer.toString(temp.getPoints()));
return row;
}
class NflPlayerHolder {
/**
* TextView object in my_league_row xml.
*/
private TextView my_fname;
private TextView my_lname;
private TextView my_team;
private TextView my_position;
private TextView my_points;
/**
* Constructor. Converts the xml txt_league_name to Java object.
* #param v
*/
public NflPlayerHolder(View v){
my_fname = (TextView)v.findViewById(R.id.player_fname);
my_lname = (TextView)v.findViewById(R.id.player_lname);
my_team = (TextView)v.findViewById(R.id.player_team);
my_position = (TextView)v.findViewById(R.id.player_position);
my_points = (TextView)v.findViewById(R.id.player_points);
}
public TextView getFname(){
return my_fname;
}
public TextView getLname(){
return my_lname;
}
public TextView getTeam(){
return my_team;
}
public TextView getPosition(){
return my_position;
}
public TextView getPoints(){
return my_points;
}
public class MyNflPlayerList extends Fragment implements AdapterView.OnItemClickListener{
private View my_layout;
private ListView my_list_view;
private static HomeActivityCommunicator my_communicator;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
my_layout = inflater.inflate(R.layout.my_nfl_player_list, container, false);
return my_layout;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
my_list_view = (ListView)getActivity().findViewById(R.id.nfl_player_list_view);
NflPlayerAdapter adapter = new NflPlayerAdapter(getActivity());
my_list_view.setAdapter(adapter);
my_list_view.setOnItemClickListener(this);
super.onActivityCreated(savedInstanceState);
}
public void setHomeActivityCommunicator(HomeActivityCommunicator the_communicator){
my_communicator = the_communicator;
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.e("mike", "the player index is " + i);
my_communicator.onMyNflPlayerListSelection(i);
}

ViewPager FragmentPagerAdapter only updates last fragment onNavigationItemSelected

I have a ViewPager hosted in a fragment that hosts two ListFragments that are populated by a Cursor returned from an SQLite query. I recently added a spinner to my Action Bar that will allow the user to sort the lists in the ViewPager. However, every time the spinner is selected, only the second list is sorted even when the first list is currently displayed. It seems like the ViewPager is not keeping track of the currently displayed ListFragment.
I have tried overriding getItemPosition in my adapter and using notifyDataSetChanged, but that doesn't help. I tried caching the position of the current active fragment in onAttach() also to no avail. I also tried using an OnSortChanged interface implemented by my adapter to try and recreate the ListFragments. I'm truly at a loss here. Here is my current code:
My main fragment:
public class BeerMenuFragment extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.beer_menu_fragment, container,
false);
ViewPager pager = (ViewPager) view.findViewById(R.id.beer_pager);
pager.setAdapter(buildAdapter());
return view;
}
private PagerAdapter buildAdapter() {
return (new BeerMenuAdapter(getChildFragmentManager()));
}
}
My FragmentPagerAdapter:
public class BeerMenuAdapter extends FragmentPagerAdapter {
private final int NUM_ITEMS = 2;
public BeerMenuAdapter(FragmentManager fm) {
super(fm);
}
/*
* (non-Javadoc)
*
* #see android.support.v4.view.PagerAdapter#getPageTitle(int)
*/
#Override
public CharSequence getPageTitle(int position) {
return BeerListFragment.getTitle(position);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
return BeerListFragment.newInstance(position);
}
}
And finally, the ListFragment:
public class BeerListFragment extends SherlockListFragment implements
OnNavigationListener {
private static final String KEY_POSITION = "position";
private static final String KEY_SPINNER = "ab_spinner";
private IconicAdapter adapter;
private static final String[] LABELS = { "Newest First", "Oldest First",
"Alphabetical" };
private Context ctxt;
private int mShowItems;
private Cursor data;
private boolean synthetic = true;
static BeerListFragment newInstance(int position) {
BeerListFragment frag = new BeerListFragment();
Bundle args = new Bundle();
args.putInt(KEY_POSITION, position);
frag.setArguments(args);
return (frag);
}
static String getTitle(int position) {
String header = "Draft";
switch (position) {
case 0:
header = "Draft";
break;
case 1:
header = "Bottle";
break;
}
return (header);
}
/*
* (non-Javadoc)
*
* #see
* android.support.v4.app.ListFragment#onCreateView(android.view.LayoutInflater
* , android.view.ViewGroup, android.os.Bundle)
*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View result = inflater.inflate(R.layout.menu_list_fragment, container,
false);
ctxt = getActivity().getApplicationContext();
SQLiteDatabase db = DatabaseHelper.getInstance(ctxt)
.getReadableDatabase();
SherlockFragmentActivity activity = getSherlockActivity();
ArrayAdapter<String> show = null;
ActionBar bar = activity.getSupportActionBar();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
show = new ArrayAdapter<String>(bar.getThemedContext(),
android.R.layout.simple_spinner_item, LABELS);
} else {
show = new ArrayAdapter<String>(activity,
android.R.layout.simple_spinner_item, LABELS);
}
show.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
bar.setListNavigationCallbacks(show, this);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState
.getInt(KEY_SPINNER));
}
data = getBeerMenuDbData(db, mShowItems);
// set up list adapter
adapter = new IconicAdapter(ctxt, data);
setListAdapter(adapter);
return (result);
}
private Cursor getBeerMenuDbData(SQLiteDatabase db, int showItems) {
String order;
String WHERE;
switch (showItems) {
case 1: // Oldest First
order = DbContract.BeerEntry.COLUMN_MODIFIED + " ASC";
break;
case 2: // Alphabetical
order = DbContract.BeerEntry.COLUMN_TITLE + " ASC";
break;
default: // Newest first
order = DbContract.BeerEntry.COLUMN_MODIFIED + " DESC";
break;
}
String[] COLUMNS = { DbContract.BeerEntry._ID,
DbContract.BeerEntry.COLUMN_TITLE,
DbContract.BeerEntry.COLUMN_MODIFIED };
WHERE = "serving='" + getTitle(getArguments().getInt(KEY_POSITION, -1))
+ "'";
return db.query(DbContract.BeerEntry.TABLE_NAME, COLUMNS, WHERE, null,
null, null, order);
}
class IconicAdapter extends CursorAdapter {
LayoutInflater inflater;
IconicAdapter(Context context, Cursor data) {
super(context, data, 0);
inflater = LayoutInflater.from(context);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
String dateString = cursor.getString(2);
String[] dateArray = new String[3];
TextView beerName = (TextView) view.findViewById(R.id.beerName);
TextView date = (TextView) view.findViewById(R.id.drinkDate);
RatingBar rb = (RatingBar) view.findViewById(R.id.ratingBar1);
beerName.setText(cursor.getString(1));
if (!dateString.isEmpty()) {
dateArray = dateString.split("-");
date.setText(dateArray[1] + "/" + dateArray[2] + "/"
+ dateArray[0]);
} else {
date.setText(dateString);
}
rb.setRating((float) Math.random() * 5.0f);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return inflater
.inflate(R.layout.beer_club_list_item, parent, false);
}
}
/*
* (non-Javadoc)
*
* #see android.support.v4.app.Fragment#onDestroy()
*/
#Override
public void onDestroy() {
super.onDestroy();
((CursorAdapter) getListAdapter()).getCursor().close();
}
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
if (synthetic) {
synthetic = false;
return true;
}
mShowItems = itemPosition;
SQLiteDatabase db = DatabaseHelper.getInstance(ctxt)
.getReadableDatabase();
Cursor newData = getBeerMenuDbData(db, mShowItems);
adapter.changeCursor(newData);
return true;
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(KEY_SPINNER, getSherlockActivity()
.getSupportActionBar().getSelectedNavigationIndex());
}
}
Thanks in advance for any help!
So, your problem is that you are calling bar.setListNavigationCallbacks(show, this) inside of your BeerListFragments. When your 1st BeerListFragment is created in your ViewPager, it sets itself as the callback for the navigation selections. Then, when your 2nd BeerListFragment is created (ViewPagers resumes pages to the left and right of the currently visible page), it sets itself as the callback for the navigation selections, and overwrites the 1st BeerListFragment, which now will no longer get the onNavigationItemSelected callback.
This all results with the behavior you are seeing, the last BeerListFragment to call bar.setListNavigationCallbacks will be the only one to receive the onNavigationItemSelected callback. This is why only the 2nd BeerListFragment is being sorted.
To solve this, I would recommend you do a few things:
Manage setting the callback for the navigation selections in the BeerMenuFragment, and pass the results to the children Fragments that are in "alive" (in onResume). You will need to use one of the answers here in order to do so.
Store the the latest sort option applied, and check in onResume of each BeerListFragment to see if its sort matches, and if not, apply the sort.
This will guarantee that all of your sorts are applied to all of your pages in the ViewPager, whether they are displayed or not at the time of the sort being applied.

Categories

Resources