FragmentActivity custom Fragment transition - android

I am trying to make some kind of transition on Fragments, and i am using default application skeleton in eclipse for creating FragmentActivity. I noticed other posts for specifying custom transition animation from xml, but it is being done on Transaction, and none is using FragmentActivity. (Which is btw much easier.)
I would like to know how to make custom transitions in FragmentActivity.
Thanks in advance!
EDIT: Somthing like this but for FragmentActivity.
MusicPlayerActivity.java
public class MusicPlayerActivity extends FragmentActivity {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// init pager and set its adapter
mSectionsPagerAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
//other init code ...
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new MainFragment();
case 1:
return new AllSongsFragment();
case 2:
return new SettingsFragment();
default:
return null;
}
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
/**
* Get title for supplied Fragment number.
*/
#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;
}
}
//other methods
}
activity_music_player.xml
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MusicPlayerActivity$OptionsFragment" >
<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"
tools:context=".MusicPlayerActivity" >
<android.support.v4.view.PagerTitleStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />
</android.support.v4.view.ViewPager>
<ListView
android:id="#+id/drawer"
android:layout_width="160dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#333333"
android:choiceMode="singleChoice" />

As you said in your comment, you're using a ViewPager. This is slightly different to performing an animation on a FragmentTransaction.
What you'll want to use is a ViewPager.PageTransformer. There are some details on how to do that here

Question is not much clear to me. But i believe this may serve your purpose.
from: http://developer.android.com/reference/android/app/Activity.html#overridePendingTransition(int, int)
public void overridePendingTransition (int enterAnim, int exitAnim)
Added in API level 5
Call immediately after one of the flavors of startActivity(Intent) or finish() to specify an explicit transition animation to perform next.
As of JELLY_BEAN an alternative to using this with starting activities is to supply the desired animation information through a ActivityOptions bundle to {#link #startActivity(Intent, Bundle) or a related function. This allows you to specify a custom animation even when starting an activity from outside the context of the current top activity.
Parameters
enterAnim A resource ID of the animation resource to use for the incoming activity. Use 0 for no animation.
exitAnim A resource ID of the animation resource to use for the outgoing activity. Use 0 for no animation.

Related

View Pager is calling other fragments on startup and on swiping too

List of components in my app is following :
TabLayout - Tab1, Tab2, Tab3.
Fragments for Tabs - Tab1.xml & class, Tab2.xml & class, Tab3.xml & class.
ViewPager to show Fragments on tabs.
So, when app starts as i debugged the startup process, it works like following :
it calls 'Tab1.class',
then it calls 'Tab2.class',
and when swipe from 'Tab1' to 'Tab2', it calls 'Tab3.class'.
and when swipe from 'Tab2' to 'Tab3', it calls nothing.
on reverse swiping :
when swipe from 'Tab3' to 'Tab2', it calls 'Tab1.class'.
then when swipe from 'Tab2' to 'Tab1', it calls nothing.
Questions :
So, why does it do that?
How can i call ONLY 'tab1.class' when app starts on 'tab1'?
How can i call ONLY 'tab2.class' when i swipe from 'tab1' to 'tab2'?
MainActivity.java
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
PagerAdapter pagerAdapter = new FixedTabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
}
class FixedTabsPagerAdapter extends FragmentPagerAdapter {
public FixedTabsPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
return new Tab1();
case 1:
return new Tab2();
case 2:
return new Tab3();
default:
return null;
}
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position)
{
case 0:
return getString(R.string.tab1);
case 1:
return getString(R.string.tab2);
case 2:
return getString(R.string.tab3);
default:
return null;
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="vwc.com.newconcept.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/main_toolbar"
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">
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
app:tabMode="scrollable"
app:tabGravity="center"
android:layout_gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v4.view.ViewPager>
</android.support.design.widget.AppBarLayout>
</android.support.v4.widget.DrawerLayout>
Please Do Tell Solution For This Problem.
setOffscreenPageLimit
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.
Hope this helps.
ViewPager mViewpager = (ViewPager)findView....
mViewPager.setOffscreenPageLimit(3);
ViewPager is intented to work in that way to avoid lag in animations while switching from one fragment to other fragment, it will load atleast one extra fragment alongside your Visible Fragment by which it makes sure there is scope to swipe.
because, while swiping view pager has capability to show two fragments simultaneously hence loads the one extra always, without two pages view pager is useless.
For Refresh Fragment When Fragment Visible
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getFragmentManager() != null) {
getFragmentManager()
.beginTransaction()
.detach(this)
.attach(this)
.commit();
}
}

'No view found for id' exception while adding tabs in dialog - android

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.

FragmentPagerAdapter not working on fragment's recreation

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.

why fragment doesn`t show up with ViewPagerIndicator

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?

replace SherlockFragment with another one

I am using Jake Wharton's TabPageIndicator with ViewPager. Each tab is a fragment that extends from SherlockFragment. In one fragment, on item click, I would like to replace a current fragment with another WITHIN THE SAME TAB. Visually, the current fragment disappears, no exception is thrown, but I get an empty space where the new fragment should be.
Code I am using to replace the fragment is:
SherlockFragment frag = new AboutFragment();
getSherlockActivity().getSupportFragmentManager()
.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(R.id.pager_content, frag, "dialogAbout")
.hide(this)
.addToBackStack(null)
.commit();
What is the correct way to replace this?
My main_activity xml is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.viewpagerindicator.TabPageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:background="#000000" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1">
<FrameLayout android:id="#+id/pager_content"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</android.support.v4.view.ViewPager>
</LinearLayout>
and in my MainActivity I have set an adapter to viewPager. Adapter extends from FragmentPagerAdapter and looks like follows:
private class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
index = position % CONTENT.length;
switch (index) {
case FRAG_TAG_DEPOSIT:
return new DepositFragment();
case FRAG_TAG_HISTORY:
return new HistoryFragment();
case FRAG_TAG_LOCATIONS:
return new LocationsFragment();
case FRAG_TAG_SETTINGS:
return new SettingsFragment();
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position) {
return getString(CONTENT[position % CONTENT.length]).toUpperCase();
}
#Override
public int getCount() {
return CONTENT.length;
}
}
What I don't understand here is - in which containter is the fragment returned from the adapter placed? I don't specifally notify where to put it, I simply state which fragment should be put at which position. Could this be the reason replacement fails?
Since you are using ViewPager to load your fragments, you don't need to change the fragment manually. Just set the fragment that you want to switch to using the setCurrentItem like this where num is the index of the fragment that you want to switch to.
viewPager.setCurrentItem(num);

Categories

Resources