Fragment Tabs not using all space - android

I'm trying to convert my activity app into a fragment following this tutorial :
http://www.exoguru.com/android/material-design/navigation/material-design-tabs-with-fragments
As I will use only two tabs, I have made this change to BlankFragment
public class BlankFragment extends Fragment {
private PagerSlidingTabStrip tabs;
private static ViewPager viewPager;
private final int int_items = 2;
public BlankFragment() { // Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View x = inflater.inflate(R.layout.fragment_blank, container, false);
tabs = (PagerSlidingTabStrip) x.findViewById(R.id.tab_strip);
viewPager = (ViewPager) x.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabs.post(new Runnable() {
#Override
public void run() {
tabs.setViewPager(viewPager);
}
});
int[][] tabStates = new int[][] {
new int[] { android.R.attr.state_pressed}, // enabled
new int[] { android.R.attr.state_selected}, // unchecked
new int[] { -android.R.attr.state_selected}
};
int[] tabColors = new int[] {R.color.colorAccent,R.color.colorAccent,R.color.colorAccent};
ColorStateList tabList = new ColorStateList(tabStates, tabColors);
tabs.setTextColor(tabList); // Setting the Tab Text Color
return x;
}
public class MyAdapter extends FragmentPagerAdapter { // Tab Adapter
public MyAdapter(FragmentManager fm) { super(fm); }
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new Tab1();
case 1 : return new Tab2();
}
return null;
}
#Override
public int getCount() { return int_items; }
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "Temps ";
case 1 :
return "Vetement ";
}
return null;
}
}
}
The thing is that I get this result :
As you can see the tabs text is not using all the space like this :
https://raw.githubusercontent.com/joseedwin84/Android-Sliding-Tabs-With-Material-Design/master/tabpic.png
So what does I need to change ?
I tried to check layout and they are all set to match_parent width.
So now I don't know where to look.
If someone can help me, It would be great.

You have to set the tabGravity to fill and tabMode to fixed of your TabLayout.
Either in xml
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tabLayout"
app:tabGravity="fill"
app:tabMode="fixed" />
Or you can do it in java
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);

Thanks I'm not using TabLayout but a PagerSlidingTabStrip, and with your answer I found in the documentation that it was a layout problem I should use app:shouldExpand="true"

Related

How to set selected tab job in on create [duplicate]

This question already has answers here:
ViewPager set current page programmatically
(3 answers)
Closed 4 years ago.
I have 3 tabs containing difference Fragments as:
Product and Services
Business Directory
Job
Bellow is my TabFragement Adapter The code is worked correctly but only 1 thing I want is:
=> I want to set Job Fragment as default in onCreate
This is my adapter.
public class TabFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 3 ;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View x = inflater.inflate(R.layout.tab_layout,null);
tabLayout = (TabLayout) x.findViewById(R.id.tabs);
viewPager = (ViewPager) x.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return x;
}
class MyAdapter extends FragmentPagerAdapter{
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new Product_Service();
case 1 : return new Business_Dir();
case 2 : return new Job();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "Product & Srevices";
case 1 :
return "Business Directory";
case 2 :
return "Job";
}
return null;
}
}
}
You can use the fragment position index to show particular fragment as default using setCurrentItem method ofViewPager docs. Do this after setting adapter on viewpager
viewPager.setCurrentItem(2, false); // job fragment index is 2
false here mean , the transition to fragment 3 will be done instantly and if you pass true then chosen fragment will be displayed using scrolling effects ( you can use true when you want to give a little tour to user for first time)

Changing tabs of TabLayout programmatically but fragments of ViewPager is not updated

I am developing an Android app. In my app, I am using TabLayout with ViewPager. I need to update the Tabs of TabLayout and its fragments programmatically when an item at the bottom navigation bar is selected. I can update the tabs of TabLayout. But the fragments of pager are not updated.
This is the issue:
As you can see in the above, tabs are changed but its fragments are not changed. List Fragment is always displayed. All the fragments are just the same with the first tab selected. I mean fragments are not changing at all.
This is my XML file for the tabs and view pager:
<android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.TabLayout
android:id="#+id/ma_tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:id="#+id/ma_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
This is my whole activity:
public class MainActivity extends AppCompatActivity {
private BottomBar bottomBar;
private TabLayout topTabLayout;
private ViewPager mainViewPager;
private MainPagerAdapter pagerAdapter;
private ArrayList<Fragment> pagerFragments;
private ArrayList<String> pagerTitleList;
protected TfrApplication app;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = (TfrApplication)getApplication();
setContentView(R.layout.activity_main);
initialize();
initViews();
setUpViews();
}
private void initialize()
{
pagerFragments = new ArrayList<Fragment>();
pagerTitleList = new ArrayList<String>();
}
private void initViews()
{
bottomBar = (BottomBar)findViewById(R.id.ma_bottom_action_bar);
mainViewPager = (ViewPager)findViewById(R.id.ma_viewpager);
topTabLayout = (TabLayout)findViewById(R.id.ma_tab_layout);
}
private void setUpViews()
{
pagerAdapter = new MainPagerAdapter(getSupportFragmentManager(),pagerFragments,pagerTitleList);
mainViewPager.setAdapter(pagerAdapter);
topTabLayout.setupWithViewPager(mainViewPager);
setUpBottomBar();
}
private void clearPagerFragments()
{
if(pagerAdapter!=null && pagerFragments!=null && pagerFragments.size()>0)
{
pagerFragments.removeAll(pagerFragments);
pagerTitleList.removeAll(pagerTitleList);
pagerAdapter.notifyDataSetChanged();
}
}
private void setUpNewsPagerFragments()
{
NewsFragment latestNewsFragment = new NewsFragment();
Bundle latestNewsBundle = new Bundle();
latestNewsBundle.putInt(NewsFragment.FIELD_CATEGORY_ID,0);
latestNewsBundle.putInt(NewsFragment.FIELD_LEAGUE_ID,0);
latestNewsBundle.putInt(NewsFragment.FIELD_COUNTRY_ID,0);
latestNewsBundle.putInt(NewsFragment.FIELD_TEAM_ID,0);
latestNewsFragment.setArguments(latestNewsBundle);
pagerTitleList.add("LATEST");
pagerFragments.add(latestNewsFragment);
PrioritizedTeamsFragment teamsFragment = new PrioritizedTeamsFragment();
pagerTitleList.add("TEAMS");
pagerFragments.add(teamsFragment);
NewsFragment articlesFragment = new NewsFragment();
Bundle articlesBundle = new Bundle();
articlesBundle.putInt(NewsFragment.FIELD_CATEGORY_ID, 0);
articlesBundle.putInt(NewsFragment.FIELD_LEAGUE_ID, 0);
articlesBundle.putInt(NewsFragment.FIELD_COUNTRY_ID, 0);
articlesBundle.putInt(NewsFragment.FIELD_TEAM_ID, 0);
articlesFragment.setArguments(articlesBundle);
pagerTitleList.add("ARTICLES");
pagerFragments.add(articlesFragment);
TopFragment topFragment = new TopFragment();
pagerTitleList.add("TOP 10");
pagerFragments.add(topFragment);
}
private void setUpMatchesPagerFragments()
{
MatchesFragment matchesFragment = new MatchesFragment();
pagerTitleList.add("MATCHES");
pagerFragments.add(matchesFragment);
StatisticsFragment statisticsFragment = new StatisticsFragment();
pagerTitleList.add("STATISTICS");
pagerFragments.add(statisticsFragment);
}
private void setUpBottomBar()
{
bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(int tabId) {
switch (tabId){
case R.id.bottom_tab_news:
clearPagerFragments();
setUpNewsPagerFragments();
pagerAdapter.notifyDataSetChanged();
break;
case R.id.bottom_tab_matches:
clearPagerFragments();
setUpMatchesPagerFragments();
pagerAdapter.notifyDataSetChanged();
topTabLayout.getTabAt(0).select();
break;
case R.id.bottom_tab_meme:
Toast.makeText(getBaseContext(),"MEME",Toast.LENGTH_SHORT).show();
break;
case R.id.bottom_tab_settings:
Toast.makeText(getBaseContext(),"Settings",Toast.LENGTH_SHORT).show();
break;
}
}
});
}
}
I showed the whole activity because code the whole activity dealing with that problem. Besides, the whole activity only contains code for creating tabs, view pager and bottom bar. All are connected.
This is my view pager adapter:
public class MainPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragmentList;
private ArrayList<String> titleList;
public MainPagerAdapter(FragmentManager fragmentManager,ArrayList<Fragment> fragmentsParam,ArrayList<String> titlesParam)
{
super(fragmentManager);
this.fragmentList = fragmentsParam;
this.titleList = titlesParam;
}
#Override
public int getCount() {
return fragmentList.size();
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}
}
Why is the content or fragments of view pager are not changed when tabs are changed? What is wrong with my code?
As you can see on bottom item selected listener I tried to set the selected fragment like this:
topTabLayout.getTabAt(0).select();
I tried this as well:
mainViewPager.setCurrentItem(0);
Both are not working.
try to add a method to swap the fragment-list and call notifyDataSetChanged() in your adapter like this:
public void notifyDataSetChanged(List<Fragment> list) {
fragmentList.removeAll();
fragmentList.addAll(list);
notifyDataSetChanged();
}
changing data in activity and call adapter.notifyDataSetChanged() may fail to update your view.You can log in getItem() to check if the adapter knows the data set has changed.
Just Check which layout you are inflating in MatchesFragment class.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
v = inflater.inflate(R.layout.matches_fragment, container, false);
}
If your tab is set correctly, under the code where the tab is set, run this again:
mainViewPager.setAdapter(pagerAdapter);
Here is my code:
selectedTab = 0;
tabLayout.getTabAt(selectedTab).select();
viewPager.setAdapter(tabsAdapter);

SlidingTabLayout and Actionbar title

I'm using a SlidingTabLayout (from the Google sources) in my app to navigate between different fragments.
I can swipe between contents just fine, but the problem I'm facing is the title of the Action bar that is acting weird.
Suppose that I have two tabs with two titles ('First Title' and 'Second Title') :
| Action bar |
| First Title | Second Title |
When I first enter the Fragment containing the SlidingTabLayout, the title of the Actionbar is like this :
| Firs... |
| First Title | Second Title |
When I swipe (to the second tab for example), the title of the actionbar becomes :
| Second Title |
| First Title | Second Title |
And stays like this. It seems that the Actionbar takes the title of the last Fragment loaded when I swipe at least once.
What I want is this :
I want to show a 'Main Title' in the Actionbar that never changes no matter what the title in the SlidingTabLayout is.
Here are some portions of my code:
** Fragment containing the SlidingTabLayout:
private String mainTitle;
....
#Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
// The mainTitle is given to this fragment by another fragment
Bundle args = getArguments();
if (args != null) {
mainTitle = args.getString("TITLE");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.layout, container, false);
mViewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
mSlidingLayout = (SlidingTabLayout) rootView.findViewById(R.id.sliding_layout);
List<Fragment> listFragments = new ArrayList<>();
List<String> listTitles = new ArrayList<>();
for (int i = 0; i < mSize; i++) {
Bundle bundle = new Bundle();
....
listFragments.add(Fragment.instanciate(getActivity(), CustomFragment.class.getName(), bundle));
listTitles.add("...");
}
mViewPager.setAdapter(new PagerAdapter(getChildFragmentManager(), listFragments, listTitles));
mSlidingLayout.setDistributedEvenly(true);
mSlidingLayout.setViewPager(mViewPager);
return rootView;
}
#Override
public void onResume() {
super.onResume();
// I TRY TO SET THE TITLE HERE !!
getActivity().getSupportActionBar().setTitle(mainTitle);
}
** Adapter:
class PagerAdapter extends FragmentPagerAdapter {
List<Fragment> fragments;
List<String> titles;
...
#Override
public Fragment getItem(int position) {
Fragment fragment = fragments.get(position);
return fragment;
}
#Override
public CharSequence getPageTitle(int position) {
// maybe the problem is in this method.
// this method is supposed to provide the titles for the tab
// but maybe it's also changing the actionbar title
return titles.get(position);
}
I'm setting the title of the ActionBar in the onResume method every time I enter a Fragment.
Thanks !
EDIT 1 :
I tried using the new SlidingTabLayout which I've got from the Google I/O, and the result is still the same !
It seems that the Title in the ActionBar is a hint at first, and then it changes to the last loaded fragment when I swipe to another fragment.
It's like it's loading fragment, and each time a fragment is loaded, the title in the ActionBar is overridden with the title of that fragment.
EDIT 2 :
I changed my code to post the latest version of it (I'm using now a SlidingTabLayout) and to show how I get my mainTitle.
you can use below code it works fine for me
public class MatchesActivity extends AppCompatActivity implements ActionBar.TabListener {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
FloatingActionButton skipButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_matches);
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
skipButton = (FloatingActionButton) findViewById(R.id.skip_next);
skipButton.setVisibility(View.GONE);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOffscreenPageLimit(1);
mViewPager.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
actionBar.addTab(
actionBar.newTab().setText("MATCHES")
.setTabListener(this));
actionBar.addTab(
actionBar.newTab().setText("PINS")
.setTabListener(this));
actionBar.addTab(
actionBar.newTab().setText("CHATS")
.setTabListener(this));
}
#Override
public void onBackPressed() {
startActivity(new Intent(MatchesActivity.this, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK & Intent.FLAG_ACTIVITY_CLEAR_TOP));
MatchesActivity.this.finish();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new MatchesFragment();
case 1:
return new PinsFragment();
case 2:
return new ConversationFragment();
default:
return new MatchesFragment();
}
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
}
I am posting here a code of mine.It worked for me.Make required changes in it and try it.I used PagerSlidingTabStrip library in it.
public class DealFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_deal, container, false);
ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewpager);
viewPager.setAdapter(new SampleFragmentPagerAdapter(getChildFragmentManager()));
PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip)view.findViewById(R.id.tabs);
tabsStrip.setBackgroundColor(Color.parseColor("#333333"));
// Attach the view pager to the tab strip
tabsStrip.setViewPager(viewPager);
return view;
}
public class SampleFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 2;
private final String tabTitles[] = new String[] { "Today's Deals", "Deals Close By" };
public SampleFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
if(position==0)
{
return new TodaysDeal();
}
else
{
return new DealsCloseBy();
}
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
}
hope it might help you.
The actionBar title doesn't change because onResume() is not called the time you swipe back.
It's because ViewPager doesn't call fragment's onResume the second time. Even though in reality the fragment is resumed.
What you can do is to move the setting of your actionbar title in your parent fragment (that contains pagertabstrip) to onCreateView instead.
For your reference:
** Fragment containing the PagerTabStrip:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.layout, container, false);
mViewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
List<Fragment> listFragments = new ArrayList<>();
List<String> listTitles = new ArrayList<>();
...
// HERE's what you want
final ActionBar actionBar = getActivity().getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(R.string.main_title);
}
mViewPager.setAdapter(new PagerAdapter(getChildFragmentManager(), listFragments));
return rootView;
}
Found it !
It was really dumb of me (it explains why others didn't have this problem)
I was setting the title also in each of the Fragments (even those contained in the Tabs), so when I swiped, the onResume on those Fragments was called and it changed the title in the ActionBar...
Thank you all for the help, I appreciate it !

How to add image and text in sliding tab layout

I am using sliding tab layout in my application which only displays text but I want to add image in tab. I have found an example of slidingtablayout with image only but I want to add both image and text in tab.
Here is the code for ViewPagerAdapter class
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
int icon[];
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
this.icon = icon;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
switch (position) {
// Open FragmentTab1.java
case 0:
tab1 fragmenttab1 = new tab1();
return fragmenttab1;
// Open FragmentTab2.java
case 1:
tab2 fragmenttab2 = new tab2();
return fragmenttab2;
case 2:
tab3 fragment = new tab3();
return fragment;
}
return null;
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return NumbOfTabs;
}
}
code of Home class
public class Home extends Fragment {
ViewPager pager;
ViewPagerAdapter adapter;
SlidingTabLayout tabs;
CharSequence Titles[] = {"tab1", "tab2", "tab3"};
int Numboftabs = 3;
public Home() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.home, container, false);
((MainActivity) getActivity()).getSupportActionBar().setTitle("Home");
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getFragmentManager(), Titles, Numboftabs);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) rootView.findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) rootView.findViewById(R.id.tabs);
tabs.setDistributeEvenly(false); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
return rootView;
}
XML code
<com.example.niroj.navigation.tab.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
android:background="#color/ColorPrimary"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1" >
</android.support.v4.view.ViewPager>
</LinearLayout>

Tablayout with icons only

I am using design support to create tabs. I am also using ViewPager for swipable tabs.
Now, I don't know how to use only icons instead of texts in tabs. I tried finding out but didn't get any success.
My code:
Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
setupViewPager(viewPager);
setupTablayout();
}
private void setupTablayout() {
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setupWithViewPager(viewPager);
}
class MyPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public MyPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
mFragmentTitleList.get(position)
}
}
private void setupViewPager(ViewPager viewPager) {
MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new frag(), "CAT");
adapter.addFrag(new frag(), "DOG");
adapter.addFrag(new frag(), "BIRD");
viewPager.setAdapter(adapter);
}
One approach is setting the icons after TabLayout.setupWithViewPager() method.
mTabLayout.setupWithViewPager(mViewPager);
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
mTabLayout.getTabAt(i).setIcon(R.drawable.your_icon);
}
The tutorial shown in the following link should cover what you want. https://github.com/codepath/android_guides/wiki/Google-Play-Style-Tabs-using-TabLayout#add-icons-to-tablayout
I copied the relevant section below.
Add Icons to TabLayout
Currently, the TabLayout class does not provide a clean abstraction model that allows for icons in your tab. There are many posted workarounds, one of which is to return a SpannableString, containing your icon in an ImageSpan, from your PagerAdapter's getPageTitle(position) method as shown in the code snippet below:
private int[] imageResId = {
R.drawable.ic_one,
R.drawable.ic_two,
R.drawable.ic_three
};
// ...
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
// return tabTitles[position];
Drawable image = context.getResources().getDrawable(imageResId[position]);
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
SpannableString sb = new SpannableString(" ");
ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
By default, the tab created by TabLayout sets the textAllCaps property to be true, which prevents ImageSpans from being rendered. You can override this behavior by changing the tabTextAppearance property.
<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
<item name="tabTextAppearance">#style/MyCustomTextAppearance</item>
</style>
<style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
<item name="textAllCaps">false</item>
</style>
In new version of TabLayout, google added TabItem which easily can add Icon through your XML with following code:
<android.support.design.widget.TabLayout
app:tabTextColor="#color/gray"
app:tabMode="fixed"
app:tabBackground="#color/red"
app:tabIndicatorHeight="4dp"
app:tabIndicatorColor="#color/purple"
app:tabPadding="2dp"
app:tabSelectedTextColor="#color/white"
app:tabMinWidth="64dp"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<!--add height and width to TabItem -->
<android.support.design.widget.TabItem
android:text="#string/tab_text"/>
<android.support.design.widget.TabItem
android:icon="#drawable/ic_android"/>
</android.support.design.widget.TabLayout>
See more here.
try this
public class GlobalActivity extends AppCompatActivity {
Toolbar toolbar;
ViewPager viewPager;
TabLayout tabLayout;
ViewPagerAdapter adapter;
private int[] tabIcons = {
R.drawable.home_ic,
R.drawable.biz_ic,
R.drawable.network_ic,
R.drawable.offers_ic,
R.drawable.message_ic_b
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_global_hub);
tab();
}
public void tab(){
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);
tabLayout.getTabAt(3).setIcon(tabIcons[3]);
tabLayout.getTabAt(4).setIcon(tabIcons[4]);
}
public void setupViewPager(ViewPager viewPager){
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new GlHubFragment(),"HOME");
adapter.addFrag(new BizForumFragment(), "BIZ FORUM");
adapter.addFrag(new NetworkFragment(), "NETWORK");
adapter.addFrag(new MessagesFragment(), "MESSAGEs");
adapter.addFrag(new OfferFragmentActivity(), "OFFER");
viewPager.setAdapter(adapter);
}
public class ViewPagerAdapter extends FragmentPagerAdapter{
private final List<Fragment> mfragmentlist =new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mfragmentlist.get(position);
}
#Override
public int getCount() {
return mfragmentlist.size();
}
public void addFrag(Fragment fragment,String title){
mfragmentlist.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position){
return mFragmentTitleList.get(position);
}
}
}
In TabLayout, setting icon is easy:
getPageTitle(position) should return null (if you don't want title to show).
Next :
tabLayout.getTabAt(0).setIcon(resId);
tabLayout.getTabAt(1).setIcon(resId);
......
None of these methods are elegant when using TabLayout as the ViewPager "decor" scenario. TabLayout Documentation Here is a simple extension of TabLayout and PagerAdapter that provides a simple drop in replacement for TabLayout that should be able to be used in either scenario without manually adding icons outside of the TabLayout class and following the usage of PagerAdapter to get the tab information.
/**
* Created by JDL on 1/18/2017.
*/
public class TabLayoutExt extends TabLayout {
protected ViewPager mViewPager;
public abstract static class TabLayoutViewPagerAdapter extends PagerAdapter {
public TabLayoutViewPagerAdapter() {
}
/**
* This method may be called by the TabLayout to obtain an icon drawable
* to for the specified tab. This method may return null
* indicating no tab icon for this page. The default implementation returns
* null.
*
* #param position The position of the title requested
* #return A drawable icon for the requested page
*/
public Drawable getPageIcon(Context context, int position) {
return null;
}
}
public TabLayoutExt(Context context) {
super(context);
}
public TabLayoutExt(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TabLayoutExt(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onAttachedToWindow() {
//Cover the implicit setup in TabLayout
if (mViewPager == null) {
final ViewParent vp = getParent();
if (vp instanceof ViewPager) {
mViewPager = (ViewPager)vp;
}
}
super.onAttachedToWindow();
}
public void addTab(#NonNull Tab tab, int position, boolean setSelected) {
if (mViewPager != null && mViewPager.getAdapter() instanceof TabLayoutViewPagerAdapter) {
Drawable icon = ((TabLayoutViewPagerAdapter) mViewPager.getAdapter()).getPageIcon(getContext(),position);
tab.setIcon(icon);
}
super.addTab(tab,position,setSelected);
}
#Override
public void setupWithViewPager(#Nullable ViewPager viewPager, boolean autoRefresh) {
mViewPager = viewPager;
super.setupWithViewPager(viewPager, autoRefresh);
}
}
So all that needs be done is extend TabLayoutViewPagerAdapter instead of PageAdapter and implement getPageIcon(Context,int) instead of or in addition to title. The drop in TabLayoutExt in your XML file, instead of the normal TabLayout. This could be extended for further modifying the tab, either with a custom view instead or something else.
With the TabLayout provided by the Material Components Library you can use:
the method setIcon to define the resourceId
the method setTabLabelVisibility to set the TAB_LABEL_VISIBILITY_UNLABELED.
Something like:
for (int i=0;i<tabLayout.getTabCount();i++){
tabLayout.getTabAt(i).setIcon(iconResId);
tabLayout.getTabAt(i).
setTabLabelVisibility(TabLayout.TAB_LABEL_VISIBILITY_UNLABELED);
}
The easiest way I've found to use icons is to use Tablayout.Tab.setIcon(drawable). This also makes it easy to highlight the selected icon. If you want to do this, follow these steps.
Step 1.
Add your images to the res.mipmap folders. (mipmap-mdpi, hdpi etc.) Judging by the other answers here it's also fine to put then in the res.drawable folders.
Step 2.
Call setIcon on all your tabs after setting up your TabLayout and ViewPager. I did this in my AdapterTabs to keep the Activity tidy.
So in your activity do this:
tablayout = (TabLayout) findViewById(R.id.tab_layout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
adapterTabs = new AdapterTabs(this, getSupportFragmentManager(), fragments, tablayout, viewPager);
viewPager.setAdapter(adapterTabs);
tablayout.setupWithViewPager(viewPager);
adapterTabs.setTabIcons();
and in your AdapterTabs, which should extend FragmentPagerAdapter, put your setTabIcons() method.
public void setTabTitlesToIcons() {
Drawable icon1 = context.getResources().getDrawable(R.mipmap.ic_1);
Drawable icon2 = context.getResources().getDrawable(R.mipmap.ic_2);
Drawable icon3 = context.getResources().getDrawable(R.mipmap.ic_3);
Drawable icon1Hilighted = context.getResources().getDrawable(R.mipmap.ic_1_selected);
Drawable icon2Hilighted = context.getResources().getDrawable(R.mipmap.ic_2_selected);
Drawable icon3Hilighted = context.getResources().getDrawable(R.mipmap.ic_3_selected);
icons.add(icon1);
icons.add(icon2);
icons.add(icon3);
iconsHilighted.add(icon1Hilighted);
iconsHilighted.add(icon2Hilighted);
iconsHilighted.add(icon3Hilighted);
for(int i = 0; i < icons.size(); i++) {
if(i == 0) {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(iconsSelected.get(i));
}
else {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(icons.get(i));
}
}
}
Make sure to store a reference to the two lists 'icons' and 'iconsHilighted'. You'll need them later. Also store a reference to the TabLayout and the ViewPager which you passed in from the activity.
Step 3.
Make sure AdapterTabs.getPageTitle() returns null.
At this point, if you run it you should see that the first icon is highlighted.
Step 4.
Implement ViewPager.OnPageChangeListener in AdapterTabs and add that listener to your viewPager
public AdapterTabs(Context context, FragmentManager fragmentManager, List<Fragment> fragments, TabLayout tabLayout, ViewPager viewPager) {
super(fragmentManager);
this.context = context;
this.tabLayout = tabLayout;
this.viewPager = viewPager;
this.viewPager.addOnPageChangeListener(this);
tabs.add(fragments.get(0));
tabs.add(fragments.get(1));
tabs.add(fragments.get(2));
}
Step 5.
Update the icons in the tabs in the onPageSelected callback in your AdapterTabs.
#Override
public void onPageSelected(int position) {
for (int i = 0; i < tabs.size(); i++) {
if(i == position) {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(iconsSelected.get(i));
}
else {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(icons.get(i));
}
}
}
Now you should see the hilighted icon being updated when you change tabs.
Try this this will definitely work .
private TabLayout tabLayout;
private ViewPager viewPager;
private int[] tabIcons = {
R.drawable.single,
R.drawable.multiple};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_picker);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("Choose contact");
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
tab();
}
public void tab(){
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Login());
adapter.addFragment(new Register());
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = 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();
}
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
}
}
As mentioned in the comments, defining the icons in the TabLayout does not work when using a PagerAdapter. For those using Kotlin, one workaround is to create an extension function like this:
fun TabLayout.setupWithViewPagerAndKeepIcons(viewPager : ViewPager?) {
val icons = mutableListOf<Drawable?>()
repeat(tabCount) {
icons.add(getTabAt(it)?.icon)
}
setupWithViewPager(viewPager)
repeat(tabCount) {
getTabAt(it)?.setIcon(icons.get(it))
}
}
Then in the layout.xml add your icons to the TabLayout:
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout">
<com.google.android.material.tabs.TabItem
android:icon="#drawable/your_icon"/>
</com.google.android.material.tabs.TabLayout>
Finally, use the extension function to setup the TabLayout with a ViewPager.
tab_layout.setupWithViewPagerAndKeepIcons(view_pager)
the simplest way is create new table by setting Icon on tablayout. below code will create two tab with icon only. use this code on onCreate() method
tablayout = (TabLayout) findViewById(R.id.order_tablayout);
tablayout.addTab( tablayout.newTab().setIcon(getResources().getDrawable(R.mipmap.ic_shopping_cart_white_24dp)) );
tablayout.addTab( tablayout.newTab().setIcon(getResources().getDrawable(R.mipmap.ic_like2_fille_white_24dp)) );
Using a ViewPager. This is how I have a tab with an icon only and no text.
TabLayout tabs...
TabLayout.Tab tab = tabs.getTabAt(0);
tab.setText("");
tab.setIcon(R.drawable.yourIcon);
This may not be the best answer for all cases, but what I found did not solve my problem yet.
After having a look at Androids implementation of tabLayout.setupWithViewPager(ViewPager pager) I came up with a solution using just listeners.
The layout structure:
| LinearLayout (vertical)
|-- TabLayout (width: match_parent)
|---- TabItem (without text, just icons)
|---- TabItem
|---- ...
|-- ViewPager
Code for the both listeners:
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
pager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
tabLayout.setScrollPosition(position, positionOffset, false);
}
#Override
public void onPageSelected(int position) {
TabLayout.Tab tab = tabLayout.getTabAt(position);
if (tab != null) {
tab.select();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Have a look at the tabLayout.setScrollPosition call inside OnPageChangeListener.onPageScrolled for the more or less good moving of the indicator while scrolling.
This may not work if the TabLayout's width is not set to match_parent (or must be scrollable).

Categories

Resources