Apply "Bounce Effect" to Overscroll in a ViewPager (FragmentPagerAdapter) - android

In my app I am trying to implement the bounce effect for the overscroll instead of android's boring normal overscroll technique.
I am trying to apply this overscroll effect to a FragmentPagerAdapter that handles quite a few fragments. How do I implement this?
Here is my current FragmentPagerAdapter if that helps:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private MainActivity mainActivity;
public SectionsPagerAdapter(MainActivity mainActivity, FragmentManager fm) {
super(fm);
this.mainActivity = mainActivity;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FragmentPages.FragmentPage1();
case 1:
return new FragmentPages.FragmentPage2();
case 2:
return new FragmentPages.FragmentPage3();
case 3:
return new FragmentPages.FragmentPage4();
case 4:
return new FragmentPages.FragmentPage5();
case 5:
return new FragmentPages.FragmentPage6();
case 6:
return new FragmentPages.FragmentPage7();
case 7:
return new FragmentPages.FragmentPage8();
case 8:
return new FragmentPages.FragmentPage9();
case 9:
return new FragmentPages.FragmentPage10();
case 10:
return new FragmentPages.FragmentPage11();
}
return null;
}
#Override
public int getCount() {
return 11;
}
}

Here sample from my project. Most of code is from that answer
public class BounceViewPager extends ViewPager {
private final static int LONG_ANIM_DURATION = 850;
private final static int SHORT_ANIM_DURATION = 150;
private final static int DEFAULT_OVERSCROLL_ANIMATION_DURATION = 200;
private GestureDetector xScrollDetector;
private FixedSpeedScroller scroller;
class XScrollDetector extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return Math.abs(distanceX) > Math.abs(distanceY);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
switch (action) {
case MotionEvent.ACTION_DOWN: {
lastMotionX = ev.getX();
activePointerId = MotionEventCompat.getPointerId(ev, 0);
break;
}
case MotionEventCompat.ACTION_POINTER_DOWN: {
final int index = MotionEventCompat.getActionIndex(ev);
lastMotionX = MotionEventCompat.getX(ev, index);
activePointerId = MotionEventCompat.getPointerId(ev, index);
break;
}
}
if (xScrollDetector.onTouchEvent(ev)) {
super.onInterceptTouchEvent(ev);
return true;
}
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) {
Timber.e(e, "");
return false;
}
}
private final static int INVALID_POINTER_ID = -1;
private class OverScrollEffect {
private float overScroll;
private Animator animator;
public void setPull(final float deltaDistance) {
overScroll = deltaDistance;
invalidateVisibleChildren();
}
private void onRelease() {
if (animator != null && animator.isRunning()) {
animator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
startAnimation();
}
#Override
public void onAnimationCancel(Animator animation) {
}
});
animator.cancel();
} else {
startAnimation();
}
}
private void startAnimation() {
animator = ObjectAnimator.ofFloat(this, "pull", overScroll, 0);
animator.setInterpolator(new DecelerateInterpolator());
final float scale = Math.abs(-overScroll);
animator.setDuration((long) (overScrollAnimationDuration * scale));
animator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.start();
}
private boolean isOverScrolling() {
if (scrollPosition == 0 && overScroll < 0) {
return true;
}
final boolean isLast = (getAdapter().getCount() - 1) == getCurrentItem();
return isLast && overScroll > 0;
}
}
final private OverScrollEffect overscrollEffect = new OverScrollEffect();
final private Camera camera = new Camera();
private float lastMotionX;
private int activePointerId;
private int scrollPosition;
private float scrollPositionOffset;
final private int touchSlop;
private float overScrollTranslation;
private int overScrollAnimationDuration;
public BounceViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
xScrollDetector = new GestureDetector(getContext(), new XScrollDetector());
setStaticTransformationsEnabled(true);
final ViewConfiguration configuration = ViewConfiguration.get(context);
touchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
super.setOnPageChangeListener(new MyOnPageChangeListener());
init();
}
private void init() {
overScrollTranslation = UiUtil.getDisplayWidth((Activity) getContext()) / 3;
overScrollAnimationDuration = DEFAULT_OVERSCROLL_ANIMATION_DURATION;
try {
Field mScroller;
mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);
scroller = new FixedSpeedScroller(getContext());
setShortAnimDuration();
mScroller.set(this, scroller);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
Timber.e(e, "");
}
}
private void invalidateVisibleChildren() {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).invalidate();
}
}
private class MyOnPageChangeListener implements OnPageChangeListener {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
scrollPosition = position;
scrollPositionOffset = positionOffset;
invalidateVisibleChildren();
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(final int state) {
if (state == SCROLL_STATE_IDLE) {
scrollPositionOffset = 0;
}
}
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
boolean callSuper = false;
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
callSuper = true;
lastMotionX = ev.getX();
activePointerId = MotionEventCompat.getPointerId(ev, 0);
break;
}
case MotionEventCompat.ACTION_POINTER_DOWN: {
callSuper = true;
final int index = MotionEventCompat.getActionIndex(ev);
lastMotionX = MotionEventCompat.getX(ev, index);
activePointerId = MotionEventCompat.getPointerId(ev, index);
break;
}
case MotionEvent.ACTION_MOVE: {
if (activePointerId != INVALID_POINTER_ID) {
final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId);
final float x = MotionEventCompat.getX(ev, activePointerIndex);
final float deltaX = lastMotionX - x;
final float oldScrollX = getScrollX();
final int width = getWidth();
final int widthWithMargin = width + getPageMargin() - (getPaddingLeft() + getPaddingRight());
final int lastItemIndex = getAdapter().getCount() - 1;
final int currentItemIndex = getCurrentItem();
final float leftBound = Math.max(0, (currentItemIndex - 1) * widthWithMargin);
final float rightBound = (Math.min(currentItemIndex + 1, lastItemIndex)) * (widthWithMargin);
final float scrollX = oldScrollX + deltaX;
if (scrollPositionOffset == 0) {
if (scrollX < leftBound) {
if (leftBound == 0) {
final float over = deltaX + touchSlop;
overscrollEffect.setPull(over / width);
}
} else if (scrollX > rightBound) {
if (rightBound == lastItemIndex * widthWithMargin) {
final float over = scrollX - rightBound - touchSlop;
overscrollEffect.setPull(over / width);
}
}
} else {
lastMotionX = x;
}
} else {
overscrollEffect.onRelease();
}
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
callSuper = true;
activePointerId = INVALID_POINTER_ID;
overscrollEffect.onRelease();
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == activePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
lastMotionX = ev.getX(newPointerIndex);
activePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
callSuper = true;
}
break;
}
}
return overscrollEffect.isOverScrolling() && !callSuper || super.onTouchEvent(ev);
}
#Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
if (child.getWidth() == 0) {
return false;
}
final int position = child.getLeft() / child.getWidth();
final boolean isFirstOrLast = position == 0 || (position == getAdapter().getCount() - 1);
if (overscrollEffect.isOverScrolling() && isFirstOrLast) {
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
final float dx = getWidth() / 2;
final int dy = getHeight() / 2;
t.getMatrix().reset();
final float translateX = overScrollTranslation * (overscrollEffect.overScroll > 0 ?
Math.min(overscrollEffect.overScroll, 1) : Math.max(overscrollEffect.overScroll, -1));
camera.save();
camera.translate(-translateX, 0, 0);
camera.getMatrix(t.getMatrix());
t.getMatrix().preTranslate(-dx, -dy);
t.getMatrix().postTranslate(dx, dy);
camera.restore();
this.invalidate();
return true;
}
return false;
}
private void setAnimationDuration(int duration) {
scroller.setDuration(duration);
}
public void setLongAnimDuration() {
setAnimationDuration(LONG_ANIM_DURATION);
}
public void setShortAnimDuration() {
setAnimationDuration(SHORT_ANIM_DURATION);
}
}
public class FixedSpeedScroller extends Scroller {
private int duration = 150;
public FixedSpeedScroller(Context context) {
super(context, new LinearOutSlowInInterpolator());
}
#Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, this.duration);
}
#Override
public void startScroll(int startX, int startY, int dx, int dy) {
super.startScroll(startX, startY, dx, dy, duration);
}
public void setDuration(int duration) {
this.duration = duration;
}
}

Related

Write over Image (Bitmap) with option to resize and re-position it

I am having an Image and I want to write on Image which can be rotated, resized and re-positioned.
I am new to Canvas. I don't understand ,How to achieve it ?
Hi i write this code for one of my project you can use it for rotated, resized and re-positioned and for add text you need to change it a little :
public class ScreenView extends View implements RotationGestureDetector.OnRotationGestureListener, ScaleGestureDetector.OnScaleGestureListener {
private Context context = null;
private Bitmap bitmap = null;
private Bitmap bitmapLocked = null;
private int baseColor = Color.parseColor("#ffffff");
public int width;
public int height;
public float touchStartX;
public float touchStartY;
public float touchX;
public float touchY;
public boolean touchDown = false;
private Products product;
ArrayList<Products> products = new ArrayList<>();
private float newAngle = 0;
private float newScale = 0;
private float scaleFactorSum = 0;
private float startScale = 0;
private RotationGestureDetector rotationDetector;
private ScaleGestureDetector scaleDetector;
private boolean isRotating = false;
private boolean isScaling = false;
private Matrix m;
private float startX;
private float startY;
private float startAngle;
private boolean isLocked;
private Paint alphaPaint = new Paint();
public ScreenView(Context context) {
super(context);
this.setup(context);
}
public ScreenView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setup(context);
}
private void setup(Context context) {
this.context = context;
rotationDetector = new RotationGestureDetector(this);
scaleDetector = new ScaleGestureDetector(context, this);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#ffffff"));
if (bitmap != null) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
for (Products item : products) {
if (getSelectedProduct() != null && !getSelectedProduct().equals(item))
canvas.drawBitmap(item.getBitmap(), item.getMatrix(), null);
else if (!touchDown) {
canvas.drawBitmap(item.getBitmap(), item.getMatrix(), null);
}
}
if (touchDown && getSelectedProduct() != null) {
canvas.drawBitmap(getSelectedProduct().getBitmap(), getSelectedProduct().getMatrix(), null);
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
invalidate();
}
public void setAvatarBitmap(Bitmap bitmap, int width, int height) {
this.bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
invalidate();
}
public void addProduct(Products item) {
products.add(item);
invalidate();
}
public void addAllProduct(ArrayList<Products> item) {
products = item;
invalidate();
}
public int getLastIdOfProduct() {
boolean position1 = false;
boolean position2 = false;
boolean position3 = false;
boolean position4 = false;
for (int i = 0; i < products.size(); i++) {
if (products.get(i).getPosition() == 1) {
position1 = true;
}
if (products.get(i).getPosition() == 2) {
position2 = true;
}
if (products.get(i).getPosition() == 3) {
position3 = true;
}
if (products.get(i).getPosition() == 4) {
position4 = true;
}
}
if (!position1 && products.size() == 0 )
return 1;
if (!position2)
return 2;
if (!position3)
return 3;
if (!position4)
return 4;
return 1;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (getSelectedProduct() == null) {
return true;
}
scaleDetector.onTouchEvent(event);
rotationDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!this.touchDown) {
touchStartX = event.getX();
touchStartY = event.getY();
startX = getSelectedProduct().x;
startY = getSelectedProduct().y;
startAngle = getSelectedProduct().angle;
touchDown = true;
}
break;
case MotionEvent.ACTION_MOVE:
touchX = event.getX();
touchY = event.getY();
if (!isScaling && !isRotating && getSelectedProduct().isCanMove()) {
getSelectedProduct().setXY(startX + (touchX - touchStartX), startY + (touchY - touchStartY));
}
this.invalidate();
break;
case MotionEvent.ACTION_UP:
if (!isScaling && !isRotating && getSelectedProduct().isCanMove()) {
getSelectedProduct().setXY(startX + (touchX - touchStartX), startY + (touchY - touchStartY));
}
touchX = 0;
touchY = 0;
touchStartX = 0;
touchStartY = 0;
this.touchDown = false;
this.invalidate();
break;
default:
break;
}
ViewParent mParent = getParent();
if (mParent != null) {
mParent.requestDisallowInterceptTouchEvent(true);
}
return true;
}
public Products getSelectedProduct() {
return product;
}
public void setProduct(Products product) {
this.product = product;
}
public void setSelectedProduct(int id) {
for (int i = 0; i <= products.size() - 1; i++) {
if (products.get(i).getId() == id) {
this.product = products.get(i);
break;
}
}
}
public ArrayList<Products> getAllProducts() {
return products;
}
#Override
public void OnRotation(RotationGestureDetector rotationDetector) {
if (!getSelectedProduct().isCanRotate()) {
return;
}
isRotating = true;
newAngle = -rotationDetector.getAngle();
getSelectedProduct().setAngle(startAngle + newAngle);
}
#Override
public void onRotationEnded(RotationGestureDetector rotationDetector) {
if (!isRotating || !getSelectedProduct().isCanRotate()) {
return;
}
getSelectedProduct().setAngle(startAngle + newAngle);
touchX = 0;
touchY = 0;
touchStartX = 0;
touchStartY = 0;
isRotating = false;
this.newAngle = 0;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
if (!getSelectedProduct().isCanScale()) {
return false;
}
newScale -= (1 - detector.getScaleFactor()) * 2;
getSelectedProduct().setScale(startScale + newScale);
return true;
}
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
if (getSelectedProduct().isCanScale()) {
isScaling = true;
startScale = getSelectedProduct().scale;
}
return true;
}
#Override
public void onScaleEnd(ScaleGestureDetector detector) {
touchX = 0;
touchY = 0;
touchStartX = 0;
touchStartY = 0;
newScale = 0;
isScaling = false;
}
public Bitmap getBitmap() {
try {
this.setDrawingCacheEnabled(false);
this.setDrawingCacheEnabled(true);
return Bitmap.createBitmap(this.getDrawingCache());
} catch (Exception e) {
return null;
}
}
public void removeProductFromList(Products item) {
if (item != null) {
products.remove(item);
product = null;
invalidate();
}
}
public void removeAllProduct() {
products.clear();
product = null;
invalidate();
}
public boolean isLocked() {
return isLocked;
}
public void setLocked(boolean locked) {
isLocked = locked;
}
}
public class RotationGestureDetector {
private static final int INVALID_POINTER_ID = -1;
private float fX, fY, sX, sY;
private int ptrID1, ptrID2;
private float mAngle;
private OnRotationGestureListener mListener;
public float getAngle() {
return mAngle;
}
public RotationGestureDetector(OnRotationGestureListener listener){
mListener = listener;
ptrID1 = INVALID_POINTER_ID;
ptrID2 = INVALID_POINTER_ID;
}
public boolean onTouchEvent(MotionEvent event){
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
ptrID1 = event.getPointerId(event.getActionIndex());
break;
case MotionEvent.ACTION_POINTER_DOWN:
ptrID2 = event.getPointerId(event.getActionIndex());
sX = event.getX(event.findPointerIndex(ptrID1));
sY = event.getY(event.findPointerIndex(ptrID1));
fX = event.getX(event.findPointerIndex(ptrID2));
fY = event.getY(event.findPointerIndex(ptrID2));
break;
case MotionEvent.ACTION_MOVE:
if(ptrID1 != INVALID_POINTER_ID && ptrID2 != INVALID_POINTER_ID){
float nfX, nfY, nsX, nsY;
nsX = event.getX(event.findPointerIndex(ptrID1));
nsY = event.getY(event.findPointerIndex(ptrID1));
nfX = event.getX(event.findPointerIndex(ptrID2));
nfY = event.getY(event.findPointerIndex(ptrID2));
mAngle = angleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY);
if (mListener != null) {
mListener.OnRotation(this);
}
}
break;
case MotionEvent.ACTION_UP:
ptrID1 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
ptrID2 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_CANCEL:
ptrID1 = INVALID_POINTER_ID;
ptrID2 = INVALID_POINTER_ID;
break;
}
if(ptrID1 == INVALID_POINTER_ID && ptrID2 == INVALID_POINTER_ID){
mListener.onRotationEnded(this);
}
return true;
}
private float angleBetweenLines (float fX, float fY, float sX, float sY, float nfX, float nfY, float nsX, float nsY)
{
float angle1 = (float) Math.atan2( (fY - sY), (fX - sX) );
float angle2 = (float) Math.atan2( (nfY - nsY), (nfX - nsX) );
float angle = ((float) Math.toDegrees(angle1 - angle2)) % 360;
if (angle < -180.f) angle += 360.0f;
if (angle > 180.f) angle -= 360.0f;
return angle;
}
public static interface OnRotationGestureListener {
public void OnRotation(RotationGestureDetector rotationDetector);
public void onRotationEnded(RotationGestureDetector rotationDetector);
}
}
for use the code :
screenView.addProduct(new Products(screenView.getLastIdOfProduct(), item.getHash(), x, y, resource, width, height, scale, position, canMove, canScale, canRotate));
the code use for this page

Slideshow with bullet in android application

how can i delete this black part and description from daimajia.slider
or is there other alternative for using a slider only with bullet on it.
Yes, you can make a slide show with just bullets and no text.
Use ViewPager to make the slides
Screen slides are transitions between one entire screen to another and
are common with UIs like setup wizards or slideshows. This lesson
shows you how to do screen slides with a ViewPager provided by the
support library. ViewPagers can animate screen slides automatically.
for adding the dots, use ViewPagerIndicator library by Jake Wharton and use the CirclePageIndicator provided by it. Done!
You can use viewpager with below class.
CirclePageIndicator.java
public class CirclePageIndicator extends View implements PageIndicator {
private static final int INVALID_POINTER = -1;
private float mRadius;
private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG);
private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG);
private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG);
private ViewPager mViewPager;
private ViewPager.OnPageChangeListener mListener;
private int mCurrentPage;
private int mSnapPage;
private float mPageOffset;
private int mScrollState;
private int mOrientation;
private boolean mCentered;
private boolean mSnap;
private int mTouchSlop;
private float mLastMotionX = -1;
private int mActivePointerId = INVALID_POINTER;
private boolean mIsDragging;
public CirclePageIndicator(Context context) {
this(context, null);
}
public CirclePageIndicator(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.vpiCirclePageIndicatorStyle);
}
public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode()) return;
//Load defaults from resources
final Resources res = getResources();
final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color);
//default_circle_indicator_fill_color
final int defaultFillColor = res.getColor(R.color.holo_blue_dark);
final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation);
final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color);
final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width);
final float defaultRadius = res.getDimension(R.dimen.default_circle_indicator_radius);
final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered);
final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap);
//Retrieve styles attributes
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0);
mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered);
mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation);
mPaintPageFill.setStyle(Style.FILL);
mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor));
mPaintStroke.setStyle(Style.STROKE);
mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor));
mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth));
mPaintFill.setStyle(Style.FILL);
mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor));
mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius);
mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap);
Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background);
if (background != null) {
setBackgroundDrawable(background);
}
a.recycle();
final ViewConfiguration configuration = ViewConfiguration.get(context);
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
}
public void setCentered(boolean centered) {
mCentered = centered;
invalidate();
}
public boolean isCentered() {
return mCentered;
}
public void setPageColor(int pageColor) {
mPaintPageFill.setColor(pageColor);
invalidate();
}
public int getPageColor() {
return mPaintPageFill.getColor();
}
public void setFillColor(int fillColor) {
mPaintFill.setColor(fillColor);
invalidate();
}
public int getFillColor() {
return mPaintFill.getColor();
}
public void setOrientation(int orientation) {
switch (orientation) {
case HORIZONTAL:
case VERTICAL:
mOrientation = orientation;
requestLayout();
break;
default:
throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL.");
}
}
public int getOrientation() {
return mOrientation;
}
public void setStrokeColor(int strokeColor) {
mPaintStroke.setColor(strokeColor);
invalidate();
}
public int getStrokeColor() {
return mPaintStroke.getColor();
}
public void setStrokeWidth(float strokeWidth) {
mPaintStroke.setStrokeWidth(strokeWidth);
invalidate();
}
public float getStrokeWidth() {
return mPaintStroke.getStrokeWidth();
}
public void setRadius(float radius) {
mRadius = radius;
invalidate();
}
public float getRadius() {
return mRadius;
}
public void setSnap(boolean snap) {
mSnap = snap;
invalidate();
}
public boolean isSnap() {
return mSnap;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mViewPager == null) {
return;
}
final int count = mViewPager.getAdapter().getCount();
if (count == 0) {
return;
}
if (mCurrentPage >= count) {
setCurrentItem(count - 1);
return;
}
int longSize;
int longPaddingBefore;
int longPaddingAfter;
int shortPaddingBefore;
if (mOrientation == HORIZONTAL) {
longSize = getWidth();
longPaddingBefore = getPaddingLeft();
longPaddingAfter = getPaddingRight();
shortPaddingBefore = getPaddingTop();
} else {
longSize = getHeight();
longPaddingBefore = getPaddingTop();
longPaddingAfter = getPaddingBottom();
shortPaddingBefore = getPaddingLeft();
}
final float threeRadius = mRadius * 3;
final float shortOffset = shortPaddingBefore + mRadius;
float longOffset = longPaddingBefore + mRadius;
if (mCentered) {
longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f);
}
float dX;
float dY;
float pageFillRadius = mRadius;
if (mPaintStroke.getStrokeWidth() > 0) {
pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f;
}
//Draw stroked circles
for (int iLoop = 0; iLoop < count; iLoop++) {
float drawLong = longOffset + (iLoop * threeRadius);
if (mOrientation == HORIZONTAL) {
dX = drawLong;
dY = shortOffset;
} else {
dX = shortOffset;
dY = drawLong;
}
// Only paint fill if not completely transparent
if (mPaintPageFill.getAlpha() > 0) {
canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill);
}
// Only paint stroke if a stroke width was non-zero
if (pageFillRadius != mRadius) {
canvas.drawCircle(dX, dY, mRadius, mPaintStroke);
}
}
//Draw the filled circle according to the current scroll
float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius;
if (!mSnap) {
cx += mPageOffset * threeRadius;
}
if (mOrientation == HORIZONTAL) {
dX = longOffset + cx;
dY = shortOffset;
} else {
dX = shortOffset;
dY = longOffset + cx;
}
canvas.drawCircle(dX, dY, mRadius, mPaintFill);
}
public boolean onTouchEvent(android.view.MotionEvent ev) {
if (super.onTouchEvent(ev)) {
return true;
}
if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
return false;
}
final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
switch (action) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
mLastMotionX = ev.getX();
break;
case MotionEvent.ACTION_MOVE: {
final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, activePointerIndex);
final float deltaX = x - mLastMotionX;
if (!mIsDragging) {
if (Math.abs(deltaX) > mTouchSlop) {
mIsDragging = true;
}
}
if (mIsDragging) {
mLastMotionX = x;
if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
mViewPager.fakeDragBy(deltaX);
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (!mIsDragging) {
final int count = mViewPager.getAdapter().getCount();
final int width = getWidth();
final float halfWidth = width / 2f;
final float sixthWidth = width / 6f;
if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) {
if (action != MotionEvent.ACTION_CANCEL) {
mViewPager.setCurrentItem(mCurrentPage - 1);
}
return true;
} else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) {
if (action != MotionEvent.ACTION_CANCEL) {
mViewPager.setCurrentItem(mCurrentPage + 1);
}
return true;
}
}
mIsDragging = false;
mActivePointerId = INVALID_POINTER;
if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
break;
case MotionEventCompat.ACTION_POINTER_DOWN: {
final int index = MotionEventCompat.getActionIndex(ev);
mLastMotionX = MotionEventCompat.getX(ev, index);
mActivePointerId = MotionEventCompat.getPointerId(ev, index);
break;
}
case MotionEventCompat.ACTION_POINTER_UP:
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
break;
}
return true;
}
#Override
public void setViewPager(ViewPager view) {
if (mViewPager == view) {
return;
}
if (mViewPager != null) {
mViewPager.setOnPageChangeListener(null);
}
if (view.getAdapter() == null) {
throw new IllegalStateException("ViewPager does not have adapter instance.");
}
mViewPager = view;
mViewPager.setOnPageChangeListener(this);
invalidate();
}
#Override
public void setViewPager(ViewPager view, int initialPosition) {
setViewPager(view);
setCurrentItem(initialPosition);
}
#Override
public void setCurrentItem(int item) {
if (mViewPager == null) {
throw new IllegalStateException("ViewPager has not been bound.");
}
mViewPager.setCurrentItem(item);
mCurrentPage = item;
invalidate();
}
#Override
public void notifyDataSetChanged() {
invalidate();
}
#Override
public void onPageScrollStateChanged(int state) {
mScrollState = state;
if (mListener != null) {
mListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
mCurrentPage = position;
mPageOffset = positionOffset;
invalidate();
if (mListener != null) {
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
#Override
public void onPageSelected(int position) {
if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) {
mCurrentPage = position;
mSnapPage = position;
invalidate();
}
if (mListener != null) {
mListener.onPageSelected(position);
}
}
#Override
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mListener = listener;
}
/*
* (non-Javadoc)
*
* #see android.view.View#onMeasure(int, int)
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mOrientation == HORIZONTAL) {
setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
} else {
setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));
}
}
/**
* Determines the width of this view
*
* #param measureSpec
* A measureSpec packed into an int
* #return The width of the view, honoring constraints from measureSpec
*/
private int measureLong(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
//We were told how big to be
result = specSize;
} else {
//Calculate the width according the views count
final int count = mViewPager.getAdapter().getCount();
result = (int)(getPaddingLeft() + getPaddingRight()
+ (count * 2 * mRadius) + (count - 1) * mRadius + 1);
//Respect AT_MOST value if that was what is called for by measureSpec
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
/**
* Determines the height of this view
*
* #param measureSpec
* A measureSpec packed into an int
* #return The height of the view, honoring constraints from measureSpec
*/
private int measureShort(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
//We were told how big to be
result = specSize;
} else {
//Measure the height
result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);
//Respect AT_MOST value if that was what is called for by measureSpec
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState)state;
super.onRestoreInstanceState(savedState.getSuperState());
mCurrentPage = savedState.currentPage;
mSnapPage = savedState.currentPage;
requestLayout();
}
#Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPage = mCurrentPage;
return savedState;
}
static class SavedState extends BaseSavedState {
int currentPage;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPage = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPage);
}
#SuppressWarnings("UnusedDeclaration")
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
#Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
Use this class in your xml :
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="fill_parent"
android:layout_height="220dp" />
<com.example.support.CirclePageIndicator
android:id="#+id/indicator"
android:layout_width="fill_parent"
android:layout_height="20dp"
android:layout_below="#+id/view_pager"
android:layout_marginTop="10dp" />

How to disable scrolling to next fragment in a horizontal scroll view group?

I've successfully implemented a customized scroll view group to use gestures to swipe between my different fragments. But i want to sometimes disable swiping to next fragment, while still allowing going back to previous fragment. How can i do that based on the code? Thank you very much.
I've created a boolean value to indicate this nameing "allowNext"
import java.util.Vector;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
public class HorizontalScrollInViewGroup extends ViewGroup {
private boolean allowNext = true;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mCurScreen;
private int mDefaultScreen = 0;
private static final int TOUCH_STATE_REST = 0;
private static final int TOUCH_STATE_SCROLLING = 1;
private static final int SNAP_VELOCITY = 500;
private int mTouchState = TOUCH_STATE_REST;
private int mTouchSlop;
private float mLastMotionX;
private int sensitivity = 30;
private boolean spring;
private Vector<HorizontalScrollInViewGroupListener> listeners;
//used for the screen changed listener
private OnScreenChangedListener screenChangedCallBack;
public HorizontalScrollInViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
mScroller = new Scroller(context);
setCurScreen(mDefaultScreen);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
listeners = new Vector<HorizontalScrollInViewGroupListener>();
//initiate the screen change listener
screenChangedCallBack = (OnScreenChangedListener)context;
}
// An interface that tells the activity the screen is switched
public interface OnScreenChangedListener {
public void onScreenChanged(int currentScreen);
}
/* (non-Javadoc)
* #see android.view.ViewGroup#onLayout(boolean, int, int, int, int)
*/
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
int childLeft = 0;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
final int childWidth = childView.getMeasuredWidth();
childView.layout(childLeft, 0, childLeft + childWidth,
childView.getMeasuredHeight());
childLeft += childWidth;
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int width = MeasureSpec.getSize(widthMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"HorizontalScrollInViewGroup only canmCurScreen run at EXACTLY mode!");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"HorizontalScrollInViewGroup only can run at EXACTLY mode!");
}
// The children are given the same width and height as the scrollLayout
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
scrollTo(getCurScreen() * width, 0);
}
#Override
public void computeScroll() {
// TODO Auto-generated method stub
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (mVelocityTracker == null)
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(event);
final int action = event.getAction();
final float x = event.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished())
mScroller.abortAnimation();
mLastMotionX = x;
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int) (mLastMotionX - x);
if (Math.abs(deltaX) > sensitivity) {
if (spring) {
scrollBy(deltaX, 0);
mLastMotionX = x;
} else {
final int childCount = getChildCount();
boolean max = getCurScreen() < childCount - 1;
boolean min = getCurScreen() > 0;
boolean canMove = deltaX > 0 ? (max ? true : false)
: (min ? true : false);
if (canMove) {
scrollBy(deltaX, 0);
mLastMotionX = x;
}
}
}
break;
case MotionEvent.ACTION_UP:
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000);
int velocityX = (int) velocityTracker.getXVelocity();
if (velocityX > SNAP_VELOCITY && getCurScreen() > 0) {
// Fling enough to move left
snapToScreen(getCurScreen() - 1);
} else if (velocityX < -SNAP_VELOCITY && getCurScreen() < getChildCount() - 1) {
// Fling enough to move right
snapToScreen(getCurScreen() + 1);
} else {
snapToDestination();
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
mTouchState = TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
break;
}
return true;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
final int action = ev.getAction();
if ((action == MotionEvent.ACTION_MOVE)
&& (mTouchState != TOUCH_STATE_REST))
return true;
final float x = ev.getX();
switch (action) {
case MotionEvent.ACTION_MOVE:
final int xDiff = (int) Math.abs(mLastMotionX - x);
if (xDiff > mTouchSlop)
mTouchState = TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_DOWN:
mLastMotionX = x;
mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
: TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mTouchState = TOUCH_STATE_REST;
break;
}
return mTouchState != TOUCH_STATE_REST;
}
public void snapToDestination() {
final int screenWidth = getWidth();
final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;
snapToScreen(destScreen);
//call back to let the activity know the current screen
screenChangedCallBack.onScreenChanged(getCurScreen());
}
public void snapToScreen(int whichScreen) {
// get the valid layout page
int lastIndex = getCurScreen();
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
if (getScrollX() != (whichScreen * getWidth())) {
final int delta = whichScreen * getWidth() - getScrollX();
mScroller.startScroll(getScrollX(), 0, delta, 0,
Math.abs(delta) * 2);
setCurScreen(whichScreen);
invalidate(); // Redraw the layout
}
for (HorizontalScrollInViewGroupListener listener : listeners)
listener.turnPage(lastIndex, whichScreen);
//call back to let the activity know the current screen
screenChangedCallBack.onScreenChanged(getCurScreen());
}
public void setToScreen(int whichScreen) {
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
setCurScreen(whichScreen);
scrollTo(whichScreen * getWidth(), 0);
//call back to let the activity know the current screen
screenChangedCallBack.onScreenChanged(getCurScreen());
}
public int getCurScreen() {
return mCurScreen;
}
public void setCurScreen(int mCurScreen) {
this.mCurScreen = mCurScreen;
}
public boolean isAllowNext() {
return allowNext;
}
public void setAllowNext(boolean allowNext) {
this.allowNext = allowNext;
}
}

how can I make this ScrollLayout loop?

I have find some guy's code, a scrollLayout that it's a view group can hold some views,and you can swipe the views in it like android's view pager.for example, if i have 3 views in it. v0,v1,v2. when when I swiped the scrollLayout, it's onViewChange(View v) invoked, the v is what view you in. but now I want loop the views in it,and how Can I do it? my demand is,
when I continue swipe it,the result is ,v0,v1,v2 v0,v1,v2,v0,v1,v2...
public class ScrollLayout extends ViewGroup {
private static final String TAG = "ScrollLayout";
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mCurScreen;
private int mDefaultScreen = 0;
private static final int TOUCH_STATE_REST = 0;
private static final int TOUCH_STATE_SCROLLING = 1;
private static final int SNAP_VELOCITY = 9600;
private int mTouchState = TOUCH_STATE_REST;
private int mTouchSlop;
private float mLastMotionX;
private float mLastMotionY;
private OnViewChangeListener mOnViewChangeListener;
/**
* 设置是否可左右滑动
* #author liux
*/
private boolean isScroll = true;
public void setIsScroll(boolean b) {
this.isScroll = b;
}
public ScrollLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScroller = new Scroller(context);
mCurScreen = mDefaultScreen;
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childLeft = 0;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
final int childWidth = childView.getMeasuredWidth();
childView.layout(childLeft, 0, childLeft + childWidth,
childView.getMeasuredHeight());
childLeft += childWidth;
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Log.e(TAG, "onMeasure");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int width = MeasureSpec.getSize(widthMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"ScrollLayout only canmCurScreen run at EXACTLY mode!");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"ScrollLayout only can run at EXACTLY mode!");
}
// The children are given the same width and height as the scrollLayout
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
// Log.e(TAG, "moving to screen "+mCurScreen);
scrollTo(mCurScreen * width, 0);
}
/**
* According to the position of current layout scroll to the destination
* page.
*/
public void snapToDestination() {
final int screenWidth = getWidth();
final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;
snapToScreen(destScreen);
}
public void snapToScreen(int whichScreen) {
//是否可滑动
if(!isScroll) {
this.setToScreen(whichScreen);
return;
}
scrollToScreen(whichScreen);
}
public void scrollToScreen(int whichScreen) {
// get the valid layout page
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
if (getScrollX() != (whichScreen * getWidth())) {
final int delta = whichScreen * getWidth() - getScrollX();
mScroller.startScroll(getScrollX(), 0, delta, 0,
Math.abs(delta) * 1);//持续滚动时间 以毫秒为单位
mCurScreen = whichScreen;
invalidate(); // Redraw the layout
if (mOnViewChangeListener != null)
{
mOnViewChangeListener.OnViewChange(mCurScreen);
}
}
}
public void setToScreen(int whichScreen) {
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
mCurScreen = whichScreen;
scrollTo(whichScreen * getWidth(), 0);
if (mOnViewChangeListener != null)
{
mOnViewChangeListener.OnViewChange(mCurScreen);
}
}
public int getCurScreen() {
return mCurScreen;
}
#Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//是否可滑动
if(!isScroll) {
return false;
}
Log.d("lightmanTouch", "Scroll onTouch "+event.getAction());
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
final int action = event.getAction();
final float x = event.getX();
final float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
//Log.e(TAG, "event down!");
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
mLastMotionX = x;
//---------------New Code----------------------
mLastMotionY = y;
//---------------------------------------------
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int) (mLastMotionX - x);
//---------------New Code----------------------
int deltaY = (int) (mLastMotionY - y);
if(Math.abs(deltaX) < 200 && Math.abs(deltaY) > 50)
break;
mLastMotionY = y;
//-------------------------------------
mLastMotionX = x;
if(Math.abs(deltaX) > 10)
scrollBy(deltaX, 0);
Log.d("movescroll", "deltax = "+ deltaX);
break;
case MotionEvent.ACTION_UP:
//Log.e(TAG, "event : up");
// if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000);
int velocityX = (int) velocityTracker.getXVelocity();
//Log.e(TAG, "velocityX:" + velocityX);
if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {
// Fling enough to move left
//Log.e(TAG, "snap left");
snapToScreen(mCurScreen - 1);
} else if (velocityX < -SNAP_VELOCITY
&& mCurScreen < getChildCount() - 1) {
// Fling enough to move right
//Log.e(TAG, "snap right");
snapToScreen(mCurScreen + 1);
} else {
snapToDestination();
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
// }
mTouchState = TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
break;
}
Log.d("SCROLLL", "before true "+System.currentTimeMillis());
return true;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//Log.e(TAG, "onInterceptTouchEvent-slop:" + mTouchSlop);
final int action = ev.getAction();
if ((action == MotionEvent.ACTION_MOVE)
&& (mTouchState != TOUCH_STATE_REST)) {
if(isScroll)
return true;
else
return false;
}
final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_MOVE:
final int xDiff = (int) Math.abs(mLastMotionX - x);
if (xDiff > mTouchSlop) {
mTouchState = TOUCH_STATE_SCROLLING;
}
break;
case MotionEvent.ACTION_DOWN:
mLastMotionX = x;
mLastMotionY = y;
mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
: TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mTouchState = TOUCH_STATE_REST;
break;
}
if(isScroll)
return mTouchState != TOUCH_STATE_REST;
else
return false;
}
/**
* 设置屏幕切换监听器
* #param listener
*/
public void SetOnViewChangeListener(OnViewChangeListener listener)
{
mOnViewChangeListener = listener;
}
/**
* 屏幕切换监听器
* #author liux
*/
public interface OnViewChangeListener {
public void OnViewChange(int view);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
int scrollX = getScrollX();
final int N = getChildCount();
final int width = getWidth();
if (scrollX < 0) {
View lastChild = getChildAt(N - 1);
Log.d("TEST", "draw extra left ,scrollX is : " + scrollX + " width:"+lastChild.getWidth());
// end of first view and draw last view at its left
canvas.save();
canvas.translate(-width, 0);
canvas.clipRect(0, 0, width, getBottom());
lastChild.draw(canvas);
canvas.restore();
} else if (scrollX > (N - 1) * width) {
Log.d("TEST", "draw extra right ,scrollX is : " + scrollX);
View firstChild = getChildAt(0);
canvas.save();
canvas.translate(N * width, 0);
canvas.clipRect(0, 0, width, getBottom());
firstChild.draw(canvas);
canvas.restore();
}
}
}

how to set custom image on space between two CirclePageIndicator in android?

I am used viewpager and also to used custom library CirclePageIndicator and problem is that image draw on select and unselect with space between two circle image draw and but select and unselect image draw and image not draw space between two image, please be help me
Actual ouput i need to and snapshot,
Device output as,
My CirclePageIndicator class as,
public class CirclePageIndicator extends View implements PageIndicator {
private static final int INVALID_POINTER = -1;
private float mRadius;
private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG);
private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG);
private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG);
private ViewPager mViewPager;
private ViewPager.OnPageChangeListener mListener;
private int mCurrentPage;
private int mSnapPage;
private float mPageOffset;
private int mScrollState;
private int mOrientation;
private boolean mCentered;
private boolean mSnap;
private int mTouchSlop;
private float mLastMotionX = -1;
private int mActivePointerId = INVALID_POINTER;
private boolean mIsDragging;
public CirclePageIndicator(Context context) {
this(context, null);
}
public CirclePageIndicator(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.vpiCirclePageIndicatorStyle);
}
#SuppressWarnings("deprecation")
public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (isInEditMode()) return;
//Load defaults from resources
final Resources res = getResources();
final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color);
final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color);
final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation);
final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color);
final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width);
final float defaultRadius = res.getDimension(R.dimen.default_circle_indicator_radius);
final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered);
final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap);
// Retrieve styles attributes
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0);
mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered);
mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation);
mPaintPageFill.setStyle(Style.FILL);
mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor));
mPaintStroke.setStyle(Style.STROKE);
mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor));
mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth));
mPaintFill.setStyle(Style.FILL);
mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor));
mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius);
mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap);
Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background);
if (background != null) {
setBackgroundDrawable(background);
}
a.recycle();
final ViewConfiguration configuration = ViewConfiguration.get(context);
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
}
public void setCentered(boolean centered) {
mCentered = centered;
invalidate();
}
public boolean isCentered() {
return mCentered;
}
public void setPageColor(int pageColor) {
mPaintPageFill.setColor(pageColor);
invalidate();
}
public int getPageColor() {
return mPaintPageFill.getColor();
}
public void setFillColor(int fillColor) {
mPaintFill.setColor(fillColor);
invalidate();
}
public int getFillColor() {
return mPaintFill.getColor();
}
public void setOrientation(int orientation) {
switch (orientation) {
case HORIZONTAL:
case VERTICAL:
mOrientation = orientation;
requestLayout();
break;
default:
throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL.");
}
}
public int getOrientation() {
return mOrientation;
}
public void setStrokeColor(int strokeColor) {
mPaintStroke.setColor(strokeColor);
invalidate();
}
public int getStrokeColor() {
return mPaintStroke.getColor();
}
public void setStrokeWidth(float strokeWidth) {
mPaintStroke.setStrokeWidth(strokeWidth);
invalidate();
}
public float getStrokeWidth() {
return mPaintStroke.getStrokeWidth();
}
public void setRadius(float radius) {
mRadius = radius;
invalidate();
}
public float getRadius() {
return mRadius;
}
public void setSnap(boolean snap) {
mSnap = snap;
invalidate();
}
public boolean isSnap() {
return mSnap;
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mViewPager == null) {
return;
}
final int count = mViewPager.getAdapter().getCount();
if (count == 0) {
return;
}
if (mCurrentPage >= count) {
setCurrentItem(count - 1);
return;
}
int longSize;
int longPaddingBefore;
int longPaddingAfter;
int shortPaddingBefore;
if (mOrientation == HORIZONTAL) {
longSize = getWidth();
longPaddingBefore = getPaddingLeft();
longPaddingAfter = getPaddingRight();
shortPaddingBefore = getPaddingTop();
} else {
longSize = getHeight();
longPaddingBefore = getPaddingTop();
longPaddingAfter = getPaddingBottom();
shortPaddingBefore = getPaddingLeft();
}
final float threeRadius = mRadius * 3;
final float shortOffset = shortPaddingBefore + mRadius;
float longOffset = longPaddingBefore + mRadius;
if (mCentered) {
longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f);
}
float dX = 0.0f;
float dY = 0.0f;
float pageFillRadius = mRadius;
if (mPaintStroke.getStrokeWidth() > 0) {
pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f;
}
//Draw stroked circles
for (int iLoop = 0; iLoop < count; iLoop++) {
float drawLong = longOffset + (iLoop * threeRadius);
if (mOrientation == HORIZONTAL) {
dX = drawLong;
dY = shortOffset;
} else {
dX = shortOffset;
dY = drawLong;
}
// Only paint fill if not completely transparent
if (mPaintPageFill.getAlpha() > 0) {
canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill);
// Bitmap mBitmapLine = BitmapFactory.decodeResource(getResources(), R.drawable.slider_line);
// canvas.drawBitmap(mBitmapLine, dX, dY, mPaintPageFill);
}
// Only paint stroke if a stroke width was non-zero
if (pageFillRadius != mRadius) {
// canvas.drawCircle(dX, dY, mRadius, mPaintStroke);
Bitmap mBitmapCircleNormal = BitmapFactory.decodeResource(getResources(), R.drawable.slider_circle_normal);
canvas.drawBitmap(mBitmapCircleNormal, dX, dY, mPaintStroke);
}
}
// Draw the filled circle according to the current scroll
float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius;
if (!mSnap) {
cx += mPageOffset * threeRadius;
}
if (mOrientation == HORIZONTAL) {
dX = longOffset + cx;
dY = shortOffset;
} else {
dX = shortOffset;
dY = longOffset + cx;
}
// System.out.println("cx === "+cx);
// Bitmap mBitmapLine = BitmapFactory.decodeResource(getResources(), R.drawable.slider_line);
// canvas.drawBitmap(mBitmapLine, dX, dY, mPaintFill);
// canvas.drawCircle(dX, dY, mRadius, mPaintFill);
Bitmap mBitmapCircleHover = BitmapFactory.decodeResource(getResources(), R.drawable.slider_circle_hover);
canvas.drawBitmap(mBitmapCircleHover, dX, dY, mPaintFill);
}
public boolean onTouchEvent(android.view.MotionEvent ev) {
if (super.onTouchEvent(ev)) {
return true;
}
if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
return false;
}
final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
switch (action) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
mLastMotionX = ev.getX();
break;
case MotionEvent.ACTION_MOVE: {
final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, activePointerIndex);
final float deltaX = x - mLastMotionX;
if (!mIsDragging) {
if (Math.abs(deltaX) > mTouchSlop) {
mIsDragging = true;
}
}
if (mIsDragging) {
mLastMotionX = x;
if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
mViewPager.fakeDragBy(deltaX);
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (!mIsDragging) {
final int count = mViewPager.getAdapter().getCount();
final int width = getWidth();
final float halfWidth = width / 2f;
final float sixthWidth = width / 6f;
if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) {
if (action != MotionEvent.ACTION_CANCEL) {
mViewPager.setCurrentItem(mCurrentPage - 1);
}
return true;
} else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) {
if (action != MotionEvent.ACTION_CANCEL) {
mViewPager.setCurrentItem(mCurrentPage + 1);
}
return true;
}
}
mIsDragging = false;
mActivePointerId = INVALID_POINTER;
if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
break;
case MotionEventCompat.ACTION_POINTER_DOWN: {
final int index = MotionEventCompat.getActionIndex(ev);
mLastMotionX = MotionEventCompat.getX(ev, index);
mActivePointerId = MotionEventCompat.getPointerId(ev, index);
break;
}
case MotionEventCompat.ACTION_POINTER_UP:
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
break;
}
return true;
}
#Override
public void setViewPager(ViewPager view) {
if (mViewPager == view) {
return;
}
if (mViewPager != null) {
mViewPager.setOnPageChangeListener(null);
}
if (view.getAdapter() == null) {
throw new IllegalStateException("ViewPager does not have adapter instance.");
}
mViewPager = view;
mViewPager.setOnPageChangeListener(this);
invalidate();
}
#Override
public void setViewPager(ViewPager view, int initialPosition) {
setViewPager(view);
setCurrentItem(initialPosition);
}
#Override
public void setCurrentItem(int item) {
if (mViewPager == null) {
throw new IllegalStateException("ViewPager has not been bound.");
}
mViewPager.setCurrentItem(item);
mCurrentPage = item;
invalidate();
}
#Override
public void notifyDataSetChanged() {
invalidate();
}
#Override
public void onPageScrollStateChanged(int state) {
mScrollState = state;
if (mListener != null) {
mListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
mCurrentPage = position;
mPageOffset = positionOffset;
invalidate();
if (mListener != null) {
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
#Override
public void onPageSelected(int position) {
if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) {
mCurrentPage = position;
mSnapPage = position;
invalidate();
}
if (mListener != null) {
mListener.onPageSelected(position);
}
}
#Override
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mListener = listener;
}
/*
* (non-Javadoc)
*
* #see android.view.View#onMeasure(int, int)
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mOrientation == HORIZONTAL) {
setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
} else {
setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));
}
}
/**
* Determines the width of this view
*
* #param measureSpec
* A measureSpec packed into an int
* #return The width of the view, honoring constraints from measureSpec
*/
private int measureLong(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
//We were told how big to be
result = specSize;
} else {
//Calculate the width according the views count
final int count = mViewPager.getAdapter().getCount();
result = (int)(getPaddingLeft() + getPaddingRight()
+ (count * 2 * mRadius) + (count - 1) * mRadius + 1);
//Respect AT_MOST value if that was what is called for by measureSpec
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
/**
* Determines the height of this view
*
* #param measureSpec
* A measureSpec packed into an int
* #return The height of the view, honoring constraints from measureSpec
*/
private int measureShort(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
//We were told how big to be
result = specSize;
} else {
//Measure the height
result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);
//Respect AT_MOST value if that was what is called for by measureSpec
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState)state;
super.onRestoreInstanceState(savedState.getSuperState());
mCurrentPage = savedState.currentPage;
mSnapPage = savedState.currentPage;
requestLayout();
}
#Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPage = mCurrentPage;
return savedState;
}
static class SavedState extends BaseSavedState {
int currentPage;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPage = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPage);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
#Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}

Categories

Resources