I am working on an viewpager with previous and next page. What I need is to increase the text of the current page, after loading the page. But while I am trying, text on the next page is changing (I know that next and previous page load on viewpager). How can I get the focused on one selected page?
What I have done is,
viewPager.setClipChildren(false);
unfortunately it doesn't work..
I recommed using position parameter in activity and you can update text based on the position recieved.
This example is for Fragments though
#Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position);
}
And in fragment you recieve this position as an argument:
public static PageFragment newInstance(int position) {
Bundle args = new Bundle();
args.putInt("position", position);
PageFragment page = new PageFragment();
page.setArguments(args);
return page;
}
In onCreateView you update your textview based on your position.
If you want to update TextView something like this:
TextView tv = (TextView) view.findViewById(R.id.yourId);
int position = getArguments().getInt("position");
tv.setText("This is page number: " + position);
i didn't really understand what you need but i think you may use this:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
//Edit
if(position==int requiredPosition)
{
// resize your text
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Related
When I get a child view from items 0 to 2 in viewpager, it works fine. When I try to get a child view from 3 onward, it returns null. How can I get all the current selected child view of viewpager?
Edited:
View view = viewPager.getChildAt(viewPager.getCurrentItem());
When viewPager.getCurrentItem() reached 3 onward, the view return null.
You need to access the Fragments which you use in your ViewPager.
In this answer https://stackoverflow.com/a/39274141/1559852 i tried to explain how to modify your ViewPager's adapter o make the fragments which you use in your ViewPager accessible.
After you implemented the code in link, you'll be able to access your fragments and it's views.
Define a public method to your Fragments like below:
public View getMyFragmentView(){
return this.mView();
}
Finally add an OnPageChangeLsitener to your ViewPager like the following code.
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// Here's your instance
final YourFragment fragment =(YourFragment)yourPagerAdapter.getRegisteredFragment(position);
final View theViewYouWantToAccess = yourFragment.getMyView();
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Edit: In your ViewPager adapter you can register the Fragment to SparseArray
#Override
public Fragment getItem(int position) {
final YourFragment fragment = new YourFragment();
// Register your fragment to Sparse Array here
registeredFragments.put(position, fragment);
return fragment;
}
I am newbie to android.I am trying to develop an application which contains a Viewpager with Tabs.My Aim is to pass the data entered in first fragment(i.e tab1) to second fragment.I am confused how to get the data in FragmentA and show it in FragmentB besides my viewpager is in Mainactivity.
some of my code is
mviewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Toast.makeText(getApplicationContext(),""+servloc,Toast.LENGTH_SHORT).show();
}
#Override
public void onPageSelected(int position) {
mviewpager.setCurrentItem(position);
int index = mviewpager.getCurrentItem();
if(position==0) {
Fragmentpageadapter adapter = (Fragmentpageadapter) mviewpager.getAdapter();
CreateInspectionFragmentA ca= (CreateInspectionFragmentA) adapter.getFragment(index);
}
above code is viewpage setonpagechangelistener..
and my pageadapter is
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
CreateInspectionFragmentA createInspectionFragmenta=new CreateInspectionFragmentA();
mPageReferenceMap.put(position, createInspectionFragmenta);
return createInspectionFragmenta;
case 1:
CreateInspectionFragmentB createInspectionFragmentb = new CreateInspectionFragmentB();
// createInspectionFragmentb.deliverData(data1,data2);
mPageReferenceMap.put(position,createInspectionFragmentb);
return createInspectionFragmentb;
case 2:
CreateInspectionFragmentC createInspectionFragmentc = new CreateInspectionFragmentC();
mPageReferenceMap.put(position,createInspectionFragmentc);
return createInspectionFragmentc;
default:
return null;
}
}
my requirement is to pass the data i entered in FragmentA in edittext to be seen in FragmentB when swiped but not when button click or something.
posibilities:
1.if there is a way to get the UI controls of FragmentA in onpageselected i can bind the EditText view and get the data.
2. using Bundle.
please help me to resolve this problem.
Thanks in Advance.
You can try this. In FragmentA you put this code
private static NameOfTheFragment instance = null;
public static NameOfTheFragment getInstance() {
return instance;
}
Then create a function to return what you want, like a List View
public ListView getList(){
return list;
}
Then in FragmentB you do this in onCreateView
ListView list = NameOfTheFragment.getInstance().getList();
Then you show list in fragment B
I have ViewPager with 3 Fragments. I just want to know is it possible to move elements (ImageView, TextView, e.t.c) in Fragment when user start to scroll the page and go to another page? What the best way to do that? Here below my code that I used before. I used it in my MainActivity. Only after test I understand that I am on the wrong way cause these code will work every time when user scroll. So is it possible to set it in Fragment?
My code that i used before in MainActivity:
#Override
public void transformPage(View page, float position) {
// transformation here
int pageWidth = page.getWidth();
ImageView mImageViewCloud = (ImageView) getView().findViewById(R.id.cloud);
ImageView mImageButterfly = (ImageView) getView().findViewById(R.id.butterfly);
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
page.setAlpha(0);
} else if (position <= 1) { // [-1,1]
if(mImageViewCloud!=null)mImageViewCloud.setTranslationX((float) (-(1 - position) * 0.5 * pageWidth));
if(mImageButterfly!=null)mImageButterfly.setTranslationX((float) ((1 - position) * 1.5 * pageWidth));
// The 0.5, 1.5, 1.7 values you see here are what makes the view move in a different speed.
// The bigger the number, the faster the view will translate.
// The result float is preceded by a minus because the views travel in the opposite direction of the movement.
} else { // (1,+Infinity]
// This page is way off-screen to the right.
page.setAlpha(0);
}
}
Any help is appreciated. Thanks!
EDIT:
AdapterFragment.java
public abstract class AdapterFragment extends Fragment {
SparseArray<AdapterFragment> registeredFragments = new SparseArray<AdapterFragment>();
#Override
public Object instantiateItem(ViewGroup container, int position) {
AdapterFragment fragment = (AdapterFragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public void pass(int farFarAway) {
for(int i = 0, nSize = registeredFragments.size(); i < nSize; i++)
registeredFragments.valueAt(i).pass(farFarAway);
}
final int pageWidth = ViewPager.getMeasuredWidth(); //after ViewPager drawn, probably its also screen width
final int scrollRange = (AdapterFragment.getCount()-1)*pageWidth;
ViewPager.OnPageChangeListener OPCL = new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
float farFarAway=(float)(position*pageWidth+positionOffsetPixels), scrollToFactor = farFarAway/scrollRange;
AdapterFragment.pass(farFarAway);
}
#Override
public void onPageScrollStateChanged(int state) {
}
};
}
have you tried ViewPager.OnPageChangeListener? there is a method in this interface onPageScrolled(int position, float positionOffset, int positionOffsetPixels), last two variables might be useful for your purposes - pass move offset to all Fragments, inside of them move Views
edit:
final int pageWidth=mainViewPager.getMeasuredWidth(); //after ViewPager drawn, probably its also screen width
final int scrollRange = (viewPagerCustomAdapter.getCount()-1)*pageWidth;
OnPageChangeListener onpcl = new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
float farFarAway=(float)(position*pageWidth+positionOffsetPixels),
scrollToFactor = farFarAway/scrollRange;
viewPagerCustomAdapter.pass(farFarAway);
}
#Override
public void onPageScrollStateChanged(int state) {
}
};
viewPagerCustomAdapter is an adapter dispatching farFarAway - how much distance ViewPager is moved starting left edge of 0 position Fragment. how to dispatch moved value to currently existing Fragments? - check this and create for loop over all registered fragments inside adapter's pass(int farFarAway). inside each Fragment you may calculate proper value for setTranslationX. you may also pass and use scrollToFactor (0.0-1.0) and position, these might be useful. e.g. position might determine if you are on current or next Fragment. note that default ViewPager memory is set to one, so there can't be more than 3 registered Fragments at once (current+both next)
edit 2:
create new class and extend all your Fragments used in your adapter
public abstract class AdapterFragment extends Fragment{
public abstract pass(int farFarAway);
}
add these lines to your adapter:
SparseArray<AdapterFragment> registeredFragments = new SparseArray<AdapterFragment>();
#Override
public Object instantiateItem(ViewGroup container, int position) {
AdapterFragment fragment = (AdapterFragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public void pass(int farFarAway) {
for(int i = 0, nsize = registeredFragments.size(); i < nsize; i++)
registeredFragments.valueAt(i).pass(farFarAway);
}
set above OnPageChangeListener for your ViewPager. In this way every Fragment gets current scroll position. so an example of use in one of your Fragments
public void pass(int farFarAway){
imageView.setTranslationX(farFarAway/10); //sample value 10, farFarAway is too big value for moving any View
}
your ImageView should move when while swiping ViewPager, adjust as you want. This whole post is almost full solution, should be useful...
PS. code not tested, might be some syntax or other bugs
Try reading about Fragment shared elements. Perhaps this is what you are looking for.
In My application, I have used the ViewPager.
Like,
(say main.xml)
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/register_header" />
And Create ViewPager object and ViewPagerAdapter(which extends FragmentPagerAdapter) object in FragmentActivity.
_mViewPager = (ViewPager) findViewById(R.id.viewPager);
_adapter = new ViewPagerAdapter(getApplicationContext(),
getSupportFragmentManager());
_mViewPager.setAdapter(_adapter);
And the Adapter class is like,
public class ViewPagerAdapter extends FragmentPagerAdapter {
private Context _context;
private FragmentManager manager;
private Fragment f;
private String classname="ViewPagerAdapter";
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
_context=context;
manager=fm;
}
#Override
public Fragment getItem(int position) {
Log.i(classname,"getItem called"+position);
f = new Fragment();
f=MyFragment.newInstance();
Bundle args = new Bundle();
args.putInt("position", position);
f.setArguments(args);
return f;
}
#Override
public int getCount() {
return User.getPageCount();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
And in MyFragment Class,
In onResume , I have to store the wigets object to the common static variable.
public void onResume() {
super.onResume();
pageIndex = getArguments().getInt("position");
User.useTextview1=textview1;
User.useTextview2= textview2;
User.current_pageIndex=pageIndex;
}
I have to update the textviews got from the User class in the FragmentActivity.
My Problem is getItem() method is called twice on First time
In Fact , the view displayed in the emulator is 0th index, but got 1st Index value in the FragmentActivity.
If I stopped the calling of getItem() method on second time, I can able to get the 0th index TextView reference in the FragmentActivity.
Please provide me the best way to do this.
Thanks
The FragmentPagerAdapter instantiates 2 Fragments on start, for index 0 and for index 1. If you want to get data from the Fragment which is on the screen, you can use setOnPageChangeListener for the Pager to get current position. Then have SparseArray with WeakReference to your fragments. Update that array in the getItem call. When onPageSelected gets called use that position to get reference to right Fragment and update User data.
Initialization of array:
private SparseArray<WeakReference<MyFragment>> mFragments = new SparseArray<WeakReference<MyFragment>>(3);
in getItem method i wrote this..
#Override
public Fragment getItem(int index) {
EditFragment frag = new EditFragment();
Bundle args = new Bundle();
args.putSerializable("currentItem", itemsList.get(index));
frag.setArguments(args);
return (frag);
}
here itemsList.get(index) is the model class object which i will use in EditFragment class.
here is that.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View result = inflater.inflate(R.layout.pager_fragment_layout, container, false);
image = (ImageView)result.findViewById(R.id.pager_image);
text = (TextView)result.findViewById(R.id.pager_item_desc);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity()).build();
ImageLoader.getInstance().init(config);
imLoader = ImageLoader.getInstance();
****NOTE
final SwapItems itemList = (SwapItems) getArguments().getSerializable("currentItem");
imagePath = itemList.getPaths().get(0);
imLoader.displayImage(imagePath,image);
text.setText(itemList.getItemDescription());
image.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new ItemImagesFragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Bundle bundle = new Bundle();
bundle.putSerializable("val", itemList);
fragment.setArguments(bundle);
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return result;
}
NOTE: here i am getting swapitems model object from previous getItem method is 'final'. this solves my issue. Earlier i was initialized the same object with static as modifier.
hope yours will also clear
My Problem is getItem() method is called twice on First time
This is not the problem, this is default feature of FragmentPagerAdapter. Its good for you to swipe from this page to the next one and previous one.
the view displayed in the emulator is 0th index, but got 1st Index value in the FragmentActivity
I got the same issue, and I know why. This because you used same Fragment in View Pager.
How to fix this is separate Fragments by using different Fragment.
I faced the same issue - getItem() method was called twice. I don't know about your purposes of using that method by mine was to trigger changes in a hosting activity when new slide appears.
Well, first of all getItem() is not a right method to get event of appearing new slide.
I used ViewPager.OnPageChangeListener listener on ViewPager itself for this purpose.
Here is what I did:
In Activity that holds slide fragments:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.signature_wizard_activity);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
onSlideChanged(position); // change color of the dots
}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {}
});
}
onPageScrolled() is called every time your slide appears, as a parameter it gets current position of the slide that is shown. Nice thing is that it is called including the first time it appears, not just when slide was changed.
When it can be used?
For example if you have some wizard activity with ViewPager where you slide fragments with some hints, you probable would like to have a bar with grey dots below the slider that would represent the number of slides in total, and one of the dots will be different color representing the current slide.
In this case ViewPager.OnPageChangeListener and method onPageScrolled() will be the best option.
Or if you have buttons PREV. and NEXT which change slides and you want to disable PREV. button on the first slide and disable NEXT button on the last slide. Here is how you do it inside onPageScrolled() method:
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(position == 0){
prevBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_grey_500));
prevBtn.setEnabled(false);
}else{
prevBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_blue));
prevBtn.setEnabled(true);
}
if(position == NUM_PAGES -1){
nextBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_grey_500));
nextBtn.setEnabled(false);
}else{
nextBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_blue));
nextBtn.setEnabled(true);
}
}
where NUM_PAGES is a constant with total number of slides
you can use this method to update your views
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// Fetch data or something...
}
}
In the CustomPagerAdapter of the ViewPager, in instantiateItem() method I'm trying to create an TextView and then for each page set a different text depending on certain condition. Text is read from a pages Cursor. Here is a code:
#Override
public Object instantiateItem(ViewGroup collection, int position) {
sc = new ScrollView(context);
sc.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
sc.setFillViewport(true);
tv = new TextView(context);
if(position < count) {
tv.setText(pages.getString(1));
pages.moveToPosition(position);
}else {
tv.setText("LOCKED");
}
tv.setTag(TAG_PAGE + position);
tv.setGravity(Gravity.CENTER);
tv.setTextColor(Color.BLACK);
tv.setTextSize(30);
sc.addView(tv);
((ViewPager) collection).addView(sc);
return sc;
}
However ViewPager behaves not as expected. The first and the second page have the same text, rest of the pages has a sign "LOCKED" as expected. When I swipe into the 4th page and come back to the first page then the first page consists of the text that suppose to be in the second page. I also tried to use myViewPager.setOffscreenPageLimit(numberOfPages) however it doesn't help.
I found this answer:
"Inside of instantiateItem, the position parameter is the position that is in need of rendering. It is NOT the position of the currently focused item that the user would see. The pages to the left and right of the currently displayed view need to be pre rendered in memory so that the animations to those screens will be smooth. "
It make sense to me but how then can I correctly display the pages content and then update it if desired? Please advise if there is different way to do it with skipping instantiateItem() method that introduce the mess and confusion into the problem. Thank you.
I have solved this problem by using a different implementation:
// Adapter class
private static class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
return PageFragment.newInstance(pages[index]); // Pages is an array of Strings
}
#Override
public int getCount() {
return numberOfPages;
}
}
// PageFragment class
public class PageFragment extends Fragment {
TextView tv;
public static PageFragment newInstance(String page) {
PageFragment pageFragment = new PageFragment();
Bundle bundle = new Bundle();
bundle.putString("pageContent", page);
pageFragment.setArguments(bundle);
return pageFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
tv = (TextView) view.findViewById(R.id.text_view);
tv.setText(getArguments().getString("pageContent"));
return view;
}
}
You can Create ViewPager Object and then set Listener onthis object.
ViewPager myPager = (ViewPager) findViewById(R.id.yourPagerid);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
myPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
//You can change textview word according to current page
switch (position) {
case 0:
break;
case 1:
break;
case 2:
break;
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// Log.d("check","onPageScrolled");
}
#Override
public void onPageScrollStateChanged(int arg0) {
// Log.d("check","onPageScrollStateChanged");
}
});