i have a problem with ActionBarActivity and ViewPager.
On my "main-activity" which is a ActionBarActivity i have some tabs, which are fragments.
I want to implement the "swipe-feature" between these tabs.
I've already read the following tutorial:
http://developer.android.com/training/implementing-navigation/lateral.html
Actually i have implemented the whole code, but my app wont work. :(
There is no "swipe-feature" between the tabs.
Here is my code of the main-activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hauptmenue_extended);
try {
actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// ViewPager ...
pagerAdapter = new CollectionPagerAdapter(
getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(1);
viewPager
.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// Add all tabs to the actionbar...
Tab tabB = actionBar.newTab();
tabB.setText("Home");
tabB.setIcon(R.drawable.icon_home);
tabB.setTabListener(new TabListener<Startmenue_activity>(this,
"Start", Startmenue_activity.class, viewPager));
actionBar.addTab(tabB);
Tab tabA = actionBar.newTab();
tabA.setText("");
tabA.setIcon(R.drawable.icon_nachrichten_sel);
tabA.setTabListener(new TabListener<Nachrichten_activity>(this,
"News", Nachrichten_activity.class, viewPager));
actionBar.addTab(tabA);
Tab tabC = actionBar.newTab();
tabC.setText("");
tabC.setIcon(R.drawable.icon_favoriten);
tabC.setTabListener(new TabListener<Favoriten_activity>(this,
"Favs", Favoriten_activity.class, viewPager));
actionBar.addTab(tabC);
And my adapter looks like this:
public class CollectionPagerAdapter extends FragmentPagerAdapter {
final int NUM_ITEMS = 3; // number of tabs
List<Fragment> fragments = new ArrayList<Fragment>();
public Fragment getItem(int pos) {
return fragments.get(pos);
}
public void addFragment(Fragment f) {
fragments.add(f);
}
public CollectionPagerAdapter(FragmentManager fm) {
super(fm);
Fragment home_Fragment = new Startmenue_activity();
addFragment(home_Fragment);
Fragment news_Fragment = new Nachrichten_activity();
addFragment(news_Fragment);
Fragment favoriten_Fragment = new Favoriten_activity();
addFragment(favoriten_Fragment);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
}
Oh and my XML of the main-activity looks like this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Hauptmenue_extended" >
<!-- The ViewPager -->
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- The main content view -->
<FrameLayout
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#fff"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.view.ViewPager>
</android.support.v4.widget.DrawerLayout>
There's a bunch of things that I don't fully understand about your code, for example, why are you putting a ListView inside the ViewPager?. Anyways if you want to implement some tabs with the swipe feature. Here is how do it:
First the xml:
<?xml version="1.0" encoding="utf-8"?>
<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.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</android.support.v4.view.ViewPager>
Now the activity:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new SampleAdapter(this, getSupportFragmentManager()));
}
}
The adapter:
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
public class SampleAdapter extends FragmentStatePagerAdapter {
Context ctxt = null;
public SampleAdapter(Context ctxt, FragmentManager mgr) {
super(mgr);
this.ctxt = ctxt;
}
#Override
public int getCount() {
return 3;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new SimpleFragment("Hi");
case 1:
return new SimpleFragment("There");
case 2:
return new SimpleFragment("Fella");
}
return null;
}
#Override
public String getPageTitle(int position) {
switch (position) {
case 0:
return "First Tab";
case 1:
return "Second Tab";
case 2:
return "Third Tab";
}
return null;
}
}
And the SimpleFragment:
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
#SuppressLint("ValidFragment")
public class SimpleFragment extends Fragment {
String text;
public SimpleFragment(String string) {
text = string;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment, container, false);
TextView textview = (TextView) root.findViewById(R.id.textView1);
textview.setText(text);
return root;
}
}
And the fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
Hope this helps :)
Try this out. But I've not tested it.
http://wptrafficanalyzer.in/blog/swipable-navigation-tabs-using-actionbarcompat-library/
Related
I am trying to create tabs in my layout. But instead of showing tab it is showing the below screen in design:
Below is the code:
**activity_mail.xml**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="200dp"
android:id="#+id/appBarLayout2">
<com.google.android.material.tabs.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"/>
</android.support.design.widget.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/white"/>
</LinearLayout>
MainActivity.java
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
public class MainActivity extends AppCompatActivity {
/* private TabAdapter adapter;
private TabLayout tabLayout;
private ViewPager viewPager;*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new TabAdapter(getSupportFragmentManager(),
MainActivity.this));
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
}
}
Tab1Fragment.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
public class Tab1Fragment extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
private int mPage;
public static Tab1Fragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
Tab1Fragment fragment = new Tab1Fragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPage = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) view;
textView.setText("Fragment #" + mPage);
return view;
}
}
TabAdapter.Java
import android.content.Context;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
public class TabAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Tab1", "Tab2", "Tab3" };
private Context context;
public TabAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
return Tab1Fragment.newInstance(position + 1);
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.PlaceholderFragment">
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:text="#string/sparta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1" />
</androidx.constraintlayout.widget.ConstraintLayout>
Also when trying to run it in my mobile, it is showing error something like:
android.widget.RelativeLayout cannot be cast to android.widget.TextView
Please suggest the way to solve this issue.
After androidX, support library are removed,
so you need to use material design which help you.
Replace your appbar with below code
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="200dp"
android:id="#+id/appBarLayout2">
this will help you.
You're using deprecated design support AppBarLayout, You need to replace it with androidx library , so replace android.support.design.widget.AppBarLayout with com.google.android.material.appbar.AppBarLayout in your layout.
<?xml version="1.0" encoding="utf-8"?><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="200dp">
<com.google.android.material.tabs.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/white" />
</LinearLayout>
For the android.widget.RelativeLayout cannot be cast to android.widget.TextView, please post the entire stack trace.
UPDATE
tab names are not coming. only green background of the tablayout is shown.
this is odd behavior, as I you already override getPageTitle in the adapter.. I just suggest not to use a hard-coded array of Strings in the adapter, instead add the tab titles in the strings.xml
Strings.xml
<resources>
<string name="tab1">Tab1</string>
<string name="tab2">Tab2</string>
<string name="tab3">Tab3</string>
</resources>
Adapter
public class TabAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
// private String tabTitles[] = new String[] { "Tab1", "Tab2", "Tab3" };
private int[] tabTitles = new int[]{R.string.tab1, R.string.tab2, R.string.tab3};
private Context context;
public TabAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
return Tab1Fragment.newInstance(position + 1);
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
// return tabTitles[position];
return context.getString(tabTitles[position]);
}
}
Please have a look at this question that might be relevant.
UPDATE 2
Try to add those listeners
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new TabAdapter(getSupportFragmentManager(),
MainActivity.this));
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
// listeners
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
}
if not working , try to set the current item of the ViewPager
viewPager.setCurrentItem(itemPosition);
I'm trying to make an app (for learning purposes) where I have a few tabs with scrollable content.
I have a collapsing app bar with a ViewPager for the main layout and three identical layouts with a TextView inside a NestedScrollView where the only difference is the image on top of the text. I also have three fragment classes with the same code inside. Everything worked fine.
But since I'm using the same layout in each tab, I thought that instead of a xml file and a java class for each tab, I could just have one of each and then somehow change the content for each tab inside my Adapter.
So I tried to just create a method to do that inside my tabFragment class. But I can't seem to find a way to modify the TextView. I keep getting a NullPointerException every time.
What am I missing?
Is my approach wrong? If so, what would be a better one? How do I solve this?
Thank you in advance :)
Here's my fragment class right now (the only one remaining ):
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import com.example.tablayoutwithscrollview.R;
public class TabFragment extends Fragment {
private TextView textView;
private int text, image;
public TabFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.tab1, container, false);
//textView = view.findViewById(R.id.textView);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
textView = getView().findViewById(R.id.textView);
}
public void setTabContent(int text, int image)
{
textView.setText(text);
textView.setCompoundDrawablesWithIntrinsicBounds(0,image,0,0);
}
}
My adapter class:
import android.content.Context;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.example.tablayoutwithscrollview.Tabs.TabFragment;
public class MyAdapter extends FragmentPagerAdapter {
private static int tabCount;
Context context;
public MyAdapter(FragmentManager fm, int tabCount, Context context){
super(fm);
this.tabCount = tabCount;
this.context = context;
}
#Override
public Fragment getItem(int position) {
TabFragment fragment;
switch (position)
{
case 0:
fragment = new TabFragment();
fragment.setTabContent(R.string.lorem_ipsum, R.drawable.jackfruit);
return fragment;
case 1:
fragment = new TabFragment();
fragment.setTabContent(R.string.lorem_ipsum, R.drawable.guava);
return fragment;
case 2:
fragment = new TabFragment();
fragment.setTabContent(R.string.lorem_ipsum, R.drawable.pomegranate);
return fragment;
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position)
{
switch (position)
{
case 0:
return context.getString(R.string.tab1_title);
case 1:
return context.getString(R.string.tab2_title);
case 2:
return context.getString(R.string.tab3_title);
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
MainActivity:
package com.example.tablayoutwithscrollview;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout = findViewById(R.id.tabLayout);
viewPager = findViewById(R.id.viewPager);
populatesTabLayout(tabLayout);
MyAdapter myAdapter = new MyAdapter(getSupportFragmentManager(), tabLayout.getTabCount(), this);
viewPager.setAdapter(myAdapter);
tabLayout.setupWithViewPager(viewPager);
}
private void populatesTabLayout(TabLayout tabLayout)
{
for (int i = 0; i<3; i++)
{
tabLayout.addTab(tabLayout.newTab());
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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/coordLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/collapseToolBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="#+id/toolbar">
<ImageView
android:id="#+id/imageView7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="#drawable/strawberry" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"></androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:visibility="visible" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And my tab layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/tabNestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableTop="#drawable/jackfruit"
android:text="#string/lorem_ipsum" />
</androidx.core.widget.NestedScrollView>
Here's how it's supposed to work (from before when each tab had a fragment class and a layout file):
The problem is that the created TabFragment instance has not been attached to the activity yet, therefore the textView does not inflated at that point.
You should pass the text to the TabFragment instance as an argument in the MyAdapter#getItem(..) method.
...
case 0:
fragment = new TabFragment();
Bundle args = new Bundle();
args.putString("key", textString);
fragment.setArguments(args);
return fragment
...
After that set the text for the TextView instance in the onViewCreated(...) method:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
textView = getView().findViewById(R.id.textView);
textView.setText(getArguments().getString("key"));
}
Or you can see a nice example at the Android Reference.
I want to create customized swipeable tabs in my android application project as I have provided in the
picture here
.
Since link only answers are not allowed in the SO, adding some kind of steps to do.
Step 1 :
Define three different set of Fragment Classes that will be used for each tabs. [ Android recommends to use fragments instead of Activity ]
Step 2 :
Define a Pager adapter that will help you to load the above three fragments under each tabs.
Step 3 :
In you main activity define the tablayout, and set the above adapter as shown in the tutorial link.
Kindly refer the below tutorial, that is very basic and help you achieve what you needed.
http://www.truiton.com/2015/06/android-tabs-example-fragments-viewpager/
Above link, only guides you to implement the swipe-able views. If you need to implement the exact design like the image you posted needs some work in your styles xml or try with drawable images here.
One more useful link
Let me know for queries.
EDIT
I'm also refering to the same thing what #kush mentioned.
Try this..
As I tried.. you can do well..
activity_main.xml
<RelativeLayout
android:id="#+id/main_layout"
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/tab_layout"/>
</RelativeLayout>
In your MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...........................
...........................
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
add PagerAdapter.java
package com.truiton.designsupporttabs;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabFragment1 tab1 = new TabFragment1();
return tab1;
case 1:
TabFragment2 tab2 = new TabFragment2();
return tab2;
case 2:
TabFragment3 tab3 = new TabFragment3();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
Reference...
http://www.truiton.com/2015/06/android-tabs-example-fragments-viewpager/
I found a way to make similar tab layout using pageadapter. Below is the code for the same.
MainActivity code:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the view from activity_main.xml
setContentView(R.layout.activity_main);
// Locate the viewpager in activity_main.xml
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
// Set the ViewPagerAdapter into ViewPager
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
}
}
MainActivity.xml
<?xml version="1.0" encoding="utf-8"?>
<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.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:textColor="#000000" />
</android.support.v4.view.ViewPager>
PageAdapter.java
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class PagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
// Tab Titles
private String tabtitles[] = new String[] { "PLAYLIST", "SONGS", "ALBUMS" };
Context context;
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
switch (position) {
// Open FragmentTab1.java
case 0:
SongsList fragmenttab1 = new SongsList();
return fragmenttab1;
// Open FragmentTab2.java
case 1:
SecondFragment fragmenttab2 = new SecondFragment();
return fragmenttab2;
// Open FragmentTab3.java
case 2:
ThirdFragment fragmenttab3 = new ThirdFragment();
return fragmenttab3;
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
return tabtitles[position];
}
}
You can create n fragments in your project. Here is the example fragment code.
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SecondFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Get the view from fragmenttab1.xml
View view = inflater.inflate(R.layout.fragment_second, container, false);
return view;
}
}
and its XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/Fragment2" />
</RelativeLayout>
Add this RESOURCE values to remove the action bar,title bar in layout in styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
</resources>
i have tried several things to display the text in the tabs on "scroll tabs" in my activity but it never shows
any ideas what happened?
below is the code:
scrollabletabs.xml:
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/pager">
<android.support.v4.view.PagerTitleStrip
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:layout_gravity="top"
android:background="#color/material_deep_teal_500"
android:id="#+id/tabtitle"
style="#style/pagertitlestrip">
</android.support.v4.view.PagerTitleStrip>
</android.support.v4.view.ViewPager>
ScrolllableTabs.java:
package com.example.pc.learn_again;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
public class ScrollableTabs extends FragmentActivity {
//get the ViewPager//
ViewPager viewPager=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scrollabletabs);
viewPager = (ViewPager) findViewById(R.id.pager);
//the connection between the ViewPager and the adapter is below//
FragmentManager fragmentManager = getSupportFragmentManager();
viewPager.setAdapter(new myadapter(fragmentManager));
}
}
class myadapter extends FragmentPagerAdapter
{
public myadapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
//as you see from the below this is how we tell the Viewpager which fragment (page) to be shown//
Fragment fragment=null;
if (position==0)
{
fragment = new ScrollableFragment1();
}
if (position==1)
{
fragment = new ScrollableFragment2();
}
if (position==2)
{
fragment = new ScrollableFragment3();
}
return fragment;
}
#Override
public int getCount() {
return 3;//this is the number of pages
}
//the below is for the titles//
#Override
public CharSequence getPageTitle(int position) {
if (position==0)
{
return "Login Screen";
}
if (position==1)
{
return " List View";
}
if (position==2)
{
return "Calculator";
}
return null;
}
}
let me point out that the fragments appear correctly and they work fine , but i do not know why the titles in the tabs do not show (is it possible that the method returns null?? and if yes....why??)
thx for the help guys :)
Use:
<android.support.v4.view.PagerTabStrip
android:id="#+id/strip"
android:layout_gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:textColor="#fff"
android:background="#android:color/holo_blue_bright"></android.support.v4.view.PagerTabStrip>
instead of
<android.support.v4.view.PagerTitleStrip
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:layout_gravity="top"
android:background="#color/material_deep_teal_500"
android:id="#+id/tabtitle"
style="#style/pagertitlestrip">
The PageTabStrip worked for me.
I'm working on an Android App and I want to use 3 tabs for navigation using Fragments for each tab, but I don't know how to create the structure for doing it.
I want to add each fragment separately because each one is different, but I don't know where to add them in FragmentActivity.
I have these files.
tabs_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<TabHost android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TabWidget
android:id="#android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="#+id/tabRateAPet"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<FrameLayout
android:id="#+id/tabViewMyRates"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<FrameLayout
android:id="#+id/tabViewGlobalRates"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>
TabsMain.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
public class MainTabsActivity extends FragmentActivity {
public static final String RATE_A_PET = "Rate a Pet";
public static final String MY_RATES = "My Rates";
public static final String GLOBAL_RATES = "Global Rates";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs_layout);
}
}
Tabs.java
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;
public class Tabs extends Fragment implements OnTabChangeListener {
private static final String TAG = "FragmentTabs";
public static final String RATE_A_PET = "Rate a Pet";
public static final String MY_RATES = "My Rates";
public static final String GLOBAL_RATES = "Global Rates";
private View mRoot;
private TabHost mTabHost;
private int mCurrentTab;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// super.onCreateView(inflater, container, savedInstanceState);
mRoot = inflater.inflate(R.layout.tabs_layout, null);
mTabHost = (TabHost) mRoot.findViewById(android.R.id.tabhost);
setupTabs();
return mRoot;
}
private void setupTabs() {
mTabHost.setup(); // important!
mTabHost.addTab(newTab(RATE_A_PET, R.string.tabRateAPet, R.id.tabRateAPet));
mTabHost.addTab(newTab(MY_RATES, R.string.tabViewMyRates, R.id.tabViewMyRates));
}
private TabSpec newTab(String tag, int labelId, int tabContentId) {
Log.d(TAG, "buildTab(): tag=" + tag);
View indicator = LayoutInflater.from(getActivity()).inflate(
R.layout.tab,
(ViewGroup) mRoot.findViewById(android.R.id.tabs), false);
((TextView) indicator.findViewById(R.id.text)).setText(labelId);
TabSpec tabSpec = mTabHost.newTabSpec(tag);
tabSpec.setIndicator(indicator);
tabSpec.setContent(tabContentId);
return tabSpec;
}
#Override
public void onTabChanged(String tabId) {
Log.d(TAG, "onTabChanged(): tabId=" + tabId);
if (RATE_A_PET.equals(tabId)) {
updateTab(tabId, R.id.tabRateAPet);
mCurrentTab = 0;
return;
}
if (MY_RATES.equals(tabId)) {
updateTab(tabId, R.id.tabViewMyRates);
mCurrentTab = 1;
return;
}
if (GLOBAL_RATES.equals(tabId)) {
updateTab(tabId, R.id.tabViewGlobalRates);
mCurrentTab = 2;
return;
}
}
private void updateTab(String tabId, int placeholder) {
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag(tabId) == null) {
fm.beginTransaction()
.replace(placeholder, new RateMyPetActivity(), tabId)
.commit();
}
}
}
I would suggest creating a separate fragment file for each tab. I recently did this as well, so I have outlined my code below:
Layout Files
activity_main.xml
<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
tab1_view.xml //add your respective tab layouts using this format (make sure to change string variables)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".DeviceFragment" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tab1_fragment_string" />
</LinearLayout>
SRC Files
MainActivity.java //notice that in the .addTab process I only used text. You can also add icons using drawables that you would need to add to your hdpi folder. I also only created three tabs in this example.
package com.example.applicationname;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
public class MainActivity extends FragmentActivity {
// Fragment TabHost as mTabHost
private FragmentTabHost mTabHost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Tab1"),
Tab1Fragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Tab2"),
Tab2Fragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("Tab3"),
Tab3Fragment.class, null);
}
}
Tab1Fragment.java //once again replicate for desired number of tabs
package com.example.applicationname;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Tab1Fragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View V = inflater.inflate(R.layout.tab1_view, container, false);
return V;
}
}
Make sure that your R.java and strings.xml files are properly set up, and then your tabs should be up and running.
TabHost doesn't retains Fragment's states. So why using TabHost?
So use ViewPager with TabLayout instead.
Prons of Viewpager over Tabhost:
ViewPager retains Fragments states. Mean Fragment will not again recreated if switched.
Inbuilt swiping feature that gives user smoother experience.
Less CPU consumption, because Tabhost recreates Fragment/Activity again and again when Tab is switched.
See the difference :
Using Tablayout + ViewPager (Supports swipe, retains Fragments states
Using TabHost (Doesn't support swipe, doesn't retain states)
Small Code for Tablayout + ViewPager
// find views by id
ViewPager viewPager = findViewById(R.id.viewpager);
TabLayout tabLayout = findViewById(R.id.tablayout);
// attach tablayout with viewpager
tabLayout.setupWithViewPager(viewPager);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
// add your fragments
adapter.addFrag(new SampleFragment(), "Tab1");
adapter.addFrag(new SampleFragment(), "Tab2");
adapter.addFrag(new SampleFragment(), "Tab3");
// set adapter on viewpager
viewPager.setAdapter(adapter);
XML layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Note If you are not using AndroidX yet, you need to change following in layout.
Change com.google.android.material.tabs.TabLayout to android.support.design.widget.TabLayout
Chagne androidx.viewpager.widget.ViewPager to android.support.v4.view.ViewPager
But I'll strongly recommend to migrate to AndroidX, see #this answer to understand why.
And this is common ViewPagerAdapter for all your Viewpager in app.
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
public void addFrag(Fragment fragment) {
mFragmentList.add(fragment);
mFragmentTitleList.add("");
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
Important Related Links
Difference between getSupportFragmentManager() and getChildFragmentManager()?
getSupportFragmentManager() versus getFragmentManager() in android 3.0+
Difference between FragmentPagerAdapter and FragmentStatePagerAdapter