Not sure what is going on here but I have implemented the Zoom features on an image-gallery in a ViewPager, ImagePagerAdapter using TouchImageView. On all my other phones and tablets the code works perfect, for zooming and page flipping. On 3 of our Motorola Razrs the Zooming acts funny on the first image. By funny I mean that when you try and zoom nothing happens on picture #1. But if you pan to the next image the zooming from image 1 has affect image 2. If you flip back to image 1 it still doesn't zoom. If you pan to image #3 then back to #1 the first image will zoom just fine. Not sure how to tackle this issue or even debug it. I have added custom animation, DepthPageTransformer, from the examples in API. This is the culprit, but not sure what in the code is causing this behavior.
import android.annotation.SuppressLint;
import android.support.v4.view.ViewPager.PageTransformer;
import android.view.View;
public class DepthPageTransformer implements PageTransformer {
private static final float MIN_SCALE = 0.55f;
// suppress compiler warning...lower Api use standard slide in but
// APIs higher than 10 will use the transform page function
#SuppressLint("NewApi")
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);
}
}
}
Apparently the animation was causing this weird behavior. Not sure why but until I figure it out I had to remove the setting of this animation.
galleryViewPager.setClickable(true);
//galleryViewPager.setAnimation(new DepthPageTransformer());
galleryViewPager.setOnClickListener(new OnClickListener() {...
Now the fling animation is using the standard. Must be the way the Motorola Razr implements the adapter fling animation that messes up the listener order.
Related
I am implementing ViewPager Transformer where, Text Alpha should slowly transformed from 0.3f(Unselected Page) - 1.0f(Selected Page) as we are swiping in viewpager.
Here is the Desired output. Viewpager Transformation image
As I am new to Android, I tried following approach, basically I am confused in what formula to apply.
public class AlphaTextTransformer implements ViewPager.PageTransformer {
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(0.3 f);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(0.3 f);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(0.3 f + Math.abs(position));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0.3 f);
}
}
}
I show 3 pages in screen at a time.Left & Right page are partially shown with Text alpha value to 0.3f.Center page text has alpha value of 1. I don't want to immediately set alpha value to 1, but rather it will be progressive as we perform sliding. Can someone please help me with correct pointer? I would really appreciate if someone can help me with Sample code.
Thanks.
Did you check the value of postion with breakpoint or log? Maybe it does not correspond to your expected value?
You should check on this library's code to see how it works, it's with pagetransformer
It seems like a challenging animation, but I have a feeling this can be done very easily. I am trying to achieve an animation between Fragments like below (see 2nd and 3rd quadrant)
Enter and exit are not difficult, but pre-displaying next and previous card's screen and seamless transition to next card is out of my knowledge scope. Please, if anyone has worked on a similar animation, give me some pointers.
EDIT
The official documentation of Android transitions on click i.e. when user clicks page is zoomed out to show last and previous page and swipe moves it to next one. My requirement is to leave the page at zoomed out level and transition on button clicks:
Question: How will be the view default out to x zoom level to show previous next page parts and transition on click.
You can customize the transition animation between fragments using PageTransformer.
ZoomOutPageTransformer
import android.support.v4.view.ViewPager;
import android.view.View;
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.85f;
private static final float MIN_ALPHA = 0.5f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
Usage
viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
Official documentation.
Checkout this and this for showing boundaries of near one.
For folks who come to this question looking for similar requirement:
As Anoop suggests, official documentation is great. Simply implement viewPager.PagerTransform and supply the class to your viewPager. Also, transformPage (the implemented function) is very important in animation transition.
Next part, was to show corners of next and previous fragments. This can be acheived through xml of fragments. Reference : Android tip viewpager with protruding children
Hopes this helps someone to create interactive apps.
UPDATE
This post shared by Anoop makes this transformation a breeze. cheers!
I'm trying to change my ViewPager transition animation.
I'd like to have the same behavior as the default gallery, when you switch from one photo to the next one. It's basically an animation where the current page goes to the left while the next one comes from behind it and grows larger.
I've seen that I can change the animation with a PageTransformer.
pager.setPageTransformer(false, new PageTransformer() {
#Override
public void transformPage(View page, float position) {
if (position < 0) {
} else {
final float normalizedposition = Math.abs(Math.abs(position) - 1);
page.setScaleX(normalizedposition / 2 + 0.5f);
page.setScaleY(normalizedposition / 2 + 0.5f);
}
}
});
With that, I have the current page sliding to the left, that's ok.
The new page starts small in size and grows, that's also ok. But, the page comes from the right to center. I'd like to remove the translation and have it already in the middle, but small, hidden by the current page.
If I add page.setTranslationX(1080 * (-(position))); then the next pages stays in the middle of the screen, but they are visible at all time above the current page. If I also add alpha to the page, the page appearing isn't hidden behind the old one.
I've tried to check in the source code of the gallery app but I didn't found any reference to the transformPage function.
Turns out to be easy. It is in the demos in the android developper website.
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);
}
}
}
See here (Depth page transformer).
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.
friends....
I got a problem with animation in betwen versions...So i will give description about the requirements of my app and problem im facing
1.My consists of animation which consists viewpager.
2.And this animation must work in lower versions such as 2.2.
3.So for this i have found a awsome library ninoldandroid.
4.I have used animation proxy for my animation.
5.It waa working fine in 4.2.
6.But when coming to 2.2 the animation was not working and the viewpager was moving with its default feature.
My code for animation is...
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();
AnimatorProxy proxy = AnimatorProxy.wrap(view);
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
proxy.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
proxy.setAlpha(1);
proxy.setTranslationX(0);
proxy.setScaleX(1);
proxy.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
proxy.setAlpha(1 - position);
// Counteract the default slide transition
proxy.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
proxy.setScaleX(scaleFactor);
proxy.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
proxy.setAlpha(0);
}
}
}
Can u tell what i have to implement to make this anim ation work in 2.2.
If u feel that the question is insuffient please let me know..Thnaq
There is a Animated view pager by jfeinstein JazzyViewPager which is used by nineoldandroid. which work from 2.2.
(Sorry for late replay)