What is the element that is used for Swarm Android app's actionbar?
I think it's neither the native android actionbar nor actionbarsherlock.
After using uiautomatorviewer, it can be seen that the base components were ImageButtons inside of a HorizontalScrollView for the left portion, and a LinearLayout with an ImageButton for the right portion.
However, this doesn't detail how to attain the sliding animation or how to space out the two functioning parts well.
I managed to recreate it using this fantastic library and a little massaging of views. Basically, you feed the Pager Sliding Tab Strip(PSTS) to the actionbar as a custom view.
//I call this in the onCreate()of my activity
void setupActionBar() {
ActionBar actionBar = getActionBar();
View vwActionBar = View.inflate(this, R.layout.action_bar_main, null);
tabs = (PagerSlidingTabStrip) vwActionBar.findViewById(R.id.tabs);
actionBar.setCustomView(vwActionBar);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
}
With the action_bar_main.xml being this
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.astuetz.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="wrap_content"
android:layout_height="?android:attr/actionBarSize"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
You also have to change how the FragmentPagerAdapter sets up the PSTS. The libraries samples hold a good example of how to do this, but here is mine.
public class MyPagerAdapter extends FragmentPagerAdapter
implements PagerSlidingTabStrip.IconTabProvider {
private final int[] ICONS = {
R.drawable.ic_home,
R.drawable.ic_dashboard,
R.drawable.ic_insights,
R.drawable.ic_stream
};
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return ICONS.length;
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
return fragments.get(position);
}
#Override public int getPageIconResId(int i) {
return ICONS[i];
}
}
Related
I have a working code for having 3 tabs, with 3 fragments that you can either horizontally swipe between to change, or you can click on the tab to go to the requested fragment.
However, I wanted to do some tweaks to my design, and I went over to the Android Developer's website: Creating swipe views with tabs
, and it looks completely different than mine. Now I wonder if I should use the code in the developer's website, or keep my own.
Right now I am using ViewPager + TabLayout.
So simple, yet working.
This also makes me wonder, how come this simple code works, but in the official documentation there's a long story. It just makes me think that if I keep my code in the current design, I might encounter some big problems in the future.
Or - if it works - then it works?
MainActivity.java:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find the view pager that will allow the user to swipe between fragments
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
// Create an adapter that knows which fragment should be shown on each page
TabsAdapter adapter = new TabsAdapter(this, getSupportFragmentManager());
// Set the adapter onto the view pager
viewPager.setAdapter(adapter);
// Find the tab layout that shows the tabs
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
// Connect the tab layout with the view pager. This will
// 1. Update the tab layout when the view pager is swiped
// 2. Update the view pager when a tab is selected
// 3. Set the tab layout's tab names with the view pager's adapter's titles
// by calling onPageTitle()
tabLayout.setupWithViewPager(viewPager);
}
}
TabsAdapter.java:
public class TabsAdapter extends FragmentPagerAdapter {
/** Context of the app */
private Context mContext;
public TabsAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
/**
* Return the {#link Fragment} that should be displayed for the given page number.
*/
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new NbFragment();
} else if (position == 1) {
return new LksFragment();
} else {
return new ChtFragment();
}
}
/**
* Return the total number of pages.
*/
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return mContext.getString(R.string.category_nb);
} else if (position == 1) {
return mContext.getString(R.string.category_lks);
} else {
return mContext.getString(R.string.category_cht);
}
}
activity_main.xml:
<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:background="#color/primary_color"
android:orientation="vertical"
tools:context="com.example.barebones.barebones.MainActivity">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
style="#style/CategoryTab"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
And you can see it is completely different than the one on their website. How could it be? I would love to get some clarification, because as a beginner, I feel lost in this sea of information. Which method should I use in order to have swiping tabs that represent different fragments?
I'm lost what you're trying to solve here. Are you perhaps trying to make it so that when you swipe horizontally, respectively changing fragments, your tab layout is updated as well? If so. I have a snippet down below, which you may have to adjust based on your variable names.
protected void initializeNavigationTransition() {
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
tabs_bottom_nav.getTabAt(i).select();
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
tabs_bottom_nav.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
updateTabIconOnSelect(current_tab, tab.getPosition());
current_tab = tab.getPosition();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
I'll have an additional note that it is possible for fragments to refresh, meaning it will be reinitialized, which might be something you do not want, especially if you're displaying data unto these fragments, which you are fetching from your API or over the network, after swiping a couple of times to different fragments if you have probably at least 4 fragments within the view pager. Hence you would need to prevent the view pager from refreshing the fragments by using the code below
viewPager.setOffscreenPageLimit(4); // 4 is the number of fragments within your view pager
viewPager.setAdapter(sectionsPagerAdapter);
I believe the cause of fragments refreshing is caused by the viewpager trying to save memory
I'm starting to write an Android app and want to have a tab navigation interface. It seems there are multiple choices, some of which may be deprecated:
Android TabHost (deprecated? but still available in Android Studio)
Tab Layout with Swipeable Views
Android Tab Activity
Material Design with Tabs
What is the best choice? Material Design with Tabs? How far back as far as APIs is this supported?
I know this isn't a pure coding question but it is probably a questions that others are pondering as well.
Thanks
extend your MainActivity to AppCompatActivity, and it will go till android version 7,
http://developer.android.com/reference/android/support/v7/app/AppCompatActivity.html
Use tabLayout and and View Pagers, To get the Swipe Effect on your Tabs
activity_main.xml
Add the Following to your MainActivity layout file.
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/vp_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:visibility="visible">
</android.support.v4.view.ViewPager>
MainActivity.java
public class MainActivity extends AppCompatActivity{
ViewPager viewPager;
FragmentPagerAdapter ft;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpaggermain);
viewPager = (ViewPager) findViewById(R.id.vp_main);
ft = new FragmentPagerAdapter(getSupportFragmentManager()) {
String [] titles = {"Subscriber","Merchant"};
final int VIEW_COUNT = 2;
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new YourFirstFragment();
case 1:
return new YourSecondFragment();
}
return null;
}
#Override
public int getCount() {
return VIEW_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
};
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
viewPager.setAdapter(ft);
tabLayout.setupWithViewPager(viewPager);
}
}
I am using the SlidingTabLayout.java and SlidingTabStrip.java files along with the Toolbar to create swipeable tabs.
I followed a couple different tutorials now and run into the same problem with how my tabs are displaying. I set setDistributeEvenly to true and changed my code to have four strings rather than 3. Now the text in my tabs are compressing rather than setting the width to the largest string value and allowing overflow for the sliding while in portrait mode. In landscape, the problem doesn't exist. http://i.imgur.com/BAqIjlI.png vs http://i.imgur.com/JgwzXSo.png
If I remove a string, the problem is solved, and if I add another string, overflow is allowed but it no longer sets the width evenly, but it again works fine in landscape.
My theory is that the calculated width for my four tabs, given the text length, is hitting some weird "sweet" spot for my screen size. It's too big to contain itself on one screen, but it's not big enough for it to trigger overflow.
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_the_square);
Toolbar appToolbar = (Toolbar) findViewById(R.id.square_toolbar); //creates instance of app_toolbar to serve as actionbar
//setting toolbar to actionbar
setSupportActionBar(appToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false); //do not have app_toolbar Title
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(new TabFragmentPagerAdapter(getSupportFragmentManager(), TheSquare.this));
//Give slidingTabLayout ViewPager
SlidingTabLayout slidingTabLayout = (SlidingTabLayout) findViewById(R.id.tabs);
//Center the tabs in the layout
slidingTabLayout.setDistributeEvenly(true);
slidingTabLayout.setCustomTabColorizer(new SlidingTabLayout.TabColorizer(){
#Override
public int getIndicatorColor(int position){
return getResources().getColor(R.color.green);
}
});
slidingTabLayout.setViewPager(viewPager);
}
TabFragmentPagerAdapter.java
public class TabFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 4;
private String tabTitles[] = new String[] { "Featured", "News", "Sports", "Life"};
private Context context;
public TabFragmentPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position + 1);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical">
<include
android:id="#+id/square_toolbar"
layout="#layout/app_toolbar"/>
<com.squareoffs.squareoffs.SlidingTabs.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="#android:color/white"/>
I'm a bit out of ideas to test, appreciate the help.
Could not resolve the 'why' of the issue, aside from my theory above, but I added spaces to each string ("News" to " News ") so they were equal length and, at least in this particular case, it resolved the problem. It's not an ideal solution as I've had to reduce padding to make sure everything looks similar in the tabs if I want the text to take up equal space but it at least displays properly.
I've got an app with left navigation drawer, switching between different fragments. Inside one of those fragment I want to implement SlidingTabLayout.
So, what I did is I copied the SlidingTabLayout.java and SlidingTabStrip.java from Google's iosched app. I used them inside my fragment:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<mynamespace.widget.SlidingTabLayout
android:id="#+id/home_fragment_tabs"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="#+id/home_fragment_pager"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="match_parent" />
</LinearLayout>
And then in my Fragment class, inside onCreateView method, I instantiated my pager and SlidingTabLayout like this:
mPager = (ViewPager) view.findViewById(R.id.home_fragment_pager);
mPager.setAdapter(new HomePagerAdapter(getActivity().getSupportFragmentManager()));
mTabs = (SlidingTabLayout) view.findViewById(R.id.home_fragment_tabs);
mTabs.setViewPager(mPager);
And this is my FragmentPagerAdapter:
class HomePagerAdapter extends FragmentPagerAdapter
{
private String[] tabs = { "Today", "This week", "With star" };
private Fragment[] tabFragments = {
new TodayTabFragment(),
new WeekTabFragment(),
new StarTabFragment()
};
public HomePagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int i)
{
return tabFragments[i];
}
#Override
public int getCount()
{
return 3;
}
#Override
public CharSequence getPageTitle(int position)
{
return tabs[position];
}
}
Also I got separate Fragment class and layout for each tab, which is nothing special. And it works, but as soon as I switch to other fragment with my navigation drawer, when I get back, content of one of tabs just dissapears. Mostly it happens to second tab. Also, if I select the HomeFragment from navigation drawer, when is already displayed, I get a nullpointerexception inside SlidingTabLayout.java at this line: mViewPager.setCurrentItem(i);
Any way of fixing it? I have no idea what to do. I guess my code would work, but inside activity. Possible to make it work inside fragment?
I also faced the same issue. Please use FragmentStatePagerAdapter instead of FragmentPagerAdapter which will solve this issue.
Solution:
What I did is instead of implementing FragmentPagerAdapter, I implemented PagerAdapter then I overriden the instantiateItem(ViewGroup container, int position) method and destroyItem() method.
Link, that helped me: http://developer.android.com/samples/SlidingTabsBasic/src/com.example.android.slidingtabsbasic/SlidingTabsBasicFragment.html
Can you try to change constructor of HomePagerAdapter to:
public HomePagerAdapter(SupportFragmentManager fm)
{
super(fm);
}
When you begin transaction instead of suuportfragmanager change it to childfragmentmanager
I want to have two tabs to navigate between Fragments, I did it with the old method but now with API 21 all methods are deprecated. I searched a lot but I didn't found any tutorial or sample. I try the SlidingTabs sample from Google but it's not built for Eclipse so I don't know how to integrate it in my app. Can someone help me? Maybe send me a link to a basic tutorial? Thank you!
Check this out, it may help you , it's a very well done menu for navigate through fragments
Just import those 2 classes : SlidingTabStrip and SlidingTabLayout in your project to have tabs in your application. You can take a look at the sample project to see how it is used.
Very simple to use. First import those 2 classes in your project and in your xml layout(my_layout.xml), add the SlidingTabLayout. I also added a viewPager in case you want to use it with a ViewPager :
<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"
android:paddingRight="#dimen/activity_horizontal_margin"
tools:context="MyActivity">
<SlidingTabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/my_pager" />
</LinearLayout>
In your activity,
public class MyActivity extends ActionBarActivity {
private SlidingTabLayout slidingTabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
viewPager = (ViewPager) findViewById(R.id.my_pager);
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
slidingTabLayout = (SlidingTabLayout)findViewById(R.id.sliding_tabs);
slidingTabLayout.setViewPager(viewPager);
}
}
And then you can define your adapter that will added to the SlidingTabLayout. For instance :
public static class MyAdapter extends FragmentPagerAdapter {
private static final int FRAGMENT_1 = 0;
private static final int FRAGMENT_2 = 1;
private static final int FRAGMENT_3 = 2;
public MyAdapter (FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i){
case FRAGMENT_1 : return new Fragment1();
case FRAGMENT_2 : return new Fragment2();
case FRAGMENT_3 : return new Fragment3();
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case FRAGMENT_1 : return "Fragment 1 Title";
case FRAGMENT_2 : return "Fragment 2 title";
case FRAGMENT_3 : return "Fragment 3 Title";
}
return super.getPageTitle(position);
}
#Override
public int getCount() {
return 3;
}
}
If it is a ViewPager you are talking about and not a NavigationDrawer type of thing, it continues to work well on API-21.
Take a look at IOSched application's code for a "Google Play" like ViewPager indicator.
EDIT
Yes setNavigationMode is deprecated as a method and as a UI/UX pattern.
From the official documentation:
This method was deprecated in API level 21.
Action bar navigation modes are deprecated and not supported by inline toolbar action bars.
Consider using other common navigation patterns instead.
Which links to common navigation patterns.
EDIT2
Fixed iosched application code link.