How to slide only half Fragment while using vertical ViewPager - android

I was looking for vertical viewpager then I found this answer
it's working fine, but now I need to slide only half of the fragment.
I did this before, using horizontal viewpager with below solution
Override the getPageWidth method of PagerAdapter and make it return 0.5f;
but because I'm using vertical viewpager instead of horizontal viewpager, and FragmentPagerAdapter does not have any override method to return height
Is there any possible solution to do it?

just replace VerticalPageTransformer class with this source
private class VerticalPageTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
if (position < -1) {
view.setAlpha(0);
} else if (position <= 1) {
view.setAlpha(1);
view.setTranslationX(view.getWidth() * -position);
float yPosition = position * (float)(view.getHeight() / 2.5);
view.setTranslationY(yPosition);
} else {
view.setAlpha(0);
}
}
}
it works perfectly ;)

Related

View pager 2: Depth Page Transformation make fragment click events disable on pager swipe up

I am using viewpager2 with fragmentStateAdapter.
Also, setting page transformer as DepthPageTransformation(transition is working correctly the way I want)
But when I swipe up the pages, the on click events on that fragment works on double click(event works after clicking twice on it)
If I remove pageTransformation from the viewPager, then it works fine.
So, not able to understand that why is transformation causing click event problem.
private static final float MIN_SCALE = 0.75f;
public void transformPage(#NonNull View view, float position) {
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0f);
Log.d("batman",position+" <-1");
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1f);
view.setTranslationY(0f);
view.setScaleX(1f);
view.setScaleY(1f);
Log.d("batman",position+" <=0");
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationY(pageHeight * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
Log.d("batman",position+" <=1");
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0f);
Log.d("batman",position+" else");
}
}
}
HomeFragment(adapter setting):
mAdapter = new ViewPagerAdapter(this);
setPageChangeListener();
mViewPager.setAdapter(mAdapter);
// mViewPager.setOffscreenPageLimit(3);
mViewPager.setPageTransformer( new DepthPageTransformer());
I want that button click event should work at one click when the page is swiped up.
The clicks of the previous fragment were getting disabled on swipe up because I was updating my fragment which is added in view pager from onPageSelected() listener, so that was making the button work on double click.
#Override
public void onPageSelected(int position) {
homePresenter.onPageSelected();
currentPg = position;
}
Maybe we cannot update our fragment from this listener.

Swipe ViewPager with animation on RecyclerView horizontal scroll- Android

I am developing an Android app in which I have one ViewPager on top and one horizontal RecyclerView below the ViewPager.
When I scroll the RecyclerView, I am updating the ViewPager item with viewPager.setCurrentItem(position). So that the ViewPager will swipe to that position.
It is working fine. But the ViewPager does not swipe with animation. It only moves to the current position.
I want apply some animation while swiping the ViewPager on RecyclerView scroll. How can I implement that animated behaviour?
Try with
viewPager.setCurrentItem(position, true)
As per the documentation of the ViewPager, it allows moving to that position smoothly.
I think you want to use fade In effect for animation.
you should import this class in your file...
public class FadePageTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(#NonNull View page, float position) {
page.setTranslationX(page.getWidth() * -position);
if (position <= -1.0F || position >= 1.0F) {
page.setAlpha(0.0F);
} else if (position == 0.0F) {
page.setAlpha(1.0F);
} else {
// position is between -1.0F & 0.0F OR 0.0F & 1.0F
page.setAlpha(1.0F - Math.abs(position));
}
}
}
And after include that class you need to set your view pager like this...
viewPager.setPageTransformer(false,new FadePageTransformer());
it Will help you to implement animation effect in view pager

Android SlidingTabs Blending Background Colors

I have a ViewPager and a SlidingTabLayout (uses com.jpardogo.materialtabstrip:library:1.1.0) that works fine. The transition used is the DepthPageTransformer. My question is how could I have a different color for every tab/fragment and when I change tabs it smoothly blends to the tab color. I would also like the same thing to happen to the tabs, toolbar, and the very top bar. Help would be very appreciated!
An example would be the 360 Security App (https://play.google.com/store/apps/details?id=com.qihoo.security&hl=en)
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}

Android ViewPager different transitions for different pages

Is it possible to setup different PageTransformers for different fragments in ViewPager?
I would like to use ZoomOutPageTransformer when the user swipes between (0, 1) and (n-1, n) fragments of ViewPager with n fragments and use the default transitions for all other cases.
What I tried:
Detect the current page with mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { ... }) and apply different transitions here. But, for example, if the user is on the first page - how to set ZoomOutPageTransformer only for the case when he will swipe to the left (0 page) and do it before animation is started?
I had a less similar requirement wherein I had applied Depth page transformer to all my pages by default and on tap of a button I changed it to Vertical page transformer and then back to Depth page. (A lil wierd but thats how it was)
I did the below:
Applied viewPager.setPageTransformer(true, new DepthPageTransformer()); for all the pages.
onClick I changed it to viewPager.setPageTransformer(true, new VerticalPageTransformer());. Now here's the catch in-order for this to function smoothly I had to use a handler in order to change the page a little later to ensure VerticalPager takes effect. I achieved this by calling viewPager.setCurrentPosition(viewPager.getCurrentItem() + 1)
After this inside onPageChangeListener's onPageSelected method I changed it back to viewPager.setPageTransformer(true, new DepthPageTransformer()); again inside a handler to ensure it's done after my vertical animation is completed.
Note - I had also accessed ViewPager's scroller to achieve the above to define my own speed for the page change.
Let me know if this makes sense, since you need it to be done based on page numbers. If it does I will share my code. :)
This is quite old, but wish it's not too late for somebody
Step 1:
Create custom ViewPager which extends from ViewPager.
Step 2:
Determine which Fragment positions (ViewPager page integers) you need to have a unique PageTransformer for them. Then add these indices into a list within the custom ViewPager.
Step 3:
Override onPageScrolled(int position, float offset, int offsetPixels):
Check if the position is in your list of indices, if so, then you have to create a Custom PageTransformer object; and then utilize the ViewPager setPageTransformer() to change the page transformation.
For positions other than that, then you've to set the default PageTransformer (or you can also you another custom PageTransformer object if you wish.
Code
public class CustomViewPager extends ViewPager {
public CustomViewPager(Context context) {
super(context);
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
PageTransformer mDepthPageTransformer = new PageTransformer() {
private static final float MIN_SCALE = 0.75f;
public void transformPage(#NonNull View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0f);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1f);
view.setTranslationX(0f);
view.setScaleX(1f);
view.setScaleY(1f);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0f);
}
}
};
PageTransformer mDefaultPageTransformer = new PageTransformer() {
#Override
public void transformPage(#NonNull View page, float position) {
}
};
#Override
protected void onPageScrolled(int position, float offset, int offsetPixels) {
List<Integer> pos = new ArrayList<>();
pos.add(0);
pos.add(n - 1); // n is the no. of pages as in the question
if (pos.contains(position)) {
this.setPageTransformer(true, mDepthPageTransformer);
} else {
this.setPageTransformer(true, mDefaultPageTransformer);
}
super.onPageScrolled(position, offset, offsetPixels);
}
}
Documentation
Slide between fragments using ViewPager
setPageTransformer() method
Note: mDepthPageTransformer used in my example is taken from the above mentioned documentation.
Inspite Of using mViewPager.setOnPageChangeListener , a single PageTransformer with different animations can help.
Have a look at first paragraph here ,
http://developer.android.com/training/animation/screen-slide.html#pagetransformer

ListView inside ViewPager won't scroll when applying a PageTransformer

I have a ViewPager in which the pages contain ListViews.
Everything works fine and my viewPAger as well as ListViews work as expected : it is possible to swipe from page to page, and the listviews scroll vertically as they should.
Now I wanted to add a PageTransformer to smooth out paging anbd I used the ZoomOutPageTransformer offered in the google docs.
Now I have a nice animation when swiping between views but the Lists are not scrollable anymore.
Here's the code :
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LayoutInflater inflater = LayoutInflater.from(getActivity());
viewPager = (ViewPager) view.findViewById(R.id.bookMenuPager);
viewPager.setPageTransformer(false, new ZoomOutPageTransformer());
pagerAdapter = new MenuPagerAdapter();
viewPager.setAdapter(pagerAdapter);
}
class MenuPagerAdapter extends PagerAdapter{
#Override
public int getCount() {
return 3; //change this as needed
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view.equals( o );
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(position == 0){
if(!rootMenuAdded){
viewPager.addView(rootMenucont, 0);
rootMenuAdded = true;
}
return rootMenucont;
}else if(position == 1){
if(!level1MenuAdded){
viewPager.addView(level1MenuCont, 0);
level1MenuAdded = true;
}
return level1MenuCont;
}else if(position == 2){
if(!level2MenuAdded){
viewPager.addView(level2MenuCont, 0);
level2MenuAdded = true;
}
return level2MenuCont;
}
//we got a problem houston
return null;
}
}
and the layout for a page :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/level1MenuCont"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<ListView
android:id="#+id/level1Menu"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#f02bb6"
>
</ListView>
</RelativeLayout>
What can I do to have my lists scrolling as expected ? What does the PageTransformer break in my ListView so that it wont scroll anymore?
Is this a known bug?
Thanks for any help :)
I think I have found a workaround for this issue.
After some investigation, I think this only happens if you apply a PageTransformer that changes the coordinates of the Views so they are all on top of each other (the two example transformers do exactly this).
When you swipe in the direction such as the NEW VIEW has a Z-index LOWER than the OLD VIEW (normally a swipe backwards), what happens with those transformers is that the OLD VIEW is on top of the NEW VIEW, with Alpha==0, and is the one that later on gets the "ghost" touches.
Unfortunately, the solution by #ngatyrauks bringToFront() didn't work for me (although it definitely should).
However, I have tweaked the transformer so invisible views are changed its visibility to "GONE". And this does the trick.
I have yet to investigate if this Visibility change has any side effects (A GONE view will return null and zeros in layout etc, so maybe this breaks other things inside ViewPager), but so far it's working perfect.
I post here a tweaked DepthPageTransformer (the same in the docs) with these changes. Hope it helps anybody!
package com.regaliz.gui.fx;
import android.util.Log;
import android.view.View;
import android.support.v4.view.ViewPager;
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final String TAG="DepthTransformer";
private static float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
Log.d(TAG, "VIew "+view+" Position: "+position);
if (position <= -1) { // [-Infinity,-1) ] ***
// RLP> I Changed to include "-1" as well: When position is -1, the view is not visible
// This page is way off-screen to the left.
view.setAlpha(0);
Log.d(TAG, "VIew "+view+" Position: "+position+", way left");
view.setVisibility(View.GONE);
} else if (position <= 0) { // [ (-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
if (position==0) {
Log.d(TAG, "View "+view+" focused now?");
}
if (view.getVisibility()!=View.VISIBLE)
view.setVisibility(View.VISIBLE);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
// I THINK THIS IS WHAT BREAKS EVERYTHING
// ViewPager normally has the views one after another, but this makes all views on top
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
if (position==1) {
Log.d(TAG, "View "+view+" invisible now?");
view.setVisibility(View.GONE);
// we totally hide the view. This seems to solve focus issue
} else {
if (view.getVisibility()!=View.VISIBLE)
view.setVisibility(View.VISIBLE);
}
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
// we totally hide the view. This seems to solve focus issue
// I have to check for strange side-effects, but so far I found none :)
view.setVisibility(View.GONE);
Log.d(TAG, "VIew "+view+" Position: "+position+", way right");
}
}
}
Here is the detail of the reason
after 4.1 that the framework respects a custom child drawing order as implied Z-ordering for dispatching touch events. If your views overlap after this page transformation they may not receive touch events in the expected order on older platform versions. Check which view is receiving the touch events to be certain.
If this is what you are seeing you have a few options:
Enforce the desired ordering as you add/remove child views in your PagerAdapter
Remove the X translation applied by the PageTransformer when a page is no longer fully visible - i.e. the "position" parameter reports a full -1 or 1.
And here is my solution
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position <= -1 || position >= 1) { // [-Infinity,-1) ] ***
// [-Infinity,-1] or [1,+Infinity]
// This page is way off-screen to the left or way off-screen to the right.
view.setAlpha(0);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 0) { // [ (-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position < 1) {
// (0,1)
// Fade the page out.
view.setAlpha(1 - position);
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
}
ref link: https://code.google.com/p/android/issues/detail?id=58918
I don't know if you got this working, but I have the same issue, with a PageDepthTransformer. I'm using a gridview though, the scrolling works, however my subsequent fragments seem to have focus and my top level Fragment doesn't register the correct onClick() events.
My work around for this was to add global layout listener to viewPager and bring the current view to the front
viewPager.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
View view = viewPager.getChildAt(currentFragmentPosition);
if (view != null) {
view.bringToFront();
}
}
)};
This seems like hackery to me, and I haven't quite got this working on rotation. But hopefully it might help you.

Categories

Resources