I receive a list (of Categories) from server and make tabs using SectionsPagerAdapter. I use one common Fragment within which I have a RecyclerView. After user logs in, I store Categories in TempData.productCategories and they are less than 15. When user selects a tab, I refresh the RecyclerView with the products of the selected Category. The issue is, currently I have 4 Categories. Only the first and the last ones have products (one product under each category). The first tab showing no product maybe because the second one is empty and Android automatically loads the second tab just after the first one. I want to see the products of the first category. Can anybody tell me what am I doing wrong?
The server gets my store ID and one store ID has less than 15 categories:
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
//doing after a delay otherwise activity is null
final int position = tab.getPosition();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
String cat = TempData.productCategories.get(position).getName();
Log.i("Temp", "pos: " + position + ", cat: " + cat);
AnyItemFragment.updateList(cat, context);
}
}, 400);
}
Here are the other methods used in this functionality:
public static void setupListForCategory(final Activity context, final RecyclerView listView, final String category) {
List<ProductUserModel> prods = getProductsUser(category);
if(prods.isEmpty()) return;
setupList(context, listView, prods);
}
And here I update the adapter:
private static void setupList(final Activity context, RecyclerView listView, List<ProductUserModel> prods){
FastItemAdapter<ProductUserModel> p = new FastItemAdapter<>();
p.add(prods);
p.withSelectable(true);
p.withOnClickListener(new FastAdapter.OnClickListener<ProductUserModel>() {
#Override
public boolean onClick(final View v, final IAdapter<ProductUserModel> adapter, final ProductUserModel item, final int position) {
PopupUtils.getUserInputQuantity(context, item, v);
return false;
}
});
//fill the recycler view
Log.i("Temp", "updating list : " + prods.size());
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(context);
listView.setLayoutManager(layoutManager);
listView.setAdapter(p);
// p.notifyAdapterDataSetChanged();
// p.notifyDataSetChanged();
listView.invalidate();
}
private static List<ProductUserModel> getProductsUser(String category) {
List<ProductUserModel> pum = new ArrayList<>();
for(int i = 0; i < TempData.productsUser.size(); i++){
if(TempData.productsUser.get(i).getCategory().equals(category))
pum.add(TempData.productsUser.get(i));
}
return pum;
}
And the sections pager adapter in the activity:
private class SectionsPagerAdapter extends android.support.v13.app.FragmentPagerAdapter {
SectionsPagerAdapter(android.app.FragmentManager fm) {
super(fm);
}
#Override
public android.app.Fragment getItem(int position) {
return AnyItemFragment.newInstance(position-1);
}
#Override
public int getCount() {
// Show 3 total pages.
return TempData.productCategories.size();
}
#Override
public CharSequence getPageTitle(int position) {
// switch (position) {
return TempData.productCategories.get(position).getName();
// case 0:
// return getString(R.string.toys);
// case 1:
// return getString(R.string.stationaries);
// case 2:
// return getString(R.string.books);
// }
// return null;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Update: My fragment:
public class AnyItemFragment extends Fragment {
static AnyItemFragment fragment;
public static Activity context;
private static String TAG = "AllItemsFragment";
int selectedPosition = 0;
#BindView(R.id.listAll)
RecyclerView listAll;
private OnFragmentInteractionListener mListener;
public AnyItemFragment() {
// Required empty public constructor
}
public static AnyItemFragment newInstance(int categoryID) {
fragment = new AnyItemFragment();
fragment.selectedPosition = categoryID;
Log.i(TAG, "sel pos: " + fragment.selectedPosition);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_inv_any_item, container, false);
ButterKnife.bind(this, view);
context = getActivity();
return view;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(!isVisibleToUser) return;
String cat = TempData.productCategories.get(fragment.selectedPosition).getName();
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
public static void updateList(String cat, Activity context){
TempData.setupListForCategory(context, fragment.listAll, cat);
}
}
I think for starters, you should keep the flow simple and not have a static fragment instance on which you keep calling refresh.
Your code right now is difficult to read and understand.
One basic thing to note with fragments is since they are already re-usable in tandem with a FragmentStatePagerAdapter, you almost never have to deal with this hassle of having a single static instance doing all the work.
Few problems I spotted right now for example were -
You want to attach multiple fragments (as many as there are categories) so you make a new instance and update the static field
public static AnyItemFragment newInstance(int categoryID) {
fragment = new AnyItemFragment();
fragment.selectedPosition = categoryID;
Log.i(TAG, "sel pos: " + fragment.selectedPosition);
return fragment;
}
What is happening right now is since the default offscreenPageLimit on your ViewPager defaults to 1 all your updates are going to the second instance of the fragment which most probably is linked with category-2 and hence nothing renders in the first tab.
You can confirm this by adding debug break-points.
What you would ideally want to do is send the categories to your ViewPagerAdapter and based on the position set the product model list to the correct fragment itself so it knows how to render post creation.
private class SectionsPagerAdapter extends android.support.v13.app.FragmentPagerAdapter {
private final Map<String, List<ProductUserModel>> mapOfCategoryAndProductUsers;
SectionsPagerAdapter(FragmentManager fm, Map<String, List<ProductUserModel>> mapOfCategoryAndProductUsers) {
super(fm);
this.mapOfCategoryAndProductUsers = mapOfCategoryAndProductUsers;
}
#Override
public android.app.Fragment getItem(int position) {
AnyItemFragment fragment = AnyItemFragment.newInstance(position-1);
// Logic to map position to category...
String category = TempData.productCategories.get(position)
fragment.setProductUsers(mapOfCategoryAndProductUsers.get(category))
return fragment;
}
#Override
public int getCount() {
// Show 3 total pages.
return TempData.productCategories.size();
}
...
...
}
And then have the render logic inside the fragment -
private List<ProductUserModel> productUsers;
public void setProductUsers(List<ProductUserModel> productUsers) {
this.productUsers = productUsers;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setupList()
}
private void setupList() {
FastItemAdapter<ProductUserModel> p = new FastItemAdapter<>();
p.add(prods);
p.withSelectable(true);
p.withOnClickListener(new FastAdapter.OnClickListener<ProductUserModel>() {
#Override
public boolean onClick(final View v, final IAdapter<ProductUserModel> adapter, final ProductUserModel item, final int position) {
PopupUtils.getUserInputQuantity(context, item, v);
return false;
}
});
//fill the recycler view
Log.i("Temp", "updating list : " + prods.size());
LayoutManager layoutManager = new LinearLayoutManager(context);
listView.setLayoutManager(layoutManager);
listView.setAdapter(p);
}
PS: You should avoid as much as you can the use of static methods, since they make unit testing a nightmare. Also if you don't test your code before hand, I'd suggest checking out unit tests and Espresso for instrumentation test to have more re-assurance around the working of your app and be free of regression blues.
Let me know if this helped or if you'd need more explanation
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.
I have a layout with two fragments in my app (one listFragment containing the titles and one containing the details.)
After starting the everything works fine. The Detail-Fragment is updated each time I click on an entry in the listfragment.
Yet after changing the orientation every new detail-Fragment is just opened upon the old detail fragment. (Due to my low reputation I can't post any screenshots, I am sorry.)
My Activity containing the two fragments:
/**
* A fragment representing a list of Items.
* <p />
* Large screen devices (such as tablets) are supported by replacing the ListView
* with a GridView.
* <p />
*/
public class MedicationTitlesFragment extends ListFragment
implements AdapterView.OnItemClickListener, SearchView.OnQueryTextListener, SearchView.OnCloseListener, LoaderManager.LoaderCallbacks<Cursor> {
/**
* The Adapter which will be used to populate the ListView/GridView with
* Views.
*/
//private ListAdapter mAdapter;
private static final String TAG = MedicationTitlesFragment.class.getSimpleName();
private static final int LOADER_ID = 1;
//private OnFragmentInteractionListener mListener;
private OnMedicationSelectedListener mMedicationSelectedListener;
/**
* The fragment's ListView/GridView.
*/
private ListView mListView;
private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallbacks;
private SearchView mSearchView;
private String mCurFilter;
private SimpleCursorAdapter mAdapter;
static final String[] RPINFO_SUMMARY_PROJECTION = new String[] {
RpEntry.Columns.SNAME, RpEntry.Columns._ID, RpEntry.Columns.ONAME, RpEntry.Columns.PHZNR,
RpEntry.Columns.ZNR_FORMATTED, RpEntry.Columns.RSIGN_P1, RpEntry.Columns.RSIGN_P5
};
// TODO: Rename and change types of parameters
public static MedicationTitlesFragment newInstance(String param1, String param2) {
MedicationTitlesFragment fragment = new MedicationTitlesFragment();
Bundle args = new Bundle();
return fragment;
}
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public MedicationTitlesFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "entered onCreate");
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item_list, container, false);
// Set the adapter
mListView = (ListView) view.findViewById(android.R.id.list);
((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter);
// Set OnItemClickListener so we can be notified on item clicks
mListView.setOnItemClickListener(this);
setEmptyText("Keine Einträge");
return view;
}
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mMedicationSelectedListener = (OnMedicationSelectedListener) activity;
//this.getListView().setOnItemClickListener(this);
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mMedicationSelectedListener = null;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Log.d(TAG, "entered onListItemClick");
getListView().setItemChecked(position, true);
Uri rpDetailUri = Uri.parse(RpInfoContentProvider.CONTENT_URI + "/" + id);
Log.d(TAG, "rpDetailUri: " + rpDetailUri.toString());
mMedicationSelectedListener.onMedicationSelected(rpDetailUri);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (null != mMedicationSelectedListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
//mListener.onFragmentInteraction(DummyContent.ITEMS.get(position).id);
}
}
/**
* The default content for this Fragment has a TextView that is shown when
* the list is empty. If you would like to change the text, call this method
* to supply the text it should use.
*/
public void setEmptyText(CharSequence emptyText) {
View emptyView = mListView.getEmptyView();
if (emptyText instanceof TextView) {
((TextView) emptyView).setText(emptyText);
}
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri = null;
if (null != mCurFilter)
baseUri = Uri.withAppendedPath(RpEntry.CONTENT_URI, Uri.encode(mCurFilter));
else
baseUri = RpEntry.CONTENT_URI;
// Now create and return a CursorLoader that will take care of
// // creating a Cursor for the data being displayed.
return new CursorLoader(
getActivity().getBaseContext(),
baseUri,
RPINFO_SUMMARY_PROJECTION,
null,
null,
RpEntry.Columns.SNAME + " COLLATE LOCALIZED ASC");
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Der Loader hat fertig geladen, die Daten können nun im UI angezeigt werden
// switch to handle multiple loaders
switch(loader.getId()) {
case LOADER_ID:
mAdapter.swapCursor(data);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
#Override
public boolean onClose() {
if (!TextUtils.isEmpty(mSearchView.getQuery())) {
mSearchView.setQuery(null, true);
}
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
Log.d(TAG, "entered onQueryTextSubmit");
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
Log.d(TAG, "enteredOnQueryTextChanged");
// Called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
getLoaderManager().restartLoader(LOADER_ID, null, mLoaderCallbacks);
return true;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnMedicationSelectedListener {
// TODO: Update argument type and name
public void onMedicationSelected(Uri uri);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setEmptyText("Keine Arzneimitteldaten geladen");
setHasOptionsMenu(true);
String[] dataColums = { RpEntry.Columns.SNAME };
int[] viewIDs = { android.R.id.text1};
mAdapter = new SimpleCursorAdapter(
getActivity().getBaseContext(),
android.R.layout.simple_list_item_1,
null,
dataColums,
viewIDs,
0);
this.setListAdapter(mAdapter);
// this.setListShown(false);
mLoaderCallbacks = this;
LoaderManager lm = getLoaderManager();
lm.initLoader(LOADER_ID, null, mLoaderCallbacks);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
Log.d(TAG, "entered onCreateOptionsMenu");
// Place an action bar item for searching.
MenuItem item = menu.add("Search");
item.setIcon(android.R.drawable.ic_menu_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
SearchView sv = new SearchView(getActivity());
sv.setOnQueryTextListener(this);
item.setActionView(sv);
}
#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.
switch (item.getItemId()) {
case R.id.action_settings:
Log.d(TAG, "action_settings clicked");
Toast.makeText(getActivity().getApplicationContext(), "Einstellungen",
Toast.LENGTH_LONG).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public static class MySearchView extends SearchView {
public MySearchView(Context context) {
super(context);
}
// The normal SearchView doesn't clear its search text when
// collapsed, so we will do this for it.
#Override
public void onActionViewCollapsed() {
setQuery("", false);
super.onActionViewCollapsed();
}
}
}
Thank you very much!
Make sure in your Activity's onCreate you have
void onCreate(Bundle savedState) {
...
if(savedState == null) {
// add your details fragment
} else {
// do not add your details fragment it's already there
}
}
im working in one small project about handling feeds im looking to handle the feeds in listview and show details in viewpager and get the same feed when i click on the listview im lost about how i can pass the cursor position to the viewpaver
that it s the complet listfragment
public class EntryListFragmentt extends ListFragment
implements OnItemClickListener ,LoaderManager.LoaderCallbacks<Cursor>{
private static final String TAG = "EntryListFragmentt";
private OnItemSelectedListener mParentOnItemSelectedListener;
/**
* Cursor adapter for controlling ListView results.
*/
private SimpleCursorAdapter mAdapter;
public static ImageLoader imageLoader;
Uri detailUri;
static int pos;
private LoaderManager.LoaderCallbacks<Cursor> mCallbacks;
/**
* Handle to a SyncObserver. The ProgressBar element is visible until the SyncObserver reports
* that the sync is complete.
*
* <p>This allows us to delete our SyncObserver once the application is no longer in the
* foreground.
*/
ConnectionDetector cd;
private Object mSyncObserverHandle;
/**
* Options menu used to populate ActionBar.
*/
private Menu mOptionsMenu;
/**
* Projection for querying the content provider.
*/
private static final String[] PROJECTION = new String[]{
FeedContract.Entry._ID,
FeedContract.Entry.COLUMN_NAME_TITLE,
FeedContract.Entry.COLUMN_NAME_LINK,
FeedContract.Entry.COLUMN_IMAG_LINK,
FeedContract.Entry.COLUMN_TEXT_ENTRY,
FeedContract.Entry.COLUMN_NAME_PUBLISHED
};
// Column indexes. The index of a column in the Cursor is the same as its relative position in
// the projection.
/** Column index for _ID */
private static final int COLUMN_ID = 0;
/** Column index for title */
private static final int COLUMN_TITLE = 1;
/** Column index for link */
private static final int COLUMN_URL_STRING = 2;
/** Column index for published */
private static final int COLUMN_IMAG_LINK = 3;
private static final int COLUMN_TEXT_ENTRY = 4;
private static final int COLUMN_PUBLISHED = 5;
AlertDialogManager alert = new AlertDialogManager();
/**
* List of Cursor columns to read from when preparing an adapter to populate the ListView.
*/
private static final String[] FROM_COLUMNS = new String[]{
FeedContract.Entry.COLUMN_NAME_TITLE,
FeedContract.Entry.COLUMN_NAME_PUBLISHED,
FeedContract.Entry.COLUMN_NAME_LINK
// FeedContract.Entry.COLUMN_TEXT_ENTRY
};
/**
* List of Views which will be populated by Cursor data.
*/
private static final int[] TO_FIELDS = new int[]{
R.id.tx_title_actu,
R.id.tx_date_actu,
R.id.img_actu
// R.id.tx_text_actu
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public static EntryListFragmentt newInstance() {
return new EntryListFragmentt();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
/**
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//View view = inflater
// .inflate(R.layout.activity_entry_list, container, false);
return container;
}
**/
/**
* Create SyncAccount at launch, if needed.
*
* <p>This will create a new account with the system for our application, register our
* {#link SyncService} with it, and establish a sync schedule.
*/
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Create account, if needed
SyncUtils.CreateSyncAccount(activity);
}
// private void loaddata(){
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mAdapter = new SimpleCursorAdapter(
getActivity(), // Current context
R.layout.actu_listitem, // Layout for individual rows
null, // Cursor
FROM_COLUMNS, // Cursor columns to use
TO_FIELDS, // Layout fields to use
0 // No flags
);
mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
private String slink;
#Override
public boolean setViewValue(View view, Cursor cursor, int i) {
if (i == COLUMN_PUBLISHED ) {
// Convert timestamp to human-readable date
Time t = new Time();
t.set(cursor.getLong(i));
((TextView) view).setText(t.format("%Y-%m-%d %H:%M"));
// Drawable fimag = ResourceUtils.getDrawableByName( imaglink, getActivity());
//String faceName = "ic_launcher";
return true;
} else if (i == COLUMN_URL_STRING ){
slink = CursorUtils.getString(FeedContract.Entry.COLUMN_NAME_LINK, cursor).trim();
// int vlink = Integer.parseInt(CursorUtils.getString(FeedContract.Entry.COLUMN_NAME_LINK, cursor));
ImageView vimage =(ImageView) view.findViewById(R.id.img_actu);
//vimage.setImageResource(getActivity().getResources().getIdentifier("app.oc.gov.ma:drawable/"+slink,null,null));
vimage.setImageDrawable(ResourceUtils.getDrawableByName(slink, getActivity()));
// imageLoader=new ImageLoader(getActivity().getApplicationContext());
//imageLoader.DisplayImage(imaglink, vimage);
// vimage.setImageResource(R.drawable.a);
// Let SimpleCursorAdapter handle other fields automatically
return true;
} else {
return false;
}
}
});
mCallbacks = this;
setListAdapter(mAdapter);
setEmptyText(getText(R.string.loading));
getLoaderManager().initLoader(0, null, mCallbacks);
}
#Override
public void onResume() {
super.onResume();
mSyncStatusObserver.onStatusChanged(0);
// Watch for sync state changes
final int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING |
ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE;
mSyncObserverHandle = ContentResolver.addStatusChangeListener(mask, mSyncStatusObserver);
}
#Override
public void onPause() {
super.onPause();
if (mSyncObserverHandle != null) {
ContentResolver.removeStatusChangeListener(mSyncObserverHandle);
mSyncObserverHandle = null;
}
}
/**
* Query the content provider for data.
*
* <p>Loaders do queries in a background thread. They also provide a ContentObserver that is
* triggered when data in the content provider changes. When the sync adapter updates the
* content provider, the ContentObserver responds by resetting the loader and then reloading
* it.
*/
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
// We only have one loader, so we can ignore the value of i.
// (It'll be '0', as set in onCreate().)
return new CursorLoader(getActivity(), // Context
FeedContract.Entry.CONTENT_URI, // URI
PROJECTION, // Projection
null, // Selection
null, // Selection args
// null); // Sort
FeedContract.Entry.COLUMN_NAME_PUBLISHED + " desc"); // Sort
}
/**
* Move the Cursor returned by the query into the ListView adapter. This refreshes the existing
* UI with the data in the Cursor.
*/
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
mAdapter.changeCursor(cursor);
}
/**
* Called when the ContentObserver defined for the content provider detects that data has
* changed. The ContentObserver resets the loader, and then re-runs the loader. In the adapter,
* set the Cursor value to null. This removes the reference to the Cursor, allowing it to be
* garbage-collected.
*/
#Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
mAdapter.changeCursor(null);
}
/**
* Create the ActionBar.
*/
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
mOptionsMenu = menu;
inflater.inflate(R.menu.main_actu, menu);
}
/**
* Respond to user gestures on the ActionBar.
*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// If the user clicks the "Refresh" button.
case R.id.menu_refresh:
cd = new ConnectionDetector(getActivity().getApplicationContext());
// Check for internet connection
if (!cd.isConnectingToInternet()) {
// Internet Connection is not present
setEmptyText(getText(R.string.noconnect));
alert.showAlertDialog(getActivity(), "Internet Connection Error",
"Please connect to working Internet connection", false);
}else {
SyncUtils.TriggerRefresh();
return true;
}
return false;
}
return super.onOptionsItemSelected(item);
}
/**
* Load an article in the default browser when selected by the user.
*/
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
}
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Get a URI for the selected item, then start an Activity that displays the URI. Any
// Activity that filters for ACTION_VIEW and a URI can accept this. In most cases, this will
// be a browser.
// Get the item at the selected position, in the form of a Cursor.
Cursor c = (Cursor) mAdapter.getItem(position);
// Get the link to the article represented by the item.
Uri detailUri = Uri.parse(FeedContract.Entry.CONTENT_URI + "/" + id);
WhatsOnFragment.newInstance(position, detailUri);
WhatsOnFragment WWhatsOnFragment = new WhatsOnFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.frame_container, WWhatsOnFragment);
//ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
//ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
}
public int getCount(int cmp) {
return cmp ;
}
public static WhatsOnFragment newInstance(int position,int cmp, Uri detailUri) {
WhatsOnFragment frag = new WhatsOnFragment();
Bundle args = new Bundle();
args.putParcelable(FeedContract.Entry.CONTENT_ITEM_TYPE, detailUri);
args.putInt(WhatsOnFragment.POSITION_KEY, position);
frag.setArguments(args);
return frag;
}
/**
* Set the state of the Refresh button. If a sync is active, turn on the ProgressBar widget.
* Otherwise, turn it off.
*
* #param refreshing True if an active sync is occuring, false otherwise
*/
public void setRefreshActionButtonState(boolean refreshing) {
if (mOptionsMenu == null) {
return;
}
final MenuItem refreshItem = mOptionsMenu.findItem(R.id.menu_refresh);
if (refreshItem != null) {
if (refreshing) {
refreshItem.setActionView(R.layout.actionbar_indeterminate_progress);
} else {
refreshItem.setActionView(null);
}
}
}
/**
* Crfate a new anonymous SyncStatusObserver. It's attached to the app's ContentResolver in
* onResume(), and removed in onPause(). If status changes, it sets the state of the Refresh
* button. If a sync is active or pending, the Refresh button is replaced by an indeterminate
* ProgressBar; otherwise, the button itself is displayed.
*/
private SyncStatusObserver mSyncStatusObserver = new SyncStatusObserver() {
/** Callback invoked with the sync adapter status changes. */
#Override
public void onStatusChanged(int which) {
getActivity().runOnUiThread(new Runnable() {
/**
* The SyncAdapter runs on a background thread. To update the UI, onStatusChanged()
* runs on the UI thread.
*/
#Override
public void run() {
// Create a handle to the account that was created by
// SyncService.CreateSyncAccount(). This will be used to query the system to
// see how the sync status has changed.
Account account = GenericAccountService.GetAccount();
if (account == null) {
// GetAccount() returned an invalid value. This shouldn't happen, but
// we'll set the status to "not refreshing".
setRefreshActionButtonState(false);
return;
}
// Test the ContentResolver to see if the sync adapter is active or pending.
// Set the state of the refresh button accordingly.
boolean syncActive = ContentResolver.isSyncActive(
account, FeedContract.CONTENT_AUTHORITY);
boolean syncPending = ContentResolver.isSyncPending(
account, FeedContract.CONTENT_AUTHORITY);
setRefreshActionButtonState(syncActive || syncPending);
}
});
}
};
}
that it s the fragment detail viewpager
public class WhatsOnFragment extends Fragment implements
LoaderCallbacks<Cursor> {
private static final String TAG="WhatsOnFragment";
private OnItemSelectedListener mParentOnImageSelectedListener;
private Handler mHandler = new Handler();
private TextView mCountdownTextView;
private ViewGroup mRootView;
private Cursor mAnnouncementsCursor;
private LayoutInflater mInflater;
private int mTitleCol = -1;
private int mDateCol = -1;
private int mUrlCol = -1;
//**********************************************''
/** Column index for _ID */
private static final int COLUMN_ID = 0;
/** Column index for title */
private static final int COLUMN_TITLE = 1;
/** Column index for link */
private static final int COLUMN_URL_STRING = 2;
/** Column index for published */
private static final int COLUMN_IMAG_LINK = 3;
private static final int COLUMN_TEXT_ENTRY = 4;
private static final int COLUMN_PUBLISHED = 5;
private static final String[] PROJECTION = new String[]{
FeedContract.Entry._ID,
FeedContract.Entry.COLUMN_NAME_TITLE,
FeedContract.Entry.COLUMN_NAME_LINK,
FeedContract.Entry.COLUMN_IMAG_LINK,
FeedContract.Entry.COLUMN_TEXT_ENTRY,
FeedContract.Entry.COLUMN_NAME_PUBLISHED
};
public static String POSITION_KEY = "position";
private static final int ANNOUNCEMENTS_LOADER_ID = 0;
private Uri detailUri;
public static int vpos;
public static WhatsOnFragment newInstance(int position, Uri detailUri) {
WhatsOnFragment frag = new WhatsOnFragment();
Bundle args = new Bundle();
args.putInt(POSITION_KEY, position);
//args.putParcelable(FeedContract.Entry.CONTENT_ITEM_TYPE, detailUri);
frag.setArguments(args);
return frag;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.v(TAG, "onAttach");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Bundle extras = getArguments();
//vpos = extras.getInt(POSITION_KEY,0);
//vpos = savedInstanceState.getInt(POSITION_KEY, 0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mInflater = inflater;
//
mRootView = (ViewGroup) inflater.inflate(R.layout.content_f,
container,false);
refresh();
return mRootView;
}
#Override
public void onDetach() {
super.onDetach();
// mHandler.removeCallbacks(mCountdownRunnable);
getActivity().getContentResolver().unregisterContentObserver(mObserver);
}
private void refresh() {
mHandler.removeCallbacks(mCountdownRunnable);
//mRootView.removeAllViews();
setupDuring();
//getLoaderManager().initLoader(0, null, this);
}
private void setupDuring() {
// Start background query to load announcements
getLoaderManager().initLoader(0, null, this);
getActivity().getContentResolver().registerContentObserver(
FeedContract.Entry.CONTENT_URI, true, mObserver);
}
/**
* Event that updates countdown timer. Posts itself again to
* {#link #mHandler} to continue updating time.
*/
private final Runnable mCountdownRunnable = new Runnable() {
public void run() {
mHandler.postDelayed(new Runnable() {
public void run() {
refresh();
}
}, 100);
return;
}
};
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), // Context
FeedContract.Entry.CONTENT_URI, // URI
PROJECTION, // Projection
null, // Selection
null, // Selection args
// null);
FeedContract.Entry.COLUMN_NAME_PUBLISHED + " desc"); // Sort
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (getActivity() == null) {
return;
}
if (data != null && data.getCount() > 0) {
mTitleCol = data.getColumnIndex(FeedContract.Entry.COLUMN_NAME_TITLE);
mDateCol = data.getColumnIndex(FeedContract.Entry.COLUMN_TEXT_ENTRY);
showAnnouncements(data);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mAnnouncementsCursor = null;
}
/**
* Show the the announcements
*/
private void showAnnouncements(Cursor announcements) {
mAnnouncementsCursor = announcements;
ViewGroup announcementsRootView = (ViewGroup) mInflater.inflate(
R.layout.detail, mRootView, false);
final ViewPager pager = (ViewPager) announcementsRootView.findViewById(
R.id.pager);
final PagerAdapter adapter = new AnnouncementsAdapter();
pager.setAdapter(adapter);
//pager.setCurrentItem(0);
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
pager.setCurrentItem(pager.getCurrentItem());
}
#Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
//Toast.makeText(getActivity().getApplicationContext(),"myposition " + position,Toast.LENGTH_LONG).show();
}
});
//mRootView.removeAllViews();
mRootView.addView(announcementsRootView);
}
public class AnnouncementsAdapter extends PagerAdapter {
#Override
public Object instantiateItem(ViewGroup pager, int position) {
mAnnouncementsCursor.moveToPosition(position);
View rootView = (View) mInflater.inflate(
R.layout.detail_fragment, pager, false);
TextView titleView = (TextView) rootView.findViewById(R.id.title);
TextView subtitleView = (TextView) rootView.findViewById(R.id.description);
//WebView desc = (WebView) rootView.findViewById(R.id.desc);
// Enable the vertical fading edge (by default it is disabled)
ScrollView sv = (ScrollView) rootView.findViewById(R.id.sv);
sv.setVerticalFadingEdgeEnabled(true);
// Set webview properties
//WebSettings ws = desc.getSettings();
//ws.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
//ws.setLightTouchEnabled(false);
//ws.setPluginState(PluginState.ON);
//ws.setJavaScriptEnabled(true);
titleView.setText(mAnnouncementsCursor.getString(mTitleCol));
subtitleView.setText(mAnnouncementsCursor.getString(mDateCol));
//desc.loadDataWithBaseURL("http://.../",mAnnouncementsCursor.getString(mDateCol), "text/html", "UTF-8", null);
pager.addView(rootView, 0);
return rootView;
}
#Override
public void destroyItem(ViewGroup pager, int position, Object view) {
pager.removeView((View) view);
}
#Override
public int getCount() {
return mAnnouncementsCursor.getCount();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public Object getItem(int position) {
WhatsOnFragment frag = new WhatsOnFragment();
Bundle args = new Bundle();
args.putInt(POSITION_KEY, position);
//args.putParcelable(FeedContract.Entry.CONTENT_ITEM_TYPE, detailUri);
frag.setArguments(args);
if (position > 0 && position < mAnnouncementsCursor.getCount() - 1) {
return position;
}
return position;
}
}
private final ContentObserver mObserver = new ContentObserver(new Handler()) {
#Override
public void onChange(boolean selfChange) {
if (getActivity() == null) {
return;
}
Loader<Cursor> loader = getLoaderManager().getLoader(ANNOUNCEMENTS_LOADER_ID);
if (loader != null) {
loader.forceLoad();
}
}
};
}
Here's how I am passing my Uri from one activity to another:
After you get the uri from your onListItemClick, add this line of code after that:
String uriString = uri.toString();
Now, you can either do it through shared preference or by passing extras from intent,
Method 1: By shared preference:
SharedPreferences prefs = getSharedPreferences("your_file_name", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("uri", uriString);
editor.commit();
Then, in your other activity or where your listview is defined, use this to retrieve the uri,
SharedPreferences mPreferences = mPreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
String uri = mPreferences.getString("uri", uri);
//To parse the uri
Uri newUri = Uri.parse(uri);
Then you can use this uri to get the information you want to.
Method 2 : Getting uri from Intent:
First : In you activity where you are getting the Uri,
Intent myIntent = new Intent(SomeActivity1.this, SomeActivity2.class);
myIntent.putExtra("uri", uri);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
setResult(RESULT_OK, myIntent);
startActivity(myIntent);
In your other activity or where your listview is defined, use this to retrieve the uri,
Intent data = getIntent();
Uri uri = data.getParcelableExtra("uri");
Now you can use this uri to get whatever information you are trying to retrieve.
Hope this answer helps .. :)
The code below defines a simple ListView with a listener that calls a simple ViewPager by passing selected item in parameters.
First the list:
public class SampleListFragment extends android.support.v4.app.ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_list, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final ArrayList<String> list = new ArrayList<String>();
list.add("object1");
list.add("object2");
list.add("object3");
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, list);
getListView().setAdapter(adapter);
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final String item = (String) adapterView.getItemAtPosition(i);
// Quick and dirty way to call the ViewPager with the selected item
final SampleViewPagerFragment sampleViewPagerFragment = SampleViewPagerFragment.newIntance(item);
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_holder, sampleViewPagerFragment).commit();
}
});
}
}
Next the ViewPager:
public class SampleViewPagerFragment extends Fragment {
public static SampleViewPagerFragment newIntance(String text){
final SampleViewPagerFragment sampleViewPagerFragment = new SampleViewPagerFragment();
final Bundle arguments = new Bundle();
arguments.putString("object", text);
sampleViewPagerFragment.setArguments(arguments);
return sampleViewPagerFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_view_pager, null);
final ViewPager viewPager = (ViewPager) view.findViewById(R.id.view_pager);
final Bundle arguments = getArguments();
if(arguments != null){
// We create the adapter with arguments of the fragment
final SampleAdapter adapter = new SampleAdapter(getChildFragmentManager(), (String) arguments.get("object"));
viewPager.setAdapter(adapter);
}
return view;
}
private class SampleAdapter extends FragmentPagerAdapter {
private String object;
public SampleAdapter(FragmentManager fm, String object){
super(fm);
this.object = object;
}
#Override
public int getCount() {
return 2;
}
#Override
public Fragment getItem(int position) {
// We pass the selected item in arguments
return SampleFragment.newInstance(object + " " + position);
}
}
}
Finally the fragment that displays the content:
public class SampleFragment extends Fragment {
public static SampleFragment newInstance(String text){
final SampleFragment sampleFragment = new SampleFragment();
final Bundle arguments = new Bundle();
arguments.putString("text", text);
sampleFragment.setArguments(arguments);
return sampleFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final TextView textView = new TextView(getActivity());
final Bundle arguments = getArguments();
if(arguments != null){
textView.setText((String) arguments.get("text"));
}
return textView;
}
}
I hope it is what you are looking for..
I am writing a simple news app as a learning exercise. Display a listfragment driven by a SQLite cursor. Click and go to detail screen. Now trying to convert detail screen to ViewPager. I do not want to pass the Cursor from listfragment to ViewPager activity, so I pass the current position in the cursor instead and then create a new Cursor. Can't seem to get the position right though. If I set it in the Activity and not getItem() it goes to the correct position but never changes. If I set it in getItem, it always starts at position 0. The key lines are
// cp.getCursor().moveToPosition(mStartPosition);
// cp.notifyDataSetChanged();
Thanks for any help.
public class ViewPagerActivity extends FragmentActivity {
private static final int NUM_PAGES = 5;
private static String mSectionSelected = "";
private static int mStartPosition;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager);
// Instantiate a ViewPager and a PagerAdapter.
mSectionSelected = (String)this.getIntent().getSerializableExtra("SECTION");
mPager = (ViewPager) this.findViewById(R.id.pager);
CursorPagerAdapter cp = new CursorPagerAdapter( getSupportFragmentManager(), mSectionSelected);
mPager.setAdapter(cp);
// cp.getCursor().moveToPosition(mStartPosition);
// cp.notifyDataSetChanged();
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
}
And here is the adapter - the key line is cursor.moveToPosition(position);
public class CursorPagerAdapter extends FragmentStatePagerAdapter {
private Cursor cursor;
private static String mSectionSelected;
public CursorPagerAdapter(FragmentManager fm, String mSection) {
super(fm);
mSectionSelected = mSection;
this.cursor = NewsManager.get(ApplicationContext.getInstance()).queryNews(mSectionSelected);
}
#Override
public PagerDetailFragment getItem(int position) {
if (cursor == null) // shouldn't happen
return null;
cursor.moveToPosition(position);
PagerDetailFragment frag;
try {
frag = PagerDetailFragment.newInstance();
String mTitle = cursor.getString(NewsDatabaseHelper.COLNUM_TITLE);
String mSection = cursor.getString(NewsDatabaseHelper.COLNUM_CATEGORY);
String mSource = cursor.getString(NewsDatabaseHelper.COLNUM_SOURCE);
String mPublishedDate = cursor.getString(NewsDatabaseHelper.COLNUM_PUBLISHDATE);
String mThumbnail = cursor.getString(NewsDatabaseHelper.COLNUM_THUMBNAIL);
String mBody = cursor.getString(NewsDatabaseHelper.COLNUM_CONTENT);
Bundle args = new Bundle();
args.putString(NewsDatabaseHelper.COLUMN_TITLE, mTitle);
args.putString(NewsDatabaseHelper.COLUMN_CATEGORY, mSection);
args.putString(NewsDatabaseHelper.COLUMN_SOURCE, mSource);
args.putString(NewsDatabaseHelper.COLUMN_PUBLISHDATE, mPublishedDate);
args.putString(NewsDatabaseHelper.COLUMN_THUMBNAIL, mThumbnail);
args.putString(NewsDatabaseHelper.COLUMN_CONTENT, mBody);
frag.setArguments(args);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return frag;
}
#Override
public int getCount() {
if (cursor == null)
return 0;
else
return cursor.getCount();
}
public void swapCursor(Cursor c) {
if (cursor == c)
return;
this.cursor = c;
notifyDataSetChanged();
}
public Cursor getCursor() {
return cursor;
}
}