Add Programatically created LinearLayout as resource to View in Fragment - android

My eventual goal is to have users be able to switch between tabs with dynamically generated content (based on user input) in an activity. I am trying to create a dynamic layout and have it load as the layout within a fragment. My code is throwing an error because the layout I am trying to provide is not an xml resource. Is what I'm trying even possible to do?
public static class JobsFragment extends Fragment{
LinearLayout l;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//set button vars here
Log.i("aaa","called frag onCreate");
l=new LinearLayout(getActivity());
Button b=new Button(getActivity());
b.setText("HI");
l.addView(b);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
Log.i("aaa","called frag onCreateView()");
//View rootView = inflater.inflate(R.layout.fragment_section_dummy, container, false);
View rootView = inflater.inflate(l, container, false);
return rootView;
}
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to one of the primary
* sections of the app.
*/
public static class AppSectionsPagerAdapter extends FragmentPagerAdapter{
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new JobsFragment();
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
return "Section " + (position + 1);
}
}
}

Make the fragment constructor accept linearlayout as parameter and use this field to be return from onCreateView
Something like following psuedo code
CustomFragment{
private LinearLayout mLayout;
CustomFragment(LinearLayout layout){
mLayout=layout;
| }
onCreatView(....)
{
return mLayout;
}
}

You need to add layout width and height programatically.
Without which it will throw error about mandatory layout parameters not provided.
addLayoutParams is the method name

Related

moving from one fragment to another using viewpager

So currently my code can move between objects from the same fragment, but I want to move between different fragments that have different layouts.What code do I need to add to viewpager to make it work? Do I need to make use of a FragentManager? Can anyone guide me on how to go about it? Thanks.
Below if my code:
ScreenSlidePagerActivity.java
public class ScreenSlidePagerActivity extends FragmentActivity {
private static final int NUM_PAGES = 5;
private ViewPager mPager;
private PagerAdapter pagerAdapter;
/**
* The pager adapter, which provides the pages to the view pager widget.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.slide_screen_viewpager);
//declare viewpager and pageradapter
mPager = findViewById(R.id.ViewPageSlide);
pagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(pagerAdapter);
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0){
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
}
else {
mPager.setCurrentItem(mPager.getCurrentItem() -1 );
}
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position) {
return new ScreenSlidePageFragment();
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
ScreenSlidePageFragment.java
public class ScreenSlidePageFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.slide_content_page, container, false
);
return rootView;
}
}
You have only one class i.e.,ScreenSlidePageFragment that extends fragments. If you want different layouts for that, its better if you create different classes that inflates different layouts. eg: if you want two layouts, create two classes and both classes should inflate different layouts. The changes need to be done are :
//inside ScreenSlidePagerAdapter
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new ScreenSlidePageFragment();
case 1:
return new NewClass();
//and so on
}
}
You have to create the new Class similar to ScreenSlidePageFragment. The only change is inflate a different layout.
public class NewClass extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.new_layout, container, false
);
return rootView;
}
}
You can create a new_layout similar to slide_content_page and customize it as you want. You can also increase the no of fragment objects and layout as you wish.
But a new way of doing this things has come. Its better if you extend FragmentStateAdapter instead of FragmentStatePagerAdapter. This is more easy and efficient. You have to override createFragment in this case instead of getItem. Ignore of you are okay with it.
Hope this is the question you have asked and this helps. Thankyou.

FragmentPagerAdapter: java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents

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?

Change Fragment with ViewPager

I am using PagerSlidingTab Library for ViewPager. And I want to change Fragment while scrolling of tabs. It is working fine. Check out my code.
I am using AsynTask() on each Fragment.
When the App opens with the MainActivity, First Fragment is attached to the activity, But It shows two AsynTask() dialog message, one from First and another from Second Fragment. And When I scroll to second tab, It shows dialog message of Third Fragment.
So, If I scroll from left to right in tabs, the Fragment right to the current fragment is displayed and if i scroll from right to left, the Fragment left to the current Fragment is displayed.
Please help me to solve the problem.
My Code:
public class PageSlidingTabStripFragment extends Fragment {
public static final String TAG = PageSlidingTabStripFragment.class
.getSimpleName();
public static PageSlidingTabStripFragment newInstance() {
return new PageSlidingTabStripFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.pager, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) view
.findViewById(R.id.tabs);
ViewPager pager = (ViewPager) view.findViewById(R.id.pager);
MyPagerAdapter adapter = new MyPagerAdapter(getChildFragmentManager());
pager.setAdapter(adapter);
tabs.setViewPager(pager);
}
public class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
private final String[] TITLES = { "Instant Opportunity", "Events",
"Experts" };
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new InstantOpportunity();
case 1:
return new Events();
case 2:
return new Experts();
default:
break;
}
return null;
}
}
}
Explanation:
It turns out there is an easier implementation for scrollable tabs which doesn't involve another library. You can easily implement tabs into your app using normal Android code straight from the default SDK.
The Code
Main Class:
public class PageSlidingTabStripFragment extends Fragment {
//Variables
private ViewPager viewPager;
private PagerTitleStrip pagerTitleStrip;
public PageSlidingTabStripFragment() {
// Required empty public constructor
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//Find your pager declared in XML
viewPager = (ViewPager) getView().findViewById(R.id.pager);
//Set the viewPager to a new adapter (see below)
viewPager.setAdapter(new MyAdapter(getFragmentManager()));
//If your doing scrollable tabs as opposed to fix tabs,
//you need to find a pagerTitleStrip that is declared in XML
//just like the pager
pagerTitleStrip = (PagerTitleStrip)
getView().findViewById(R.id.pager_title_strip);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.[your layout name here], container, false);
}
}
Adapter:
//Note: this can go below all of the previous code. Just make sure it's
//below the last curly bracket in your file!
class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int arg0) {
Fragment fragment = null;
if (arg0 == 0) {
fragment = new InstantOpportunity();
}
if (arg0 == 1) {
fragment = new Events();
}
if (arg0 == 2) {
fragment = new Experts();
}
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return "Instant Opportunity";
}
if (position == 1) {
return "Events";
}
if (position == 2) {
return "Experts";
}
return null;
}
}
Conclusion:
I hope this helps you understand another way to make scrollable tabs! I have examples on my Github Page about how to make each type (That being Fixed or Scrollable).
Links:
Fixed Tabs Example - Click Here
Scrollable Tabs Example - Click Here
Hope this helps!
Edit:
When asked what to import, make sure you select the V4 support fragments.
please use this example..its very easy.i already implement that.
reference link
hope its useful to you.its best example of pager-sliding-tabstrip.
Use
framelayout compulsory:
FrameLayout fl = new FrameLayout(getActivity());
fl.addView(urFragementView);
and then set your fragement view in this framelayout.

Populate 5 fragment pages with separate arraylists

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).

How to display different text on each page in ViewPager, instantiateItem() confusion

In the CustomPagerAdapter of the ViewPager, in instantiateItem() method I'm trying to create an TextView and then for each page set a different text depending on certain condition. Text is read from a pages Cursor. Here is a code:
#Override
public Object instantiateItem(ViewGroup collection, int position) {
sc = new ScrollView(context);
sc.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
sc.setFillViewport(true);
tv = new TextView(context);
if(position < count) {
tv.setText(pages.getString(1));
pages.moveToPosition(position);
}else {
tv.setText("LOCKED");
}
tv.setTag(TAG_PAGE + position);
tv.setGravity(Gravity.CENTER);
tv.setTextColor(Color.BLACK);
tv.setTextSize(30);
sc.addView(tv);
((ViewPager) collection).addView(sc);
return sc;
}
However ViewPager behaves not as expected. The first and the second page have the same text, rest of the pages has a sign "LOCKED" as expected. When I swipe into the 4th page and come back to the first page then the first page consists of the text that suppose to be in the second page. I also tried to use myViewPager.setOffscreenPageLimit(numberOfPages) however it doesn't help.
I found this answer:
"Inside of instantiateItem, the position parameter is the position that is in need of rendering. It is NOT the position of the currently focused item that the user would see. The pages to the left and right of the currently displayed view need to be pre rendered in memory so that the animations to those screens will be smooth. "
It make sense to me but how then can I correctly display the pages content and then update it if desired? Please advise if there is different way to do it with skipping instantiateItem() method that introduce the mess and confusion into the problem. Thank you.
I have solved this problem by using a different implementation:
// Adapter class
private static class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
return PageFragment.newInstance(pages[index]); // Pages is an array of Strings
}
#Override
public int getCount() {
return numberOfPages;
}
}
// PageFragment class
public class PageFragment extends Fragment {
TextView tv;
public static PageFragment newInstance(String page) {
PageFragment pageFragment = new PageFragment();
Bundle bundle = new Bundle();
bundle.putString("pageContent", page);
pageFragment.setArguments(bundle);
return pageFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
tv = (TextView) view.findViewById(R.id.text_view);
tv.setText(getArguments().getString("pageContent"));
return view;
}
}
You can Create ViewPager Object and then set Listener onthis object.
ViewPager myPager = (ViewPager) findViewById(R.id.yourPagerid);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
myPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
//You can change textview word according to current page
switch (position) {
case 0:
break;
case 1:
break;
case 2:
break;
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// Log.d("check","onPageScrolled");
}
#Override
public void onPageScrollStateChanged(int arg0) {
// Log.d("check","onPageScrollStateChanged");
}
});

Categories

Resources