Libraries:
https://github.com/chrisbanes/Android-PullToRefresh
https://github.com/JakeWharton/Android-ViewPagerIndicator
In the Sample PullToRefreshListInViewPagerActivity only works with PageAdapter.
I couldn't find a way to put it to work with FragmentPageAdapter.
Sample:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ptr_list_in_vp);
mViewPager = (ViewPager) findViewById(R.id.vp_list);
mViewPager.setAdapter(new ListViewPagerAdapter());
}
private class ListViewPagerAdapter extends PagerAdapter {
#Override
public View instantiateItem(ViewGroup container, int position) {
Context context = container.getContext();
PullToRefreshListView plv = (PullToRefreshListView) LayoutInflater.from(context).inflate(
R.layout.layout_listview_in_viewpager, container, false);
ListAdapter adapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1,
Arrays.asList(STRINGS));
plv.setAdapter(adapter);
plv.setOnRefreshListener(PullToRefreshListInViewPagerActivity.this);
// Now just add ListView to ViewPager and return it
container.addView(plv, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
return plv;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public int getCount() {
return 3;
}
}
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
new GetDataTask(refreshView).execute();
}
private static class GetDataTask extends AsyncTask<Void, Void, Void> {
PullToRefreshBase<?> mRefreshedView;
public GetDataTask(PullToRefreshBase<?> refreshedView) {
mRefreshedView = refreshedView;
}
#Override
protected Void doInBackground(Void... params) {
// Simulates a background job.
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mRefreshedView.onRefreshComplete();
super.onPostExecute(result);
}
}
}
You can add a ListFragment to the FragmentPageAdapter (or FragmentStatePageAdapter) and add the Pull-To-Refresh feature on it.
The Android-PullToRefresh repository has an example about ListFragment.
The Android Developers website has a sample code on how to make FragmentPagerAdapter or FragmentStatePagerAdapter.
You can also take a look at my test project: https://github.com/caiguanhao/FSPAtest
Related
I am writing a simple view pager test app that loads a bunch of data from a website and creates pages to display them.
For the most part the displaying is pretty much all works. However, it falls apart when I load a new set of data to display. When I get a new set, it loads all the data perfectly well however, instead of starting from view 0 it starts at a random location. It could start at the end or somewhere in the middle.
I want all the data to load from page 1, like a book. If you load a new book the book should start from page 1 not a random page.
Reloading calls
I've tried using GotCampDetails() which sets the local variable in the class.
viewPager.setCurrentItem(0);
in my fragment but it doesn't work. Also called notifydatasetchanged() on my adapter, still didn't work.
What am I missing?
public class ViewPagerFragment extends Fragment implements WebReadResultsListener {
private ArrayList<HashMap<String, String>> campDetails;
CustomPagerAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.camp_viewpager, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
if (campDetails != null && ! campDetails.isEmpty()) {
ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewpager);
adapter = new CustomPagerAdapter(getActivity(), campDetails, viewPager);
viewPager.setAdapter(adapter);
viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
}
}
#Override
public boolean GotCampDetails(ArrayList<HashMap<String, String>> campDetails) {
this.campDetails = campDetails;
return true;
}
#Override
public boolean GotCampList(ArrayList<HashMap<String, String>> campDetails) {
return false;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getFragmentManager().putFragment(outState,"fragmentInstanceSaved",getFragmentManager().findFragmentById(R.id.content));
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Handle orientation changes here
}
}
Adapter:
public class CustomPagerAdapter extends PagerAdapter implements ColorChangeListener {
private ArrayList<HashMap<String, String>> campDetails;
private ViewGroup collection;
private Context mContext;
private boolean isRunning = false;
private ColorChangeListener colorChangeListener;
private int color= pink;
private int currentposition;
private ViewPager viewPager;
public CustomPagerAdapter(Context context, final ArrayList<HashMap<String, String>> campDetails, ViewPager viewPager) {
this.campDetails=campDetails;
this.mContext = context;
this.viewPager = viewPager;
colorChangeListener = (ColorChangeListener) mContext;
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
currentposition = pos;
if (campDetails.get(currentposition).get("color").equals("green")) {
color = green;
} else {
color = pink;
}
ColorAppBar(color);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public Object instantiateItem(ViewGroup collection, final int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.child_item, collection, false);
if (campDetails.size() <= 0) {
Toast.makeText(mContext, "Error in getting camp details", Toast.LENGTH_SHORT).show();
return null;
}
if (campDetails.get(position).get("description").equals("RD") ) {
layout.setBackgroundColor(mContext.getResources().getColor(green));
} else {
layout.setBackgroundColor(mContext.getResources().getColor(pink));
}
collection.addView(layout);
this.collection = collection;
TextView eName = (TextView) layout.findViewById(R.id.en);
TextView nEName= (TextView) layout.findViewById(R.id.nen);
TextView textView6 = (TextView) layout.findViewById(R.id.textView6);
// ImageView nextImg = (ImageView) groupLayout.get(index).findViewById(R.id.nextImg);
eName.setText(campDetails.get(position).get("name"));
if (position+1 < campDetails.size()) {
nEName.setText(campDetails.get(position+1).get("name"));
textView6.setVisibility(View.VISIBLE);
} else {
nEName.setText("You are DONE!!");
textView6.setVisibility(View.INVISIBLE);
}
return layout;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
#Override
public int getCount() {
return campDetails.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public CharSequence getPageTitle(int position) {
return campDetails.get(position).get("name");
}
#Override
public void ColorAppBar(int color) {
colorChangeListener.ColorAppBar(color);
}
}
I finally managed to get it done.
I had to delay the function call setCurrentItem by a few milliseconds. Race condition? I don't know why this is the case but now it works perfectly.
Here is what I added in case someone else may find it useful:
pager.postDelayed(new Runnable() {
#Override
public void run() {
pager.setCurrentItem(pos);
}
}, 100);
I'm having trouble following the details well enough to pinpoint the problem, but this guy seems to have accomplished what you're trying to do: dynamically add and remove view to viewpager
hope it helps
I have been working on an app to take the blog feed and parse and display it in the app using the Recycler and Card View. I got to the point of adding sliding tabs to display articles in each of the categories in the site in separate tabs. I parse the feed using the category URL and am able to display it using the same Recycler view adapter.
Here comes the problem, as I swipe through the tabs quickly, the content doesn't load in some cases. In some cases, I get articles from one category displayed in another category's tab.
Below is the code for my Tabs fragment:
public class TabsFragment extends Fragment {
ViewPager mViewPager;
ViewPagerAdapter mAdapter;
SlidingTabLayout mSlidingTabLayout;
CharSequence Titles[] = {"Home", "Events", "Category", "Bookmarks", "News"};
int NoOfTabs = 5;
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
private MyRecyclerViewAdapter myRecyclerViewAdapter;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_tabs, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
mAdapter = new ViewPagerAdapter(Titles, NoOfTabs);
mProgressBar = (ProgressBar) view.findViewById(R.id.loading_spinner);
mViewPager = (ViewPager) view.findViewById(R.id.pager);
mViewPager.setAdapter(mAdapter);
mSlidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.tabs);
mSlidingTabLayout.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.secondaryBackgroundColor);
}
#Override
public int getDividerColor(int position) {
return getResources().getColor(R.color.secondaryBackgroundColor);
}
});
mSlidingTabLayout.setViewPager(mViewPager);
}
public class ViewPagerAdapter extends PagerAdapter {
CharSequence mTitles[];
int mNoOfTabs;
public ViewPagerAdapter(CharSequence[] titles, int noOfTabs) {
mTitles = titles;
mNoOfTabs = noOfTabs;
}
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
#Override
public int getCount() {
return mNoOfTabs;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = getActivity().getLayoutInflater().inflate(R.layout.pager_item_articles,
container, false);
container.addView(view);
ProcessArticles processArticles;
processArticles = new ProcessArticles(null, mTitles[position]);
processArticles.execute();
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
myRecyclerViewAdapter = new MyRecyclerViewAdapter(new ArrayList<Article>(),
getActivity().getApplicationContext());
mRecyclerView.setAdapter(myRecyclerViewAdapter);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return object == view;
}
}
public class ProcessArticles extends GetXmlData {
public ProcessArticles(String searchCriteria, String category) {
super(searchCriteria, category);
}
#Override
public void execute() {
super.execute();
ProcessData processData = new ProcessData();
processData.execute();
}
public class ProcessData extends DownloadXmlData {
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParseArticles parseArticles = new ParseArticles(getData());
boolean operationStatus = parseArticles.process();
if (operationStatus) {
ArrayList<Article> allArticles = parseArticles.getArticles();
myRecyclerViewAdapter.loadNewData(allArticles);
} else {
Toast.makeText(getActivity().getApplicationContext(), "Error establishing correction.", Toast.LENGTH_SHORT).show();
Log.d("MainActivity", "Error establishing correction.");
}
}
}
}
}
The code for the activity displaying the tabs is:
public class TabsActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_tabs);
activateToolbarWithHomeEnabled();
if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
TabsFragment fragment = new TabsFragment();
transaction.replace(R.id.tab_content_frame, fragment);
transaction.commit();
}
}
}
How do I separate the content according to category in the tabs? I have tried to reduce the amount of code, so, I have used the same Recycler adapter. Is there any solution to this problem? Or should I change the method of implementation? I am looking to implement something like the Play Newsstand app.
I made an app which has 100 pages and change through swipe, but I want to add "Go to page" option so I can go to the specific page easily.
public class ViewPagerExampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpager_example);
ExtendedViewPager mViewPager = (ExtendedViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(new TouchImageAdapter());
}
static class TouchImageAdapter extends PagerAdapter {
private static int[] images = { R.drawable.page3, R.drawable.page4,
R.drawable.page5, R.drawable.page6, R.drawable.page7,
R.drawable.page8, R.drawable.page9, R.drawable.page10, R.drawable.page11,
R.drawable.page12, R.drawable.page13, R.drawable.page14,
R.drawable.page15, R.drawable.page16, R.drawable.page17,
R.drawable.page18, R.drawable.page19, R.drawable.page20, R.drawable.page21,
R.drawable.page22, R.drawable.page23, R.drawable.page24,
R.drawable.page25, R.drawable.page26, R.drawable.page27,
R.drawable.page28, R.drawable.page29, R.drawable.page30,
R.drawable.page31, R.drawable.page32, R.drawable.page33, R.drawable.page34,
R.drawable.page35, R.drawable.page36, R.drawable.page37,
R.drawable.page38, R.drawable.page39, R.drawable.page40, R.drawable.page41,
R.drawable.page42, R.drawable.page43, R.drawable.page44,
R.drawable.page45, R.drawable.page46, R.drawable.page47,
R.drawable.page48, R.drawable.page49, R.drawable.page50, R.drawable.page51,
R.drawable.page52, R.drawable.page53, R.drawable.page54,
R.drawable.page55, R.drawable.page56, R.drawable.page57,
R.drawable.page58, R.drawable.page59, R.drawable.page60, R.drawable.page61,
R.drawable.page62, R.drawable.page63, R.drawable.page64,
R.drawable.page65, R.drawable.page66, R.drawable.page67,
R.drawable.page68, R.drawable.page69, R.drawable.page70, R.drawable.page71,
R.drawable.page72, R.drawable.page73, R.drawable.page74 };
#Override
public int getCount() {
return images.length;
}
#Override
public View instantiateItem(ViewGroup container, int position) {
TouchImageView img = new TouchImageView(container.getContext());
img.setImageResource(images[position]);
container.addView(img, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
return img;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
#Override
public void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
long lastPress;
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
if (interstitial.isLoaded())
interstitial.show();
}
}
To switch the ViewPager to a specific page, you just need to call setCurrentItem().
i have a fragment activity that have 4 page and load from 4 link from internet
when program start customlist show lists but when i change page the view show white page
my fragment :
public class VpiAbsTestActivitynouser extends SherlockFragmentActivity {
private static final String[] CONTENT = new String[] {" page1","page2","page3","page4"};
TestFragmentAdapter mAdapter;
ViewPager mPager;
PageIndicator mIndicator;
TextView mSearchView;
public String[] xmlURLArray = new String[]{"link1.xml","link2.xml","link3.xml","link4.xml"};
protected void onCreate(Bundle savedInstanceState) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_tabs);
Intent i = new Intent(this, transparentone.class);
startActivity(i);
mAdapter = new TestFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
mIndicator.setCurrentItem(1);
}
class TestFragmentAdapter extends FragmentPagerAdapter {
private int mCount = CONTENT.length;
public TestFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Bundle args = new Bundle();
args.putString("url", xmlURLArray[position]);
return customlist.newInstance(args);
}
#Override
public int getCount() {
return mCount;
}
public CharSequence getPageTitle(int position) {
return VpiAbsTestActivitynouser.CONTENT[position % VpiAbsTestActivitynouser.CONTENT.length].toUpperCase();
}
#Override
public void destroyItem(View collection, int position, Object view) {
((ViewPager) collection).removeView((View) view);
}
}
}
and my custom list code is :
public class customlist extends SherlockFragment {
int fragment_position_in_viewpager = 0;
// All static variables
public static customlist newInstance(Bundle args) {
customlist fragment = new customlist();
fragment.setArguments(args);
return fragment;
}
ListView list;
LazyAdapterbeth adapter1;
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
URL = getArguments().getString("url");
}
new getFeed().execute();
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(
R.layout.dovomi, container, false);
return root;
}
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getArguments() != null) {
fragment_position_in_viewpager = getArguments().getInt("position");
//Update the Fragment on ViewPager Position.
}
}
private class getFeed extends AsyncTask<Void, Void, Document> {
#Override
protected void onPreExecute() {
}
protected Document doInBackground(Void... params) {
}
protected void onPostExecute(Document doc) {
}
list=(ListView)getView().findViewById(R.id.list);
adapter1=new LazyAdapterbeth(getActivity(), songsList);
adapter1.notifyDataSetChanged();
list.setAdapter(adapter1);
how i can refresh view when change the view from page 1 to page 2 ?
As your code is very long, I didn't analyse it deeply but the following solutions come to my mind:
1) onCreateView for each fragment method is regularly called when fragment is recreated/its view hierarchy is recreated
Thus it can be one place for refreshing. However onCreateView is called slightly earlier than before paging displaying (usually where you display page nr 2, onCreateView for page number 3 is executed). The best idea is to put a short code displaying Toast in onCreateView and then you will know if it's ok for you.
2) Your main activity (extending FragmentActivity) can get 3 methods which are executed when swiping between fragments. It will look more or less in the following way:
public MyActivity extends FragmentActivity implements OnPageChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivityPageAdapter = new MainActivityPageAdapter (this, getSupportFragmentManager());
mainActivityViewPager = (ViewPager) findViewById(R.id.main_activity_view_pager);
mainActivityViewPager.setAdapter(mainActivityPageAdapter);
//set listener (for navigator)
mainActivityViewPager.setOnPageChangeListener(this);
}
//and now you have 3 methods
#Override
public void onPageScrollStateChanged(int state) {
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
You can read more http://developer.android.com/reference/android/support/v4/view/ViewPager.OnPageChangeListener.html
I have a CarsFragment which is inculde cars. One page is one trade (Ferrari, Mercedes) and on every page has a list with models of actual trade.
The main view:
public class CarsFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.cars_fragment, container, false);
pager = (ViewPager) view.findViewById(R.id.carsPager);
adapter = new CarsPagerAdapter(getChildFragmentManager());
pager.setAdapter(adapter);
return view;
}
}
Adapter:
public class CarsPagerAdapter extends FragmentStatePagerAdapter {
private final FragmentManager fm;
private String[] cars = new String[]{"Ferrari","Mercedes"};
public MatchesPageAdapter(final FragmentManager fm) {
super(fm);
this.fm = fm;
}
#Override
public int getCount() {
return cars.length;
}
#Override
public Fragment getItem(final int position) {
return FragmentModelList.newInstance(cars[position]);
}
#Override
public void destroyItem(final ViewGroup container, final int position, final Object object) {
super.destroyItem(container, position, object);
}
}
List:
public class FragmentModelList extends Fragment {
public static FragmentModelList newInstance(String trade) {
FragmentModelList fragmentModelList = new FragmentModelList();
Bundle args = new Bundle();
args.putString("trade", trade);
fragmentModelList.setArguments(args);
return fragmentModelList;
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_matches_list_view, container, false);
list = (ListView) view.findViewById(R.id.modelList);
return view;
}
#Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
modelListAdapter = new ModelListAdapter(getActivity());
list.setAdapter(modelListAdapter);
loadModels();
}
private void loadModels() {
new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(final Void... params) {
try {
List<Model> result = Downloader.getModelsByName(getArguments().getString("trade"));
modelListAdapter.setData(result);
return true;
} catch (Exception ex) {
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (!success) {
// Show error
} else {
// Update list
modelListAdapter.notifyDataSetChanged();
}
}
}.execute();
}
}
and the modelListAdapter set row where one row inculde 2 image and some textview.
And the problem:
when i swiping on the viewpager it isn't smooth :( a loged it and when created the next or previous page (depends on swipe direction) the animation will be bad, is lagging.
What is the solution?
(SGS4 android 4.2.2 - where is the project butter :(( )