My goal is to use ViewPager (like here) to let user slide through 5 different pages (a tutorial) before my MainActivity starts...
I've downloaded Animations.zip from the link above and its almost what I need, except for supporting older versions (what I managed by changing android.app references to android.support.v4.app) and using totally different layouts instead of using the same view like in the example...
My code compiles and runs, but on the phone's screen I can't see the slides changing. The action bar appears, its buttons are working fine, and I can even see that blue glow when I reach the first/last page and try to slide again... I guess android is generating default layouts for some reason.
While debugging, I've noticed that onCreateView() inside the fragment never runs. Any idea why? My code is as below:
como_usar_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView style="?android:textAppearanceMedium"
android:id="#+id/texto_como_usar_fragment"
android:padding="16dp"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="aglaglalglaglalgalgalglag"
android:textColor="#color/branco"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/logo"
/>
ComoUsarFragment.java
public class ComoUsarFragment extends Fragment {
/**
* The argument key for the page number this fragment represents.
*/
public static final String ARG_PAGE = "page";
/**
* The fragment's page number, which is set to the argument value for {#link #ARG_PAGE}.
*/
private int mPageNumber;
/**
* Factory method for this fragment class. Constructs a new fragment for the given page number.
*/
public static Fragment create(int pageNumber) {
Fragment fragment = new Fragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
public ComoUsarFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
//this is an attempt to set different views for each page, you'll see I dont use this piece of code yet
int pagina;
switch (mPageNumber){
case 0: pagina = R.layout.como_usar0;
break;
case 1: pagina = R.layout.como_usar1;
break;
case 2: pagina = R.layout.como_usar2;
break;
default: pagina = R.layout.como_usar_fragment;
break;
}
// Inflate the layout containing a title and body text.
ViewGroup rootView = (ViewGroup) inflater
.inflate(R.layout.como_usar_fragment, container, false);
// Set the title view to show the page number.
((TextView) rootView.findViewById(android.R.id.text1)).setText("aaaaa "+mPageNumber);
return rootView;
}
/**
* Returns the page number represented by this fragment object.
*/
public int getPageNumber() {
return mPageNumber;
}
}
You are returning a standard fragment instead of your own subclass
public static Fragment create(int pageNumber) {
Fragment fragment = new Fragment();
...
should be
public static Fragment create(int pageNumber) {
Fragment fragment = new ComoUsarFragment();
...
Related
I'm trying to create the following scenario:
User clicks a Button > this shows a DialogFragment
The DialogFragment contains a ViewPager, which has 2 tabs - one shows a colour picker fragment and the other a symbol picker fragment
Each picker fragment contains an adapter which transforms an array of colours/symbols into a nice grid.
However, it's currently showing up blank - the DialogFragment appears, with the other parts of the fragment, but no adapter view.
Here's what I have:
The initial activity is called EditActivity. It has a Button, which, when clicked, calls this function to reveal the DialogFragmentPickers:
public void showPickers() {
if(mDialogFragmentPickers == null) return;
mDialogFragmentPickers.setColourSet(mColourSet);
mDialogFragmentPickers.show(mFragmentManager, "Pickers");
}
DialogFragmentPickers is initialised in the onCreate method of EditActivity like this:
mDialogFragmentPickers = new DialogFragmentPickers();
The ColourSet being passed in is basically just an array of the colours that are to be shown in the picker. DialogFragmentPickers should then pass it on through to the FragmentColourPicker when it's initialised.
The DialogFragmentPickers class looks like this (I've only shown the parts pertaining to the ColourPicker, but the SymbolPicker works in the same way):
public class DialogFragmentPickers extends DialogFragment {
private PickersPagerAdapter mPagerAdapter;
private ViewPager mViewPager;
private ColourSet mColourSet;
private FragmentColourPicker mColourPicker;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
// Inflate layout
View view = inflater.inflate(R.layout.dialog_fragment_pickers, container, false);
mPagerAdapter = new PickersPagerAdapter(getChildFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = view.findViewById(R.id.pager);
mViewPager.setAdapter(mPagerAdapter);
return view;
}
public void setColourSet(ColourSet colourSet) {
mColourSet = colourSet;
if(mColourPicker == null) getColourPickerFragment();
else mColourPicker.setColourSet(mColourSet);
}
private void getColourPickerFragment() {
if (mPagerAdapter == null) return;
mColourPicker = (FragmentColourPicker) mPagerAdapter.getItem(0);
if(mColourSet != null) mColourPicker.setColourSet(mColourSet);
}
public class PickersPagerAdapter extends FragmentPagerAdapter
{
PickersPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new FragmentColourPicker();
case 1:
return new FragmentSymbolPicker();
default:
return null;
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getResources().getString(R.string.colours);
case 1:
return getResources().getString(R.string.symbols);
}
return null;
}
}
The layout file for this contains:
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Current + adjacent page titles...-->
<android.support.v4.view.PagerTitleStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />
</android.support.v4.view.ViewPager>
The first Fragment used in this pager is FragmentColourPicker. It is defined like this:
public class FragmentColourPicker extends Fragment {
GridView mColourGrid;
Context mContext;
ColourSet mColourSet;
ChartColourAdapter mColourAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_colour_picker, container, false);
mColourGrid = view.findViewById(R.id.gridview_colourPicker);
initialiseWithColourSet(); // Returns without doing anything if colourSet is not set up yet
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mContext = getActivity();
}
#Override
public void onDestroy(){ super.onDestroy();}
public void setColourSet(ColourSet thisColourSet) {
mColourSet = thisColourSet;
initialiseWithColourSet(); // Returns without doing anything if the colourGrid is not set up yet
}
public void initialiseWithColourSet() {
// Make sure that the colourSet and the colourGrid have both been initialised
if(mColourSet == null) return;
if(mColourGrid == null) return;
// Now set up ChartColourAdapter to display colours in grid
// Initialise currently highlighted colour to default
// Set on click listener for each colour
mColourAdapter = new ChartColourAdapter(mContext,
R.layout.adapter_pattern_colour_cell_layout,
mColourSet.getColours());
mColourGrid.setAdapter(mColourAdapter);
}
}
and the layout file for FragmentColourPicker (fragment_colour_picker.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/colour_picker_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/fui_transparent"
android:orientation="vertical">
<GridView
android:id="#+id/gridview_colourPicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorBg"
android:paddingBottom="#dimen/activity_standard_margin"
android:columnWidth="#dimen/grid_cell_column_width"
android:gravity="center"
android:horizontalSpacing="10dp"
android:numColumns="auto_fit"
android:padding="#dimen/activity_small_margin"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" />
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="#string/prompt_swipe_for_symbols"
android:padding="#dimen/activity_small_margin"
android:background="#color/colorBg"
/>
</LinearLayout>
When I run all of this, the DialogFragment appears when the button is clicked, and shows the FragmentColourPicker. I can swipe to the FragmentSymbolPicker and back. However, the only thing shown in the ColourPicker is the TextView which prompts the user to swipe across to see the symbols. The GridView with the actual colours in it doesn't show at all.
From the debugger, I think the issue is that initialiseWithColourSet only ever seems to have either colourSet OR colourGrid set - never both. This makes it return without attempting to set up the colour adapter.
If initialiseWithColourSet is called from onCreateView, then colourGrid is set, but colourSet is not (since it hasn't been passed in yet). That's reasonable enough. However, when colourSet is passed in later (from the DialogFragment), colourGrid has gone back to being null, so again the function returns without doing anything.
I clearly have something in the wrong order, or am re-initialising the colourGrid / ColourPicker without realising it.
It looks like an order issue to me. To ensure you're getting your data to the Fragment at the right time, I would pass the data that the fragments need into the Adapter via the constructor. I would keep a reference of them there and then instantiate the fragments using a static newInstance(... requiredData) method. Then, you can be sure that when they are "created" by the adapter, they'll have the required information.
Something like this:
Your fragment class:
...
Object myRequiredData;
static FragmentColourPicker newInstance(... requiredData) {
FragmentColourPicker f = new FragmentColourPicker();
f.setRequiredData(requiredData);
return f;
}
public void setRequiredData(Object reqData){
this.myRequiredData = reqData;
}
...
Your adapter class:
public class PickersPagerAdapter extends FragmentPagerAdapter {
Object reqData0;
Object reqData1;
PickersPagerAdapter(FragmentManager fm, Object reqData0, Object reqData1) {
super(fm);
this.reqData0 = reqData0;
this.reqData1 = reqData1;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return FragmentColourPicker.newInstance(reqData0);
case 1:
return FragmentSymbolPicker.newInstance(reqData1);
default:
return null;
}
}
...
}
I have been trying to implement a ViewPager with different fragments.
And the problem is when i run the app, in the ViewPager, out of all the pages, only one page is visible and that page only gets changed when I slide over to the other pages in the ViewPager.
Take a look at my code,(although I checked it many times referring it with online resources).
This is what each of my fragments look like:
public class fragment1 extends Fragment {
/* Variable to store reference to the ACtivity */
Activity mCurrentActivity;
/* Variable storing reference to the ArrayList */
private ArrayList<Word> mDefaultWords;
/**
* THe empty public Constructor
*/
public fragment1(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/** Getting reference to the Activity */
mCurrentActivity = getActivity();
// Populating the ArrayList here
// And later in the onActivityCreated callback I set an adapter on the ArrayList
return inflater.inflate(R.layout.activity_others, container, false);
}
#Override
public void onActivityCreated(Bundle savedStateInstance){
super .onActivityCreated(savedStateInstance);
/**
* Creating {#link ArrayAdapter} to link the {#link String}
* from {#link ArrayList} {#param
*/
MyAdapter adaptItems = new MyAdapter(mCurrentActivity, mDefaultWords);
// Getting the id of the ListView in numberActivity.xml
ListView myList = (ListView) mCurrentActivity.findViewById(R.id.theList);
//Chaning background color
myList.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.holo_purple));
// Setting the adapter with the {#link ListView}
myList.setAdapter(adaptItems);
}
}
}
My Activity setting the adapter class extending FragmentPagerAdapter as a private inner class and setting the adapter on the ViewPager.
public class Main2Activity extends AppCompatActivity {
private ViewPager mViewPager;
private FragmentPagerAdapter mFragmentStatePagerAdapter;
private FragmentManager mFragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mFragmentManager = getSupportFragmentManager();
mViewPager = (ViewPager) findViewById(R.id.theViewPager);
mFragmentStatePagerAdapter = new MyFragmentStatePagerAdapter(mFragmentManager);
/* Setting the apdapter on the pager */
mViewPager.setAdapter(mFragmentStatePagerAdapter);
}
public class MyFragmentStatePagerAdapter extends FragmentPagerAdapter {
public MyFragmentStatePagerAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
#Override
public int getCount(){
return 4;
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new fragment1();
} else if (position == 1){
return new fragment2();
} else if (position == 2) {
return new fragment3();
} else {
return new fragment4();
}
}
}
}
And here is the layout with the ViewPager
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/theViewPager"
android:visibility="visible" />
As I said, when I run the app only one page gets displayed, other pages are present in the ViewPager but they are blank and displays the default background color,
And the one page that is displayed is the one that gets changed when I swipe left or right in the ViewPager.
So what's the issue?
dont downvote the question, its a genuine problem.
So, I worked my way around, let me say how.
What happened is, I was working on a cloned project that had a old gradle version and sdktools version was also not updated and was quite old.
and the min API targetted was API 15
And I was testing my application on API 21.
So, what I did is I used a different layouts for each of my fragments.
That is for each fragment I created its own XML layout.
And that worked perfectly.
Odd problem, so I updated the gradle and sdktools, to avoid such weird problems.
I apologise in advance if this question is NOT as interesting as others might expect. Firstly there are not that many answers to questions about the most recent version of Android Studio (that is version 2.1.2). Also I have noticed people seldom use the templates provided by the IDE(I believe its there to speed up the development process).
How do I modify the code for the Tabbed Activity template? I am currently staring at the code generated by the IDE for the template. I am clueless how to modfiy it to include the fragments for the three sections it has by default. I have gone over the code and to some extent understand the structure and what the parts do, but it does so in a way that is completely different from how the official docs tell people to do it from scratch.
I have created one Fragment and hope to create two more. How do I place them inside the tabs, using the template?
Can someone please put me through and also direct me to useful materials in this regard?
Ok from the current structure, I can see that in the .java file there is code for the Activity and the default Fragment(called as placeholder fragment). I have tried to replace the default Fragment with one of my Fragment by calling it in the onCreateView(). The thing is how do I add other Fragments. The template code:
.java file
package name;
public class myUI extends AppCompatActivity {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_UI);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_my_UI, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_my_UI, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
/**
* 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 PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "SECTION 1";
case 1:
return "SECTION 2";
case 2:
return "SECTION 3";
}
return null;
}
}
}
It is this .java file that has me thinking, there is only one Fragment XML layout but it appears that a trick is being used to replicate it across the three tabs(along with the TextView component in it).
My question is this, I have my own Fragments created (with their own behaviours), how do I make them part of the TabbedActivity? In what part of its code do I put it? Also if it is not to much trouble can someone explain what is actually goin on in the code(I mean the area where one Fragment is appears three times)?
The XML Layout for the Activity itself is given below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.myProject.myProject.MyUI">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
I hope this helps someone else (since this question is one year old, I bet you already figured it out). It's actually not that difficult. The template is overwhelming at first, but with enough attention you can understand it. Anyway, here it goes:
First thing I noticed is this piece of code:
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "SECTION 1";
case 1:
return "SECTION 2";
case 2:
return "SECTION 3";
}
return null;
}
If you change the return under getCount() to, say, 2; and delete the case 2: under getPageTitle(int position), the activity shows only two tabs.
The objects get called in this order: First, SectionsPageAdapter get instantiated in onCreate(). This ends up calling this method:
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
As you can see, this asks PlaceholderFragment for a new instance for every tab you have specified. No need to change anything here. Now let's go to PlaceholderFragment.newInstance(int sectionNumber)...
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
So, it seems like it defines an argument (sectionNumber), sets it and returns the fragment. No need to change anything here either. Then, it looks like it depends on the only method we haven't looked at yet: onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState). And it makes sense, since it takes as an argument the Bundle argument. Let's take a look:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
The contents of every fragment are defined here. So, it would make sense to make your changes here.
This is an example of how I changed it for my project:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView;
TextView textView;
switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
case 1:
rootView = inflater.inflate(R.layout.fragment_infraestructuras, container, false);
textView = (TextView) rootView.findViewById(R.id.section_label1);
textView.setText("Infraestructuras");
return rootView;
case 2:
rootView = inflater.inflate(R.layout.fragment_incidentes, container, false);
textView = (TextView) rootView.findViewById(R.id.section_label2);
textView.setText("Incidentes");
return rootView;
}
return null;
}
I created a new layout for each tab.
I'm developing an application in which i use a ViewPager.
Underneath the ViewPager, there are some bullet points that should indicate which page is displayed, but their behaviour is wrong.
Here's the activity part:
ind1 = (ImageView)findViewById(R.id.page1);
ind2 = (ImageView)findViewById(R.id.page2);
ind3 = (ImageView)findViewById(R.id.page3);
ind4 = (ImageView)findViewById(R.id.page4);
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
Here's the Adapter:
/*Adapter for ViewPager*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter{
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(position){
case 0:
ind1.setImageResource(on);
ind2.setImageResource(off);
ind3.setImageResource(off);
ind4.setImageResource(off);
return Frag1.newInstance();
case 1:
ind1.setImageResource(off);
ind2.setImageResource(on);
ind3.setImageResource(off);
ind4.setImageResource(off);
return Frag2.newInstance();
case 2:
ind1.setImageResource(off);
ind2.setImageResource(off);
ind3.setImageResource(on);
ind4.setImageResource(off);
return Frag3.newInstance();
case 3:
ind1.setImageResource(off);
ind2.setImageResource(off);
ind3.setImageResource(off);
ind4.setImageResource(on);
return Frag4.newInstance();
default:
ind1.setImageResource(on);
ind2.setImageResource(off);
ind3.setImageResource(off);
ind4.setImageResource(off);
return Frag1.newInstance();
}
}
#Override
public int getCount() {
return NUM_PAGES; /*NUM_PAGES = 4*/
}
}
Here's Frag1 (the other Fragments are equal to Frag1, the only differences are the layout and the loaded HTML file):
public class Frag1 extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_page_1, container, false);
WebView wv = (WebView) rootView.findViewById(R.id.webView1);
wv.loadUrl("file:///android_asset/html/tabel1.html");
wv.setBackgroundColor(0x00000000);
wv.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
return rootView;
}
public static Frag1 newInstance(){
Frag1 f = new Frag1();
return f;
}
}
The wrong behaviour is the following: when activity starts, the first fragment is displayed but the 'active' bullet point is the second, for the second page the active point is the third, for the third page is active the fourth, for the fourth page the fourth point remains active. If i swipe back to the third page the second bullet point is active.
In simple terms, the active bullet point doesn't match with the displayed page.
I tried to print the position in the Adapter, like following, under each case::
Toast.makeText(context, String.valueOf(position), Toast.LENGTH_SHORT).show();
When activity starts, are printed two consecutive message, 0 and 1, without interacting with the ViewPager.
When i change page, the position is always wrong, but the relative fragment are displayed correctly.
I tried to set the bullet point state in the fragments class, but nothing changed.
Why the adapter indicates the wrong position? How can i make that the correct bullet point indicates the right displayed page?
I am using a ViewPager to show 9 fragments. In each of these fragments, I want to just show a different picture. I want to use one single fragment layout, but dynamically add in the picture. Also, would like add a "Continue" button on the last fragment that when pressed will go to another activity.
How do I go about making a fragment layout dynamic?
Main Activity
public class StoryboardPageActivity extends FragmentActivity {
// The number of pages (wizard steps) to show in this demo.
private static final int NUM_PAGES = 9;
// The pager widget, which handles animation and allows swiping horizontally to access previous and next wizard steps.
private ViewPager mPager;
// The pager adapter, which provides the pages to the view pager widget.
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storyboard_page);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.storyboardPager);
mPagerAdapter = new StoryboardPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
#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 {
// Otherwise, select the previous step.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
// A simple pager adapter that represents 5 fragment objects, in sequence.
private class StoryboardPagerAdapter extends FragmentStatePagerAdapter {
public StoryboardPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return StoryboardFragment.newInstance(position);
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
Fragment
public class StoryboardFragment extends Fragment {
private static final String KEY_POSITION = "position";
static StoryboardFragment newInstance(int position) {
StoryboardFragment frag = new StoryboardFragment();
Bundle args = new Bundle();
args.putInt(KEY_POSITION, position);
frag.setArguments(args);
return(frag);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_storyboard_page, container, false);
ImageView image = (ImageView)rootView.findViewById(R.id.imgStoryboard);
int position = getArguments().getInt(KEY_POSITION, -1);
int[] images = {R.drawable.storyboard1, R.drawable.storyboard2, R.drawable.storyboard3,
R.drawable.storyboard4, R.drawable.storyboard5, R.drawable.storyboard6,
R.drawable.storyboard7, R.drawable.storyboard8, R.drawable.storyboard9};
image.setImageResource(images[position]);
return rootView;
}
}
Fragment XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff" >
<ImageView
android:id="#+id/imgStoryboard"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:contentDescription="#string/storyboardSlide" />
</RelativeLayout>
How do I go about making a fragment layout dynamic?
The same way you make any other "layout dynamic". If you want to put an image in an ImageView, call setImageBitmap() or setImageDrawable() or whatever. For example, the PagerAdapter could supply the position to the fragment (via a factory method), and the fragment could then know what image to load.
This sample project demonstrates populating the hint of an EditText with a custom value based upon the page's position.
With respect to the "Continue" button, either have a separate fragment class for that (and appropriate smarts in your PagerAdapter, or always have the button in your layout, but set to android:visibility="gone" by default, toggling it via setVisibility(View.VISIBLE) for the fragment that needs it.