I've been stuck for days on this. I have an activity that will parse html and sort the information into 5 arraylists. Each arraylist is a weekday. I want to take each arraylist and display the information in a listview on a separate page, so monday will be displayed on one page and then by swiping you move to tuesday and so on.
I have taken the eclipse default scrollable tabs + swipe for navigation and I'm trying to build from there.
So essentially I want to populate 5 pages of data with 5 arraylists, 1 arraylist for each page. Any ideas how I assign an arraylist to listview in a specific page?
Here is the code I have so far
public class DisplayOnlineTimetable extends FragmentActivity {
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
String value;
Document doc = null;
private ListView mainListView ;
static ViewGroup mViewGroup;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_display_online_timetable_dummy);
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.display_online_timetable, menu);
return true;
}
/**
* 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 i) {
return DummySectionFragment.newInstance(i);
}
#Override
public int getCount() {
return 5;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
//monday
case 0:
return getString(R.string.title_section1).toUpperCase(l);
//tuesday
case 1:
return getString(R.string.title_section2).toUpperCase(l);
//wednesday
case 2:
return getString(R.string.title_section3).toUpperCase(l);
//thursday
case 3:
return getString(R.string.title_section3).toUpperCase(l);
//friday
case 4:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
public void createTimetable(ArrayList<SingleClass> list, Elements elements, Day day)
{
}
private class CreateTimetables extends AsyncTask<URL, Integer, Long>
{
protected Long doInBackground(URL... urls) {
}
protected void onPostExecute(Long result)
{
}
}
}
DummySectionFragment Class
public class DummySectionFragment extends ListFragment {
private Integer arrayListId;
ViewGroup myViewGroup;
public static final String CATEGORY_POSITION = "section_number";
public static DummySectionFragment newInstance(int pos) {
DummySectionFragment f = new DummySectionFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt(CATEGORY_POSITION, pos);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
//get the id for your array list
arrayListId = getArguments() != null ? getArguments().getInt(CATEGORY_POSITION) - 1 : 1;
}
//create the list view layout
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myViewGroup = container;
View v = inflater.inflate(R.layout.list_row, container, false);
return v;
}
//populate the list view row
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter<SingleClass> arrayAdapter =
new ArrayAdapter<SingleClass>(getActivity(), android.R.id.list, R.layout.list_row);
setListAdapter(arrayAdapter);
}
}
What you need to do is standard, and you are almost there.
First in your ViewPager adapter's getItem methods, initiate the Fragment with which position it is on:
#Override
public Fragment getItem(int i) {
return DummySectionFragment.newInstance(i);
}
Next, in your Fragment class, create a constructor to instantiate it:
public static DummySectionFragment newInstance(int pos) {
DummySectionFragment f = new DummySectionFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt(CATEGORY_POSITION, pos);
f.setArguments(args);
return f;
}
And now make your DummySectionFragment extend a ListFragment, and in the onActivityCreated method you can populate it:
public class DummySectionFragment extends ListFragment {
private Integer arrayListId;
//the constructor from above
#Override
public void onCreate(Bundle savedInstanceState) {
//get the id for your array list
arrayListId = getArguments() != null ? getArguments().getInt(CATEGORY_POSITION) - 1 : 1;
}
//create the list view layout
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myViewGroup = container;
View v = inflater.inflate(R.layout.fragment_list, container, false);
return v;
}
//populate the list view row
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter<String> arrayAdapter =
new ArrayAdapter<String>(this, android.R.layout.list, <your_array_list_row.xml>);
setListAdapter(adapter);
}
}
The above code for your Fragment class will get the id for your array based on the position of the fragment, and create an ArrayAdapter for it, and use this adapter to populate a listview fragment. Now all you have to do is create the xml layout for the list:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
One last thing is make sure all your Fragment class are from the same set of library (eg. either the regular Fragment lib or support.v4).
Related
I have been trying to show different layouts in different tabs in the swipeable TabLayout using PagerTabStrip. Can anybody help?
I want to show one layout in first tab, second different layout in 2nd tab etc.
public class MainActivity extends FragmentActivity {
// create object of FragmentPagerAdapter
SectionsPagerAdapter mSectionsPagerAdapter;
// viewpager to display pages
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the five
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
/**
* A FragmentPagerAdapter that returns a fragment corresponding to one of
* the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#SuppressLint("NewApi")
#Override
public Fragment getItem(int position) {
switch (position) {
case 0: {
//Show 1st Layout(Here I need HELP)
//HELP HELP HELP
}case 1:
{
//Show 2nd Layout(Here I need HELP)
//HELP HELP HELP
}
default:
}
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
// Show 5 total pages.
return 6;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Section 1";
case 1:
return "Section 2";
case 2:
return "Section 3";
case 3:
return "Section 4";
case 4:
return "Section 5";
case 5:
return "Section 6";
}
return null;
}
}
/**
* A dummy fragment representing a section of the app, but that simply
* displays dummy text.
*/
public static class DummySectionFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Create a new TextView and set its text to the fragment's section
// number argument value.
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
textView.setTextSize(25);
textView.setText(Integer.toString(getArguments().getInt(
ARG_SECTION_NUMBER)));
return textView;
}
}
}
View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
switch (getArguments().getInt(ARG_SECTION_NUMBER))
{
case 1: {
rootView = inflater.inflate(R.layout.fragment_bba, container, false);
break;
}
case 2: {
rootView = inflater.inflate(R.layout.fragment_bcom, container, false);
break;
}
case 3: {
rootView = inflater.inflate(R.layout.fragment_bca, container, false);
break;
}
}
return rootView;
Ok for the people who want to solve this problem using design patterns.
Find full working solution Here.
If u write the fragment based on if-else condition it may solve the problem
switch(fragmentId)
{
case 1:
{
fragment 1 related stuff
}
case 2:
{
fragment 2 related stuff
}
.......
.......
and so on
But the problem with this approach is if in future,
1) you decide to add more fragments
or
2) you decide to change some functionality of existing fragment
Then you will have to modify the existing code (inside if-else condition)
Not a preferred programming practice
Instead you can follow this approach
public abstract class BasicFragment extends Fragment {
public BasicFragment newInstance()
{
Log.d("Rohit", "new Instance");
Bundle args = new Bundle();
// args.putInt(ARG_PAGE, page);
BasicFragment fragment = provideYourFragment();
fragment.setArguments(args);
return fragment;
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater,ViewGroup parent, Bundle savedInstanseState)
{
View view = provideYourFragmentView(inflater,parent,savedInstanseState);
return view;
}
public abstract BasicFragment provideYourFragment();
public abstract View provideYourFragmentView(LayoutInflater inflater,ViewGroup parent, Bundle savedInstanceState);
}
Your Fragment implementation
public class ImageFragment extends BasicFragment{
#Override
public BasicFragment provideYourFragment() {
return new ImageFragment();
}
#Override
public View provideYourFragmentView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.image_fragment,parent,false);
//Get your parent layout of fragment
RelativeLayout layout = (RelativeLayout)view;
//Now specific components here
ImageView imageView = (ImageView)layout.findViewById(R.id.myImage);
imageView.setImageResource(android.R.drawable.ic_media_play);
return view;
}
}
Happy coding
Trying to create application with view pager inside navigation drawer. I've options to select from navigation and depending on that (outer selection), i have to populate different number of fragments in view pager.
I've used tutorials to create navigation drawer and view pager separately from Google docs. As per docs, view pager have fixed number of fragments. if i hard code that way everything works fine.
But, when i try to make it dynamic as per left selection, i'm getting illegal state exception
for instance, I've implemented fragmentstatepageradapter,
public class innerFragment extends Fragment {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
public static final String active_outer_option = "section_number";
public innerFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_outer, container,
false);
Log.d("logs", "onCreateView:innerFragment()");
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MainActivity) activity).onSectionAttached(Integer
.parseInt(getArguments().getString(active_outer_option)));
Log.d("logs", "onAttach:innerFragment()");
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private int active_outer_option= 0;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Log.d("logs", "getItem(int " + position + ")");
active_outer_option = position;
Bundle b = new Bundle();
b.putString("section_number", "" + position);
DummySectionFragment fragment = new DummySectionFragment();
fragment.setArguments(b);
return fragment;
}
#Override
public int getCount() {
switch (active_outer_option) {
case 0:
return 9;
case 1:
return 2;
case 2:
return 2;
case 3:
return 2;
case 4:
return 4;
default:
return 0;
}
}
#Override
public CharSequence getPageTitle(int position) {
Log.d("logs", "getPageTitle(int " + position + ")");
return "OP " + String.valueOf(position);
}
}
public static class DummySectionFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("logs", "onCreateView:DummySectionFragment()");
View rootView = inflater.inflate(R.layout.fragment_inner,
container, false);
TextView dummyTextView = (TextView) rootView
.findViewById(R.id.section_label);
dummyTextView.setText(getArguments().getString(ARG_SECTION_NUMBER));
return rootView;
}
}
}
when i run this application, its giving "Unfortunately application stopped working" and exception is:
java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 9, found: 2 Pager id: com.xxx.xxx:id/pager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.xxx.xxx.innerFragment$SectionsPagerAdapter
any idea whats wrong with that exception and code?
Edit:
from my debugging first everything is fine and gettitle is called twice with index 0 and 1 and after that getcount is called with index and getting exception.
does this ring any bells?
I'm trying to create tabs with swipe view using fragment. I found a solution but it provides a single dummy text layout for each tabs instead of using separated layout. I'd like to create three different classes with three different layouts and use them in tabs and if possible then using a custom background for each tabs (while selected/not selected). I can do all these things without fragment but using fragment it seems challenging.
public class MainActivity extends FragmentActivity {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
/**
* A dummy fragment representing a section of the app, but that simply
* displays dummy text.
*/
public static class DummySectionFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_dummy, container, false);
TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
}
To achieve your target you must use ActionBarSherlock library, and to call other fragments you should not need to use Intent,
I have written same kind of program few months ago to call different Fragments i used below code
#Override
public Fragment getItem(int arg0) {
switch (arg0) {
// Open FragmentTab1.java
case 0:
FragmentTab1 fragmenttab1 = new FragmentTab1();
return fragmenttab1;
// Open FragmentTab2.java
case 1:
FragmentTab2 fragmenttab2 = new FragmentTab2();
return fragmenttab2;
// Open FragmentTab3.java
case 2:
FragmentTab3 fragmenttab3 = new FragmentTab3();
return fragmenttab3;
}
return null;
}
and to call show different - different layouts for each and every Fragment you should call different - different Fragments and also need to write XMLs too .....
FragmentTab1.java :-
public class FragmentTab1 extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Get the view from fragmenttab1.xml
View view = inflater.inflate(R.layout.fragment1, container, false);
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
setUserVisibleHint(true);
}
}
fragment1.xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Your Layout Goes Here for Fragment1" />
</RelativeLayout>
in a same way you have to write classes and xmls for all needed Fragments....
for more detailed information or to try out an example, use this :
http://www.androidbegin.com/tutorial/android-actionbarsherlock-viewpager-tabs-tutorial/
in the following link that help you how to create Tab fragment in sperated intents:
Tab Fragments
I'm new to Android programming.
I have a list of items, when the user clicks on an item it takes them to a screen with that item details.
I want the user to have the ability to swipe right and left to view other items' details in the list, instead of going back to the list and choosing another item.
I read that I need to use ViewPager for the ability to swipe right and left, so I did that.
ViewPager works fine, but my problem when I click any item on the list I always get to the first page in the ViewPager.
I don't want that, what I want is if I click on item 4 on the list it takes me to page 4 in the view pager and still have the ability to swipe right and left to view the details of other items.
I know how to set the page in viewpager by using mPager.setCurrentItem(0)
But I don't know how to set it according to which item was selected from the list (i.e which item launched the activity).
Here is my code:
Main activity which contains the listview:
public class Main extends SherlockListActivity implements OnItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView mylist = (ListView) findViewById(android.R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.simple_list_reda_1, R.id.list_content, getResources().getStringArray(R.array.items_list_array) );
mylist.setAdapter(adapter);
mylist.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0,View arg1, int position, long arg3)
{
Intent n = null;
switch (position){
case 0:
n = new Intent(getApplicationContext(), ViewPagerClass.class);
break;
case 1:
n = new Intent(getApplicationContext(), ViewPagerClass.class);
break;
case 2:
n = new Intent(getApplicationContext(), ViewPagerClass.class);
break;
case 3:
n = new Intent(getApplicationContext(), ViewPagerClass.class);
break;
}
if(null!=n)
startActivity(n);
}
});
}
}
ViewPagerClass
public class ViewPagerClass extends SherlockFragmentActivity{
static final int NUM_ITEMS = 4;
MyAdapter mAdapter;
ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.viewpager_layout);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.viewpager);
mPager.setAdapter(mAdapter);
//mPager.setCurrentItem(2);
final ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayUseLogoEnabled(false);
ab.setDisplayShowHomeEnabled(false);
}
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
switch(position){
case 0: return FirstPageFragment.newInstance();
case 1: return SecondPageFragment.newInstance();
case 2: return ThirdPageFragment.newInstance();
case 3: return FourthPageFragment.newInstance();
}
return null;
}
}
public static class FirstPageFragment extends Fragment {
public static FirstPageFragment newInstance() {
FirstPageFragment f = new FirstPageFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment1, container, false);
return V;
}
}
public static class SecondPageFragment extends Fragment {
public static SecondPageFragment newInstance() {
SecondPageFragment f = new SecondPageFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment2, container, false);
return V;
}
}
public static class ThirdPageFragment extends Fragment {
public static ThirdPageFragment newInstance() {
ThirdPageFragment f = new ThirdPageFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment3, container, false);
return V;
}
}
public static class FourthPageFragment extends Fragment {
public static ThirdPageFragment newInstance() {
ThirdPageFragment f = new ThirdPageFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment4, container, false);
return V;
}
}
Finally viewpager_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<android.support.v4.view.ViewPager
android:id="#+android:id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
So in short What I want is:
If I click on item 3 in the list I go to screen with the details on item 3, and if I swipe to the right I get to item 4, and if I swipe to the left I get to item 2.
In the onItemClickListener() you need to add an extra to the intent so you can get it when that activity launches.
n.putExtra("POSITION_KEY", position);
In the ViewPagerClass onCreate() using the
int position = getIntent().getIntExtra("POSITION_KEY", 0);
mPager.setCurrentItem(position);
That should do what you are wanting to do.
Can it be possible to slide the viewpager half of the screen?
My ultimate goal is to display two list view at a time, after first page slide, left list would be the previous list.
So Like as below..
list1,list2
list2,list3
list3,list4
Any solutions?
Thanks
Okay, I am going to take a stab at this. I accomplished what (I think) you are trying to do. My application has 3 ListViews, and each list contains different content fetched from an online source and populates a ViewPager using custom adapters and ListViews. The custom adapter is then assigned to a fragment on a PagerAdapter. I copied a lot of my code from a Google resource, and will try to outline what I did.
First, I added a ViewPager to my layout for my MainActivity
activity_main.xml:
<android.support.v4.view.ViewPager
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- add a PagerTitleStrip -->
<android.support.v4.view.PagerTitleStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"/>
</android.support.v4.view.ViewPager>
Then, I created a separate ListView layout I could use for my custom adapters:
listview.xml
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#E6E6E6"
android:background="#E6E6E6"
tools:context=".MainActivity" />
After I had these set, I dug into my activity. The rest takes place within MainActivity.java:
First, lay out some variables:
public class MainActivity extends FragmentActivity implements OnNavigationListener {
// your pager adapter
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
// your custom adapters (look this up on your own if you do not understand)
ArrayList<ListEntry> listOneArrayList = null;
ArrayList<ListEntry> listTwoArrayList = null;
CustomAdapterListOne customAdapterListOne = null;
CustomAdapterListTwo customAdapterListTwo = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// more on that in the next block...
}
}
Now, let's get into onCreate() and start creating!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// set up your pager adapter
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// if you want to set a default view:
mViewPager.setCurrentItem(0);
// now, run some AsyncTasks to load up our lists
// I use AsyncTasks because I fetch my data from a server
new generateListOne().execute();
new generateListTwo().execute();
}
/*
* Get the entries and create a list adapter
*/
private class generateListOne extends AsyncTask<String, Void, Object> {
#Override
protected Object doInBackground(String... args) {
listOneArrayList = new ArrayList<ListEntry>();
// this is where I would do all of my networking stuff
// and populate my arraylist
return null;
}
#Override
protected void onPostExecute(Object result) {
// you have to create a new xml layout for 'listview_row' to use here v
customAdapterListOne = new CustomAdapterListOne(self, R.layout.listview_row, listOneArrayList);
/** Very important! This is where you specify where the list goes: **/
// * Note: Fragment pages start at 0!
ListSectionFragment fragment = (ListSectionFragment) getSupportFragmentManager().findFragmentByTag(
"android:switcher:"+R.id.viewpager+":0"); // <- this is where you specify where the list goes
if (fragment != null) { // <- Could be null if not instantiated yet
if(fragment.getView() != null) {
customAdapterListOne.notifyDataSetChanged();
fragment.updateListOneDisplay(customAdapterListOne);
}
}
}
}
I'm not going to write out generateListTwo(), but hopefully you understand the concept from generateListOne(). Pay very close attention to what is happening in onPostExecute(). Now, we have to write out the FragmentPagerAdapter and our ListSection Fragment. Also, we have to include our custom list Adapter. All of that stuff follows:
/*
* Your Custom Adapter Class
*/
private class CustomAdapterListOne extends ArrayAdapter<ListEntry> {
/*
* Read up on the rest of this for custom adapter if you
* are unfamilar. There are plenty of resources..
*
* I am not going to type it all out.
*/
}
/*
* SectionsPagerAdapter class for FragmentPagerAdapter title
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new ListSectionFragment();
Bundle args = new Bundle();
args.putInt(ListSectionFragment.ARG_SECTION_NUMBER, i + 1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
// make sure this is correct
int yourNumberOfLists = 5;
return yourNumberOfLists;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0: return "First List";
case 1: return "Second List";
//case 2: etc..
}
return null;
}
public boolean onInterceptTouchEvent(MotionEvent event) {
return false;
}
}
/*
* ListSectionFragment class for ListFragment(s)
*/
public static class ListSectionFragment extends ListFragment {
public static final String ARG_SECTION_NUMBER = "section_number";
public static int CURRENT_SECTION = 0;
static ListSectionFragment newInstance(int num) {
ListSectionFragment fragment = new ListSectionFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
public void updateListOneDisplay(ArrayAdapter<ListEntry> listOneAdapter) {
setListAdapter(listOneAdapter);
}
public void updateListTwoDisplay(ArrayAdapter<ListEntry> listTwoAdapter) {
setListAdapter(listTwoAdapter);
}
// etc..
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
CURRENT_SECTION = args.getInt(ARG_SECTION_NUMBER);
// note, we are using your listview here v
View view = inflater.inflate(R.layout.listview, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// and just for kicks:
Log.i(TAG, "Item clicked: " + position);
}
}
Don't forget your last } to close out the MainActivity.java class. Hopefully this helps someone, I know it took me forever to figure out. The effect that this code provides is similar to that of the Android Place application.
Edit: I forgot to mention when the list loads. When a list gains focus, it also loads the previous and next list. This makes it possible to transition to it and have it already be there ready to go. For example:
You go to list 2 and list 1 and list 3 are loaded. You then go to list 3 (and it transitions smoothly because it is loaded already), and list 4 and list 2 are loaded. This ensures that when you transition to a new list, it is already loaded or in the process of being generated.