I have the following code for my fragment. I pretty much took this from a basic view pager example and slapped it into a fragment to test for a project I'm working on.
I'm using ACtionBarSherlock, and viewPagerIndicator libraries. The Fragment below contains a viewPager that in this example is supposed to swipe between simple title strings.
I tried the example with the ViewPager and ViewPagerIndicator in an activity, and no problem. But the second I put it into a fragment. BOOM, nothing but a black screen... NO errors, just a black screen...I feel like I must be inflating, or accessing the layout incorrectly or something...
Any ideas?
Here's the code:
public class TestFragment extends SherlockFragment {
//~Constants----------------------------------------------
//~Data Fields--------------------------------------------
//~Constructors--------------------------------------------
#Override
public void onCreate(Bundle savedInstanceState) {
//Setup view
super.onCreate(savedInstanceState);
View view = onCreateView(getLayoutInflater(savedInstanceState), null, savedInstanceState);
ViewPagerAdapter adapter = new ViewPagerAdapter( this.getSherlockActivity() );
ViewPager pager =
(ViewPager)view.findViewById(R.id.free_time_day_pager);
TitlePageIndicator indicator =
(TitlePageIndicator)view.findViewById(R.id.titles);
pager.setAdapter( adapter );
indicator.setViewPager( pager );
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.free_time_fragment_layout, null, false);
return view;
}
//~Methods-------------------------------------------------
}
Dont call onCreateView that is wrong.
onCreateView is an overridden method which is called by the FragmentManger to handle the Fragment lifecycle.
private ViewPager mViewPager;
private TitlePagerIndicator mIndicator;
// Called first
#Override
public void onCreate(Bundle savedInstanceState) {
//Setup view
super.onCreate(savedInstanceState);
}
// Called second
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.free_time_fragment_layout, null, false);
return view;
}
// Called third
#Override
public View onViewCreated(View v){
super.onViewCreated(v);
mViewPager = (ViewPager) v.findViewById(R.id.free_time_day_pager);
mIndicator = (TitlePageIndicator)v.findViewById(R.id.titles);
}
public void onActivityCreated(Bundle bdl){
super.onActivityCreated(bdl);
ViewPagerAdapter adapter = new ViewPagerAdapter( getSherlockActivity() );
mViewPager.setAdapter(adapter);
mIndicator.setViewPager(pager);
}
Also be aware if you are using a FragmentPagerAdapter you require a special method to create the ViewPagerFragment, its a bit tricky but refer to this gist.
Read about Fragment Lifecycles here too.
Cheers
Use this.
compile 'com.android.support:appcompat-v7:23.0.1'
work for me.
Related
I have implemented Pager Sliding Strip and it is working totally fine.
I have 5 tabs each containing different fragment. When I click on 2nd tab to load respective fragment, it also load details of 3rd fragment, it showing the toast I coded in 3rd tab's fragment.
this is totally ruined the apps performance, How come I solve this problem I don't have any idea whats actually going on.
I am working on a really big project I cannot post the whole code.
Please Help me with this, I will post the respective code on demand.
Regards.
EDIT
Notification Fragment which is loading another fragment
ListView notification_listview;
ArrayList<FragmentNotificationDTO> arraylist;
NotificationAdapter adapter;
private static View notificationView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (notificationView != null) {
ViewGroup parent = (ViewGroup) notificationView.getParent();
if (parent != null)
parent.removeView(notificationView);
}
notificationView = inflater.inflate(R.layout.fragment_notification,
container, false);
initLayout(notificationView);
loadData();
return notificationView;
}
private void initLayout(View view) {
notification_listview = (ListView) view.findViewById(R.id.notification_listview);
arraylist = new ArrayList<FragmentNotificationDTO>();
adapter = new NotificationAdapter(mContext, arraylist);
notification_listview.setAdapter(adapter);
}
This is Food Fragment which is loaded also when we click on Notification Tab
private static View foodlistView;
RelativeLayout rl_foodshare, rl_foodrequested, rl_foodkitchen;
TextView tv_foodshare, tv_foodrequested, tv_foodkitchen;
ImageView img_foodshare, img_foodrequested, img_foodkitchen;
Fragment fr;
FragmentManager fm;
FragmentTransaction fragmentTransaction;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (foodlistView != null) {
ViewGroup parent = (ViewGroup) foodlistView.getParent();
if (parent != null)
parent.removeView(foodlistView);
}
foodlistView = inflater.inflate(R.layout.fragment_location_list,
container, false);
initLayout(foodlistView);
ChangeFragment(1);
return foodlistView;
}
MainActivity.java which contains the PagerSlidingStrip & View Pager
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()));
PagerSlidingTabStrip PGSTRIP = (PagerSlidingTabStrip) findViewById(R.id.tabs);
PGSTRIP.setViewPager(viewPager);
viewPager.setOffscreenPageLimit(0);
}
I solved my problem by overriding this method in each of my fragment and then calling the loading method when fragment's visibility is true to user.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// load data here
}else{
// fragment is no longer visible
}
}
i have an ActionBar that has 2 tabs and each tabs layout is a fragment. in 1 of these tabs , there is a listView. and i want to set ArrayAdapetr for it. but when i run app, error occurred and error is about my application context. my code is :
public class TarfandFrag extends Fragment {
String values[] = new String[]{"sadeq","ali"};
ListView listView;
Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tarfad_layout,container,false);
listView = (ListView) view.findViewById(R.id.list_tarfand);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayAdapter adapter = new ArrayAdapter(context,android.R.layout.simple_list_item_1,values);
listView.setAdapter(adapter);
}
}
but its not working. notice that i don't want use listFragment or anything else. i replace context with getActivity() , context.getApplicationContext, getActivity.getApplicationContext. but not working. plz help meeeee
Assing getActivity() to context in onCreate.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context=getActivity();
}
In a fragment, onCreate() is called before onCreateView(). the consequence of this is that, at the point onCreate() is called, your ListView is not yet associated with an element in the layout (as your are doing this in onCreateView() which gets called later) and will hence resolve to null and you will get a null pointer exception when you set the adapter for the ListView. Move the code setting the adapter to within the onCreateView() method and use getActivity() and you should be fine.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tarfad_layout,container,false);
listView = (ListView) view.findViewById(R.id.list_tarfand);
// Here listview will not be null as it is now bound to an object
ArrayAdapter adapter = new ArrayAdapter(getActivity(),android.R.layout.simple_list_item_1,values);
listView.setAdapter(adapter);
return view;
}
I used PagerSlidingTabStrip and have to fragments.
In each fragments, I used AsyncTask to get data from server.
Below is my fragment class that gets html from server and displays listview.
public class MainFragmentSubList extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main_list, container, false);
ListView mainList = (ListView) view.findViewById(R.id.fragment_list);
ArrayList<String> infoList;
// this is AsyncTask class and i made an interface.
new GetHtml(new OnRequestFinish(){
#Override
void onFinish(){
// Below are about ui
ArrayList<String> titleList = (ArrayList<String>) User.subName.clone();
int size = infoList.size();
MainListAdapter adapter = new MainListAdapter(titleList, infoList, size + 1);
mainList.setAdapter(adapter);
}
}).execute();
return view;
}
Since AsyncTask does things in background, return view; didn't work as I expected.
Here is my main activity that has fragments.
public class MainActivity extends ActionBarActivity {
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabs.setShouldExpand(true);
tabs.setViewPager(pager);
}
}
How can I return View from fragment using AsyncTask?
Go ahead and setup your view in onCreateView. Init and set your adapter too, with an empty list. For convenience you make the adapter and your list member variables.
Make sure that onFinish is invoked by AsyncTask's onPostExecute, so that it runs on the correct thread. When it is called, you update your list and then call the adapter's notifyDataSetChanged() method.
I put a FragmentTabHost into a ViewPager, but the tab content has gone after I rotate the device. The tab content will come back if I click on another tab to refresh content. Is there anything wrong in my code? Please help me know.
public class MyActivity extends FragmentActivity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LayoutInflater inflater = getLayoutInflater();
View tabView = inflater.inflate(R.layout.tab, null);
FragmentTabHost tabHost = (FragmentTabHost) tabView.findViewById(android.R.id.tabhost);
tabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("Tab1"), TabContent1Fragment.class, null);
tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("Tab2"), TabContent2Fragment.class, null);
View page2 = inflater.inflate(R.layout.page2, null);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
List<View> list = new ArrayList<View>();
list.add(page2);
list.add(tabView);
viewPager.setAdapter(new DemoPagerAdapter(list));
}
}
public class TabContent1Fragment extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.tab_content_1, null);
}
}
public class DemoPagerAdapter extends PagerAdapter
{
private List<View> mModeViewPageList;
public DemoPagerAdapter(List<View> modeViewPageList)
{
this.mModeViewPageList = modeViewPageList;
}
#Override
public Object instantiateItem(ViewGroup container, int position)
{
container.addView(mModeViewPageList.get(position), 0);
return mModeViewPageList.get(position);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object)
{
container.removeView(mModeViewPageList.get(position));
}
#Override
public int getCount()
{
return mModeViewPageList.size();
}
#Override
public boolean isViewFromObject(View view, Object o)
{
return view == o;
}
}
Thanks to my friend, finally I found the reason was that I used PagerAdapter.
When device is rotated, all views will be recreated. But without extra codes for fragment management, PagerAdapter is not able to mange the state of the fragments inside views (tab content fragments in realtabcontent in my case) and the child fragment of a view will disappear after rotation.
So I should change all views for ViewPager into fragments and use FragmentPagerAdapter instead.
One more thing, it should be used getChildFragmentManager() from Fragment in onCreateView instead of getSupportFragmentManger() from FragmentActivity to manage the child fragments in a fragment.
I wanted to point out an important point in Light's answer. If you convert an Activity to a Fragment then you may have been using getSupportFragmentManager. When converting it, you may have changed it to getActivity().getSupportFragmentManager(). It will seemingly work until you leave and return to the fragment, and you'll find some fragments missing until you scroll the pager.
The solution is to change getActivity().getSupportFragmentManager() to getChildFragmentManager().
I'm developing an application, which consists of a FragmentActivity with three Fragments. I want to go from the first fragment to the third and last one with "next" buttons. For that, I'm using a viewPager and pagerAdpater (I disabled the paging/swiping on the viewpager). My "next" buttons have been implemented in their own fragments. I have one xml layout for each fragment and one for the fragmentActivity containing the viewpager.
I am trying to use an OnClickListener where I could use the setCurrentItem(index) method and go from the first to the last view.
The problem is that i don't know where I could put the OnClickListener, since I don't have the viewpager reference in my fragment.
How can I get the viewpager reference in my fragments? Do I have to put my OnClickListener method somewhere else?
Here is the code of one of my 3 Fragments:
public class InitializationStep1 extends Fragment{
private PagerAdapter mPagerAdapter;
CustomViewPager pager;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = (LinearLayout)inflater.inflate(R.layout.initialization_step1_layout, container, false);
Button button = (Button) v.findViewById(R.id.goToStep2);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
CustomViewPager pager = (CustomViewPager) v.findViewById(R.id.viewpager);
if(pager == null)
System.out.println("It's null..."); // always getting a null value
else
pager.setCurrentItem(0);
}
});
return v;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
setUserVisibleHint(true);
}
}
and this is my FragmentActivity:
public class Initialization extends FragmentActivity{
private PagerAdapter mPagerAdapter;
CustomViewPager pager;
Button b1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.viewpager_initialization_layout);
//initialize the pager
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, InitializationStep1.class.getName()));
fragments.add(Fragment.instantiate(this, InitializationStep2.class.getName()));
fragments.add(Fragment.instantiate(this, InitializationStep3.class.getName()));
this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);
pager = (CustomViewPager)super.findViewById(R.id.viewpager);
pager.setPagingEnabled(false);
pager.setAdapter(this.mPagerAdapter);
pager.setCurrentItem(0);
}
}
To sum all this up, I have:
- implemented 3 Fragments (1, 2 and 3)
and I would like to get:
- Each Fragment containing a button to go to the next Fragment (1 -> 2 -> 3).
- The last fragment containing a "finish" button (because there is no next Fragment to navigate to)
I assume that this is a very simple action, but I'm relatively new in Android development and couldn't figure this out. I'm maybe trying to use the wrong component to do that.
Thanks
I just had the same problem, try this! In your Initialization FragmentActivity:
public CustomViewPager getpager(){
return pager;
}
In "InitializationStep1":
CustomViewPager pager;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = (LinearLayout)inflater.inflate(R.layout.initialization_step1_layout, container, false);
pager = ((Initialization)getActivity()).getpager();
Button next = (Button) v.findViewById(R.id.button1);
next.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
pager.setCurrentItem(2);
}
});
In this way, you can get the viewpager object that you declare in your FragmentActivity, so you can use it in each fragment to switch between fragments as you want!