The code for dept page transformation animation appears when slide to left, to achieve the similar effect when sliding to right I did work around but have no success.
Depth Page Tranfomer
I want the same effect when I back to previous image that is the coming image must zoom out and current image slide to right. Any solution or fix for this?
This code solves the problem, but is written in C#,i use Xamarin.Android, but it should be easy to translate to java, because it is translated from Java.
It is a class derived from RecyclerView.ViewHolder because in my code I use a RecyclerView to display multiple ViewPager.
I implement the interfaces
ViewPager.IPageTransformer
ViewPager.IOnPageChangeListener
In Java are
ViewPager.PageTransformer
ViewPager.OnPageChangeListener
In the same class to know if this dragging to the right or to the left.
And the transformation change in the direction
public class PhotoPaisViewHolder : RecyclerView.ViewHolder,
ViewPager.IPageTransformer,
ViewPager.IOnPageChangeListener
{
private static AtomicInteger sNextGeneratedId = new AtomicInteger(1);
/**
* Generate a value suitable for use in {#link #setId(int)}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* #return a generated ID value
*/
public static int GenerateViewId()
{
for (;;)
{
int result = sNextGeneratedId.Get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.CompareAndSet(result, newValue))
{
return result;
}
}
}
public ViewPager Pager { get; private set; }
// Get references to the views defined in the CardView layout.
public PhotoPaisViewHolder(View itemView)
: base(itemView)
{
// This for support multiple pagers in the same RecyclerView
Pager = itemView.FindViewById<ViewPager>(Resource.Id.pager);
if (Build.VERSION.SdkInt < BuildVersionCodes.JellyBeanMr1)
{
Pager.Id = PhotoPaisViewHolder.GenerateViewId();
}
else
{
Pager.Id = View.GenerateViewId();
}
Pager.AddOnPageChangeListener(this);
Pager.SetPageTransformer(reverse, this);
}
//For control the transformation
private static float MIN_SCALE = 0.75f;
private int currentPos;
private bool reverse;
private bool dragging;
public void TransformPage(View view, float position)
{
// Console.WriteLine(position);
int pageWidth = view.Width;
if (position < -1)
{ // [-Infinity,-1)
// This page is way off-screen to the left.
view.Alpha = 0;
}
else if (position <= 0)
{ // [-1,0]
// Use the default slide transition when moving to the left page
if (reverse)
{
TransformUpView(view);
}
else
{
TransformDownView(view, position, pageWidth);
}
}
else if (position <= 1)
{ // (0,1]
// Fade the page out.
if (reverse)
{
TransformDownView(view, position, pageWidth);
}
else
{
TransformUpView(view);
}
}
else
{ // (1,+Infinity]
// This page is way off-screen to the right.
view.Alpha = 0;
}
}
private static void TransformDownView(View view, float position, int pageWidth)
{
view.Alpha = 1 - Math.Abs(position);
// Counteract the default slide transition
view.TranslationX = pageWidth * -position;
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.Abs(position));
view.ScaleX = scaleFactor;
view.ScaleY = scaleFactor;
}
private static void TransformUpView(View view)
{
view.Alpha = 1;
view.TranslationX = 0;
view.ScaleX = 1;
view.ScaleY = 1;
}
public void OnPageScrollStateChanged(int state)
{
dragging = state == ViewPager.ScrollStateDragging;
}
public void OnPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
if (dragging)
{
if (position < currentPos)
{
if (reverse)
{
reverse = !reverse;
Pager.SetPageTransformer(reverse, this);
}
}
else
{
if (!reverse)
{
reverse = !reverse;
Pager.SetPageTransformer(reverse, this);
}
}
}
}
public void OnPageSelected(int position)
{
currentPos = position;
}
}
Related
I want to center the clicked position in the Recyclerview. I am able to scroll the Recyclerview to certain position but i want to middle that position in the screen.
I used this method to scroll to that position.
videoRecyclerview.scrollToPosition(position);
If you are using a RecyclerView and LinearLayoutManager this will work:
private void scrollToCenter(View v) {
int itemToScroll = mRecyclerView.getChildPosition(v);
int centerOfScreen = mRecyclerView.getWidth() / 2 - v.getWidth() / 2;
mLayoutManager.scrollToPositionWithOffset(itemToScroll, centerOfScreen);
}
if you use linearlayoutManager, you can use this code,
linearLayoutManager.scrollToPositionWithOffset(2, 20);
(linearLayoutManager.void scrollToPositionWithOffset (int position,
int offset))
Setting the offset to 0 should align with the top
first move scroll to your item, but whenever recyclerView scrolls it just brings the item in visible region, it is never sure that the item is in center or not, so we find the center item and then check if we are on next to center to item or behind it, here is working logic
recyclerView.smoothScrollToPosition(index);
int firstVisibleItemPosition = rvLayoutManager.findFirstVisibleItemPosition();
int lastVisibleItemPosition = rvLayoutManager.findLastVisibleItemPosition();
int centerPosition = (firstVisibleItemPosition + lastVisibleItemPosition) / 2;
if (index > centerPosition) {
recyclerView.smoothScrollToPosition(index + 1);
} else if (index < centerPosition) {
recyclerView.smoothScrollToPosition(index - 1);
}
If you need smooth scroll to centre for LieanerLayoutManager both horizontal & vertical
Copy the entire code and simply call** scrollToCenter:
public void scrollToCenter(LinearLayoutManager layoutManager, RecyclerView recyclerList, int clickPosition) {
RecyclerView.SmoothScroller smoothScroller = createSnapScroller(recyclerList, layoutManager);
if (smoothScroller != null) {
smoothScroller.setTargetPosition(clickPosition);
layoutManager.startSmoothScroll(smoothScroller);
}
}
// This number controls the speed of smooth scroll
private static final float MILLISECONDS_PER_INCH = 70f;
private final static int DIMENSION = 2;
private final static int HORIZONTAL = 0;
private final static int VERTICAL = 1;
#Nullable
private LinearSmoothScroller createSnapScroller(RecyclerView mRecyclerView, RecyclerView.LayoutManager layoutManager) {
if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
return null;
}
return new LinearSmoothScroller(mRecyclerView.getContext()) {
#Override
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
int[] snapDistances = calculateDistanceToFinalSnap(layoutManager, targetView);
final int dx = snapDistances[HORIZONTAL];
final int dy = snapDistances[VERTICAL];
final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
if (time > 0) {
action.update(dx, dy, time, mDecelerateInterpolator);
}
}
#Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
}
private int[] calculateDistanceToFinalSnap(#NonNull RecyclerView.LayoutManager layoutManager, #NonNull View targetView) {
int[] out = new int[DIMENSION];
if (layoutManager.canScrollHorizontally()) {
out[HORIZONTAL] = distanceToCenter(layoutManager, targetView,
OrientationHelper.createHorizontalHelper(layoutManager));
}
if (layoutManager.canScrollVertically()) {
out[VERTICAL] = distanceToCenter(layoutManager, targetView,
OrientationHelper.createHorizontalHelper(layoutManager));
}
return out;
}
private int distanceToCenter(#NonNull RecyclerView.LayoutManager layoutManager,
#NonNull View targetView, OrientationHelper helper) {
final int childCenter = helper.getDecoratedStart(targetView)
+ (helper.getDecoratedMeasurement(targetView) / 2);
final int containerCenter;
if (layoutManager.getClipToPadding()) {
containerCenter = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;
} else {
containerCenter = helper.getEnd() / 2;
}
return childCenter - containerCenter;
}
it's worked for me with this code :
layoutManager.scrollToPositionWithOffset(pos - 1,0);
//on the click callback
view.OnClickListener { callback?.onItemClicked(it)}
// code in activity or your fragment
override fun onItemClicked(view: View) {
val position = recyclerView.getChildLayoutPosition(view)
recyclerView.smoothScrollToPosition(position)
}
simplest hack ever, this was good enough for me:
videoRecyclerview.scrollToPosition(position+2);
if position+2 is within the arraylist.
Above is my issue screenshot. I just want to remove the opacity while I swipe up and down. When I swipe down, the current page turns transparent. I need to remove that transparency. Instead of extending the ViewPager, I have extended the activity. Can anyone give me solution for this issue?
public class VerticalViewPager extends Activity {
private static final float MIN_SCALE = 0.75f;
PagerAdapter adapter;
private static final float MIN_ALPHA = 0.75f;
private boolean a;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.verticalviewpager);
fr.castorflex.android.verticalviewpager.VerticalViewPager verticalViewPager = (fr.castorflex.android.verticalviewpager.VerticalViewPager) findViewById(R.id.verticalviewpager);
adapter = new MyCustomAdapter(VerticalViewPager.this, SplashScreen.newsidArray, SplashScreen.newsdescArray, SplashScreen.newstitleArray,
SplashScreen.newsimageArray, SplashScreen.newsdateArray, SplashScreen.newsauthorArray, SplashScreen.newsurlArray);
verticalViewPager.setOffscreenPageLimit(1);
verticalViewPager.setAdapter(adapter);
verticalViewPager.setPageTransformer(false, new PageTransformer() {
#Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position <= -1.0F) {
view.setAlpha(1);
Log.e("1", "test1");
} else if (position < 0F) {
view.setAlpha(1);
Log.e("2", "test2");
} else if (position >= 0F) {
view.setAlpha(0.9F - position);
view.setTranslationY((int) ((float) (pageHeight) * -position));
Log.e("3", "test3" + position);
} else if (position > 1.0F) {
view.setAlpha(1);
// view.setTranslationX(position < 0 ? 0f : -pageHeight * position);
Log.e("4", "test4");
}
}
});
}
}
Please try this.
And you have to confirm not using setAlpha() anywhere for page layout.(e.g. layout xml)
verticalViewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
#Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position >= 0) {
view.setTranslationY(position < 0 ? 0f : -pageHeight * position);
}
}
});
I got the answer, you need to set the background for the view you are animating. By default it is transparent
android:background="#FFFFFF"
If more than 50% of the follower of View B is visible,
on release the ViewPager will animate to the View B instead of goind back to View A.
How can I change this point of switching from 50% to x%?
You can do this by overriding the onScrollChanged() function, here's an example:
#Override
public void onScrollChanged(ViewPager vp, int x, int y, int oldx, int oldy) {
// We take the last son in the ViewPager
View view = (View) vp.getChildAt(vp.getChildCount() - 1);
if (diff < view.getBottom()/2) {
// do the animation
}
}
Let me know if that worked or not (in order for me to know if I should remove the Answer from here).
Thanks
You can build your own customized ViewPager and override the proper method with your own float-value. something like :
public CustomViewpager extends ViewPager {
#Override
private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) {
int targetPage;
if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) {
targetPage = velocity > 0 ? currentPage : currentPage + 1;
} else {
//change your values here for whatever you need for your purposes
final float truncator = currentPage >= mCurItem ? 0.4f : 0.6f;
targetPage = (int) (currentPage + pageOffset + truncator);
}
if (mItems.size() > 0) {
final ItemInfo firstItem = mItems.get(0);
final ItemInfo lastItem = mItems.get(mItems.size() - 1);
// Only let the user target pages we have items for
targetPage = Math.max(firstItem.position, Math.min(targetPage, lastItem.position));
}
return targetPage;
}
}
I need to write a custom transition for a ViewPager on an app with android:minSdkVersion="9".
I'm trying to run the ZoomOutPageTransformer given here.
I get no compiling error, and on a Samsung Galaxy S running Android 2.3.3 (API 10), the line
pager.setPageTransformer(true, new ZoomOutPageTransformer());
does not give any error, but the code in ZoomOutPageTransformer's transformPage is never executed.
The code works perfectly if I set android:minSdkVersion="11" and use my Nexus 4 (API 17).
Can these PageTransformers be used with API 9 and 10? Otherwise, how can I create custom transitions for ViewPager?
EDIT
Here's the code I use:
public class HomeFragment extends Fragment{
ViewPager mNewsTitlePager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.home_content, container, false);
}
#Override
public void onActivityCreated (Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
mNewsTitlePager = (ViewPager) getView().findViewById(R.id.news_title_pager);
mNewsTitlePager.setPageTransformer(true, new ZoomOutPageTransformer());
mNewsTitlePager.setAdapter(new NewsPagerAdapter(news_item_list));
}
private class NewsPagerAdapter extends PagerAdapter {
private List<News> news_item_list;
private LayoutInflater inflater;
NewsPagerAdapter(List<News> news_item_list) {
this.news_item_list = news_item_list;
inflater = getActivity().getLayoutInflater();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public void finishUpdate(View container) {
}
#Override
public int getCount() {
return this.news_item_list.size();
}
#Override
public Object instantiateItem(ViewGroup view, int position) {
TextView news_title = (TextView) inflater.inflate(R.layout.news_title_item, view, false);
news_title.setText(news_item_list.get(position).title);
((ViewPager) view).addView(news_title, 0);
return news_title;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
#Override
public Parcelable saveState() {
return null;
}
#Override
public void startUpdate(View container) {
}
}
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private float MIN_SCALE = 0.85f;
private 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);
}
}
}
}
I copied the ViewPager class from here and removed the if statement for the version and called it TransformableViewPager
public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
if (Build.VERSION.SDK_INT >= 11) {
final boolean hasTransformer = transformer != null;
final boolean needsPopulate = hasTransformer != (mPageTransformer != null);
mPageTransformer = transformer;
setChildrenDrawingOrderEnabledCompat(hasTransformer);
if (hasTransformer) {
mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD;
} else {
mDrawingOrder = DRAW_ORDER_DEFAULT;
}
if (needsPopulate) populate();
}
}
I also had to change all PageTransformer to ViewPager.PageTransformer. Then did the transformations in ZoomOutPageTranformer like this,
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB){
// > 11 version
view.setAlpha(0);
}
else
{
// Nine Old Androids version
ViewHelper.setAlpha(view, 0);
}
This worked even for 2.2
Ok: I got the answer at the beginning of the doc:
As property animation is only supported as of Android 3.0 and forward, setting a PageTransformer on a ViewPager on earlier platform versions will be ignored.
I'll use ViewFlipper instead.
None of the answers above are the correct answer even if they work,
Here is mine, do not forget to add nineoldandroids.jar to your libs folder:
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) {
ViewHelper.setAlpha(view, 0);
} else if (position <= 1) { // [-1,1]
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) {
ViewHelper.setTranslationX(view,horzMargin - vertMargin / 2);
} else {
ViewHelper.setTranslationX(view,-horzMargin + vertMargin / 2);
}
ViewHelper.setScaleX(view,scaleFactor);
ViewHelper.setScaleY(view, scaleFactor);
ViewHelper.setAlpha(view, MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else {
ViewHelper.setAlpha(view,0);
}
}
}
Hi I am using the Gallery widget to show images downloaded from the internet.
to show several images and I would like to have a gradual zoom while people slide up and down on the screen. I know how to implement the touch event the only thing I don't know how to make the whole gallery view grow gradually. I don't want to zoom in on one image I want the whole gallery to zoom in/out gradually.
EDIT3: I manage to zoom the visible part of the gallery but the problem is I need to find a way for the gallery to find out about it and update it's other children too.
What happens is if 3 images are visible then you start zooming and the gallery does get smaller, so do the images but what I would like in this case is more images to be visible but I don't know how to reach this desired effect. Here's the entire code:
public class Gallery1 extends Activity implements OnTouchListener {
private static final String TAG = "GalleryTest";
private float zoom=0.0f;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
Gallery g;
LinearLayout layout2;
private ImageAdapter ad;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery_1);
layout2=(LinearLayout) findViewById(R.id.layout2);
// Reference the Gallery view
g = (Gallery) findViewById(R.id.gallery);
// Set the adapter to our custom adapter (below)
ad=new ImageAdapter(this);
g.setAdapter(ad);
layout2.setOnTouchListener(this);
}
public void zoomList(boolean increase) {
Log.i(TAG, "startig animation");
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(g, "scaleX", zoom),
ObjectAnimator.ofFloat(g, "scaleY", zoom)
);
set.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
set.setDuration(100).start();
}
public class ImageAdapter extends BaseAdapter {
private static final int ITEM_WIDTH = 136;
private static final int ITEM_HEIGHT = 88;
private final int mGalleryItemBackground;
private final Context mContext;
private final Integer[] mImageIds = {
R.drawable.gallery_photo_1,
R.drawable.gallery_photo_2,
R.drawable.gallery_photo_3,
R.drawable.gallery_photo_4,
R.drawable.gallery_photo_5,
R.drawable.gallery_photo_6,
R.drawable.gallery_photo_7,
R.drawable.gallery_photo_8
};
private final float mDensity;
public ImageAdapter(Context c) {
mContext = c;
// See res/values/attrs.xml for the <declare-styleable> that defines
// Gallery1.
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 1);
a.recycle();
mDensity = c.getResources().getDisplayMetrics().density;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
convertView = new ImageView(mContext);
imageView = (ImageView) convertView;
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setLayoutParams(new Gallery.LayoutParams(
(int) (ITEM_WIDTH * mDensity + 0.5f),
(int) (ITEM_HEIGHT * mDensity + 0.5f)));
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mImageIds[position]);
return imageView;
}
}
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE
&& event.getPointerCount() > 1) {
midPoint(mid, event);
if(mid.y > start.y){
Log.i(TAG, "Going down (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); // going down so increase
if ((Math.abs(mid.y - start.y) > 10) && (zoom<2.5f)){
zoom=zoom+0.1f;
midPoint(start, event);
zoomList(true);
}
return true;
}else if(mid.y < start.y){
Log.i(TAG, "Going up (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); //smaller
if ((Math.abs(mid.y - start.y) > 10) &&(zoom>0.1)){
midPoint(start, event);
zoom=zoom-0.1f;
zoomList(false);
}
return true;
}
}
else if (event.getAction() == MotionEvent.ACTION_POINTER_DOWN) {
Log.e(TAG, "Pointer went down: " + event.getPointerCount());
return true;
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
Log.i(TAG, "Pointer going up");
return true;
}
else if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.i(TAG, "Pointer going down");
start.set(event.getX(), event.getY());
return true;
}
return false;
// indicate event was handled or not
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
I realise I will probably have to extend the Gallery or even another View group or create my own class but I don't know where to start: which method use the one responsible for scaling...
EDIT4: I don't know if he question is clear enough. Here is an example of states:
State one: initial state, we have 3 images in view
State 2: we detect vertical touches going up with 2 fingers = we have to zoom out
state 3: we start zooming = animation on the gallery or on the children???
state 4: gallery detects that it's 3 children are smaller
state 5: gallery adds 1 /more children according to the new available space
LAST UPDATE:
Thanks to all that have posted but I have finally reached a conclusion and that is to not use Gallery at all:
1. It's deprecated
2. It's not customizable enough for my case
If you want to animate several images at once you may want to consider using OpenGl, I am using libgdx library:
https://github.com/libgdx/libgdx
The following ScalingGallery implementation might be of help.
This gallery subclass overrides the getChildStaticTransformation(View child, Transformation t) method in which the scaling is performed. You can further customize the scaling parameters to fit your own needs.
Please note the ScalingGalleryItemLayout.java class. This is necessary because after you have performed the scaling operationg on the child views, their hit boxes are no longer valid so they must be updated from with the getChildStaticTransformation(View child, Transformation t) method.
This is done by wrapping each gallery item in a ScalingGalleryItemLayout which extends a LinearLayout. Again, you can customize this to fit your own needs if a LinearLayout does not meet your needs for layout out your gallery items.
File : /src/com/example/ScalingGallery.java
/**
* A Customized Gallery component which alters the size and position of its items based on their position in the Gallery.
*/
public class ScalingGallery extends Gallery {
public static final int ITEM_SPACING = -20;
private static final float SIZE_SCALE_MULTIPLIER = 0.25f;
private static final float ALPHA_SCALE_MULTIPLIER = 0.5f;
private static final float X_OFFSET = 20.0f;
/**
* Implemented by child view to adjust the boundaries after it has been matrix transformed.
*/
public interface SetHitRectInterface {
public void setHitRect(RectF newRect);
}
/**
* #param context
* Context that this Gallery will be used in.
* #param attrs
* Attributes for this Gallery (via either xml or in-code)
*/
public ScalingGallery(Context context, AttributeSet attrs) {
super(context, attrs);
setStaticTransformationsEnabled(true);
setChildrenDrawingOrderEnabled(true);
}
/**
* {#inheritDoc}
*
* #see #setStaticTransformationsEnabled(boolean)
*
* This is where the scaling happens.
*/
protected boolean getChildStaticTransformation(View child, Transformation t) {
child.invalidate();
t.clear();
t.setTransformationType(Transformation.TYPE_BOTH);
// Position of the child in the Gallery (... +2 +1 0 -1 -2 ... 0 being the middle)
final int childPosition = getSelectedItemPosition() - getPositionForView(child);
final int childPositionAbs = (int) Math.abs(childPosition);
final float left = child.getLeft();
final float top = child.getTop();
final float right = child.getRight();
final float bottom = child.getBottom();
Matrix matrix = t.getMatrix();
RectF modifiedHitBox = new RectF();
// Change alpha, scale and translate non-middle child views.
if (childPosition != 0) {
final int height = child.getMeasuredHeight();
final int width = child.getMeasuredWidth();
// Scale the size.
float scaledSize = 1.0f - (childPositionAbs * SIZE_SCALE_MULTIPLIER);
if (scaledSize < 0) {
scaledSize = 0;
}
matrix.setScale(scaledSize, scaledSize);
float moveX = 0;
float moveY = 0;
// Moving from right to left -- linear move since the scaling is done with respect to top-left corner of the view.
if (childPosition < 0) {
moveX = ((childPositionAbs - 1) * SIZE_SCALE_MULTIPLIER * width) + X_OFFSET;
moveX *= -1;
} else { // Moving from left to right -- sum of the previous positions' x displacements.
// X(n) = X(0) + X(1) + X(2) + ... + X(n-1)
for (int i = childPositionAbs; i > 0; i--) {
moveX += (i * SIZE_SCALE_MULTIPLIER * width);
}
moveX += X_OFFSET;
}
// Moving down y-axis is linear.
moveY = ((childPositionAbs * SIZE_SCALE_MULTIPLIER * height) / 2);
matrix.postTranslate(moveX, moveY);
// Scale alpha value.
final float alpha = (1.0f / childPositionAbs) * ALPHA_SCALE_MULTIPLIER;
t.setAlpha(alpha);
// Calculate new hit box. Since we moved the child, the hitbox is no longer lined up with the new child position.
final float newLeft = left + moveX;
final float newTop = top + moveY;
final float newRight = newLeft + (width * scaledSize);
final float newBottom = newTop + (height * scaledSize);
modifiedHitBox = new RectF(newLeft, newTop, newRight, newBottom);
} else {
modifiedHitBox = new RectF(left, top, right, bottom);
}
// update child hit box so you can tap within the child's boundary
((SetHitRectInterface) child).setHitRect(modifiedHitBox);
return true;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Helps to smooth out jittering during scrolling.
// read more - http://www.unwesen.de/2011/04/17/android-jittery-scrolling-gallery/
final int viewsOnScreen = getLastVisiblePosition() - getFirstVisiblePosition();
if (viewsOnScreen <= 0) {
super.onLayout(changed, l, t, r, b);
}
}
private int mLastDrawnPosition;
#Override
protected int getChildDrawingOrder(int childCount, int i) {
//Reset the last position variable every time we are starting a new drawing loop
if (i == 0) {
mLastDrawnPosition = 0;
}
final int centerPosition = getSelectedItemPosition() - getFirstVisiblePosition();
if (i == childCount - 1) {
return centerPosition;
} else if (i >= centerPosition) {
mLastDrawnPosition++;
return childCount - mLastDrawnPosition;
} else {
return i;
}
}
}
File : /src/com/example/ScalingGalleryItemLayout.java
public class ScalingGalleryItemLayout extends LinearLayout implements SetHitRectInterface {
public ScalingGalleryItemLayout(Context context) {
super(context);
}
public ScalingGalleryItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScalingGalleryItemLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private Rect mTransformedRect;
#Override
public void setHitRect(RectF newRect) {
if (newRect == null) {
return;
}
if (mTransformedRect == null) {
mTransformedRect = new Rect();
}
newRect.round(mTransformedRect);
}
#Override
public void getHitRect(Rect outRect) {
if (mTransformedRect == null) {
super.getHitRect(outRect);
} else {
outRect.set(mTransformedRect);
}
}
}
File : /res/layout/ScaledGalleryItemLayout.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.ScalingGalleryItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gallery_item_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp" >
<ImageView
android:id="#+id/gallery_item_image"
android:layout_width="360px"
android:layout_height="210px"
android:layout_gravity="center"
android:antialias="true"
android:background="#drawable/gallery_item_button_selector"
android:cropToPadding="true"
android:padding="35dp"
android:scaleType="centerInside" />
<TextView
android:id="#+id/gallery_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#drawable/white"
android:textSize="30sp" />
</com.example.ScalingGalleryItemLayout>
To keep the state of the animation after it is done, just do this on your animation:
youranim.setFillAfter(true);
Edit :
In my project, I use this method and i think, it's help you :
http://developer.sonymobile.com/wp/2011/04/12/how-to-take-advantage-of-the-pinch-to-zoom-feature-in-your-xperia%E2%84%A2-10-apps-part-1/
U can do Image Zoom pinch option for gallery also.
by using below code lines:
you can download the example.
https://github.com/alvinsj/android-image-gallery/downloads
I hope this example will help to u..if u have any queries ask me.....
This is solution
integrate gallery component in android with gesture-image library
gesture-imageView
And here is full sample code
SampleCode