-
-
Save devunwired/8cbe094bb7a783e37ad1 to your computer and use it in GitHub Desktop.
<!-- Copyright (c) 2012 Wireless Designs, LLC | |
Permission is hereby granted, free of charge, to any person obtaining | |
a copy of this software and associated documentation files (the | |
"Software"), to deal in the Software without restriction, including | |
without limitation the rights to use, copy, modify, merge, publish, | |
distribute, sublicense, and/or sell copies of the Software, and to | |
permit persons to whom the Software is furnished to do so, subject to | |
the following conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
--> | |
<?xml version="1.0" encoding="utf-8"?> | |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<com.example.pagercontainer.PagerContainer | |
android:id="@+id/pager_container" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:background="#CCC"> | |
<android.support.v4.view.ViewPager | |
android:layout_width="150dp" | |
android:layout_height="100dp" | |
android:layout_gravity="center_horizontal" /> | |
</com.example.pagercontainer.PagerContainer> | |
</RelativeLayout> |
/* | |
* Copyright (c) 2012 Wireless Designs, LLC | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining | |
* a copy of this software and associated documentation files (the | |
* "Software"), to deal in the Software without restriction, including | |
* without limitation the rights to use, copy, modify, merge, publish, | |
* distribute, sublicense, and/or sell copies of the Software, and to | |
* permit persons to whom the Software is furnished to do so, subject to | |
* the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be | |
* included in all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
package com.example.pagercontainer; | |
import android.app.Activity; | |
import android.graphics.Color; | |
import android.os.Bundle; | |
import android.support.v4.view.PagerAdapter; | |
import android.support.v4.view.ViewPager; | |
import android.view.Gravity; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.TextView; | |
/** | |
* PagerActivity: A Sample Activity for PagerContainer | |
*/ | |
public class PagerActivity extends Activity { | |
PagerContainer mContainer; | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.main); | |
mContainer = (PagerContainer) findViewById(R.id.pager_container); | |
ViewPager pager = mContainer.getViewPager(); | |
PagerAdapter adapter = new MyPagerAdapter(); | |
pager.setAdapter(adapter); | |
//Necessary or the pager will only have one extra page to show | |
// make this at least however many pages you can see | |
pager.setOffscreenPageLimit(adapter.getCount()); | |
//A little space between pages | |
pager.setPageMargin(15); | |
//If hardware acceleration is enabled, you should also remove | |
// clipping on the pager for its children. | |
pager.setClipChildren(false); | |
} | |
//Nothing special about this adapter, just throwing up colored views for demo | |
private class MyPagerAdapter extends PagerAdapter { | |
@Override | |
public Object instantiateItem(ViewGroup container, int position) { | |
TextView view = new TextView(PagerActivity.this); | |
view.setText("Item "+position); | |
view.setGravity(Gravity.CENTER); | |
view.setBackgroundColor(Color.argb(255, position * 50, position * 10, position * 50)); | |
container.addView(view); | |
return view; | |
} | |
@Override | |
public void destroyItem(ViewGroup container, int position, Object object) { | |
container.removeView((View)object); | |
} | |
@Override | |
public int getCount() { | |
return 5; | |
} | |
@Override | |
public boolean isViewFromObject(View view, Object object) { | |
return (view == object); | |
} | |
} | |
} |
/* | |
* Copyright (c) 2012 Wireless Designs, LLC | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining | |
* a copy of this software and associated documentation files (the | |
* "Software"), to deal in the Software without restriction, including | |
* without limitation the rights to use, copy, modify, merge, publish, | |
* distribute, sublicense, and/or sell copies of the Software, and to | |
* permit persons to whom the Software is furnished to do so, subject to | |
* the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be | |
* included in all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
package com.example.pagercontainer; | |
import android.content.Context; | |
import android.graphics.Point; | |
import android.support.v4.view.ViewPager; | |
import android.util.AttributeSet; | |
import android.view.MotionEvent; | |
import android.widget.FrameLayout; | |
/** | |
* PagerContainer: A layout that displays a ViewPager with its children that are outside | |
* the typical pager bounds. | |
*/ | |
public class PagerContainer extends FrameLayout implements ViewPager.OnPageChangeListener { | |
private ViewPager mPager; | |
boolean mNeedsRedraw = false; | |
public PagerContainer(Context context) { | |
super(context); | |
init(); | |
} | |
public PagerContainer(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
init(); | |
} | |
public PagerContainer(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
init(); | |
} | |
private void init() { | |
//Disable clipping of children so non-selected pages are visible | |
setClipChildren(false); | |
//Child clipping doesn't work with hardware acceleration in Android 3.x/4.x | |
//You need to set this value here if using hardware acceleration in an | |
// application targeted at these releases. | |
setLayerType(View.LAYER_TYPE_SOFTWARE, null); | |
} | |
@Override | |
protected void onFinishInflate() { | |
try { | |
mPager = (ViewPager) getChildAt(0); | |
mPager.setOnPageChangeListener(this); | |
} catch (Exception e) { | |
throw new IllegalStateException("The root child of PagerContainer must be a ViewPager"); | |
} | |
} | |
public ViewPager getViewPager() { | |
return mPager; | |
} | |
private Point mCenter = new Point(); | |
private Point mInitialTouch = new Point(); | |
@Override | |
protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
mCenter.x = w / 2; | |
mCenter.y = h / 2; | |
} | |
@Override | |
public boolean onTouchEvent(MotionEvent ev) { | |
//We capture any touches not already handled by the ViewPager | |
// to implement scrolling from a touch outside the pager bounds. | |
switch (ev.getAction()) { | |
case MotionEvent.ACTION_DOWN: | |
mInitialTouch.x = (int)ev.getX(); | |
mInitialTouch.y = (int)ev.getY(); | |
default: | |
ev.offsetLocation(mCenter.x - mInitialTouch.x, mCenter.y - mInitialTouch.y); | |
break; | |
} | |
return mPager.dispatchTouchEvent(ev); | |
} | |
@Override | |
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { | |
//Force the container to redraw on scrolling. | |
//Without this the outer pages render initially and then stay static | |
if (mNeedsRedraw) invalidate(); | |
} | |
@Override | |
public void onPageSelected(int position) { } | |
@Override | |
public void onPageScrollStateChanged(int state) { | |
mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE); | |
} | |
} |
I used two viewpager..in first pager i have only images of product. now if user swipe image from pager 1 then in pager 2 i want to set its different prices..how to do that can any one help?
http://stackoverflow.com/questions/41217237/viewpager-not-getting-last-item
@PrinceRK I am also wondering same. Was checking this code, and surprisingly it is not working for me at all.
@devunwired is there any updates on this code you made. Code seems workable but still it's not working in my scenario. I have ViewPager
inside RecyclerView
. So I have to use wrap_content
for ViewPager
. And have made customization in onMeasure
to get wrapped content. Then I used your piece of code for getting preview of previous and next view. Unfortunately I am not getting it. I don't know what I am missing. I will give CustomViewPager
code over here. In that there is also vertical swipe related code, but that is what I am not using in the discussed scenario. Just wrapping the height. isWrap
is true in below code
/**
* Created by Jimit Patel on 29/07/15.
*/
public class CustomViewPager extends ViewPager {
private static final String TAG = CustomViewPager.class.getSimpleName();
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
public static final int NONE = 0;
public static final int HEIGHT = 1;
public static final int WIDTH = 2;
private boolean isPagingEnabled, isSwipeable, isSquare, isWrap;
private int mSwipeOrientation;
private ScrollerCustomDuration mScroller = null;
private double heightRatio, widthRatio;
private int mCalculationType;
private View mCurrentView;
public CustomViewPager(Context context) {
super(context);
this.isPagingEnabled = true;
this.isSwipeable = true;
isSquare = false;
mCalculationType = NONE;
heightRatio = 0;
widthRatio = 0;
mSwipeOrientation = HORIZONTAL;
postInitViewPager();
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setIsSquare(context, attrs);
setDimensionRatio(context, attrs);
setSwipeOrientation(context, attrs);
this.isPagingEnabled = true;
this.isSwipeable = true;
postInitViewPager();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!this.isPagingEnabled || !this.isSwipeable)
return false;
return super.onTouchEvent(mSwipeOrientation == VERTICAL ? swapXY(event) : event);
}
@Override
public boolean onInterceptHoverEvent(MotionEvent event) {
// return super.onInterceptHoverEvent(event);
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (!this.isPagingEnabled || !this.isSwipeable)
return false;
else if (mSwipeOrientation == VERTICAL) {
boolean intercepted = super.onInterceptHoverEvent(swapXY(event));
swapXY(event);
return intercepted;
}
return super.onInterceptTouchEvent(event);
}
public void setPagingEnabled(boolean isPagingEnabled) {
this.isPagingEnabled = isPagingEnabled;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
boolean isDefault;
int width, height;
switch (mCalculationType) {
case WIDTH: {
isDefault = false;
height = MeasureSpec.getSize(heightMeasureSpec);
width = (int) ((float) (((float) (heightRatio > 0 ? heightRatio : 1) / (float) (widthRatio > 0 ? widthRatio : 1)) * height));
break;
}
case HEIGHT: {
isDefault = false;
width = MeasureSpec.getSize(widthMeasureSpec);
height = (int) ((float) (((float) (widthRatio > 0 ? widthRatio : 1) / (float) (heightRatio > 0 ? heightRatio : 1)) * width));
break;
}
default: {
isDefault = true;
width = widthMeasureSpec;
height = heightMeasureSpec;
break;
}
}
if (!isDefault) {
setMeasuredDimension(width, height);
measureChildren(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), (isSquare
? MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY) : MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)));
} else {
if (!isSquare && isWrap) {
if (mCurrentView == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
height = 0;
mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = mCurrentView.getMeasuredHeight();
if (h > height) height = h;
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, isSquare ? widthMeasureSpec : heightMeasureSpec);
}
}
}
public void measureCurrentView(View currentView) {
mCurrentView = currentView;
requestLayout();
}
public void setSwipeOrientation(int swipeOrientation) {
if (swipeOrientation == HORIZONTAL || swipeOrientation == VERTICAL)
mSwipeOrientation = swipeOrientation;
else
throw new IllegalStateException("Swipe Orientation can be either CustomViewPager.HORIZONTAL" +
" or CustomViewPager.VERTICAL");
initSwipeMethods();
}
private void setIsSquare(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SquareViewPager);
boolean isSquare = typedArray.getBoolean(R.styleable.SquareViewPager_square_dimens, false);
setIsSquare(isSquare);
typedArray.recycle();
}
private void setSwipeOrientation(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomViewPager);
mSwipeOrientation = typedArray.getInteger(R.styleable.CustomViewPager_swipe_orientation, 0);
typedArray.recycle();
initSwipeMethods();
}
private void setDimensionRatio(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SquareViewPager);
int ratioWidth = typedArray.getInteger(R.styleable.SquareViewPager_width_ratio, 0);
int ratioHeight = typedArray.getInteger(R.styleable.SquareViewPager_height_ratio, 0);
int calculationType = typedArray.getInteger(R.styleable.SquareViewPager_calculation, 0);
setDimensionRatio(ratioWidth, ratioHeight, calculationType);
typedArray.recycle();
}
private void setDimensionRatio(int ratioWidth, int ratioHeight, int calculationType) {
this.widthRatio = ratioWidth;
this.heightRatio = ratioHeight;
this.mCalculationType = calculationType;
}
public void setIsSquare(boolean isSquare) {
this.isSquare = isSquare;
}
public void setHeightRatio(double heightRatio) {
this.heightRatio = heightRatio;
}
public void setWidthRatio(double widthRatio) {
this.widthRatio = widthRatio;
}
public boolean isSquare() {
return this.isSquare;
}
public boolean isWrap() {
return isWrap;
}
public void setWrap(boolean wrap) {
isWrap = wrap;
}
public void setSwipeEnabled(boolean isSwipeable) {
this.isSwipeable = isSwipeable;
}
/**
* Override the Scroller instance with our own class so we can change the
* duration
*/
private void postInitViewPager() {
try {
Field scroller = ViewPager.class.getDeclaredField("mScroller");
scroller.setAccessible(true);
Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");
interpolator.setAccessible(true);
mScroller = new ScrollerCustomDuration(getContext(),
(Interpolator) interpolator.get(null));
scroller.set(this, mScroller);
} catch (Exception e) {
}
}
private void initSwipeMethods() {
if (mSwipeOrientation == VERTICAL) {
// The majority of the work is done over here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
}
/**
* Set the factor by which the duration will change
*/
public void setScrollDurationFactor(double scrollFactor) {
mScroller.setScrollDurationFactor(scrollFactor);
}
public int measureFragment(View view) {
if (view == null)
return 0;
view.measure(0, 0);
return view.getMeasuredHeight();
}
/**
* Determines the height of this view
*
* @param measureSpec A measureSpec packed into an int
* @param view the base view with already measured height
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec, View view) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
// set the height from the base view if available
if (view != null) {
result = view.getMeasuredHeight();
}
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
/**
* Determines the width of this view
*
* @param measureSpec A measureSpec packed into an int
* @param view the base view with already measured width
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec, View view) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
// set the height from the base view if available
if (view != null) {
result = view.getMeasuredWidth();
}
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
private MotionEvent swapXY(MotionEvent event) {
float width = getWidth();
float height = getHeight();
float newX = (event.getY() / height) * width;
float newY = (event.getX() / width) * height;
event.setLocation(newX, newY);
return event;
}
private class VerticalPageTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(View page, float position) {
if (position < -1) {
// This page is way off-screen to the left
page.setAlpha(0);
} else if (position <= 1) {
page.setAlpha(1);
// Counteract the default slide transition
page.setTranslationX(page.getWidth() * -position);
// set Y position to swipe in from top
float yPosition = position * page.getHeight();
page.setTranslationY(yPosition);
} else {
// This page is way off screen to the right
page.setAlpha(0);
}
}
}
}
And in PagerAdapter
, I am using this piece of code to get measurement
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition) {
View view = (View) object;
CustomViewPager pager = (CustomViewPager) container;
if (null != view) {
mCurrentPosition = position;
pager.measureCurrentView(view);
}
}
Guys, I have a problem.
I have 3 items visible.
If I select the 3rd item it will return item on 2nd position.
Do you guys have this problem?