I want to create ViewPager with this tutorial:
ViewPager example
But i don't know how can I use my own activity on First layout or Second layout.
This is function which change layout:
private void setTab(){
_mViewPager.setOnPageChangeListener(new OnPageChangeListener(){
#Override
public void onPageScrollStateChanged(int position) {}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
switch(position){
case 0:
findViewById(R.id.first_tab).setVisibility(View.VISIBLE);
findViewById(R.id.second_tab).setVisibility(View.INVISIBLE);
break;
case 1:
findViewById(R.id.first_tab).setVisibility(View.INVISIBLE);
findViewById(R.id.second_tab).setVisibility(View.VISIBLE);
break;
}
}
});
}
I want to create ViewPager with this tutorial: ViewPager example
That is not an especially good sample. Please consider using PagerTitleStrip, PagerTabStrip (both in the Android Support package, along with ViewPager) or one of the classes from ViewPagerIndicator.
But i don't know how can I use my own activity on First layout or Second layout.
ViewPager does not hold activities. It holds views, optionally managed by fragments. The concept of having activities inside of other activities is not recommended and is officially deprecated.
Related
This is already being implemented in Google Play and I want to use it in my app.
I've implemented the sliding tabs and toolbar using the android design library. My application features 4 tabs and I want to achieve this kind of color change among these tabs. Here are the screenshots of the Google Play app which I was referring to.
First Tab
Second Tab
Third Tab - same root as above links with the extension /Mc3a7.png (Apologies for this, but I'm not able to post more than 2 links due to a low reputation.)
Please note that a solution which is being implemented in JAVA will be preferred by me over one which suggests using XML for this purpose :)
if your are using view-pager you can set listener on it and then change toolbar color
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
toolbar.setBackgroundColor(Color.YELLOW);
break;
case 1:
toolbar.setBackgroundColor(Color.GREEN);
break;
case 2:
toolbar.setBackgroundColor(Color.RED);
break;
default:
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Well, I think the title is quite self explanatory. I have a ViewPager in my HomeActivity, the ViewPager contains 5 fragments at the moment.
When one of the fragments is visible by calling ViewPager's onPageScrolled I want to modify some views inside the current displayed fragment according to some conditions in the HomeActiviy.
After some research, it seems like I cannot find a good way to communicate in the direction HomeActivity --> Fragments inside ViewPager.
I have easily solved the communication in the direction Fragments in ViewPager --> HomeActivity using an Interfacebut this trick seems to not be working on the other direction.
I can access each time the current displayed fragment using a method on my FragmentStatePagerAdapter
public Fragment getActiveFragment(int position){
return myFragmentsList.get(position);
}
However, by doing that, I would have to cast each Fragment into its class MyFragment1 MyFragment2 MyFragment3....
Any easy clean way to achieve that?. Here is the relevant portion of the code:
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (currentStatus == 1){
Fragment activeFrag = mPagerAdapter.getActiveFragment(mPager.getCurrentItem());
//here I would like to modify one of the 5 fragments
}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {}
});
Define an interface,
interface FragmentListenerInterface {
public void onFragmentSelected();
}
Implement this interface in all of your fragments. change the communication between fragment and viewpager. write a method to return fragmentlistenerinterface instead of fragment.
public FragmentListenerInterface getActiveFragment(int position){
return (FragmentListenerInterface) myFragmentsList.get(position);
}
After this just say, in your code
public void onPageSelected(int position) {
mViewPager.getActiveFragment(position).onFragmentSelected();
}
And implement onFragmentSelected() in every fragment.
I am trying to get a Fragment reference using the findFragmentById() but it always returns a null object. I have used FragmentPagerAdapter and attached a OnPageChangeListener So that whenever I scroll to a specific Fragment, say FragmentB, a method of FragmentB should be fired.
I have the following code:
mPager.addOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
if (position == 1) {
FragmentB fb = (FragmentB) getSupportFragmentManager().findFragmentById(R.id.fragment_b);
fb.refreshList();
//fb is always null
Toast.makeText(MainActivity.this,"Scrolled", Toast.LENGTH_SHORT).show();
//Toast is working fine
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2){}
#Override
public void onPageScrollStateChanged(int arg0){}
});
Just do this instead:
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
PagerAdapter pagerAdapter = (PagerAdapter) mPager.getAdapter();
if (position == 1) {
FragmentB fragmentB = (FragmentB)pagerAdapter.getItem(position);
fragmentB.refreshList();
}
}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {}
});
The problem with findFragmentById is not intended to be used in this way:
Finds a fragment that was identified by the given id either when inflated from XML or as the container ID when added in a transaction. This first searches through fragments that are currently added to the manager's activity; if no such fragment is found, then all fragments currently on the back stack associated with this ID are searched.
You should call it to get which fragment is in your fragment's container (for example, if you're using Navigation Drawer and you want to know which of the fragment is in the viewport), while you're using ViewPager, which hosts multiple fragments.
I hope, it helps.
findFragmentById() will always return null if you're not declaring your fragment in your activity's content view(it's .xml file) because you can't set a fragment's ID programmatically!
If you're interested in that here is what your code might look like inside an activity's xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/my_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.mypackage.MyFragment"/>
</LinearLayout>
And this way, looking up a fragment in the FragmentManager with findFragmentById() would return you the proper instance of MyFragment.
findFragmentById() is one way of looking up fragments in the FragmentManager but there is also another way through findFragmentByTag().
In your case you most probably set up those fragments in an instance of a PagerAdapter through the following method:
#Override
public Fragment getItem(int position) {}
Now there are a lot of examples and answers encouraging you to use some reflection to get a fragment from the FragmentManager. Android automatically generates a tag for each fragment and you can get this name with the following method:
private static String getFragmentName(int viewId, int id) {
return "android:switcher:" + viewId + ":" + id;
}
And then you could build a getter method to get a fragment like this:
public Fragment getFragmentForPosition(int position) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag(getFragmentName(mViewPager.getId(), getItemId(position)));
return fragment; // May be null if the fragment is not found. Handle that case too wherever you call this method.
}
Where viewId is the ID from the xml file of the ViewPager and id can be obtained in the adapter anywhere with getItemId(position).
This will work but it is a bit of an ugly solution because of the reflection used here.
This is a really easy but ugly solution which should work if the Android team doesn't change their logic for generating tags :)
Please refer to the this SO response for a list of other possible solutions.
Good day all, i have a slight issue i can't seem to get my head around it. i have a ViewPager of 3 fragments and this ViewPager is contained in a FrameLayout. What i am trying to do is that for every fragment, the background image of the FrameLayout Changes.
my FragmentActivity is:
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), fragments);
pager = (ViewPager)findViewById(R.id.viewpager);
pager.setAdapter(pagerAdapter);
and in my MyPagerAdapter, i instantiate the fragments in the getItem() method:
#Override
public Fragment getItem(int position) {
return MyFragment.newInstance(position);
}
Now i can setup the values for the Views in the fragment correctly using the position
public static MyFragment newInstance(int position){ //Add arraylist of hashmaps to populate it here.
MyFragment my_fragment = new MyFragment();
Bundle bundle = my_fragment.getArguments();
if(bundle == null){
bundle = new Bundle();
}
bundle.putInt(FRAGMENT_POSITION, position);
my_fragment.setArguments(bundle);
return my_fragment;
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if(args != null){
position = args.getInt(FRAGMENT_POSITION);
}
//do other operations and Methods on views based on position.
and then at somepoint, i call a method `((MyFragmentActivity)getActivity()).setLayoutBackground(resId) which sets the Background of the FrameLayout in the container Activity. My trouble is that, i can't seem to differentiate which fragment is being called due to the nature that ViewPagers Load all the fragments together and I keep getting the same background for all the fragments in the ViewPager.
In MyFragmentActivity, i tried changing it in the PageChangeListener but no luck, i noticed that i am passing the same value all the time and so keep getting the same thing.
public void setLayoutBackground(int resId){
layoutResId = resId;
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
app.setBackground(layout, layoutResId)
//Log.d(TAG, "i am resId" + layoutResId);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
}
What i need to do is pass the Position of the Fragment to the FragmentActivity so that it will load the correct Background but can't seem to figure it out. (The background drawable to load is based on a logic, so i can't define it from the start)Any Ideas how i could go about this or what i could be doing wrong because it has dealt with my weekend so far.. :) Many Thanks in Advance.
Instead of letting the Fragment set the layout background directly, have an HashMap<Integer, Integer> fragmentBackgrounds; field variable in the Activity and replace the method call to ((MyFragmentActivity)getActivity()).setLayoutBackground(resId) with ((MyFragmentActivity)getActivity()).setFragmentBackground(position, resId) where the Activity then puts the resId into the fragmentBackgrounds map with a key representing the position and the value representing the resId. In the onPageSelected() method of the PageChangeListener, use the position it gives you to look up the resource in your map that that Fragment would like and set the layout background at that time (unless the key doesn't exist or the value is null or 0 of course).
You should also consider not calling the setFragmentBackground in the way that you are, because that assumes that the hosting Activity will always be an instance of MyFragmentActivity and instead you should define an interface with the setFragmentBackground method and make the Activity implement that interface. Then, in the Fragment, override onAttach, check that the Activity that the Fragment is being attached to implements the interface with instanceof and assign the Activity to a field variable in the Fragment called listener. In onDetach() set the listener to null and always check if the listener is null before calling any methods on it.
I am doing graph using onDraw() method. I have four different Fragments which contains different graphs. I used ViewPager to show the graph in swipe model.
When I call viewPager.getCount() it's getting called multiple times. Later I found that the onDraw() method was calling each time I touched the screen or when I swipe the fragment. I really wondered why the Fragment is called several times while using ViewPager. I didn't get any proper solution for this, can anyone guide me how to restrict multiple calling of getCount() or calling Fragment when doing a swipe.
Try this,
Add a mViewPager.setOnPageChangeListener(mPageLitsener);
And
define as,
private ViewPager.OnPageChangeListener mPageLitsener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
((FirstFragment)mViewPagerAdapter.getItem(0)).onUpdate();
break;
case 1:
((SecondFragment)mViewPagerAdapter.getItem(1)).onUpdate();
break;
case 2:
((ThirdFragment)mViewPagerAdapter.getItem(2)).onUpdate();
break;
default:
((FirstFragment)mViewPagerAdapter.getItem(0)).onUpdate();
break;
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageScrollStateChanged(int arg0) {}
};
Then call a public method inside of Fragment (i.e, onUpdate()), and define that as what you need.