I have two listfragment and one fragment in my application. I show you first fragment.
The application starts, Asynctask retrieves data and put them in arrayNews.
I think the problem is the update of listview or adapter in listfragment that does not refresh.
If I change the phone's orientation => listfragment (+ listview) appears correctly.
If I go to fragment 3 (fragment in 2 and 3 in memory), then come back on fragment 1 => it works correctly.
Sorry for my english ^^
public class MainActivity extends FragmentActivity implements ActionBar.TabListener
{
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
public static ArrayList<Data> arrayNews = new ArrayList<Data>();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Fragment> listeFragments = new Vector<Fragment>();
listeFragments.add(Fragment.instantiate(this, ActualiteFragment.class.getName()));
listeFragments.add(Fragment.instantiate(this, DossierFragment.class.getName()));
listeFragments.add(Fragment.instantiate(this, ForumFragment.class.getName()));
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), listeFragments);
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
#Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++)
{
actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
}
if (arrayDossier.size() == 0 && arrayDossier.size() == 0)
{
chargement_donnees();
}
}
public void chargement_donnees()
{
AsyncTaskChargement chargNews = new AsyncTaskChargement();
chargNews.execute();
}
public class AsyncTaskChargement extends AsyncTask<Void, Integer, Void>
{
private ProgressDialog dialog = new ProgressDialog(MainActivity.this);
#Override
protected void onPreExecute()
{
super.onPreExecute();
dialog.setMessage("Chargement des données ...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected Void doInBackground(Void... arg0)
{
arrayNews = ContainerData_news.getFeeds();
return null;
}
#Override
protected void onPostExecute(Void result)
{
if (this.dialog.isShowing())
{
this.dialog.dismiss();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.menu_refresh:
chargement_donnees();
return true;
default:
return false;
}
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
mViewPager.setCurrentItem(tab.getPosition());
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
public class SectionsPagerAdapter extends FragmentPagerAdapter
{
List<Fragment> listeFragments;
public SectionsPagerAdapter(FragmentManager fm, List<Fragment> listeFragments)
{
super(fm);
this.listeFragments = listeFragments;
}
#Override
public Fragment getItem(int position)
{
return listeFragments.get(position);
}
#Override
public int getCount()
{
return listeFragments.size();
}
#Override
public CharSequence getPageTitle(int position)
{
switch (position)
{
case 0:
return getString(R.string.title_section1).toUpperCase();
case 1:
return getString(R.string.title_section2).toUpperCase();
case 2:
return getString(R.string.title_section3).toUpperCase();
}
return null;
}
}
public static class ActualiteFragment extends ListFragment
{
public ActualiteFragment()
{
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setListAdapter(new AdapterListe(getActivity(), arrayNews));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.listfragment, container, false);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id)
{
...
}
}
}
I found an easy way to update such list
Steps would be.:
1. declare onCreateView in ListFragment
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.TheLayoutContainingAListView, container, false);
return view;
}
TheLayoutContainingAListView.xml should contain only a listview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>
</LinearLayout>
The android:id must be "#android:id/list" . however you may try other things.. I didn't..
2. In onPostExecute of your AsyncTask (Asynctask should be in MainActivity), do everything that you want to do.. i.e. declare an adapter, and setAdapter
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
lv = (ListView) findViewById(android.R.id.list);
CustomAdapter adapt = new CustomAdapter(MainActivity.this,
android.R.id.list, fetch); //You can use ArrayAdapter.. i wanted a custom one
lv.setAdapter(adapt);
showFragment(YOUR Fragment, false);
super.onPostExecute(result);
}
showFragment is just a function i used to show a particular fragment and hide all others.. you can easily achieve it by FragmentTransaction show() and hide() methods.
Use youradapter.notifyDataSetChanged(); in onPostExecute to force a redraw of your list.
Related
when i run this code,the toast in two different fragments are displayed on one tab. when i swipe to next tab nothing is displayed.
this is is my main tab activity:
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Offers", "Distance", "Happy Hours","Shop List" };
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
this is adapter class :
public class TabsPagerAdapter extends FragmentStatePagerAdapter {
Bundle bundle = new Bundle();
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
Fragment of = new OfferFragment();
bundle.putString("OfferFragment", "OfferFragment");
of.setArguments(bundle);
return of;
case 1:
Fragment df = new DistanceFragment();
bundle.putString("DistanceFragment", "DistanceFragment");
df.setArguments(bundle);
return df;
case 2:
Fragment hf = new HappyHoursFragment();
bundle.putString("HappyHoursFragment", "HappyHoursFragment");
hf.setArguments(bundle);
return hf;
case 3:
Fragment sf = new ShoplistFragment();
bundle.putString("ShoplistFragment", "ShoplistFragment");
sf.setArguments(bundle);
return sf;
}
return null;
}
#Override
public int getCount() {
return 4;
}
}
this is my first fragment :
public class OfferFragment extends Fragment {
private String name;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// public static final String ARG_OBJECT = "object";
View rootView = inflater.inflate(R.layout.offerfragment, container,
false);
Bundle args = getArguments();
TextView txtview = (TextView) rootView.findViewById(R.id.offer);
name = args.getString("OfferFragment");
txtview.setText(args.getString("OfferFragment"));
display();
return rootView;
}
private void display() {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), name, Toast.LENGTH_SHORT).show();
}
}
this is my second fragment :
public class DistanceFragment extends Fragment {
private String name;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.distancefragment, container, false);
Bundle args = getArguments();
TextView txtview = (TextView) rootView.findViewById(R.id.distance);
name = args.getString("DistanceFragment");
txtview.setText(args.getString("DistanceFragment"));
display();
return rootView;
}
private void display() {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), name, Toast.LENGTH_SHORT).show();
}
}
any suggestions are appreciated. am stuck with this.
This is because next fragment is created by pager
before showing toast check if that fragment is visible or not
if(fragmentName.this.isVisible())
{
// do your stuff here
}
Write onResume() in every fragment class.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
//Display Toast message here
}
}
I have a Fragment with a TableLayout. The data in the table is from a SQLite db. The SQLite db is populated from a RESTful webservice in an AsyncTask in the MainActivity. The Fragment must wait for the task to complete before populating the table. The Fragment listens for the task onPostExecute() method to be called. When it is, the method onLoadAndStoreComplete in the Fragment is called. This all works.
What doesn't work is that I need the fragment activity in order to create new TableRows and TextViews in onLoadAndStoreComplete and I can't get it.
I've tried:
- making a class member fragmentActivity and assigning in onCreateView(), but by the time it gets to onLoadAndStoreComplete(), it is null.
- calling this.getActivity() again in onLoadAndStoreComplete(), but it returns null.
How do I get the fragment activity?
MyFragment.java:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
fragmentActivity = this.getActivity(); // return value is valid
...
}
#Override
public void onLoadAndStoreComplete() {
fragmentActivity = this.getActivity(); // returns null
...
}
from MainActivity.java (extends ActionBarActivity)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = this;
setContentView(R.layout.activity_main);
Resources resources = getResources();
String[] tabTitleArray = { resources.getString(R.string.first_fragment),
resources.getString(R.string.second_fragment),
resources.getString(R.string.help_fragment) };
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getSupportActionBar();
mAdapter = new TabsPagerAdapter(this.getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tab_name : tabTitleArray) {
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
}
// On swiping the ViewPager, select the respective tab
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position) ;// on changing the page, make respected tab selected
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
String url = "http://myrestfulwebservice";
Fragment secondFragment = mAdapter.getItem(SECOND_TAB);
new LoadAndStoreDataTask((OnLoadAndStoreCompleteListener)secondFragment).execute(url);
}
} // end OnCreate
TabsPagerAdapter.java
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment();
case 1:
return new SecondFragment();
case 2:
return new HelpFragment();
}
return null;
}
#Override
public int getCount() {
return 3; // get item count - equal to number of tabs
}
public static void setTabColor(TabHost tabhost) {
for(int i=0;i<tabhost.getTabWidget().getChildCount();i++) {
tabhost.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#FF0000")); //unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab()).setBackgroundColor(Color.parseColor("#0000FF")); // selected
}
}
I haven't tested this, but it seems to me that it would work.
Add a Context parameter to the constructor for both TabsPagerAdapter and MyFragment.
Something like this:
TabsPagerAdapter.java:
public class TabsPagerAdapter extends FragmentPagerAdapter {
private Context mCtx;
public TabsPagerAdapter(FragmentManager fragmentManager, Context context) {
super(fragmentManager);
mCtx = context;
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment(mCtx);
case 1:
return new SecondFragment(mCtx);
case 2:
return new HelpFragment(mCtx);
}
return null;
}
#Override
public int getCount() {
return 3; // get item count - equal to number of tabs
}
public static void setTabColor(TabHost tabhost) {
for(int i=0;i<tabhost.getTabWidget().getChildCount();i++) {
tabhost.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#FF0000")); //unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab()).setBackgroundColor(Color.parseColor("#0000FF")); // selected
}
}
MainActivity.java:
mAdapter = new TabsPagerAdapter(this.getSupportFragmentManager(), this);
MyFragment.java (do this in FirstFragment, SecondFragment, and HelpFragment):
public static class MyFragment extends Fragment {
private Context fragmentActivity ;
public MyFragment(Context context){
fragmentActivity = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//.........
return rootView;
}
#Override
public void onLoadAndStoreComplete() {
//do something with fragmentActivity
}
}
It seems the AsyncTask starts too early. suggest loading the db in onActivityCreated(), it's be called after onCreateView
#Override
public void onActivityCreated (Bundle savedInstanceState) {
//load your db here
}
it is a few days I try to solve this problem whitout success. Please help me.
I use the tabs navigation with viewpager.There are four fragments. I use async task for download the data I need to put in the view. when the app is started, the first fragments is ampty. But when i swipe to the second or the third, they have data. if i swipe from the second to the first, it has data too. so i guess i may be something wrong with notifyDataSetChanged, but i tried and it doesnt work.
MainActivity.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
final ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(1);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
//private ArrayList hasLoadedPages = new ArrayList<Integer>();
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(mAppSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public static class AppSectionsPagerAdapter extends FragmentPagerAdapter {
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
//case 0:
// return new LaunchpadSectionFragment();
default:
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1);
fragment.setArguments(args);
return fragment;
}
}
#Override
public int getCount() {
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
String str="";
if (position==0){
str = "one";
}else if(position==1){
str = "two";
}else if(position==2){
str = "three";
}else if(position==3){
str = "four";
}
return str;
}
#Override
public void notifyDataSetChanged()
{
super.notifyDataSetChanged();
}
}
public static class DummySectionFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_section_dummy, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
Bundle args = getArguments();
mCid = args.getInt(ARG_SECTION_NUMBER);
mNewsData = new ArrayList<HashMap<String,Object>>();
mNewsList = (ListView)getView().findViewById(android.R.id.list);
mNewsListAdapter = new SimpleAdapter(this.getActivity(), mNewsData, R.layout.newslist_item,
new String[]{"newslist_item_title","newslist_item_digest","newslist_item_source","newslist_item_ptime"},
new int[]{R.id.newslist_item_title,R.id.newslist_item_digest,R.id.newslist_item_source,R.id.newslist_item_ptime});
View loadMoreLayout = this.getLayoutInflater(savedInstanceState).inflate(R.layout.loadmore, null);
mNewsList.setAdapter(mNewsListAdapter);
mNewsList.addFooterView(loadMoreLayout);
mNewsList.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Intent intent = new Intent(getActivity(), NewsDetailsActivity.class);
startActivity(intent);
intent.putExtra("newsDate", mNewsData);
intent.putExtra("position", position);
startActivity(intent);
}
});
mLoadMoreBtn = (Button)getView().findViewById(R.id.loadmore_btn);
mLoadMoreBtn.setOnClickListener(loadMoreListener);
loadNewsAsyncTask = new LoadNewsAsyncTask();
loadNewsAsyncTask.execute(mCid,0,true);
}
}
private static class LoadNewsAsyncTask extends AsyncTask<Object, Integer, Integer>
{
#Override
protected void onPreExecute()
{
mLoadMoreBtn.setText(R.string.loadmore_txt);
}
#Override
protected Integer doInBackground(Object... params)
{
return getSpeCateNews((Integer)params[0],mNewsData,(Integer)params[1],(Boolean)params[2]);
}
#Override
protected void onPostExecute(Integer result)
{
switch (result)
{
case NONEWS:
mLoadMoreBtn.setText(R.string.no_news);
break;
case NOMORENEWS:
mLoadMoreBtn.setText(R.string.no_more_news);
break;
case LOADERROR:
mLoadMoreBtn.setText(R.string.load_news_failure);
break;
}
mNewsListAdapter.notifyDataSetChanged();
mLoadMoreBtn.setText(R.string.loadmore_btn);
}
}
You are using FragmentPagerAdapter please change it to FragmentStatePagerAdapter and run again
Difference between FragmentPagerAdapter and FragmentStatePagerAdapter
About FragmentPagerAdapter Google's guide says:
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.
And about FragmentStatePagerAdapter:
This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.
I want to create PullToRefresh list fragment with pager.
I'm using ActionBarSherlock, and this implementation of the list. I had no problems without fragment, but I need to support two-pane layout.
layout files
activity
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SubcatNavActivity" />
</LinearLayout>
fragment
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/subcat_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Activity is pretty simple
public class SubcatNavActivity extends SherlockFragmentActivity
{
private SubcatNavPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_subcat_nav);
mPager = new SubcatNavPager(this);
mPager.initialisePaging();
setProgressBarIndeterminateVisibility(true);
}
}
I have created pager class to also use it later in main activity for two-pane mode.
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;
public class SubcatNavPager implements ActionBar.TabListener
{
public SectionsPagerAdapter mSectionsPagerAdapter;
public ViewPager mViewPager;
private SherlockFragmentActivity mFragmentActivity;
public SubcatNavPager(SherlockFragmentActivity fa) {
mFragmentActivity = fa;
}
public void initialisePaging() {
mFragmentActivity.setTitle(mFragmentActivity.getResources().getString(SiteContent.curr_cat.nameID));
try {
List<Fragment> fragments = new Vector<Fragment>();
mSectionsPagerAdapter = new SectionsPagerAdapter(mFragmentActivity.getSupportFragmentManager(), fragments);
for (int i = 0; i < SiteContent.curr_cat.content.size(); ++i) {
Fragment tmp = SiteContent.curr_cat.fragment.newInstance();
if (!(tmp instanceof ContentDownloader)) {
throw new IllegalStateException(
"Fragment must implement content downloader interface.");
}
Bundle args = new Bundle();
args.putInt(SubcatListFragment.SUBCAT_IDX, i);
tmp.setArguments(args);
fragments.add((Fragment)tmp);
}
mViewPager = (ViewPager)mFragmentActivity.findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
final ActionBar actionBar = mFragmentActivity.getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mViewPager
.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
}
actionBar.setDisplayHomeAsUpEnabled(true);
}
catch (Exception e) {}
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) {
int pos = tab.getPosition();
SiteContent.setCurrSubCat(pos);
mViewPager.setCurrentItem(pos);
((ContentDownloader)mSectionsPagerAdapter.getItem(pos)).downloadContent(false);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
public class SectionsPagerAdapter extends FragmentPagerAdapter
{
private List<Fragment> fragments;
public SectionsPagerAdapter(FragmentManager fm, List<Fragment> fList) {
super(fm);
fragments = fList;
}
#Override
public Fragment getItem(int position) {
Fragment tmp = fragments.get(position);
return tmp;
}
#Override
public int getCount() { return fragments.size(); }
#Override
public CharSequence getPageTitle(int position) {
return mFragmentActivity.getResources().getString(SiteContent.curr_cat.content.get(position).nameID);
}
}
}
And finally, the fragment itself
import com.actionbarsherlock.app.SherlockListFragment;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
public class SubcatListFragment extends SherlockListFragment implements ContentDownloader
{
public static final String SUBCAT_IDX = "subcat_idx";
protected ArrayAdapter<SiteItem> adapter;
protected DownloadSubcatTask loadTask;
protected SiteSubcat subcat;
private PullToRefreshListView mPullToRefreshListView;
private boolean loadRequested;
public SubcatListFragment() {
adapter = null;
loadRequested = false;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
subcat = SiteContent.curr_cat.content.get(args.getInt(SUBCAT_IDX));
adapter = new ArrayAdapter<SiteItem>(getActivity(), android.R.layout.simple_list_item_1, subcat.items);
this.setListAdapter(adapter);
if (loadRequested == true)
downloadContent(false);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_subcat_nav, container, false);
ListView lv = (ListView) layout.findViewById(R.id.subcat_list);
ViewGroup parent = (ViewGroup) lv.getParent();
int lvIndex = parent.indexOfChild(lv);
parent.removeViewAt(lvIndex);
mPullToRefreshListView = new PullToRefreshListView(layout.getContext());
mPullToRefreshListView.setMode(Mode.BOTH);
mPullToRefreshListView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>()
{
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
downloadContent(true);
}
});
parent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams());
return layout;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Intent subcatIntent = new Intent(getActivity(), NewsActivity.class);
SiteContent.setCurrItem((int)id);
startActivity(subcatIntent);
}
#Override
public void downloadContent(boolean bRefresh) {
// on first call to onTabSelected this fragment is not created, yet
if (subcat == null)
loadRequested = true;
else
{
loadRequested = false;
if (loadTask == null && (adapter.isEmpty() == true || bRefresh == true))
(loadTask = new DownloadSubcatTask()).execute(subcat.getUrl());
}
}
protected void showProgress(boolean bShow) {
getActivity().setProgressBarIndeterminateVisibility(bShow);
}
private class DownloadSubcatTask extends DownloadTask {
public DownloadSubcatTask() {}
#Override
protected void onPreExecute() {
super.onPreExecute();
showProgress(true);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
adapter.clear();
loadTask = null;
try {
SiteContent.curr_cat.parser.newInstance().parse(result, adapter);
}
catch (Exception e) {}
mPullToRefreshListView.onRefreshComplete();
adapter.notifyDataSetChanged();
showProgress(false);
}
}
}
As you can see, everything consists of stuff from examples. But the problem is that list is not shown when I start the app. I can see the tabs, the loading indicator is gone (and I know adapter has data) but list area is clear white. And I can't pull the list to refresh it. But if i try to swap pages, suddenly data appears in previous page (actually not previous, but the one before). It seems it has something to do with adapter loading first two fragments, but I can figure out what's wrong.
How to make lists appears when they are loaded?
And more general question, is this the right architecture to go on?
EDIT:
if I remove all pull-to-refresh code like this
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View layout = inflater.inflate(R.layout.fragment_subcat_nav, container, false);
return layout;
}
and set default list id in the fragment layout android:id="#android:id/list" list view is displayed as it should. can't figure out why pull-to-refresh causes problems.
this is how i fixed the problem (list fragment need to return a list view)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_subcat_nav, container, false);
ListView lv = (ListView) layout.findViewById(android.R.id.list);
mPullToRefreshListView = new PullToRefreshListView(getActivity());
mPullToRefreshListView.setLayoutParams(lv.getLayoutParams());
mPullToRefreshListView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>()
{
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
downloadContent(true);
}
});
return mPullToRefreshListView;
}
I am using the following library for my sliding menu (https://github.com/bk138/LibSlideMenu) in my app.
In my app the sliding menu works. I can slide from right to left and the menu will appear. But the problem is that when I am in the menu I can't slide back to the fragment were I came from.
The only way to get back is using back button. Also when you are in the menu I don't have the padding on the right where you see the previous fragment on the background.
I am searching for it like days. I have searched the example for the problem but couldn't find the essential thing that i am forgetting.
My main activity:
public class MainActivity extends SlidingFragmentActivity {
private Fragment rFrag;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setBehindContentView(R.layout.menu_frame);
if (savedInstanceState != null)
rFrag = getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
if (rFrag == null)
rFrag = new RecentGridFragment();
FragmentTransaction fragment = getSupportFragmentManager().beginTransaction();
fragment.replace(R.id.content_frame, rFrag);
MenuFragment mFrag = new MenuFragment();
fragment.replace(R.id.menu_frame, mFrag);
fragment.commit();
//Sliding menu
SlidingMenu sMenu = new SlidingMenu(this);
sMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
sMenu.setShadowWidthRes(R.dimen.shadow_width);
sMenu.setShadowDrawable(R.drawable.shadow);
sMenu.setBehindScrollScale(0.25f);
sMenu.setFadeDegree(0.25f);
sMenu.setSlidingEnabled(true);
sMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
return super.onCreateOptionsMenu(menu);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "mContent", rFrag);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
toggle();
}
return super.onOptionsItemSelected(item);
}
public void switchContent(final Fragment inputFrag) {
rFrag = inputFrag;
FragmentTransaction fragment = getSupportFragmentManager().beginTransaction();
fragment.replace(R.id.content_frame, inputFrag);
fragment.commit();
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
getSlidingMenu().showContent();
}
}, 50);
}}
Menu:
public class MenuFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.list, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] birds = getResources().getStringArray(R.array.birds);
ArrayAdapter<String> colorAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, birds);
setListAdapter(colorAdapter);
}}
The mainfragment that has the content
public class RecentGridFragment extends Fragment {
private int mImgRes;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mImgRes = R.drawable.peacock;
GridView gv = (GridView) inflater.inflate(R.layout.list_grid, null);
gv.setBackgroundResource(android.R.color.black);
gv.setAdapter(new GridAdapter());
return gv;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
private class GridAdapter extends BaseAdapter {
#Override
public int getCount() {
return 30;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.grid_item, null);
}
ImageView img = (ImageView) convertView.findViewById(R.id.grid_item_img);
img.setImageResource(mImgRes);
return convertView;
}
}}
I have found my mistake:
I need to get the slidingactivity instead of making a new one.
SlidingMenu sMenu = this.getSlidingMenu();