I make a simple example of tab view using fragment and pager .I want to send to send data from one fragment to another fragment when user use tab button. I will give you more detail I have one list view in one tab . In that i take one array list to display the data in list view.I want to send that list view in another fragment . So I make one interface and implement it on main activity .But I don’t know how to send on which event to send fragment .when user select tab I want to send array list to second fragment
here is my code
mainActivity
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
ViewPager viewPager;
FragmentpagerAdapter fragmentpagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionBar =getActionBar();
viewPager = (ViewPager) findViewById(R.id.pager);
fragmentpagerAdapter =new FragmentpagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(fragmentpagerAdapter);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.addTab(actionBar.newTab().setText("Stations").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("fav Station").setTabListener(this));
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
actionBar.setSelectedNavigationItem(i);
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
}
#Override
public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
Fragmentone fragmentOne = (Fragmentone) getSupportFragmentManager().findFragmentByTag(makeFragmentName(R.id.pager,0));
// get your arraylist using method of FragmentOne
ArrayList<DataModel> yourArrayList = fragmentOne.getData();
// refer your second fragment and set the above arraylist in that
FragmentTwo fragmentTwo = (FragmentTwo) getSupportFragmentManager().findFragmentByTag(makeFragmentName(R.id.pager, 1));
fragmentTwo.setData(yourArrayList);
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
}
private static String makeFragmentName(int viewPagerId, int index) {
return "android:switcher:" + viewPagerId + ":" + index;
}
}
fragmentone
public class Fragmentone extends Fragment {
ArrayList<DataModel> name;
boolean isPressed=false;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one, container, false);
name=new ArrayList<DataModel>();
name.add(new DataModel("First Station",false));
name.add(new DataModel("Second Station",false));
ListView listView = (ListView) view.findViewById(R.id.list_view);
CustomAdapter customAdapter =new CustomAdapter(getActivity(),name);
listView.setAdapter(customAdapter);
return view;
}
public ArrayList getData() {
return name;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
FragmentTwo
public class FragmentTwo extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_two, container, false);
}
public void methodInFragmentB(ArrayList arrayList){
for (int i=0;i<arrayList.size();i++){
}
}
public void setData(ArrayList<DataModel> yourArrayList){
Toast.makeText(getActivity(), "ArrayList Size: " + yourArrayList.size(), Toast.LENGTH_SHORT).show();
}
}
PagerAdaper
public class FragmentpagerAdapter extends FragmentPagerAdapter {
public FragmentpagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
return new Fragmentone();
case 1:
return new FragmentTwo();
default:
break;
}
return null;
}
#Override
public int getCount() {
return 2;
}
}
customAdapater
public class CustomAdapter extends BaseAdapter implements View.OnClickListener {
private Activity activity;
private ArrayList data;
private static LayoutInflater inflater = null;
boolean isPressed=false;
public CustomAdapter(Activity a, ArrayList d) {
/********** Take passed values **********/
activity = a;
data = d;
inflater = (LayoutInflater) activity.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
if (data.size() <= 0)
return 1;
return data.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public void onClick(View v) {
}
/*********
* Create a holder Class to contain inflated xml file elements
*********/
public static class ViewHolder {
public TextView text;
public ImageButton imageButton;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View vi = convertView;
final ViewHolder holder;
if (convertView == null) {
/****** Inflate tabitem.xml file for each row ( Defined below ) *******/
vi = inflater.inflate(R.layout.row_layout, null);
/****** View Holder Object to contain tabitem.xml file elements ******/
holder = new ViewHolder();
holder.text = (TextView) vi.findViewById(R.id.station_name);
holder.imageButton = (ImageButton) vi.findViewById(R.id.favorite);
holder.imageButton.setBackgroundResource(R.drawable.off);
/************ Set holder with LayoutInflater ************/
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
if (data.size() <= 0) {
holder.text.setText("No Data");
} else {
DataModel dataModel = (DataModel) data.get(position);
/************ Set Model values in Holder elements ***********/
holder.text.setText(dataModel.getText());
// this is for overall row click
vi.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("row is click","row click"+position);
}
});
// this is for image button onclick
holder.imageButton.setOnClickListener(new View.OnClickListener() {
DataModel dataModel = (DataModel) data.get(position);
#Override
public void onClick(View v) {
if(dataModel.isselected()){
holder.imageButton.setBackgroundResource(R.drawable.off);
dataModel.setIsselected(false);
}else{
holder.imageButton.setBackgroundResource(R.drawable.on);
dataModel.setIsselected(true);
}
isPressed = !isPressed; // reverse
}
});
;
}
return vi;
}
}
MainActivity.xml
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/pager"
>
</android.support.v4.view.ViewPager>
fragmentone.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#325633"
>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/list_view">
</ListView>
</LinearLayout>
Fragmenttwo.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ee2333">
</LinearLayout>
rowlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/station_name"
android:padding="10dp"
android:textColor="#eee345"
android:textAppearance="?android:textAppearanceLarge"
/>
<ImageButton android:id="#+id/favorite"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="#00ffffff"
/>
</LinearLayout>
I need to to send ArrayList name; in second fragment ..I used interface but I don't know on event how to get value of that array list when user swipe or tab on tab view in second fragment?
Here i am posting some code that might help, see the scenario is like this,
Your tabs are in your Activity so the click and swipe events would be handled there so declaring Interface will not help as you can not fire that Callback method in Tab swipe or click, so what you can do is create a method in FragmentOne which will return you ArrayList like below
public ArrayList<String> getData(){
return yourArrayList();
}
now in FragmentTwo create a method that will receive the ArrayList from FragmentOne like below
public void setData(ArrayList<String> yourArrayList){
Toast.makeText(YourActivity.this,"ArrayList Size: "+yourArrayList.size(),Toast.LENGTH_SHORT).show();
}
Now about how to reference the Fragments in your Activity you can do something like this:
private static String makeFragmentName(int viewPagerId, int index) {
return "android:switcher:" + viewPagerId + ":" + index;
}
Now in Tab Swipe or click call above method to Refer your fragments like below
ArrayList<String> yourArrayList = new ArrayList<>();
FragmentOne fragmentOne = getSupportFragmentManger().findFragmentByTag(makeFragmentName(viewPagerId,0))
if(fragmentOne != null){
// get your arraylist using method of FragmentOne
yourArrayList = fragmentOne.getData();
}
// refer your second fragment and set the above arraylist in that
FragmentTwo fragmentTwo = getSupportFragmentManger().findFragmentByTag(makeFragmentName(viewPagerId,1))
if(fragmentTwo != null){
fragmentTwo.setData(yourArrayList);
}
and you are done
see above 0 and 1 are index of fragments in adapter you will need to manage that
let me know if you need further help
In your first fragment named Fragmentone, do something like this:
if(callBack!=null){
callBack.sendData(yourDataArrayList);
}
After doing this see what are you getting in log.
Related
Recently started with Android development and am in the process of creating a screen slide that would appear after selecting an image that is part of a gallery (grid view). I followed the Android Tutorial here however the problem that I am running into is the ViewPager doesn't seem to work (logs in the activity aren't printing out), and the only thing I see in the new fragment is some text.
Below I have included the code, and any assistance would be appreciated!
This is where the initial call from the gallery is made to show the slider goToGallerySlider()
PhotoGalleryFragment.java
public class PhotoGalleryFragment extends BaseFragment {
private static final String TAG = PhotoGalleryFragment.class.getSimpleName();
public static final String EVENT_ID_EXTRA = "EventDetailFragment.EventIdExtra";
private GridView grid;
public List<EventPhoto> eventDetailPhotoList;
#Bind(R.id.photoRoll)
GridView photoRoll;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_event_detail_photo_gallery, container, false);
grid = (GridView) view.findViewById(R.id.photoRoll);
Context aContext = getActivity().getBaseContext();
grid.setAdapter(new PhotoGalleryAdapter(aContext, eventDetailPhotoList));
grid.setOnItemClickListener((parent, v, position, id) ->
goToGallerySlider(parent, v, position, id));
return view;
}
#Override
public int getTitleResourceId() {
return R.string.photo_gallery;
}
private void goToGallerySlider(ViewGroup parent, View v, int position, long id) {
Log.d(TAG, "!!!We are in the goToGallerySlider() call function!");
GallerySliderFragment sliderFragment = new GallerySliderFragment();
sliderFragment.eventDetailPhotoList = eventDetailPhotoList;
getBaseActivity().setFragment(sliderFragment, true);
}
}
fragment_photo_gallery_slider.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView style="?android:textAppearanceMedium"
android:id="#+id/textView_in_slider_fragment"
android:padding="16dp"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/lorem" />
</RelativeLayout>
activity_photo_gallery_slider.xml
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
GallerySliderFragment.java
public class GallerySliderFragment extends BaseFragment {
private static final String TAG = GallerySliderFragment.class.getSimpleName();
public List<EventPhoto> eventDetailPhotoList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "!!!We are inside the onCreate in GallerySliderFragment");
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.fragment_event_detail_photo_gallery_slider, container, false);
((AngelPointsApplication) getActivity().getApplication()).getComponent().inject(this);
ButterKnife.bind(this, view);
return view;
}
public int getTitleResourceId() {return R.string.gallery_slider; }
}
PhotoGalleryActivity.java
public class PhotoGalleryActivity extends BaseActivity {
private static final String TAG = PhotoGalleryFragment.class.getSimpleName();
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
private static final int NUM_PAGES = 5;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "!!!We are in the onCreate in PhotoGalleryActivity");
setContentView(R.layout.activity_event_detail_photo_gallery_slider);
mPager = (ViewPager) findViewById(R.id.viewPager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
Log.d(TAG, "!!!In PhotoGalleryActivity user pressed BACK Button on 1st Image");
super.onBackPressed();
} else {
Log.d(TAG, "!!!In PhotoGalleryActivity user pressed BACK Button to see previous photo");
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
/**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
Log.d(TAG, "!!!In PhotoGalleryActivity get next item position");
return new GallerySliderFragment();
}
#Override
public int getCount() {
Log.d(TAG, "!!!In PhotoGalleryActivity get count: " + NUM_PAGES);
return NUM_PAGES;
}
}
}
I have a fragment A, containing a listview. To this listview I add a listheader containing a ViewPager that pages through childfragments.
When the user clicks an item in the list, the listfragment A gets replaced by a detail-view-fragment of that listitem.
I want the user to be able to go back to the list by clicking the back button.
So far everything works, except when the user presses the back button to pop the detail fragment from the stack to get back to the listview fragment A, the app crashes with an
java.lang.IllegalArgumentException: No view found for id 0x7f06002e (com.makamedia.hockeyweb:id/news_header_pager) for fragment NewsHeaderFragment{41f7b6f8 #0 id=0x7f06002e android:switcher:2131099694:0}
My suspicion is, that maybe the nested fragments for the viewpager in the listheader get recreated before the viewpager gets recreated, thus crashing the app, but I am not sure.
Any help is appreciated!
My ViewPagerAdapter for the listheader-viewpager (removed some unrelated code):
public class NewsHeaderAdapter extends FragmentPagerAdapter {
private int mCount;
public final NewsListAdapter mListAdapter;
public NewsHeaderAdapter(FragmentManager fm, int count, long autoSwipeInterval, NewsListAdapter adapter) {
super(fm);
this.mCount = count;
this.mListAdapter = adapter;
}
#Override
public Fragment getItem(int pos) {
return NewsHeaderFragment.getNew(this.mListAdapter.getItem(pos));
}
public void setCount(int newCount){
if(newCount < 1){
this.mCount = 1;
} else if(newCount >= this.mListAdapter.getCount()){
this.mCount = this.mListAdapter.getCount();
} else {
this.mCount = newCount;
}
}
#Override
public int getCount() {
return mCount;
}
#Override
public CharSequence getPageTitle(int position) {
return this.mListAdapter.getItem(position).getTitle();
}
}
My news detail fragment (pretty straight forward):
public class NewsHeaderFragment extends Fragment {
private NewsItem mNewsItem;
private TextView mHeaderNewsBigTitle;
private ImageView mHeaderNewsBigImage;
// Convenience method for creating a new fragment with parameters
public static NewsHeaderFragment getNew(NewsItem item){
NewsHeaderFragment fragment = new NewsHeaderFragment();
Bundle args = new Bundle();
args.putSerializable(Constants.SIG_NEWS_ITEM, item);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.row_big_news, container, false);
Bundle newsHeaderArgs = getArguments();
mNewsItem = (NewsItem)newsHeaderArgs.getSerializable(Constants.SIG_NEWS_ITEM);
setupUI(rootView);
fillUI();
return rootView;
}
private void fillUI() {
mHeaderNewsBigTitle.setText(mNewsItem.getTitle());
Picasso.with(getActivity()).load(mNewsItem.getImageBig2x()).into(mHeaderNewsBigImage);
}
private void setupUI(View rootView) {
mHeaderNewsBigTitle = (TextView) rootView.findViewById(R.id.news_big_title);
mHeaderNewsBigImage = (ImageView) rootView.findViewById(R.id.news_big_img);
}
}
My viewpager is declared in xml in a row-layout and added like so:
private void addHeaderPager(int count) {
if(mNewsListAdapter != null && mNewsListAdapter.getCount()>0) {
if (count >= mNewsListAdapter.getCount()) {
count = mNewsListAdapter.getCount() - 1;
}
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mHeader = (RelativeLayout) inflater.inflate(R.layout.row_big_news_pager, null);
mHeaderPager = (ViewPager) mHeader.findViewById(R.id.news_header_pager);
mHeaderPagerAdapter = new NewsHeaderAdapter(getChildFragmentManager(), count, 6000, mNewsListAdapter);
mHeaderPager.setOffscreenPageLimit(count);
mHeaderPager.setAdapter(mHeaderPagerAdapter);
// Bind the title indicator to the adapter
CirclePageIndicator circleIndicator = (CirclePageIndicator) mHeader.findViewById(R.id.news_header_pager_indicator);
circleIndicator.setViewPager(mHeaderPager);
mNewsListView.addHeaderView(mHeader);
}
}
Are you sure tha you use the right FragmentManager in addHeaderPager()?
I normally use getFragmentManager() and if there is a parent fragment I have to use getParentFragment().getFragmentManager() - if I don't I get the same error ("No view found for id") when trying to replace the current visible fragment.
I am trying to implement a scroller like show in the image below.
I have tried using viewpager but it only shows one item at a time. And I need to show 5 of them and of different sizes. The one in middle needs to be bigger.
Each Item is a frameLayout that contains an ImageView and a TexView, I dont have any problem implementing that part. The problem is it needs to be a scroller and have many items in scroller e.g upto 15 maybe. But should have only 5 items visible at any one time just like shown below. I have tried many implementations. Please some one give me a working example as I have already tried many examples none of them works perfectly. I have waisted more than a week on this one.
You can control it by overriding getPageWidth() in the PagerFragmentAdapter:
#Override
public float getPageWidth(int position) {
return(0.4f);
}
and making sure the size of your images is not too large, so that the page width fits multiple images.
Here are all the steps to set this up:
1) Add a fragment container to your activity layout, where you will load the PhotoPagerFragment:
<!-- PHOTO PAGER FRAGMENT -->
<FrameLayout
android:id="#+id/photoPagerFragmentContainer"
android:layout_width="match_parent"
android:layout_height="150dp"
android:tag="sticky"
android:layout_gravity="center_horizontal" >
</FrameLayout>
2) Inject the PhotoPagerFragment in your activity's onCreate():
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
//Insert the fragment
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.photoPagerFragmentContainer);
if (fragment == null) {
fragment = new PhotoPagerFragment();
fm.beginTransaction()
.add(R.id.photoPagerFragmentContainer, fragment)
.commit();
}
}
3) Create a layout for your PhotoPagerFragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/photoPager"
android:layout_width="fill_parent"
android:layout_height="120dp"
android:layout_marginTop="2dp"/>
</LinearLayout>
4) Create your PhotoPagerFragment:
public class PhotoPagerFragment extends Fragment {
private ViewPager mPhotoPager;
private PagerAdapter mPhotoAdapter;
public static final String TAG = "PhotoPagerFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_photo_pager, container, false);
mPhotoAdapter = new PhotoPagerFragmentAdapter(getActivity().getSupportFragmentManager());
mPhotoPager = (ViewPager) view.findViewById(R.id.photoPager);
mPhotoPager.setAdapter(mPhotoAdapter);
return view;
}
}
5) And the adapter:
public class PhotoPagerFragmentAdapter extends FragmentPagerAdapter {
private int[] Images = new int[] {
R.drawable.photo_1, R.drawable.photo_2,
R.drawable.photo_3, R.drawable.photo_4,
R.drawable.photo_5, R.drawable.photo_6
};
private int mCount = Images.length;
public PhotoPagerFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return PhotoDetailsFragment.newInstance(Images[position]);
}
#Override
public int getCount() {
return mCount;
}
#Override
public float getPageWidth(int position) {
return(0.4f);
}
public void setCount(int count) {
if (count > 0 && count <= 10) {
mCount = count;
notifyDataSetChanged();
}
}
}
6) And finally, your PhotoDetailsFragment that will show each image:
public final class PhotoDetailsFragment extends Fragment {
private int photoResId;
private static final String TAG = "PhotoDetailsFragment";
public static final String EXTRA_PHOTO_ID = "com.sample.photo_res_id";
public static PhotoDetailsFragment newInstance(int photoResId) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_PHOTO_ID, photoResId);
PhotoDetailsFragment fragment = new PhotoDetailsFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
photoResId = (Integer)getArguments().getSerializable(EXTRA_PHOTO_ID);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final ImageView image = new ImageView(getActivity());
image.setImageResource(photoResId);
// Hook up the clicks on the thumbnail views
image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
...
}
});
LinearLayout layout = new LinearLayout(getActivity());
layout.setLayoutParams(new LayoutParams(-1, -1));
layout.setGravity(Gravity.CENTER);
layout.addView(image);
return layout;
}
}
Have a Linearlayout inside to that having 3 different framelayout. In that frame layout am adding the fragments dynamically inside the adaper getview. Initially the adapter getview gets called twice. Then later it called once for every flip. Have added the flip view functionality along with that. In that for first screen before any flip, the dynamic fragments are not getting added to the main view. But for the later flipped screens it's getting added properly.
Please help me on this.
Thanks in advance.
public class MainActivity extends Activity {
private FragmentTransaction fragMentTra = null;
protected FlipViewController flipView;
private LayoutInflater inflater;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
flipView = new FlipViewController(this);
flipView.setAdapter(new BaseAdapter() {
public int getCount() {
return 2;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
#SuppressLint("NewApi")
public View getView(int position, View convertView, ViewGroup parent) {
View layout = convertView;
if (convertView == null) {
inflater = LayoutInflater.from(parent.getContext());
layout = inflater.inflate(R.layout.activity_main, null);
AphidLog.d("created new view from adapter: %d", position);
}
NewsFragment[] newsFragment_obj = new NewsFragment[GlobalValues.titile.length];
fragMentTra = getFragmentManager().beginTransaction();
for (int i = 0; i < GlobalValues.titile.length; i++) {
newsFragment_obj[i] = new NewsFragment(
GlobalValues.titile[i], GlobalValues.content[i]);
AphidLog.d("Array Loc: %d", i);
}
fragMentTra.add(R.id.fragment_container1, newsFragment_obj[0],
"Fragment1");
fragMentTra.add(R.id.fragment_container2, newsFragment_obj[1],
"Fragment2");
fragMentTra.add(R.id.fragment_container3, newsFragment_obj[2],
"Fragment3");
fragMentTra.commit();
return layout;
}
});
setContentView(flipView);
}
I tried out the sample code from the API and it didn't really work so I implemented my own:
FragmentPagerSupport
public class FragmentPagerSupport extends FragmentActivity {
static final int NUM_ITEMS = 10;
MyAdapter mAdapter;
ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mAdapter = new MyAdapter(getSupportFragmentManager());
Log.i("Pager", "mAdapter = " + mAdapter.toString());
mPager = (ViewPager)findViewById(R.id.pager);
if (mPager == null)
Log.i("Pager", "mPager = null");
else
Log.i("Pager", "mPager = " + mPager.toString());
Log.i("Pager", "Setting Pager Adapter");
mPager.setAdapter(mAdapter);
}
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
Log.i("Pager", "MyAdapter constructor");
}
#Override
public int getCount() {
Log.i("Pager", "MyAdapter.getCount()");
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
Log.i("Pager", "MyAdapter.getItem()");
return TestFragment.newInstance(position);
}
}
public static class TestFragment extends Fragment {
public static TestFragment newInstance(int position) {
Log.i("Pager", "TestFragment.newInstance()");
TestFragment fragment = new TestFragment();
Bundle args = new Bundle();
args.putInt("position", position);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i("Pager", "TestFragment.onCreateView()");
LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.fragment_item, null);
int position = getArguments().getInt("position");
TextView tv = (TextView)layout.findViewById(R.id.text);
tv.setText("Fragment # " + position);
tv.setTextColor(Color.WHITE);
tv.setTextSize(30);
return layout;
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
fragment_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/hello"
/>
</LinearLayout>
My question is, instead of creating a new Fragment instance each time the user swipes left and right, how do I save a fragment's state (to some data structure) and then restore it?
The API demo doesn't seem to have any state information saving code at all.
Use ViewPager.setOffscreenPageLimit() in FragmentActivity
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setOffscreenPageLimit(2);
See more at How do I tell my custom FragmentPagerAdapter to stop destroying my fragments?
just override this method in FragmentpagerAdapter
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
super.destroyItem(ViewGroup container, int position, Object object);
}
remove super.destroyItem(ViewGroup container, int position, Object object);
from your code
Update:
In the getItem of MyAdapter you return a new instance of your Fragment. Android will not call getItem on every swipe. It will only call getItem to get a new instance, but will reuse the existing instances as long as they are availible.
About the state part of the Demo. I can't help you. I think the normal techniques for restoring state in Fragements/Activities apply here, so nothing special when loading it in a ViewPager (but I might be wrong).
If you override
public void destroyItem(View container, int position, Object object)
without calling super, the fragment will not be destroyed and will be reused.
The adapter should be extended from FragmentStatePagerAdapter instead of FragmentPageAdapter and the adapter will keep reference from position to fragment item. On the activity or fragment parent, set listener OnPageChangeListener for PageIndicator to detect the position of fragment item has been activated and update related data's state.
About the data state of fragment item, I think should save/restore state from Activity or Fragement parent.
The adapter can add some code as following:
public static class MyAdapter extends FragmentStatePagerAdapter {
private SparseArray<TestFragment> mPageReferenceMap
= new SparseArray<TestFragment>();
...
#Override
public Object instantiateItem(ViewGroup viewGroup, int position) {
Object obj = super.instantiateItem(viewGroup, position);
//Add the reference when fragment has been create or restore
if (obj instanceof TestFragment) {
TestFragment f= (TestFragment)obj;
mPageReferenceMap.put(position, f);
}
return obj;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
//Remove the reference when destroy it
mPageReferenceMap.remove(position);
super.destroyItem(container, position, object);
}
public TestFragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
...
}
Hope this help.
I tripped on some similar ground...
I wanted to keep my fragments saved within my adapter to avoid useless reloading since I only had 5 fragments in the FragmentPagerAdapter.
I basically had to create an array and override the getItem(position) method:
private StoryListFragment[] fragmentsArray
= new StoryListFragment[getCount()];
public SectionsAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if(fragmentsArray[position]!=null)
return fragmentsArray[position];
StoryListFragment storyListFragment = null;
switch(position){
case(0):
storyListFragment = StoryListFragment.newInstance(StoriesBank.NEWS);
break;
case(1):
storyListFragment = StoryListFragment.newInstance(StoriesBank.FEATURES);
break;
case(2):
storyListFragment= StoryListFragment.newInstance(StoriesBank.ARTS);
break;
}
fragmentsArray[position] = storyListFragment;
return storyListFragment;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
StoryListFragment fragment = (StoryListFragment) super.instantiateItem(container, position);
fragmentsArray[position] = fragment;
return fragment;
}