I want to design my tabitems from a tablayout, but the tabs are not made in my .xml file. I don't know exactly where my tabs get generated, but it looks like it happens in a adapter
Normally you would make a drawable to design views like buttons, but can I do this also for tabs in a tabLayout?
My MainActivity doesn't create tabItems on startup, and I'm only gathering the data for the fragments here
#Override
protected void onCreate(Bundle savedInstance)
{
super.onCreate(savedInstance);
recentCardItems = new ArrayList<>();
followingCardItems = new ArrayList<>();
//This method sets the views in the abstract class DrawerLayoutActivity
setMenuLayoutElements(R.layout.activity_main, R.id.toolbar_main, R.id.drawer_layout_main);
setCardAdapterToReviewList();
configureFireStoreToLoadNewReviewsIntoList();
}
My adapter class, with the tabs "All" and "Following"
final int PAGE_COUNT = 2;
private String tabTitles[] = new String[] { "All", "Following" };
private Context context;
private List<CardItem> cardItemsRecent;
private List<CardItem> cardItemsFollowing;
private RecyclerViewFragment fragmentRecent;
private RecyclerViewFragment fragmentFollowing;
public RecyclerFragmentAdapter(FragmentManager fm, Context context, List<CardItem> cardItemsRecent, List<CardItem> cardItemsFollowing) {
super(fm);
this.context = context;
this.cardItemsRecent = cardItemsRecent;
this.cardItemsFollowing = cardItemsFollowing;
this.fragmentRecent = RecyclerViewFragment.newInstance(cardItemsRecent, R.layout.fragement_recyclerview_home, R.id.recyclerView);
this.fragmentFollowing = RecyclerViewFragment.newInstance(cardItemsFollowing, R.layout.fragment_recyclerview_following, R.id.reyclerViewFollowing);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
Fragment fragmentToReturn;
switch (position)
{
case 0:
fragmentToReturn = fragmentRecent;
break;
case 1:
fragmentToReturn = fragmentFollowing;
break;
default:
fragmentToReturn = null;
}
return fragmentToReturn;
}
//this getPageTitle method seems like it generates the titles of my tabs
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
public RecyclerViewFragment getFragmentRecent() {
return fragmentRecent;
}
public RecyclerViewFragment getFragmentFollowing() {
return fragmentFollowing;
}
As shown here my xml.file doesn't have tabitems
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
Also here in this image you can see it
I'm expecting a tabitem which I can give an #drawable shape, so it has a custom made layout, like a white background or something.
This is what my MainActivity shows at the moment
you can directly add tabs to tablayout using addTab method.
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.addTab(new TabLayout.newTab().setText("All"));
tabLayout.addTab(new TabLayout.newTab().setText("Following"));
Related
I try to populate a TabLayout with a ViewPager but unfortunately it doesn't get populated.
I followed this tutorial to get in touch: TabLayout and ViewPager in your Android App. The tutorial uses the old Support Library v4. My project is based on AndroidX and i want to stay with it. The official documentation of TabLayout said that I need to create the TabLayout inside the ViewPager but that's not working at all. So i created the following XML layout file:
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primaryColor"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabTextColor="#color/primaryTextColor" />
</androidx.viewpager.widget.ViewPager>
</LinearLayout>
I setup the ViewPager with the following lines to connect TabLayout with ViewPager:
public class MyActivity extends AppCompatActivity {
...
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
...
// tab layout
ViewPager viewPager = findViewById(R.id.viewpager);
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(this, getSupportFragmentManager());
viewPager.setAdapter(adapter);
TabLayout tabLayout = findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
...
}
...
}
My Adapter is a FragmentPagerAdapter
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private Context context;
public MyFragmentPagerAdapter(Context context, FragmentManager fm) {
super(fm);
this.context = context;
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new MyFragment1();
} else {
return new MyFragment2();
}
}
#Override
public int getCount() {
return 2;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return context.getString(R.string.building);
case 1:
return context.getString(R.string.buff);
default:
return null;
}
}
}
One of my Fragments looks like this:
public class MyFragment1 extends Fragment {
public MyFragment () {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_building, container, false);
}
}
Here is a picture how it looks like:
Empty ViewPager
Question
So why is the TabLayout not populated at all? I'm working with Android Studio and the Design Manager just shows me an empty TabLayout and ViewPager. I guess, it would precompile the TabLayout but it is just empty...
Please help me because i stuck at this topic. I really want to code it like this to get benefit of swiping tabs and stuff.
Thanks a lot!
Here is an example from one of my projects .Create and populate ViewPager, something like this:
<androidx.viewpager.widget.ViewPager
android:id="#+id/loginViewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/loginTitle">
<com.google.android.material.tabs.TabLayout
android:id="#+id/loginTabContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
app:tabIndicatorColor="#color/colorPrimary"
app:tabRippleColor="#color/colorPrimary"
app:tabSelectedTextColor="#color/colorPrimaryDark"
app:tabTextAppearance="#style/TabLayoutTheme">
<com.google.android.material.tabs.TabItem android:text="first tab" />
<com.google.android.material.tabs.TabItem android:text="second tab" />
</com.google.android.material.tabs.TabLayout>
</androidx.viewpager.widget.ViewPager>
Then in your activity create a FragmentStatePagerAdapter to decide what to return in each page. my codes are in kotlin, but java version is the same:
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
override fun getCount(): Int = NUM_PAGES
override fun getItem(position: Int): Fragment = when (position) {
1 -> FirstFragment()
0 -> SecondFragment()
else -> FirstFragment()
}
override fun getPageTitle(position: Int): CharSequence? {
return when (position) {
0 -> "First Title"
1 -> "Second Title"
else -> "First Title"
}
}
}
And finally in your Activity:
val pagerAdapter = ScreenSlidePagerAdapter(supportFragmentManager)
loginViewPager.adapter = pagerAdapter
Put your TabLayout inside your ViewPager like below.
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#color/colorPrimaryDark"
app:tabGravity="fill"
app:tabIndicatorColor="#color/colorPrimaryLight"
app:tabMaxWidth="0dp"
app:tabMode="scrollable"
app:tabRippleColor="#color/colorPrimaryLight"
app:tabSelectedTextColor="#color/colorPrimaryLight"
app:tabTextColor="#android:color/white" />
</androidx.viewpager.widget.ViewPager>
make sure that android:layout_height of your TabLayout is set to wrap_content.
When you put your TabLayout inside your ViewPager, you don't need to keep below lines:
TabLayout tabLayout = findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
Everything else in your code is correct.
Also, now that I see your code, layout_height of your TabLayout is set to match_parent, so TabLayout is taking whole space in your screen, giving no height to ViewPager, also, in your XML, there is no container to hold your ViewPager and TabLayout (like LinearLayout, FrameLayout etc).
<android.support.design.widget.CoordinatorLayout 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.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"
app:tabGravity="fill"
style="#style/Base.Widget.Design.TabLayout"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
viewPager = (ViewPager)rootView. findViewById(R.id.viewpager);
ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager());
adapter.addFragment(new FragAllONE(), "ONE");
adapter.addFragment(new FragAllTWO(), "TWO");
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(1);
viewPager.setCurrentItem(0);
viewPager.addOnPageChangeListener(this);
tabLayout = (TabLayout)rootView. findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
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();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object object = super.instantiateItem(container, position);
if (object instanceof Fragment) {
Fragment fragment = (Fragment) object;
String tag = fragment.getTag();
}
return object;
}
public void restoreState(Parcelable state, ClassLoader loader) {
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
I found a solution on another thread Use Tab layout in MVVM architecture with the data binding library. I'm using Android Data Binding so the TabLayout wasn't assigned to the ViewPager. So my code was correct but not accordingly to the Data Binding.
Nevertheless, thanks for your posts here!
so i have the classic viewpager in a tablayout that looks something like this:
My viewPagerAdapter class looks like this:
public class HomePagerAdapter extends FragmentPagerAdapter {
int mNumOfTabs;
public HomePagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeFragment tab1 = new TabHomeFragment();
return tab1;
case 1:
TabShopFragment tab2 = new TabShopFragment();
return tab2;
case 2:
TabMeFragment tab3 = new TabMeFragment();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
So now on one of the tabs i need to add a fragment on top of it. so its a search fragment really. i do a search in the tab bar and i want the back end search results to appear in only ONE of the tabs (the first one). but i want the search results displayed in a fragment called searchFragmentResults and i want it to be laid out on top of the first tab. Then when user hits the back button it will just go back to the original content in the first tab. Is this possible with view pager ?
so visually when i hit the search icon on the first tabs tabBar it should bring up a searchView and when i search for the users query it should bring up a another fragment with the results but only in the tab that it started from. Here is an example:
i cant call fragtransaction.replace(somecontentview, somefragment); (or its add method) because i did not add them to a contentview. i let the viewpager do it for me. So how is this achieved ?
i figured out how to do this. The tab should be a fragment who's purpose is to only contain other fragments. the idea is based off of this SO. But i had a need to do it for a viewPager. Lets go through the steps. first the viewpager adapter:
public class HomePagerAdapter extends FragmentStatePagerAdapter {
//integer to count number of tabs
int tabCount;
private Fragment mCurrentFragment;
private String[] tabTitles = new String[]{"tab0", "tab1", "tab2", "tab3"};
//Constructor to the class
public HomePagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeContainerFragment tab1 = new Tab0ContainerFragment();
return tab1;
case 1:
TabShopFragment tab2 = new Tab1ContainerFragment();
return tab2;
case 2:
TabMeFragment tab3 = new Tab2ContainerFragment();
return tab3;
case 3:
TabBagFragment tab4 = new Tab3ContainerFragment();
return tab4;
default:
return null;
}
}
//Overriden method getCount to get the number of tabs
#Override
public int getCount() {
return tabCount;
}
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
//* this is key to get the current tab to pop the fragments afterwards**/
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
Lets go into a container to see how it would look:
add this to your xml for all the containers (along with anything else you want visually but they ALL must have the same id of container_framelayout:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="#+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" />
</android.support.design.widget.CoordinatorLayout>
you dont have to put it in a coordinatorLayout i just find it fixes some bugs and works well.
In your fragments base class i copied almost the same code from the SO i mentioned above but slight modification if you want to add tag or not:
public void replaceFragment(Fragment fragment, boolean addToBackStack,String tag) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment,tag);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
Now lets look at the activities layout:
<?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.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabTextColor="#color/black"
app:tabSelectedTextColor="#android:color/darker_gray"
/>
Now i'll show you how to set up the tablayout in the activity hosting the tablayout:
its standard:
public class HomePageActivity implements TabLayout.OnTabSelectedListener {
private final int NUM_OF_TABS = 4;
#BindView(R.id.pager)
public ViewPager viewPager;
public HomePagerAdapter adapter;
#BindView(R.id.tabLayout)
TabLayout tabLayout;
#NonNull
#Override
public HomePagePresenter createPresenter() {
return new HomePagePresenter();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homepage);
ButterKnife.bind(this);
initView();
}
private void initView() {
for (int i = 0; i < NUM_OF_TABS; i++)
tabLayout.addTab(tabLayout.newTab());
adapter = new HomePagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
//Adding adapter to pager
viewPager.setAdapter(adapter);
tabLayout.addOnTabSelectedListener(this);
tabLayout.setupWithViewPager(viewPager);
// configure tab icons
int[] imageTabResId = {
R.drawable.welcome1,
R.drawable.welcome2,
R.drawable.welcome3,
R.drawable.welcome1};
for (int i = 0; i < imageTabResId.length; i++) {
tabLayout.getTabAt(i).setIcon(imageTabResId[i]);
}
}
/** this is key. we get the current fragment showing and pop it **/
#Override
public void onBackPressed() {
boolean isPopFragment = false;
isPopFragment = ((BaseFragment) adapter.getCurrentFragment()).popFragment();
if (!isPopFragment) {
finish();
}
}
#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) {
}
}
I guess the major part is onBackPress getting the current fragment.
I have struggled in the past couple of days to find the solution to this problem:
I have one activity which contains a tab layout and a view pager. The view pager is filled with fragments using an adapter. Tabs are created with this viewpager and are fixed. My question is how can I change the layout of tabs dynamically (for example after a button click) ?
This is xml file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.Dark" />
<android.support.design.widget.TabLayout
android:id="#+id/tablayout"
android:layout_width="match_parent"
android:layout_height="65dp"
android:background="#color/white"
app:tabMode="fixed"
app:tabGravity="fill"
android:theme="#style/ThemeOverlay.AppCompat.Dark" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
This is Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupToolbar();
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout);
setupTabLayout(tabLayout);
}
private void setupToolbar(){
...
}
public void setupViewPager(ViewPager viewPager) {
pageAdapter = new FragmentPageAdapter(getApplicationContext(), getSupportFragmentManager());
pageAdapter.addFragment(ContentFragment.newInstance(), "Following", R.drawable.following);
pageAdapter.addFragment(ContentFragment.newInstance(), "Discover", R.drawable.flower);
pageAdapter.addFragment(ContentFragment.newInstance(), "", R.drawable.camera);
pageAdapter.addFragment(ProfileFragment.newInstance(), "Profile", R.drawable.profile);
pageAdapter.addFragment(ContentFragment.newInstance(), "Task List", R.drawable.list);
viewPager.setAdapter(pageAdapter);
}
public void setupTabLayout(TabLayout tabLayout) {
try {
tabLayout.setupWithViewPager(viewPager);
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
tab.setCustomView(pageAdapter.getTabView(i));
}
tabLayout.requestFocus();
}
catch(Exception ex){
Log.e("errr2", ex.getMessage());
}
}
This is adapter:
public class FragmentPageAdapter extends FragmentStatePagerAdapter {
private Context mContext;
private List<Fragment> mFragments = new ArrayList<>();
private List<String> mFragmentTitles = new ArrayList<>();
private List<Integer> mFragmentIcons = new ArrayList<>();
public FragmentPageAdapter(Context context, FragmentManager fm) {
super(fm);
this.mContext = context;
}
public void addFragment(Fragment fragment, String title, int drawable) {
mFragments.add(fragment);
mFragmentTitles.add(title);
mFragmentIcons.add(drawable);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getItemPosition(Object object)
{
return POSITION_UNCHANGED;
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitles.get(position);
}
public View getTabView(int position) {
View tab = LayoutInflater.from(mContext).inflate(R.layout.tabbar_view, null);
TextView tabText = (TextView) tab.findViewById(R.id.tabText);
ImageView tabImage = (ImageView) tab.findViewById(R.id.tabImage);
tabText.setText(mFragmentTitles.get(position));
tabImage.setBackgroundResource(mFragmentIcons.get(position));
if (position == 3) {
tab.setSelected(true);
}
return tab;
}
}
The normal way to replace a fragment is by calling
fragmentManager.beginTransaction().replace(placeholderId, editPrifileFragment).commit();
but what should I use for placeholderId in this case ? because in activity layout I don't have a placeholder for fragments, just a viewpager.
So how can I replace the fragment dynamically and also keep the back button functionality ?
I have searched a lot and found some hacky solutions , but I think this is a very common situation and should have a better solution.
thanks.
Your ViewPager Fragment should hold the placeholderId.
So in your Fragment (which is part of the ViewPager) you can call getChildFragmentManager() to add Fragment like you usually do.
childFragmentManager.beginTransaction().add(placeholderId, editPrifileFragment).addToBackStack(null).commit();
I am using https://github.com/astuetz/PagerSlidingTabStrip a navigation drawer(http://androidshenanigans.blogspot.com.es/2015/03/material-design-template.html).
When I put the fragment of the tabs in the navigation fragment I can not click on the tabs.
Also, when I add an item to fragment tab.It happens
the button is placed on top of the tab.If I do not navigation drawer, it works perfectly.
The code
AdapatadorTabs
public class AdapatadorTabs extends FragmentPagerAdapter {
final int PAGE_COUNT = 2;
private String tabTitles[] = new String[] { "Tab1", "Tab2" };
public AdapatadorTabs(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FragmentTab1();
case 1:
return new FragmentTab2();
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}}
FragmentTabGeneral
public class FragmentTabGeneral extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
private ViewPager viewPager;
public FragmentTabGeneral() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_telefonos, container, false);
// Get the ViewPager and set it's PagerAdapter so that it can display items
viewPager = (ViewPager)view.findViewById(R.id.pager);
viewPager.setAdapter(new AdapatadorTabs(getChildFragmentManager()));
// Give the PagerSlidingTabStrip the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip)view.findViewById(R.id.tabs);
// Attach the view pager to the tab strip
tabs.setViewPager(viewPager);
return view;
}}
FragmentTabGeneral XML
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/frameTabs"
tools:context="com.prueba.NavigationDrawer.Fragmentos.FragmentTabGeneral">
<com.astuetz.PagerSlidingTabStrip
android:id="#+id/tabs"
android:background="#ffff000c"
android:textColor="#ffffffff"
app:pstsIndicatorColor="#ffffffff"
app:pstsDividerColor="#ffff000c"
app:pstsIndicatorHeight="2dp"
app:pstsShouldExpand="true"
android:layout_width="match_parent"
android:layout_height="48dip" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/tabs"
tools:context=".MainActivity" /></FrameLayout>
the code navigation is the template, if you need him, you can ask him http://androidshenanigans.blogspot.com.es/2015/03/material-design-template.html
greetings and thanks!
I'm new to Android and therefore faced such problem.
How can I change layout from:
To:
XML fragment_main:
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.snbgearassistant.MainActivity$PlaceholderFragment" >
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
So I need these tabs having grid layout with different content.
You must use a GridView inside the ViewPager. So, in your MainActivity, you would have this layout.
Create the activity_main.xml layout
This is the main layout. Everything will live inside of it, including your fragments and tabs.
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.myapp.gridview.MainActivity" />
Create your MainActivity.java class
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener
{
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Here we load the xml layout we created above
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// 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.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
#Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++)
{
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
/**
* 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 new PlaceholderFragment();
}
#Override
public int getCount()
{
// Show 3 total pages.
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;
}
}
}
Don't forget to create your strings for these R.string.title_section1, ... strings on your code, or you will have an error.
Now we must create a layout for the fragment (the page that will be displayed inside the tab), and it must contain a GridView.
Create a fragment_main.xml layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:stretchMode="columnWidth"
android:numColumns="2" />
</FrameLayout>
Now let's define the fragment class that will take care of inflating this layout and handling the views.
Create a fragment to inflate the GridView layout: PlaceHolderFragment.java
/**
* A placeholder fragment containing a the gridview
*/
public 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() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Here we inflate the layout we created above
GridView gridView = (GridView) rootView.findViewById(R.id.gridview);
gridView.setAdapter(new MyAdapter(MainActivity.this.getApplicationContext()));
return rootView;
}
}
Now we must create an adapter class to handle each item of the GridView, this way you can manage the behavior of each one.
Create the Adapter to support the GridView items: MyAdapter.java
As you can see here, we are adding some items to the GridView by adding them to an ArrayList of the type Item defined in the end of the adapter class.
private class MyAdapter extends BaseAdapter
{
private List<Item> items = new ArrayList<Item>();
private LayoutInflater inflater;
public MyAdapter(Context context)
{
inflater = LayoutInflater.from(context);
items.add(new Item("Image 1", Color.GREEN));
items.add(new Item("Image 2", Color.RED));
items.add(new Item("Image 3", Color.BLUE));
items.add(new Item("Image 4", Color.GRAY));
items.add(new Item("Image 5", Color.YELLOW));
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int i)
{
return items.get(i);
}
#Override
public long getItemId(int i)
{
return items.get(i).colorId;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup)
{
View v = view;
ImageView picture;
TextView name;
if(v == null)
{
v = inflater.inflate(R.layout.gridview_item, viewGroup, false);
v.setTag(R.id.picture, v.findViewById(R.id.picture));
v.setTag(R.id.text, v.findViewById(R.id.text));
}
picture = (ImageView)v.getTag(R.id.picture);
name = (TextView)v.getTag(R.id.text);
Item item = (Item)getItem(i);
picture.setBackgroundColor(item.colorId);
name.setText(item.name);
return v;
}
private class Item
{
final String name;
final int colorId;
Item(String name, int drawableId)
{
this.name = name;
this.colorId = drawableId;
}
}
}
Now to make the GridView items keep with the correct width, aligned side by side, we use a custom class to define the measured dimension.
Why this needs to be done? According to #kcoppock's answer:
Basically, in Android's ImageView class, there's no way to simply specify "hey, keep a square aspect ratio (width / height) for this view" unless you hard code width and height. You could do some manual adjustment of LayoutParams in the adapter's getView, but frankly, it's much simpler to let ImageView handle all the measurements, and just override the results to say "Whatever the width ends up being, make my height stay the same". You never have to think about it, it's always square, and it just works as expected. Basically this is the easiest way to keep the view square.
Create a class SquareImageView.java
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class SquareImageView extends ImageView
{
public SquareImageView(Context context)
{
super(context);
}
public SquareImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
}
}
Now we must define the XML layout for the GridView items.
Create a XML layout gridview_item.xml
As you can see, here we add two items to the layout. One is a element of the type SquareImageView (the class we created above) and the TextView which is a label for each image.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.myapp.gridview.SquareImageView
android:id="#+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
/>
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:layout_gravity="bottom"
android:textColor="#android:color/white"
android:background="#55000000"
/>
</FrameLayout>
And here it is, I tested the code and this is the final result. Of course you would change those colors for your images, but this is the approach you should follow.
Note: To set images instead of colors to the GridView item, in your getView() method of the MyAdapter class use setImageResource(int) instead of setBackgroundColor(int).
Answer Given By rogcg is very good and nice. But the Images for each fragment is same. I like to add some codes in the mainactivity which has viewpager.I think we can use fragment instead of activity, Here is the code.The same code as the Main Activity given by rogcg. Add these codes too.
In Layout for mainfragment add ActionBarlayout,toolbar and slidingtablayout
In Mainfragment,add
private List<Fragment> mFragments = new Vector<Fragment>();
in oncreate(), create three fragments ,
mFragments.add(new HomeFragment());
mFragments.add(new Title1());
mFragments.add(new Title2());
mFragments.add(new Title3());
in onCreateView(),add
mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
tabLayout = (SlidingTabLayout) v.findViewById(R.id.tabanim_tabs);
tabLayout.setViewPager(mViewPager);
in SectionPageAdapter class,add
#Override
public Fragment getItem(int position) {
return mFragments.get(position+1);
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position)
{
case 0:
return getString(R.string.English).toUpperCase(l);
case 1:
return getString(R.string.Tamil).toUpperCase(l);
case 2:
return getString(R.string.Hindi).toUpperCase(l);
}
return null;
}
Now add any view in Title1() fragment as you usage and add any things in it I think this message was useful. please vote for me. Thank you.