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.
Related
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 have a situation I need some advice on. I have an app that has an expandable list view. Each child click sends the user to the next activity, which is a tab layout with a list view. The tab layout has 3 tabs. I'm trying to figure out how to send data to the 3 tabs listviews when child is clicked on expandable listview.
Originally I was going to set it up in the setOnChildClickListener like so:
expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
if (groupPosition == 0) {
if (childPosition == 0) {
mCustomListViewAdapter.addAdapterItem(new CustomObject("Squats", "60%", "6", "150", false));
listViewFri.setAdapter(mCustomListViewAdapter);
EDIT: this is my tablayout activity that sets up the 3 tabs. I'm not sure where to access the bundled extras.
public class WorkoutDaysActivity extends BaseActivity {
ListView listViewFri = (ListView) findViewById(R.id.listViewFri);
ListView listViewMon = (ListView) findViewById(R.id.listViewMon);
ListView listViewWed = (ListView) findViewById(R.id.listViewWed);
/**
* 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.workout_days);
Bundle extras = getIntent().getBundleExtra("args");
mToolBar = activateToolbarWithHomeEnabled();
setUpNavigationDrawer();
// 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);
}
#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_workout_days, 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) {
switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
case 1:
View rootView = inflater.inflate(R.layout.fragment_workout_days, container, false);
Bundle extras = getArguments();
CustomObject objects = (CustomObject) extras.getSerializable("w29w1");
return rootView;
case 2: View rootView2 = inflater.inflate(R.layout.fragment_sub_page1, container, false);
TextView textView2 = (TextView) rootView2.findViewById(R.id.textView2);
textView2.setText("Workout 29 Week 1");
return rootView2;
case 3:
View rootView3 = inflater.inflate(R.layout.fragment_sub_page2, container, false);
TextView textView3 = (TextView) rootView3.findViewById(R.id.txtFrag3);
textView3.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView3;
default: View rootView4 = inflater.inflate(R.layout.fragment_workout_days, container, false);
TextView textView4 = (TextView) rootView4.findViewById(R.id.txtFrag1);
textView4.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView4;
}
}
}
/**
* 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 "Monday";
case 1:
return "Wednesday";
case 2:
return "Friday";
}
return null;
}
}
}
I thought it would go in this part like so:
switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
case 1:
View rootView = inflater.inflate(R.layout.fragment_workout_days, container, false);
Bundle extras = getArguments();
CustomObject objects = (CustomObject) extras.getSerializable("w29w1");
CustomListViewAdapter customListViewAdapter = new CustomListViewAdapter(this, objects);
But im getting an error under (this, objects) saying "cannot be applied to .placeholderfragment .custom object" "PlaceholderFragment cannot be converted to Context"
This is what I put in the onChildClick:
Bundle extras = new Bundle();
final ArrayList<CustomObject> objects = new ArrayList<CustomObject>();
objects.add(new CustomObject("Squat", "65%", "6", "150", false));
extras.putSerializable("w29w1", objects);
Intent intent = new Intent(getApplicationContext(), WorkoutDaysActivity.class);
intent.putExtra("args", extras);
startActivity(intent);
Thanks for the help! please let me know if you need to see any of my code to better understand what I'm trying to do!
I'm having some difficulty understanding the question completely, but here's my thoughts so far.
Are you attempting to set the same instance of the list adapter on each list? If you want the same general behaviour, but to tie different data to a list, be sure you are instantiating new adapter instances for each list.
i.e.
myList1.setAdapter(new MyAdapter());
myList2.setAdapter(new MyAdapter());
rather than
MyAdapter myAdapter = new MyAdapter();
myList1.setAdapter(myAdapter);
myList2.setAdapter(myAdapter);
Additionally, it is wise to move data through intents when communicating with another activity. In your initial activity, when an action prompts launching the next activity, put the extras into the intent before calling startActivity(). Then, inside the next activity, you will call getIntent().getXXXExtra("...") where the XXX is type-matched to the extra you are extracting, and ... is the correct key you placed on the extra in the previous activity.
If you are using fragments contained in activities, make use of Fragment.setArguments() (in activity2) and Fragment.getArguments() (in fragment2) to pass the extras from fragment1 to activity2 to fragment2.
Passing Extras Around
When you click an item and want to launch a new activity (a new view to display), a good approach is to bundle up the information needed, pass it to the new activity, unwrap all that information and then apply it to the views as you desire.
For example...
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
if (groupPosition == 0) {
if (childPosition == 0) {
Bundle extras = new Bundle();
// Put all the extras you need. This can be primitives like int, boolean, double, or complex objects using the Serializable interface
// For example, say your CustomObject implements Serializable
CustomObject customObject = new CustomObject("Squats", "60%", "6", "150", false);
extras.putSerializable("object_key_here", customObject);
Intent intent = new Intent(getContext(), NextActivityHere.class);
intent.putExtra("args", extras);
startActivity(intent);
}
}
In the activity containing the fragment which contains the list:
// Likely in onCreate()
Bundle extras = getIntent.getBundleExtra("args");
MyFragment myFragment = new MyFragment();
myFragment.setArguments(extras);
// Use fragment manager to add the fragment to your view
In the fragment (myFragment) containing the list:
// Likely in onCreate()
Bundle extras = getArguments();
CustomObject customObject = (CustomObject) extras.getSerializable("object_key_here");
// Now you can use the object to set up the adapter, etc...
Hopefully this helps at least show how to get data from the original activity to the fragment containing the list. Usually I see myself passing an ArrayList of data if I'm going to be populating a list. Without knowing too much about your scenario, it's difficult to be more specific.
Layouts with Tabs
You may want to do some reading on TabLayouts and ViewPagers. These are the models used to create paged layouts with tabs.
Implementing these views should greatly reduce the complexity of the Activity. Inside your activity's onCreate() method, you would set up the TabLayout and ViewPager to host your Monday, Wednesday, and Friday fragments.
Each of Monday, Wednesday, and Friday fragment would be an instantiation of the same fragment class which contains the list you wish to fill (if I'm getting the correct vision of the app's layout).
List of MY Assumptions
Assume the XML file is named activity_tab_host.xml
Assume the TabLayout has an id="tab_layout"
Assume the ViewPager has an id="view_pager"
Assume the activity file is named TabHostActivity.java
Assume the fragment with the list is called WorkoutDetailFragment.java
Assume your fragment receives the data through its constructor. You can either do this or pass it through the arguments as you've done. I'm just attempting to minimize code while communicating the general idea. The fragment just needs to get the data! Try not to get hung up on specific methods and code shown here; you may find it easier to pass data through a constructor, etc.
Assume the list of data is ready in the ArrayLists of CustomObjects, simply referred to as mondayData, wednesdayData, and fridayData
Assume you've created your custom adapter called SectionsPagerAdapter
Guidance Code (Not 100% of what is needed)
Get the TabLayout and ViewPager views from the XML view source file:
// TabHostActivity.java::onCreate()
setContentView(R.layout.activity_tab_host);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
Set up your ViewPager:
// TabHostActivity.java::onCreate()
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getFragmentManager());
// Create fragment to populate the tabs
WorkoutDetailFragment mondayFragment = new WorkoutDetailFragment(mondayData);
WorkoutDetailFragment wednesdayFragment = new WorkoutDetailFragment(wednesdayData);
WorkoutDetailFragment fridayFragment = new WorkoutDetailFragment(fridayData);
// Add pages (fragments) to the adapter, passing the fragment and tab title
adapter.addFragment(mondayFragment, "Monday");
adapter.addFragment(wednesdayFragment, "Wednesday");
adapter.addFragment(fridayFragment, "Friday");
// Tie the adapter to your ViewPager
viewPager.setAdapter(adapter);
Tie the ViewPager to the TabView:
// TabHostActivity.java::onCreate()
tabLayout.setupWithViewPager(viewPager);
The main takeaway regarding where to instantiate new fragments is...
The ViewPager is a device used for holding fragments, allowing the user to change between these fragments in a single activity. You should be instantiating fragments within the TabHostActivity.java activity and setting up the fragments within a ViewPager.
My above example simplifies the situation by passing list data in through the WorkoutDetailFragment constructor. This is one of two easy ways to pass data to a fragment.
Passing data through the fragment constructor:
public class WorkoutDetailFragment extends Fragment {
private ArrayList<Object> listData;
public WorkoutDetailFragment(ArrayList<Object> listData) {
this.listData = listData;
}
// Rest of the code for the fragment...
}
Passing data through fragment arguments
// TabHostActivity.java
Bundle args = new Bundle(); // May have received this bundle from extras already. If so, use Bundle args = getIntent.getExtra(...
args.putExtra("list_data", listData); // Where listData is an ArrayList<CustomObject> in your case (Monday/Wednesday/Friday data)
WorkoutDetailFragment fragment = new WorkoutDetailFragment();
fragment.setArguments(args);
// Add the fragment to the view pager...
// Inside WorkoutDetailFragment.java retrieve list data from args using getArguments().getSerializable("list_data")
Hopefully this helps!
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();
...
I'm currently working on an app that will hopefully act like an "eBook" player. Having read through a number of tutorials related to fragments, I decided to take the 'Fragment/ Viewpager' approach.
Moving into a little more detail, I decided to follow a great tutorial on nested fragments by Linden Darlinghttps://plus.google.com/100467024733771542884/posts/24HcFW5hEiV.
I created a 'webview' fragment for each individual book page, with it's own layout. So if my book consists of 6 pages, then I'll have BookPage1Fragment, BookPage2Fragment, BookPage3Fragment, BookPage4Fragment, BookPage5Fragment, BookPage6Fragment etc. I the managed to get this working within the viewpager, so all swiping through fragments etc working fine. The problem is, only one fragment at a time is visible on screen. I'd like to have two fragments (multi-pane), when on running the app on large devices and landscape orientation and single-pane (one fragment at a time) when running on smaller devices or portrait view. I want to display a two pane layout with one fragment left and one fragment righT.
See code below:
public class ParentFragment extends Fragment {
public static final String TAG = ParentFragment.class.getSimpleName();
public static ParentFragment newInstance() {
return new ParentFragment();
}
#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.fragment_parent, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewPager);
mViewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
}
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 6;
}
/*
#Override
public Fragment getItem(int position) {
Bundle args = new Bundle();
args.putInt(TextViewFragment.POSITION_KEY, position);
return TextViewFragment.newInstance(args);
}
*/
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new BookPage1Fragment();
case 1:
return new BookPage2Fragment();
case 2:
return new BookPage3Fragment();
case 3:
return new BookPage4Fragment();
case 4:
return new BookPage5Fragment();
case 5:
return new BookPage6Fragment();
default:
return getItem(0);
}
}
#Override
public CharSequence getPageTitle(int position) {
return "Fragment # " + position;
}
}
}
Basically two fragments appearing on landscape mode and one fragment appearing at a time when in portrait mode, just as the example describes on developer.blogspot http://android-developers.blogspot.in/2011/02/android-30-fragments-api.html, but embedded within a viewpager.
Here is my main.layout.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout> xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
Here is what my webview fragment
public class WebViewFragment extends Fragment {
#SuppressLint("SetJavaScriptEnabled")
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mainView = (View) inflater.inflate(R.layout.fragment_web, container, false);
WebView myWebView = (WebView) mainView.findViewById(R.id.webview);
myWebView.loadUrl("file:///android_asset/Ebook-001.html");
myWebView.setWebViewClient(new MyWebViewClient());
myWebView.getSettings().setBuiltInZoomControls(true);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.getSettings().setSupportZoom(true);
myWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
myWebView.getSettings().setAllowFileAccess(true);
myWebView.getSettings().setDomStorageEnabled(true);
myWebView.getSettings().setUseWideViewPort(true);
myWebView.getSettings().setLoadWithOverviewMode(true);
return mainView;
}
}
here is my webview fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<WebView
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
So in conclusion I'd like to:
1: Display two fragments within viewpager in landscape mode, and single in portrait mode.
2: Use one activity regardless of the device size, and decide at runtime whether to combine fragments in the layout (to create a multiple-pane design) or swap fragments (to create a single-pane design)
Hope this all makes sense! Thank you in advance for any suggestions...
You have to create a layout file for the landscape mode.You have to create a file in res folder with layout-land name.In that folder create a layout with same name which is placed in layout file.Android automatically access it when screen is change to landscape mode.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am working on an Android app. Our designer has the idea that we need a paging control looks like Etsy iPhone. (See the image below)
Basically you can swipe on the grey title bar or the content to switch screen.
Is there any existing 3rd party control does this?
I would recommend you to use Jake Whartons ViewPageIndicator(or just a normal ViewPager):
Create a Fragment for every of your Layouts and set the layout to your Fragment with the onCreateView() methode inside your fragment(only if you want to have different layouts. If you have the same Layout but just different data, you can just use one Fragment and pass the data in the getItem() methode)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.layout, container, false);
}
Now create a FragmentPagerAdapter there sould be a methode called getItem(). Switch the Position and set it to your Fragment:
#Override
public Fragment getItem(int position) {
switch(position){
case 0:
TestFragment fragment = new TestFragment();
return fragment;
case 1:
TestFragment2 fragment2 = new TestFragment2();
return fragment2;
}
return defaultFragment fragment3 = new defaultFragment();
return fragment3;
}
Now you should be able to swipe to your Layouts(Fragments) easily
You need to use the ViewPager widget. Check out the Android developer blog to get an idea about how it works: Horizontal View Swiping with ViewPager.
If you need backwards compatibility with Android 2.x, check out the Android Compatibility Library.
All explained there: Implement Horizontal Paging (Swipe Views)
Some code from that page:
public class CollectionDemoActivity extends FragmentActivity {
// When requested, this adapter returns a DemoObjectFragment,
// representing an object in the collection.
DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
// ViewPager and its adapters use support library
// fragments, so use getSupportFragmentManager.
mDemoCollectionPagerAdapter =
new DemoCollectionPagerAdapter(
getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mDemoCollectionPagerAdapter);
}
}
// Since this is an object collection, use a FragmentStatePagerAdapter,
// and NOT a FragmentPagerAdapter.
public class DemoCollectionPagerAdapter extends
FragmentStatePagerAdapter {
public DemoCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new DemoObjectFragment();
Bundle args = new Bundle();
// Our object is just an integer :-P
args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return 100;
}
#Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
}
// Instances of this class are fragments representing a single
// object in our collection.
public static class DemoObjectFragment extends Fragment {
public static final String ARG_OBJECT = "object";
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// The last two arguments ensure LayoutParams are inflated
// properly.
View rootView = inflater.inflate(
R.layout.fragment_collection_object, container, false);
Bundle args = getArguments();
((TextView) rootView.findViewById(android.R.id.text1)).setText(
Integer.toString(args.getInt(ARG_OBJECT)));
return rootView;
}
}
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTitleStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:textColor="#fff"
android:paddingTop="4dp"
android:paddingBottom="4dp" />
</android.support.v4.view.ViewPager>