I have decided for remaking UI of my app by using ViewPagerIndicator and TitlePageIndicator, but I have following problems:
1) Fragments that are for each page are not displayed.
2) Swipe betwen two pages does not work.
I am using ActionBarSherlock as I did with tabs.
I have not changed anything in Fragmens since it has workrd fine when I was using tabs and I have written following code:
public class CustomFragmentAdapter extends FragmentPagerAdapter {
private final String[] TITLES = new String[] {
"General",
"Companies",
"Discounts"
};
public final int NUM_TITLES = TITLES.length;
public CustomFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Log.v("POSITION", "position: "+position);
switch (position) {
case 0:
return new General();
case 1:
return new Companies();
case 2:
return new Discounts();
}
return null;
}
#Override
public int getCount() {
return NUM_TITLES;
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position % NUM_TITLES].toUpperCase();
}
}
and
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager()));
TitlePageIndicator indicator = (TitlePageIndicator) findViewById(R.id.indicator);
indicator.setViewPager(mViewPager);
indicator.setCurrentItem(0);
and my XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.viewpagerindicator.TitlePageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
As I have seen most of the tutorials and examples are quiet similar to my code, but I still can't make it work. I have tried almost everything. It was also not working when I have put there some dummy fragments with just some TextView. I also have tried to remove ViewPagerIndicator and try only ViewPager, but it was not working for me.
I am probably missing something, but I can't find it.
Thank you very much in advance for your advices.
One difference I see from a similar Activity of mine is that you're not setting the current item of the pager:
mViewPager.setCurrentItem(0, false);
I have found the problem which was missing android:orientation="vertical" in activity layout xml
Related
In the middle of my layout I want to have 2 tabs to choose between viewing 2 different lists in the second half of the screen. How can I do this?
Here is an image illustrating what I wish to achieve. This image has a questions tab and an answers tab in the middle of the screen. Depending on which tab you select it shows a different listview:
I wish to achieve this exact same thing.
I tried doing it with TabHost widget, but for the life of me I couldn't get rid of the title bar (I tried selecting themes with no title bar, tried setting the theme in the manifest to a no title bar one)
I also tried make action bar tabs, but those were at the top of the screen....
How can I create tabs in the middle of my screen like in the image?
I had to do the same today! I tried with PagerTabStrip, because I thought you can't use TabLayout if it's not with a Toolbar. Turns out I was wrong, and it's even used in Google iosched. So you can put a TabLayout + ViewPager wherever you want.
I know you want to do some very custom tabs, which would be easier to customize if they were buttons, but in my opinion it's better to use TabLayout + ViewPager, since it makes things more scalable.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<LinearLayout
android:id="#+id/top_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"></LinearLayout>
<RelativeLayout
android:id="#+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/top_layout"
android:layout_weight="1">
<android.support.design.widget.TabLayout
android:id="#+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:minHeight="60dp"
app:tabGravity="fill"
app:tabIndicatorColor="#color/colorAccentSecondary"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/colorAccentSecondary"
app:tabTextAppearance="#style/TournamentWaitingTimerTabTextAppearance" />
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/pager_header"></android.support.v4.view.ViewPager>
</RelativeLayout>
</LinearLayout>
MainActivity class:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Locate the viewpager in activity_main.xml
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
// Set the ViewPagerAdapter into ViewPager
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new LeftFragment(), "Players");
adapter.addFrag(new RightFragment(), "Prizes");
viewPager.setAdapter(adapter);
TabLayout mTabLayout = (TabLayout) findViewById(R.id.pager_header);
mTabLayout.setupWithViewPager(viewPager);
}
class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
You can change the adapter you use, it doesn't matter.
To customize tabs, I'd take a look at this amazing tutorial.
You can try using a ViewPager with PagerTabStrip
You can add fragments as page tabs by implementing a FragmentPagerAdapter
In your layout xml file, you should be able to move around the ViewPager to anywhere in your layout like you would most other components. I haven't tried centering it, but I have placed things above and below it, and it behaves as you would expect.
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
</android.support.v4.view.ViewPager>
FragmentPagerAdapter example
public class FragmentPagerAdapter extends android.support.v4.app.FragmentPagerAdapter
{
final int PAGE_COUNT = 2;
private final String[] PAGE_TITLES =
{
"Fragment1",
"Fragment2"
};
public FragmentPagerAdapter()
{
super(getSupportFragmentManager());
}
#Override
public int getCount()
{
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position)
{
return PAGE_TITLES[position];
}
#Override
public Fragment getItem(int position)
{
switch(position)
{
case 0:
return new Fragment1();
case 1:
return new Fragment2();
default:
return null;
}
}
}
and in your main Acivity:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
mCustomPagerAdapter = new FragmentPagerAdapter();
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mCustomPagerAdapter);
...
}
I have an activity in which I want to show a dialog with 2 tabs. I have the following code on button click which will show the dialog:
Dialog dialog = new Dialog(this);
// select_category is having ViewPager and TabLayout inside of a Framelayout
dialog.setContentView(R.layout.select_category);
ViewPager objViewPager = (ViewPager) dialog.findViewById(R.id.viewPager);
objViewPager.setAdapter(new MyTabsAdapter(getSupportFragmentManager()));
TabLayout mTabLayout = (TabLayout) dialog.findViewById(R.id.tabLayout);
mTabLayout.setTabTextColors(getResources().getColorStateList(R.color.tabcolors));
mTabLayout.setupWithViewPager(objViewPager);
dialog.show();
Adaper for ViewPager is as,
public class MyTabsAdapter extends FragmentPagerAdapter {
String[] tabs = {"FIRST", "SECOND"};
public MyTabsAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0: {
// for now, returning plain fragment for simplicity
return new Fragment();
}
case 1: {
return new Fragment();
}
default:
return null;
}
}
}
select_category.xml is,
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background"
android:theme="#style/NoActionBarTheme">
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/view_pager_top_margin"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary" />
</FrameLayout>
When I run this code I'm getting IllegalArgumentException as,
java.lang.IllegalArgumentException: No view found for id 0x7f0a00da
(com.myapp:id/viewPager) for fragment Fragment
The TabLayout I'm using is from Google's design support library (android.support.design.widget.TabLayout).
I have no idea where I'm getting wrong. Please help!
Any tutorial / guide suggestion would be appreciated.
I read the documentation on FragmentPagerAdapter # FragmentPagerAdapter. In the webpage, the getItem() is coded differently than your code. Their suggestion is:
#Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
Notes:
You also have to define the static method newInstance.
I think you have to extend (subclass) a Fragment. In the above webpage, it subclass ListFragment.
I'm using ViewPager with PagerTabStrip in fragment A and everything works fine. Items are populated. ...Until I replace A with B and then replace again B with A.
fragment xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#222222"
android:textColor="#color/blue" />
</android.support.v4.view.ViewPager>
Debuggin shows that after second replacement getItem(int position) is never reached in FragmentPagerAdapter. Tabs are empty.
Adapter for tabs:
private class ChannelsFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = dataChannelsList.size();
public ChannelsFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
return dataChannelsList.get(position).getLang();
}
#Override
public Fragment getItem(int position) {
//This switch isnt reached for second replacement. Dunno why
switch (position){
case 0:
return FragmentChannelsUkr.newInstance();
case 1:
return FragmentChannelsRus.newInstance();
case 2:
return FragmentChannelsPol.newInstance();
default:
return null;
}
}
}
}
But again if I rotate the phone when tabs are empty they suddenly recreated in normal usual way.
the adapter call in onCreateView():
View rootView = inflater.inflate(R.layout.fragment_channels,container, false);
ViewPager viewPager = (ViewPager) rootView.findViewById(R.id.pager);
viewPager.setAdapter(new ChannelsFragmentPagerAdapter(getFragmentManager()));
Any ideas what invokes such behaviour? Appreciate any help with explanation.
Tell if some more code needed
You might be running out of memory or it would turn out to be a huge process reloading your fragments again. Try using FragmentStatePagerAdapter instead of FragmentPagerAdapter.
I have a activity whose content view is a fragment, I added viewpager and viewpagerindicator to this activity. I created an FragmentPagerAdapter for the pager, the adapter constructs three fragments for displaying three tabs. But when I run the project, only see the pager title shows up. Why doesn`t the three fragments show up?
I created the pager and indicator on create of the Activity lifecycle.
public class BrowserActivity extends SherlockFragmentActivity
implements ReposFragment.OnFileSelectedListener, StarredFragment.OnStarredFileSelectedListener, OnBackStackChangedListener {
super.onCreate(savedInstanceState);
setContentView(R.layout.seadroid_main);
adapter = new SeafileTabsAdapter(getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
TabPageIndicator indicator = (TabPageIndicator)findViewById(R.id.indicator);
indicator.setViewPager(pager);
indicator.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(final int position) {
currentPosition = position;
supportInvalidateOptionsMenu();
disableUpButton();
}
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
});
the adapter constructs three fragments for displaying three tabs view
class SeafileTabsAdapter extends FragmentPagerAdapter implements
IconPagerAdapter {
public SeafileTabsAdapter(FragmentManager fm) {
super(fm);
}
private ReposFragment reposFragment = null;
private ActivitiesFragment activitieFragment = null;
private StarredFragment starredFragment = null;
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
if (reposFragment == null) {
reposFragment = new ReposFragment();
}
return reposFragment;
case 1:
if (starredFragment == null) {
starredFragment = new StarredFragment();
}
return starredFragment;
case 2:
if (activitieFragment == null) {
activitieFragment = new ActivitiesFragment();
}
return activitieFragment;
default:
return new Fragment();
}
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.tabs_library).toUpperCase();
case 1:
return getString(R.string.tabs_starred).toUpperCase();
case 2:
return getString(R.string.tabs_activity).toUpperCase();
default:
return null;
}
}
#Override
public int getIconResId(int index) {
return ICONS[index];
}
#Override
public int getCount() {
return ICONS.length;
}
}
the layout file seadroid_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.viewpagerindicator.TabPageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
UPDATE
I have found that ViewPager tutorials used LineaLayout as the root container. So is it necessary to change FragmentLayout to be LineaLayout here. When I changed to LineaLayout, the app crashed, and the log is
12-02 07:01:13.636: E/AndroidRuntime(3807): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.seafile.seadroid2/com.seafile.seadroid2.ui.activity.BrowserActivity}: android.view.InflateException: Binary XML file line #21: Error inflating class LineaLayout
12-02 07:01:13.636: E/AndroidRuntime(3807):at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
Try switching the root view in your XML to LinearLayout. Right now you are using FrameLayout, which has the effect of putting your ViewPager on top of your TabPageIndicator. Also, since the layout_height is 0, you're not going to see your fragments. I suspect this is your problem -- clearly you meant to use LinearLayout.
Also, be careful with your SeafileTabsAdapter class. Right now it is caching the fragments, which seemed logical to me when I started using FragmentPagerAdapter too. However, FragmentPagerAdapter caches the fragments too, so you have a danger of a memory leak with this approach. If you want to call getItem directly, without auto-creating a fragment each time, then you can first call findFragmentByTag to see if the fragment is there yet. The string Android uses for the tag can be found in the source, or in this SO question:
Replace Fragment inside a ViewPager
Hope this helps. I'm still a bit confused about your code, because in the description you say you have a ViewPager inside a fragment, but the posted code seems to show a ViewPager inside your activity.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.viewpagerindicator.TabPageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
I hope this answers your concern in your comment. If you instead mean that the sherlock code is expecting a FrameLayout as the root view (this would surprise me, although I haven't used it), then all you need to do is put the LinearLayout above as a child of the FrameLayout you had before. Does that make sense?
I'm new to Android, there's so much unknown that I don't even know which direction to look for solutions.. I hope experienced developers can enlighten me on this..
I have a UI design that is quite different from common Android app layout, most of which I've seen so far use Tabs or the upper-left corner control button..
My Main Activity is 1) full-screen without ActionBar 2) has a fixed "control panel" layer occupying the bottom half of the screen 3) a full-screen ViewPager (contains three pages, can swipe left and right) below the "control panel" layer.
I'm able to achieve either 1&2 or 1&3 but not all together. I think the main problem is to add the control panel on top of the ViewPager within the same screen.
I tried to put ViewPager and "control panel" as two fragments inside the MainActivity layout.. it didn't work... below is the layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.MainActivity">
<fragment
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:layout="#layout/fragment_pager"/>
<fragment android:name="com.example.MainFragment"
android:layout_width="fill_parent"
android:layout_height="200dip"
android:layout_gravity="bottom"
tools:layout="#layout/fragment_main"/>
</LinearLayout>
In case you need more info, attach my MainActivity as well
public class MainActivity extends FragmentActivity {
static final int NUM_ITEMS = 3;
private FragmentPagerAdapter mAdapter;
private ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getActionBar();
actionBar.hide();
setContentView(R.layout.activity_main);
mAdapter = new DashboardAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(1);
}
public static class DashboardAdapter extends FragmentPagerAdapter {
public DashboardAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FirstFragment();
case 1:
return new SecondFragment();
case 2:
return new ThirdFragment();
default:
return null;
}
}
}
}
I got Error inflating class fragment, so probably happens when I create the fragment
inflater.inflate(R.layout.first_fragment, container, false);
Because "control panel" is outside the ViewPager, thus the view cannot be inflated... Then what's the correct way of doing it?
Use a RelativeLayout as the root of your MainActivity.
The ViewPager should be the first child with match_parent.
Your control panel can be aligned at the bottom using layout_alignParentBottom="true". This will also make it on top of the ViewPager.