I have a list of fragments implemented together with FragmentStatePagerAdapter. I must replace the current fragment with a new one each time the button don't like will be clicked. The problem with the ViewPager. In my case the ViewPager scroll exactly list.size() -1 times smoothly, All other scrolling disable the smoothly scrolling.
doNotLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fragmentList.set(viewPager.getCurrentItem(), alternativeList.get(viewPager.getCurrentItem()));
viewPagerAdapter.notifyDataSetChanged();
viewPager.setCurrentItem(currentPos + 1, true);
}
});
I have no idea why the smoothly scrolling is so limited with fragmentList-size and how can I turn off this behaviour.
Related
Suppose I am having 5 fragments in viewpager. Lets say Fragment A, B, C, D, E.
I have a button on fragment A to go to fragment B. When I press this button, viewpager scrolls to fragment B. Somehow I controlled the duration of fragment A to B. Now the thing is, I have an scrollable container in Fragment B. I want to scroll that container during the Scroll between A to B happens. Now its scrolling after I am going from Fragment A to B. I want this happen between this transition.
Inside first fragment:
#Override
public void onClick(View view) {
if(view.getId() == bottomLayout.getId())
{
MainActivity.pager.setCurrentItem(1);
}
}
It will change my pager position 0 to 1. Now when its changing. I controlled the scroll speed of viewpager. On top of second fragment, I have a ScrollView, I need to perform scroll on this scrollview as fragment is changing,not after its changed.
To animate the view of the FragmentB, you need to tell it to start animation as soon as you call viewPager.setCurrentItem().
Inside FragmentA's click listener, you will ask the parent Activity to change the ViewPager item (see Communicating with the Activity to know how this should be done) :
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
activityCallback.setViewPagerItem(POSITION_OF_FRAGMENT_B);
}
});
In your Activity in which the ViewPager resides, you will write:
public void setViewPagerItem(int position) {
viewPager.setCurrentItem(position);
// following asks the fragmentB to start its animation on its view.
if (position == POSITION_OF_FRAGMENT_B) {
fragmentB.startYourAnimation();
}
}
In FragmentB, you add a method:
public void startYourAnimation() {
// write your code to animate your ListView or whatever you want to
// animate inside the FragmentB
}
Notes:
Unless you've called viewPager.setOffscreenPageLimit(), an instance of FragmentB will already exist if you're doing it from FragmentA or FragmentC,
a Fragment should not communicate with other fragments directly, instead they should use their parent Activity as a middle person. See Communicating with Other Fragments.
No it is not possible to do so because any scrollable view like listview or recyclerview, the items are created only when it is visible to user and only when scrolled, so if that fragment is not visible, you cannot scroll any of its child scrollable view.
I'm using Android Tutorial Bubbles library to add informative bubbles referring to views in my UI. My main UI consists of three tabs using a ViewPager. And I would like the tutorial for the second tab to begin only when the user navigates to that tab. I am able to catch the event that the user navigates to the tab using an OnPageChangeListener.
The problem is that the onPageSelected() method fires before the views are in their correct positions, meaning that the highlighted area that is supposed to surround the view of interest is significantly shifted. I could solve this using Thread.sleep() for a short period of time; is there a cleaner way of handling this?
Here's my code:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
if (position == 1) {
sensorReadingFragment.showTutorial();
}
}
});
Ok, you can delay it as
pager.post(new Runnable() {
#Override
public void run() {
pager.setCurrentItem(position_tab);
// Perform your operations
}
});
I need a ViewPager that enables to user to swipe images. But on a click on the images, a new activity has to start with another, bigger viewpager that contains the same images.
How can i implement a click listener while still keeping the swipe on the viewpager?
It should be pretty straight-forward, and has nothing to do with your ViewPager. Just add onClickListener to your ImageView:
ImageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// start new activity here
}
}
});
or add the onClick in XML:
<ImageView
...
android:onClick="startTheOtherActivity" />
I've got an App with a LinearLayout to which rectangular fragments are added below each other over time from top to bottom.
At some point the screen is full and the new fragments are "hidden" outside the view of the screen. What I'd like to do then is to make the App scroll to bottom every time a new fragment is added.
A fragment is added everytime a button in the activity is pushed or a checkbox in the above fragment is checked.
So I've tried the following in the onClickListeners and in the onCreateView of the fragments:
fm.beginTransaction().add(R.id.activity_uhf_layout, fragment).commit(); //Adding fragment
runOnUiThread(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(0, scrollView.getBottom());
}});
This works sometimes, the fragment is added and the screen scrolls down, but its like 1/8 times.
I've tried other things such as:
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(0, scrollView.getBottom());
}
});
Which basically gives the same result and I've tried without the Runnable post, which doesn't work at all.
The result I'm getting is that the layout is only scrolled down to the bottom of the fragment which is already present and not all the way down to the end of the new fragment which has just been added by the fragmentmanager.
To me it seems that even though the fragment is added, the LayoutManager hasn't really "detected it" or something similar, but how to get around it, I'm not really sure about.
You could also try doing this.
fm.executePendingTransactions();
runOnUiThread(new Runnable() {
#Override
public void run() {
//Linearlayout is the layout the fragments are being added to.
View view = linearLayout.getChildAt(linearLayout.getChildCount()-1);
scrollView.scrollTo(0, view.getY() + view.getHeight());
}});
I don't know that the executePendingTransactions() is necessary, but if the view has been added, then that should work.
i wrote a FragmentActivity with a ViewPager, i did not want to use the actionbar for the tabs (because i did not want the tabs to be positioned over the menu) and also not the PagerTabStrip solution, because i could not customize it as i wanted.
so i wrote an own linearlayout as tabs container:
<LinearLayout
android:id="#+id/main_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:orientation="horizontal" >
</LinearLayout>
with an View.OnClickListener for each of each tab
OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(final View view) {
mapTabs.get(lastSelectedTab).setSelected(false);
view.setSelected(true);
Runnable runnable = new Runnable() {
#Override
public void run() {
int index = Integer.parseInt(view.getTag().toString());
FragmentActivity.setTab(index);
lastSelectedTab = index;
}
};
handler.post(runnable);
}
};
}
public static void setTab(int index) {
FragmentActivity.viewPager.setCurrentItem(index, true); // true or false does not make any difference
}
this is the method i wrote to add the single tabs to the tab container (main_tabs):
private void addTab(LayoutInflater inflater, ViewGroup tabs, int imageId, View.OnClickListener onClickListener) {
inflater.inflate(R.layout.main_tab, tabs);
int index = tabs.getChildCount() - 1;
ImageView ivTab = (ImageView) tabs.getChildAt(index);
ivTab.setTag(String.valueOf(index)); // stored the tab index
ivTab.setImageResource(imageId);
ivTab.setOnClickListener(onClickListener);
mapTabs.put(index, ivTab); // add an imageview to the tab
}
i used the runnalbe so that i see the highlighting of the tab immediately, and not after the slight delay when the new page appears. i also stored the last selected tab in order to deselect it when the new one gets selected.
i store all tabs in a map in order to access them later for selection.
this is the OnPageChangeListener i wrote (to highlight the associated tab):
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
mapTabs.get(position).setSelected(true); // selected the tag asociated with the current visible page
mapTabs.get(lastSelectedTab).setSelected(false); // deselectes the last selected tab
lastSelectedTab = position;
ListFragment<?> item = FragmentActivity.fragmentAdapter.getItem(position);
setTitle(item.getTitle());
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
everything works fine, i am just not clear about the performance:
when i scroll to the next page, everything goes very fast and smooth. the next page appears immediately without any dealy; only the menu in the action bar (created in the onCreateOptionsMenu(Menu menu, MenuInflater inflater) method of each Fragment) appears with a slight delay (about 500-700 ms).
but when i click on one of the tabs, the selected page appears not immediately but with a slight delay (actually the same time the menu needs to appear as mentioned above: menu and page appear together at the same time). bzw. this happens also when i use the tabstrip solution.
i guess if its possible to achieve a delay-less page change by scrolling, it should be possible somehow to achieve the same performance for the tab clicks.
but what do i do wrong?
and is there a possibility to make the menu appear immediately just like the pages when scrolling? can the different menus not be cached just like the pages?
the solution was extremely simple. i just had to keep all my 4 tabs in the ViewPager so that they don't need to get recreated (and therefore don't cause the short delay after each tab-clicki). i just had to add following lines to the onCreate method.
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setOffscreenPageLimit(4);
to avoid delay between tabs click in view pager should set the limit of tabs like
pager.setOffscreenPageLimit(4);
try this
myViewPager.animate().translationX(0f).setDuration(1000);
where 1000 is delay in milliseconds