my problem is pretty simple but I don't see how to solve it... I didn't find any response to this problem.
I have 2 viewPager and when a page is selected I want to know which viewPager it comes from in onPageSelected().
There is my code :
public class MainActivity {
private ViewPager mCardsPager;
private ViewPager mIpsPager;
private MyCreditCardsPagerAdapter mCardsAdapter;
private MyInstantPaiementPagerAdapter mIpsAdapter;
private List<PayMethod> mCards;
private List<PayMethod> mIps;
//fill Pager/Adapter/List
#Override
public void onPageSelected(int position) {
if () {//If the page comes from mCardsPager
//do Something with mCards
} else { //else the page comes from mIpsPager
//do Something with mIps
}
}
}
You can set different listeners for each ViewPager rather than implement on Activity class.
Like this
mCardsPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
AND
mIpsPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
Setting same OnPageChangeListener for multiple ViewPager will not work. You need to create a class which implements OnPageChangeListener. In this class add a constructor which takes ViewPager as an input parameter and hold the value in a data member. Finally, use this class for adding OnPageChangeListener
Related
As many applications I have MainActivity with ViewPager.
When I select option in NavigationDrawer I want to change one fragment in ViewPager. So to achieve that I created something like this:
Option click listener:
#Override
public void onItemClick(View view, int pos) {
mainActivity.changeFragment(pos);
}
MainActivity method:
public void changeFragment(final int key) {
mDrawerLayout.closeDrawers();
new Handler(Looper.getMainLooper()).post(new Runnable(){
#Override
public void run() {
mainPagerAdapter.setKey(key);
}
});
}
And MainPagerAdapter:
public class MainPagerAdapter extends FragmentStatePagerAdapter {
public final static int NUM_OF_PAGES = 2;
private int mCurrentFragmentKey = 0;
public MainPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == HOME) {
if (mCurrentFragmentKey == 0)
return new Fragment1();
else
return new Fragment2();
} else
return new SecondViewPagerFragment();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return NUM_OF_PAGES;
}
public void setKey(int key) {
mCurrentFragmentKey = key;
notifyDataSetChanged();
}
Question:
Unfortunately it's not working properly because when I select option whole view stutters giving bad performance. How can I fix that?
Edit
I changed notifying pager that data set changed into this:
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
mainPagerAdapter.setKey(key);
}
}, 500);
And now everything works fine, but I'm not sure that is best solution. Could someone help me with this?
What about if you have various adapter that extends FragmentStatePagerAdapter and when you need to change the contents in the viewpager, you simple call pager.setAdapter(anotherAdapter)?
If setAdapter supply the views to be shown, changing the adapter probably will make the content of your viewpager change.
I'm trying to get SlidingMenu to work alongside ViewPager and I have followed the examples inside the library to the letter. The source for my Activity can be found bellow.
The problem is that despite the fact that the SlidingMenu and ViewPager work fine together there is this problem that after opening the SlidingMenu for the first time and closing it afterwards the ViewPager starts acting weird.
By weird I mean when you swipe to right and left the UI gets stuck on one page and doesn't change and I mean it's only the UI as I can see in the logger that the pages actually change.
I have searched the web extensively and although there has been a lot of similar problems with implementing SlidingMenu alongside ViewPager, my problem seems to be unique.
Any help is appreciated.
public class MainTabActivity extends SlidingFragmentActivity {
private static final String TAG = "MainTabActivity";
#InjectView(R.id.tabHostPager)
ViewPager tabHostPager;
#InjectView(R.id.tabs)
PagerSlidingTabStrip tabStrip;
FragmentPagerAdapter pagerAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_tab);
setBehindContentView(R.layout.sliding_menu_layout);
loadSlidingMenu();
ButterKnife.inject(this);
pagerAdapter = new MainTabAdapter(getSupportFragmentManager());
tabHostPager.setAdapter(pagerAdapter);
//Assign the TabStrip it's ViewPager
tabStrip.setViewPager(tabHostPager);
tabStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
break;
default:
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
tabHostPager.setCurrentItem(0);
}
private void loadSlidingMenu() {
// configure the SlidingMenu
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
getSlidingMenu().setMode(SlidingMenu.LEFT);
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
getSlidingMenu().setShadowWidth(100);
getSlidingMenu().setFadeDegree(0.35f);
getSlidingMenu().setBehindWidth(width / 100 * 90);
}
private class MainTabAdapter extends FragmentPagerAdapter {
public MainTabAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 4;
}
#Override
public Fragment getItem(int position) {
return Friends.newInstance();
}
#Override
public CharSequence getPageTitle(int position) {
return "Home";
}
}
}
Finally I managed to solve it. It had something to with manageLayers method from the SlidingMenu class.
Commenting out the method body was all it took:
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void manageLayers(float percentOpen) {
/*if (Build.VERSION.SDK_INT < 11) return;
boolean layer = percentOpen > 0.0f && percentOpen < 1.0f;
final int layerType = layer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
if (layerType != getContent().getLayerType()) {
getHandler().post(new Runnable() {
public void run() {
Log.v(TAG, "changing layerType. hardware? " + (layerType == View.LAYER_TYPE_HARDWARE));
getContent().setLayerType(layerType, null);
getMenu().setLayerType(layerType, null);
if (getSecondaryMenu() != null) {
getSecondaryMenu().setLayerType(layerType, null);
}
}
});
}*/
}
I have a FragmentActivity which has a ViewPager and my question is:
Where does setTitle(int index) method come from?
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int state) {
};
#Override
public void onPageScrolled(int pos, float posOffset, int a) {{
};
#Override
public void onPageSelected(int pos) {
String title = Integer.toString(pos);
setTitle(title); // where are you coming from?
}
});
It's from the surrounding (not listed) FragmentActivity. The FragmentActivity inherits it from Activity. See the API-Documentation of FragmentActivity and Activity for more information.
The method comes from activity.
https://developer.android.com/reference/android/app/Activity.html#setTitle(java.lang.CharSequence)
At the moment, i have a viewpager,when page scroll,i have load api for get new information.
But in the first load viewpager,progress loading display two twice because it load first page and next page.
I only want to load the first page in viewpager.
How must I do?
best way is to create one interface. and implement this interface to all fragment.
e.g.
public interface FragmentInterface {
void fragmentBecameVisible();
}
in ur viewpager activity put like this e.g
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener(){
#Override
public void onPageSelected(int position){
FragmentInterface fragment = (FragmentInterface) mAdapter.instantiateItem(viewPager, position);
if (fragment != null) {
fragment.fragmentBecameVisible();
}
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2){
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
in your fragment like
public class TestFragmet extends Fragment implements FragmentInterface {
#Override
public void fragmentBecameVisible() {
// your task to execute
}
}
Put OffScreenPageLimit to ZERO. It won't load other fragments.
viewPager.setOffscreenPageLimit(0);
I must clear that I am looking for an example or answer where I can use various differnt layout designs in a viewpager and the data in all the pages would be dynamic and all pages can be interacted by the user.
My Use Case and current approach towards the problem :
So I have got 8 different types of question types and so I have created layouts for all of them. Also I the data in the views for these layouts has to be populated via java Map that has fetched data from the sqlite DB.
But a test may contain 25 questions with different layouts out of the above 8. And for all these 25 questions I want to use a Viewpager and a Fragment that will return the required layout based on the passed question type value out of my java map.
My apporach towards this :
I have created an activity and have inflated it with a viewpager layout :
R.layout.practice_pager
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/test_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
*Activity Edited code *
public class TestActivity extends FragmentData implements FragmentData{
FragmentManager manager=getSupportFragmentManager();
private ViewPager mViewPager;
private MyFragmentPagerAdapter mMyFragmentPagerAdapter;
int PAGE_COUNT = 0;
GrePracticeTestRecord p=new GrePracticeTestRecord();
private HashMap<Integer, GrePracticeResultRecord> mPracResultMap;
public static int fragmentToReturn=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.practice_pager);
mViewPager = (ViewPager) findViewById(R.id.test_container);
//This function is called to fetch the data from sqlite db and fill the map with data
LoadingTestView();
PAGE_COUNT=mPracRecordMap.size();
initPager();
}
//here I initialize the pager and set the adapter to it
public void initPager()
{
p.setQUES(mPracRecordMap.get(1).getQUES());
p.setEXPL(mPracRecordMap.get(1).getEXPL());
fragmentToReturn=Integer.parseInt(mPracRecordMap.get(1).getQTYPE());
setData(p);
mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),fList);
mViewPager.setAdapter(mMyFragmentPagerAdapter);
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
mMyFragmentPagerAdapter.notifyDataSetChanged();
p.setQUES(mPracRecordMap.get(mViewPager.getCurrentItem()+1).getQUES());
p.setEXPL(mPracRecordMap.get(mViewPager.getCurrentItem()+1).getEXPL());
setData(p);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void setData(GrePracticeTestRecord p) {
// TODO Auto-generated method stub
}
#Override
public GrePracticeTestRecord getData() {
// TODO Auto-generated method stub
return p;
}
}
My Adapter Edited code
public class MyFragmentPagerAdapter extends FragmentStatePagerAdapter{
private List<Fragment> fragments;
public MyFragmentPagerAdapter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
/** This method will be invoked when a page is requested to create */
#Override
public Fragment getItem(int position) {
System.out.println("value of position "+position);
return this.fragments.get(position);
}
/** Returns the number of pages */
#Override
public int getCount() {
return this.fragments.size();
}
#Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return MyFragmentPagerAdapter.POSITION_NONE;
}
}
Interface FragmentData
public interface FragmentData {
public void setData(GrePracticeTestRecord p);
public GrePracticeTestRecord getData();
}
TestFragment Edited code
public class TestFragment extends Fragment {
AnswerEnterListener callBack;
FragmentData fD;
Button submitAnswer;
EditText userAnswer;
TextView qText,expl;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.qtype1, container, false);
}
public interface AnswerEnterListener
{
public void onInputAnswer(String ans);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
callBack=(AnswerEnterListener) activity;
fD=(FragmentData) activity;
} catch (Exception e) {
// TODO: handle exception
}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
qText=(TextView) getActivity().findViewById(R.id.question_text);
expl=(TextView)getActivity().findViewById(R.id.explanation_text);
qText.setText(Html.fromHtml(fD.getData().getQUES()));
expl.setText(Html.fromHtml(fD.getData().getEXPL()));
}
}
Similar to TestFragment , I have not the other fragments too. Each for a layout type.
Issues :
The first layout is repeated two times at the first time , and also when I swipe back then the position of data is misplaced.
Is this the right approach, I have been suggested by someone that you should use three fragments and update the left and right fragments with data , but this actually bounced off me. Can anyone share a good example of it or a blog.
I must clear that I am looking for an example or answer where I can
use various differnt layout designs in a viewpager and the data in all
the pages would be dynamic and all pages can be interacted by the
user.
This should be quite easy to make but you seem to have complicated this a lot. You need to do something like this:
Get the data from the database with the LoadingTestView(); function.
Initialize the ViewPager and set it's adapter. The adapter will return the proper fragment instance in the getItem() method, based on whatever criteria you have.
In the fragments, retrieve the data from the activity which should expose the data through some method.
I've made a simple example that you can find here.