Unable to start activity with java.lang.NullPointerException on Fling - android

When I am trying to fling example this error faced. with java Null pointer exception.
My java code
public class LearnCount extends Activity {
private FlingGallery mGallery;
public boolean onTouchEvent(MotionEvent event) {
return mGallery.onGalleryTouchEvent(event);
}
private String[] teststr = {
"test1","test2","test3","test4","test5"
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.main);
LinearLayout productHolder = (LinearLayout) findViewById(R.id.linearLayoutOfCount);
mGallery = new FlingGallery(this);
mGallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1, teststr) {
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println(mGallery.getCurrentPosition() + " position");
if (convertView != null
&& convertView instanceof GalleryViewItem) {
GalleryViewItem galleryView = (GalleryViewItem) convertView;
//galleryView.pImage.setImageResource(mImageIds[position]);
galleryView.b.setText(teststr[position]);
return galleryView;
}
GalleryViewItem gvi = new GalleryViewItem(getApplicationContext(), position);
gvi.b.setText(teststr[position]);
return gvi;
}
});
productHolder.addView(mGallery);
}
public class GalleryViewItem extends TableLayout {
private TextView b;
public GalleryViewItem(Context context, int position) {
super(context);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.test, null);
b = (TextView) v.findViewById(R.id.test);
this.addView(v);
}
}
public class FlingGallery extends FrameLayout {
// Constants
private final int swipe_min_distance = 120;
private final int swipe_max_off_path = 250;
private final int swipe_threshold_veloicty = 400;
// Properties
private int mViewPaddingWidth = 0;
private int mAnimationDuration = 250;
private float mSnapBorderRatio = 0.5f;
private boolean mIsGalleryCircular = false;
// Members
private int mGalleryWidth = 0;
private boolean mIsTouched = false;
private boolean mIsDragging = false;
private float mCurrentOffset = 0.0f;
private long mScrollTimestamp = 0;
private int mFlingDirection = 0;
public int mCurrentPosition = 0;
private int mCurrentViewNumber = 0;
private Context mContext;
private Adapter mAdapter;
private FlingGalleryView[] mViews;
private FlingGalleryAnimation mAnimation;
private GestureDetector mGestureDetector;
private Interpolator mDecelerateInterpolater;
public FlingGallery(Context context) {
super(context);
mContext = context;
mAdapter = null;
mViews = new FlingGalleryView[3];
mViews[0] = new FlingGalleryView(0, this);
mViews[1] = new FlingGalleryView(1, this);
mViews[2] = new FlingGalleryView(2, this);
mAnimation = new FlingGalleryAnimation();
mGestureDetector = new GestureDetector(new FlingGestureDetector());
mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext,
android.R.anim.decelerate_interpolator);
}
public void setPaddingWidth(int viewPaddingWidth) {
mViewPaddingWidth = viewPaddingWidth;
}
public void setAnimationDuration(int animationDuration) {
mAnimationDuration = animationDuration;
}
public void setSnapBorderRatio(float snapBorderRatio) {
mSnapBorderRatio = snapBorderRatio;
}
public int getCurrentPosition() {
return mCurrentPosition;
}
public void setIsGalleryCircular(boolean isGalleryCircular) {
if (mIsGalleryCircular != isGalleryCircular) {
mIsGalleryCircular = isGalleryCircular;
if (mCurrentPosition == getFirstPosition()) {
// We need to reload the view immediately to the left to
// change it to circular view or blank
mViews[getPrevViewNumber(mCurrentViewNumber)]
.recycleView(getPrevPosition(mCurrentPosition));
}
if (mCurrentPosition == getLastPosition()) {
// We need to reload the view immediately to the right to
// change it to circular view or blank
mViews[getNextViewNumber(mCurrentViewNumber)]
.recycleView(getNextPosition(mCurrentPosition));
}
}
}
public int getGalleryCount() {
return (mAdapter == null) ? 0 : mAdapter.getCount();
}
public int getFirstPosition() {
return 0;
}
public int getLastPosition() {
return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;
}
private int getPrevPosition(int relativePosition) {
int prevPosition = relativePosition - 1;
if (prevPosition < getFirstPosition()) {
prevPosition = getFirstPosition() - 1;
if (mIsGalleryCircular == true) {
prevPosition = getLastPosition();
}
}
return prevPosition;
}
private int getNextPosition(int relativePosition) {
int nextPosition = relativePosition + 1;
if (nextPosition > getLastPosition()) {
nextPosition = getLastPosition() + 1;
if (mIsGalleryCircular == true) {
nextPosition = getFirstPosition();
}
}
return nextPosition;
}
private int getPrevViewNumber(int relativeViewNumber) {
return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;
}
private int getNextViewNumber(int relativeViewNumber) {
return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;
}
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
// Calculate our view width
mGalleryWidth = right - left;
if (changed == true) {
// Position views at correct starting offsets
mViews[0].setOffset(0, 0, mCurrentViewNumber);
mViews[1].setOffset(0, 0, mCurrentViewNumber);
mViews[2].setOffset(0, 0, mCurrentViewNumber);
}
}
public void setAdapter(Adapter adapter) {
mAdapter = adapter;
mCurrentPosition = 0;
mCurrentViewNumber = 0;
// Load the initial views from adapter
mViews[0].recycleView(mCurrentPosition);
mViews[1].recycleView(getNextPosition(mCurrentPosition));
mViews[2].recycleView(getPrevPosition(mCurrentPosition));
// Position views at correct starting offsets
mViews[0].setOffset(0, 0, mCurrentViewNumber);
mViews[1].setOffset(0, 0, mCurrentViewNumber);
mViews[2].setOffset(0, 0, mCurrentViewNumber);
}
private int getViewOffset(int viewNumber, int relativeViewNumber) {
// Determine width including configured padding width
int offsetWidth = mGalleryWidth + mViewPaddingWidth;
// Position the previous view one measured width to left
if (viewNumber == getPrevViewNumber(relativeViewNumber)) {
return offsetWidth;
}
// Position the next view one measured width to the right
if (viewNumber == getNextViewNumber(relativeViewNumber)) {
return offsetWidth * -1;
}
return 0;
}
void movePrevious() {
// Slide to previous view
mFlingDirection = 1;
processGesture();
}
void moveNext() {
// Slide to next view
mFlingDirection = -1;
processGesture();
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
movePrevious();
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
moveNext();
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
}
return super.onKeyDown(keyCode, event);
}
public boolean onGalleryTouchEvent(MotionEvent event) {
boolean consumed = mGestureDetector.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
if (mIsTouched || mIsDragging) {
processScrollSnap();
processGesture();
}
}
return consumed;
}
void processGesture() {
int newViewNumber = mCurrentViewNumber;
int reloadViewNumber = 0;
int reloadPosition = 0;
mIsTouched = false;
mIsDragging = false;
if (mFlingDirection > 0) {
if (mCurrentPosition > getFirstPosition()
|| mIsGalleryCircular == true) {
// Determine previous view and outgoing view to recycle
newViewNumber = getPrevViewNumber(mCurrentViewNumber);
mCurrentPosition = getPrevPosition(mCurrentPosition);
reloadViewNumber = getNextViewNumber(mCurrentViewNumber);
reloadPosition = getPrevPosition(mCurrentPosition);
}
}
if (mFlingDirection < 0) {
if (mCurrentPosition < getLastPosition()
|| mIsGalleryCircular == true) {
// Determine the next view and outgoing view to recycle
newViewNumber = getNextViewNumber(mCurrentViewNumber);
mCurrentPosition = getNextPosition(mCurrentPosition);
reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);
reloadPosition = getNextPosition(mCurrentPosition);
}
}
if (newViewNumber != mCurrentViewNumber) {
mCurrentViewNumber = newViewNumber;
// Reload outgoing view from adapter in new position
mViews[reloadViewNumber].recycleView(reloadPosition);
}
// Ensure input focus on the current view
mViews[mCurrentViewNumber].requestFocus();
// Run the slide animations for view transitions
mAnimation.prepareAnimation(mCurrentViewNumber);
this.startAnimation(mAnimation);
// Reset fling state
mFlingDirection = 0;
//checkNextBackButton(mCurrentPosition);
System.out.println("positionFiling" + mCurrentPosition);
}
void processScrollSnap() {
// Snap to next view if scrolled passed snap position
float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;
int rollOffset = mGalleryWidth - (int) rollEdgeWidth;
int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
if (currentOffset <= rollOffset * -1) {
// Snap to previous view
mFlingDirection = 1;
}
if (currentOffset >= rollOffset) {
// Snap to next view
mFlingDirection = -1;
}
}
public class FlingGalleryView {
private int mViewNumber;
private FrameLayout mParentLayout;
private FrameLayout mInvalidLayout = null;
private LinearLayout mInternalLayout = null;
private View mExternalView = null;
public FlingGalleryView(int viewNumber, FrameLayout parentLayout) {
mViewNumber = viewNumber;
mParentLayout = parentLayout;
// Invalid layout is used when outside gallery
mInvalidLayout = new FrameLayout(mContext);
mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
// Internal layout is permanent for duration
mInternalLayout = new LinearLayout(mContext);
mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
mParentLayout.addView(mInternalLayout);
}
public void recycleView(int newPosition) {
if (mExternalView != null) {
mInternalLayout.removeView(mExternalView);
}
if (mAdapter != null) {
if (newPosition >= getFirstPosition()
&& newPosition <= getLastPosition()) {
mExternalView = mAdapter.getView(newPosition,
mExternalView, mInternalLayout);
} else {
mExternalView = mInvalidLayout;
}
}
if (mExternalView != null) {
mInternalLayout.addView(mExternalView,
new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
}
}
public void setOffset(int xOffset, int yOffset,
int relativeViewNumber) {
// Scroll the target view relative to its own position relative
// to currently displayed view
mInternalLayout.scrollTo(getViewOffset(mViewNumber,
relativeViewNumber)
+ xOffset, yOffset);
}
public int getCurrentOffset() {
// Return the current scroll position
return mInternalLayout.getScrollX();
}
public void requestFocus() {
mInternalLayout.requestFocus();
}
}
public class FlingGalleryAnimation extends Animation {
private boolean mIsAnimationInProgres;
private int mRelativeViewNumber;
private int mInitialOffset;
private int mTargetOffset;
private int mTargetDistance;
public FlingGalleryAnimation() {
mIsAnimationInProgres = false;
mRelativeViewNumber = 0;
mInitialOffset = 0;
mTargetOffset = 0;
mTargetDistance = 0;
}
public void prepareAnimation(int relativeViewNumber) {
// If we are animating relative to a new view
if (mRelativeViewNumber != relativeViewNumber) {
if (mIsAnimationInProgres == true) {
// We only have three views so if requested again to
// animate in same direction we must snap
int newDirection = (relativeViewNumber == getPrevViewNumber(mRelativeViewNumber)) ? 1
: -1;
int animDirection = (mTargetDistance < 0) ? 1 : -1;
// If animation in same direction
if (animDirection == newDirection) {
// Ran out of time to animate so snap to the target
// offset
mViews[0].setOffset(mTargetOffset, 0,
mRelativeViewNumber);
mViews[1].setOffset(mTargetOffset, 0,
mRelativeViewNumber);
mViews[2].setOffset(mTargetOffset, 0,
mRelativeViewNumber);
}
}
// Set relative view number for animation
mRelativeViewNumber = relativeViewNumber;
}
// Note: In this implementation the targetOffset will always be
// zero
// as we are centering the view; but we include the calculations
// of
// targetOffset and targetDistance for use in future
// implementations
mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset();
mTargetOffset = getViewOffset(mRelativeViewNumber,
mRelativeViewNumber);
mTargetDistance = mTargetOffset - mInitialOffset;
// Configure base animation properties
this.setDuration(mAnimationDuration);
this.setInterpolator(mDecelerateInterpolater);
// Start/continued animation
mIsAnimationInProgres = true;
}
protected void applyTransformation(float interpolatedTime,
Transformation transformation) {
// Ensure interpolatedTime does not over-shoot then calculate
// new offset
interpolatedTime = (interpolatedTime > 1.0f) ? 1.0f
: interpolatedTime;
int offset = mInitialOffset
+ (int) (mTargetDistance * interpolatedTime);
for (int viewNumber = 0; viewNumber < 3; viewNumber++) {
// Only need to animate the visible views as the other view
// will always be off-screen
if ((mTargetDistance > 0 && viewNumber != getNextViewNumber(mRelativeViewNumber))
|| (mTargetDistance < 0 && viewNumber != getPrevViewNumber(mRelativeViewNumber))) {
mViews[viewNumber].setOffset(offset, 0,
mRelativeViewNumber);
}
}
}
public boolean getTransformation(long currentTime,
Transformation outTransformation) {
if (super.getTransformation(currentTime, outTransformation) == false) {
// Perform final adjustment to offsets to cleanup animation
mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);
// Reached the animation target
mIsAnimationInProgres = false;
return false;
}
// Cancel if the screen touched
if (mIsTouched || mIsDragging) {
// Note that at this point we still consider ourselves to be
// animating
// because we have not yet reached the target offset; its
// just that the
// user has temporarily interrupted the animation with a
// touch gesture
return false;
}
return true;
}
}
private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener {
public boolean onDown(MotionEvent e) {
// Stop animation
mIsTouched = true;
// Reset fling state
mFlingDirection = 0;
return true;
}
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
if (e2.getAction() == MotionEvent.ACTION_MOVE) {
if (mIsDragging == false) {
// Stop animation
mIsTouched = true;
// Reconfigure scroll
mIsDragging = true;
mFlingDirection = 0;
mScrollTimestamp = System.currentTimeMillis();
mCurrentOffset = mViews[mCurrentViewNumber]
.getCurrentOffset();
}
float maxVelocity = mGalleryWidth
/ (mAnimationDuration / 1000.0f);
long timestampDelta = System.currentTimeMillis()
- mScrollTimestamp;
float maxScrollDelta = maxVelocity
* (timestampDelta / 1000.0f);
float currentScrollDelta = e1.getX() - e2.getX();
if (currentScrollDelta < maxScrollDelta * -1)
currentScrollDelta = maxScrollDelta * -1;
if (currentScrollDelta > maxScrollDelta)
currentScrollDelta = maxScrollDelta;
int scrollOffset = Math.round(mCurrentOffset
+ currentScrollDelta);
// We can't scroll more than the width of our own frame
// layout
if (scrollOffset >= mGalleryWidth)
scrollOffset = mGalleryWidth;
if (scrollOffset <= mGalleryWidth * -1)
scrollOffset = mGalleryWidth * -1;
mViews[0].setOffset(scrollOffset, 0, mCurrentViewNumber);
mViews[1].setOffset(scrollOffset, 0, mCurrentViewNumber);
mViews[2].setOffset(scrollOffset, 0, mCurrentViewNumber);
}
return false;
}
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
if (Math.abs(e1.getY() - e2.getY()) <= swipe_max_off_path) {
if (e2.getX() - e1.getX() > swipe_min_distance
&& Math.abs(velocityX) > swipe_threshold_veloicty) {
movePrevious();
}
if (e1.getX() - e2.getX() > swipe_min_distance
&& Math.abs(velocityX) > swipe_threshold_veloicty) {
moveNext();
}
}
return false;
}
public void onLongPress(MotionEvent e) {
// Finalise scrolling
mFlingDirection = 0;
processGesture();
}
public void onShowPress(MotionEvent e) {
}
public boolean onSingleTapUp(MotionEvent e) {
// Reset fling state
mFlingDirection = 0;
return false;
}
}
}
}
My log cat error message is:
I am the beginner for android, something wrong my code?

LinearLayout productHolder = (LinearLayout) findViewById(R.id.linearLayoutOfCount);
Is returning null. Make sure you are referencing the correct id.

Related

Swipe refresh layout is not working for web view.

I am using swipe refresh layout but it is not working for web view. It is working for a simple activity layout, but when i am using a web view it's not working properly.
Here is my code.
public class SwipeActivity extends Activity implements OnRefreshListener{
SwipeRefreshLayout swipeLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
#Override public void run() {
swipeLayout.setRefreshing(false);
}
}, 5000);
}
}
And this one is swipe refresh layout.
public class SwipeRefreshLayout extends ViewGroup {
private static final long RETURN_TO_ORIGINAL_POSITION_TIMEOUT = 300;
private static final float ACCELERATE_INTERPOLATION_FACTOR = 1.5f;
private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
private static final float PROGRESS_BAR_HEIGHT = 4;
private static final float MAX_SWIPE_DISTANCE_FACTOR = .6f;
private static final int REFRESH_TRIGGER_DISTANCE = 120;
private SwipeProgressBar mProgressBar; //the thing that shows progress is going
private View mTarget; //the content that gets pulled down
private int mOriginalOffsetTop;
private OnRefreshListener mListener;
private MotionEvent mDownEvent;
private int mFrom;
private boolean mRefreshing = false;
private int mTouchSlop;
private float mDistanceToTriggerSync = -1;
private float mPrevY;
private int mMediumAnimationDuration;
private float mFromPercentage = 0;
private float mCurrPercentage = 0;
private int mProgressBarHeight;
private int mCurrentTargetOffsetTop;
// Target is returning to its start offset because it was cancelled or a
// refresh was triggered.
private boolean mReturningToStart;
private final DecelerateInterpolator mDecelerateInterpolator;
private final AccelerateInterpolator mAccelerateInterpolator;
private static final int[] LAYOUT_ATTRS = new int[] {
android.R.attr.enabled
};
private final Animation mAnimateToStartPosition = new Animation() {
#Override
public void applyTransformation(float interpolatedTime, Transformation t) {
int targetTop = 0;
if (mFrom != mOriginalOffsetTop) {
targetTop = (mFrom + (int)((mOriginalOffsetTop - mFrom) * interpolatedTime));
}
int offset = targetTop - mTarget.getTop();
final int currentTop = mTarget.getTop();
if (offset + currentTop < 0) {
offset = 0 - currentTop;
}
setTargetOffsetTopAndBottom(offset);
}
};
private Animation mShrinkTrigger = new Animation() {
#Override
public void applyTransformation(float interpolatedTime, Transformation t) {
float percent = mFromPercentage + ((0 - mFromPercentage) * interpolatedTime);
mProgressBar.setTriggerPercentage(percent);
}
};
private final AnimationListener mReturnToStartPositionListener = new BaseAnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
// Once the target content has returned to its start position, reset
// the target offset to 0
mCurrentTargetOffsetTop = 0;
}
};
private final AnimationListener mShrinkAnimationListener = new BaseAnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
mCurrPercentage = 0;
}
};
private final Runnable mReturnToStartPosition = new Runnable() {
#Override
public void run() {
mReturningToStart = true;
animateOffsetToStartPosition(mCurrentTargetOffsetTop + getPaddingTop(),
mReturnToStartPositionListener);
}
};
// Cancel the refresh gesture and animate everything back to its original state.
private final Runnable mCancel = new Runnable() {
#Override
public void run() {
mReturningToStart = true;
// Timeout fired since the user last moved their finger; animate the
// trigger to 0 and put the target back at its original position
if (mProgressBar != null) {
mFromPercentage = mCurrPercentage;
mShrinkTrigger.setDuration(mMediumAnimationDuration);
mShrinkTrigger.setAnimationListener(mShrinkAnimationListener);
mShrinkTrigger.reset();
mShrinkTrigger.setInterpolator(mDecelerateInterpolator);
startAnimation(mShrinkTrigger);
}
animateOffsetToStartPosition(mCurrentTargetOffsetTop + getPaddingTop(),
mReturnToStartPositionListener);
}
};
/**
* Simple constructor to use when creating a SwipeRefreshLayout from code.
* #param context
*/
public SwipeRefreshLayout(Context context) {
this(context, null);
}
/**
* Constructor that is called when inflating SwipeRefreshLayout from XML.
* #param context
* #param attrs
*/
public SwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMediumAnimationDuration = getResources().getInteger(
android.R.integer.config_mediumAnimTime);
setWillNotDraw(false);
mProgressBar = new SwipeProgressBar(this);
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mProgressBarHeight = (int) (metrics.density * PROGRESS_BAR_HEIGHT);
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
mAccelerateInterpolator = new AccelerateInterpolator(ACCELERATE_INTERPOLATION_FACTOR);
final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
setEnabled(a.getBoolean(0, true));
a.recycle();
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
removeCallbacks(mCancel);
removeCallbacks(mReturnToStartPosition);
}
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(mReturnToStartPosition);
removeCallbacks(mCancel);
}
private void animateOffsetToStartPosition(int from, AnimationListener listener) {
mFrom = from;
mAnimateToStartPosition.reset();
mAnimateToStartPosition.setDuration(mMediumAnimationDuration);
mAnimateToStartPosition.setAnimationListener(listener);
mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);
mTarget.startAnimation(mAnimateToStartPosition);
}
/**
* Set the listener to be notified when a refresh is triggered via the swipe
* gesture.
*/
public void setOnRefreshListener(SwipeActivity swipeActivity) {
mListener = swipeActivity;
}
private void setTriggerPercentage(float percent) {
if (percent == 0f) {
// No-op. A null trigger means it's uninitialized, and setting it to zero-percent
// means we're trying to reset state, so there's nothing to reset in this case.
mCurrPercentage = 0;
return;
}
mCurrPercentage = percent;
mProgressBar.setTriggerPercentage(percent);
}
/**
* Notify the widget that refresh state has changed. Do not call this when
* refresh is triggered by a swipe gesture.
*
* #param refreshing Whether or not the view should show refresh progress.
*/
public void setRefreshing(boolean refreshing) {
if (mRefreshing != refreshing) {
ensureTarget();
mCurrPercentage = 0;
mRefreshing = refreshing;
if (mRefreshing) {
mProgressBar.start();
} else {
mProgressBar.stop();
}
}
}
/**
* Set the four colors used in the progress animation. The first color will
* also be the color of the bar that grows in response to a user swipe
* gesture.
*
* #param colorRes1 Color resource.
* #param colorRes2 Color resource.
* #param colorRes3 Color resource.
* #param colorRes4 Color resource.
*/
public void setColorScheme(int colorRes1, int colorRes2, int colorRes3, int colorRes4) {
ensureTarget();
final Resources res = getResources();
final int color1 = res.getColor(colorRes1);
final int color2 = res.getColor(colorRes2);
final int color3 = res.getColor(colorRes3);
final int color4 = res.getColor(colorRes4);
mProgressBar.setColorScheme(color1, color2, color3,color4);
}
/**
* #return Whether the SwipeRefreshWidget is actively showing refresh
* progress.
*/
public boolean isRefreshing() {
return mRefreshing;
}
private void ensureTarget() {
// Don't bother getting the parent height if the parent hasn't been laid out yet.
if (mTarget == null) {
if (getChildCount() > 1 && !isInEditMode()) {
throw new IllegalStateException(
"SwipeRefreshLayout can host only one direct child");
}
mTarget = getChildAt(0);
mOriginalOffsetTop = mTarget.getTop() + getPaddingTop();
}
if (mDistanceToTriggerSync == -1) {
if (getParent() != null && ((View)getParent()).getHeight() > 0) {
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mDistanceToTriggerSync = (int) Math.min(
((View) getParent()) .getHeight() * MAX_SWIPE_DISTANCE_FACTOR,
REFRESH_TRIGGER_DISTANCE * metrics.density);
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
mProgressBar.draw(canvas);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();
mProgressBar.setBounds(0, 0, width, mProgressBarHeight);
if (getChildCount() == 0) {
return;
}
final View child = getChildAt(0);
final int childLeft = getPaddingLeft();
final int childTop = mCurrentTargetOffsetTop + getPaddingTop();
final int childWidth = width - getPaddingLeft() - getPaddingRight();
final int childHeight = height - getPaddingTop() - getPaddingBottom();
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() > 1 && !isInEditMode()) {
throw new IllegalStateException("SwipeRefreshLayout can host only one direct child");
}
if (getChildCount() > 0) {
getChildAt(0).measure(
MeasureSpec.makeMeasureSpec(
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
MeasureSpec.EXACTLY));
}
}
/**
* #return Whether it is possible for the child view of this layout to
* scroll up. Override this if the child view is a custom view.
*/
public boolean canChildScrollUp() {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (mTarget instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTarget;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return mTarget.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(mTarget, -1);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
ensureTarget();
boolean handled = false;
if (mReturningToStart && ev.getAction() == MotionEvent.ACTION_DOWN) {
mReturningToStart = false;
}
if (isEnabled() && !mReturningToStart && !canChildScrollUp()) {
handled = onTouchEvent(ev);
}
return !handled ? super.onInterceptTouchEvent(ev) : handled;
}
#Override
public void requestDisallowInterceptTouchEvent(boolean b) {
// Nope.
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
boolean handled = false;
switch (action) {
case MotionEvent.ACTION_DOWN:
mCurrPercentage = 0;
mDownEvent = MotionEvent.obtain(event);
mPrevY = mDownEvent.getY();
break;
case MotionEvent.ACTION_MOVE:
if (mDownEvent != null && !mReturningToStart) {
final float eventY = event.getY();
float yDiff = eventY - mDownEvent.getY();
if (yDiff > mTouchSlop) {
// User velocity passed min velocity; trigger a refresh
if (yDiff > mDistanceToTriggerSync) {
// User movement passed distance; trigger a refresh
startRefresh();
handled = true;
break;
} else {
// Just track the user's movement
setTriggerPercentage(
mAccelerateInterpolator.getInterpolation(
yDiff / mDistanceToTriggerSync));
float offsetTop = yDiff;
if (mPrevY > eventY) {
offsetTop = yDiff - mTouchSlop;
}
updateContentOffsetTop((int) (offsetTop));
if (mPrevY > eventY && (mTarget.getTop() < mTouchSlop)) {
// If the user puts the view back at the top, we
// don't need to. This shouldn't be considered
// cancelling the gesture as the user can restart from the top.
removeCallbacks(mCancel);
} else {
updatePositionTimeout();
}
mPrevY = event.getY();
handled = true;
}
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mDownEvent != null) {
mDownEvent.recycle();
mDownEvent = null;
}
break;
}
return handled;
}
private void startRefresh() {
removeCallbacks(mCancel);
mReturnToStartPosition.run();
setRefreshing(true);
mListener.onRefresh();
}
private void updateContentOffsetTop(int targetTop) {
final int currentTop = mTarget.getTop();
if (targetTop > mDistanceToTriggerSync) {
targetTop = (int) mDistanceToTriggerSync;
} else if (targetTop < 0) {
targetTop = 0;
}
setTargetOffsetTopAndBottom(targetTop - currentTop);
}
private void setTargetOffsetTopAndBottom(int offset) {
mTarget.offsetTopAndBottom(offset);
mCurrentTargetOffsetTop = mTarget.getTop();
}
private void updatePositionTimeout() {
removeCallbacks(mCancel);
postDelayed(mCancel, RETURN_TO_ORIGINAL_POSITION_TIMEOUT);
}
/**
* Classes that wish to be notified when the swipe gesture correctly
* triggers a refresh should implement this interface.
*/
public interface OnRefreshListener {
public void onRefresh();
}
/**
* Simple AnimationListener to avoid having to implement unneeded methods in
* AnimationListeners.
*/
private class BaseAnimationListener implements AnimationListener {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
}

SwipeRefreshLayout not showing colors at first and only shows when .setRefreshing(false) called

I am making an android app that uses a SwipeRefreshLayout around a RelativeLayout in a fragment in a ViewPager. When I first open the app and swipe to refresh, the refresh disc shows, but it is blank with no colors.
http://i.stack.imgur.com/VzUeB.png
Then, the next time I swipe to refresh, there is no preview of the refresh (the disc does not come down), and when I release, it takes a second to show. I think it only runs when swipeRefreshLayout.setRefreshing(false) is called, and so it only shows for a split second.
This is my code:
swipeRefreshLayout = (SwipeRefreshLayout)view.findViewById(R.id.swipe_container);
swipeRefreshLayout.setColorSchemeResources(R.color.accentColor, R.color.colorPrimary, R.color.colorPrimaryDark);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
TypedValue typed_value = new TypedValue();
getActivity().getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, typed_value, true);
DisplayMetrics dm = getResources().getDisplayMetrics();
int height = dm.heightPixels;
swipeRefreshLayout.setProgressViewOffset(false, -200, height / 8);
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
}
});
try {
result = new GetReadResultTask().execute().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
if (result != null && connected) {
AlphaAnimation fadeOut = new AlphaAnimation(1.0f, 0.0f);
AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
stepsTextView.setAnimation(fadeOut);
fadeOut.setDuration(1200);
fadeOut.setFillAfter(true);
List<Bucket> buckets = result.getBuckets();
for (int iii = 0; iii < buckets.size(); iii++) {
dumpDataSet(buckets.get(iii).getDataSet(DataType.AGGREGATE_STEP_COUNT_DELTA));
}
stepsTextView.setAnimation(fadeIn);
fadeIn.setDuration(1200);
fadeIn.setFillAfter(true);
series.resetData(data);
}
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
});
}
});
Use following code for this..
SwipeActivity Activity is as follows..
public class SwipeActivity extends Activity implements OnRefreshListener{
SwipeRefreshLayout swipeLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
#Override public void run() {
swipeLayout.setRefreshing(false);
}
}, 5000);
}
}
SwipeRefreshLayout is follows.
public class SwipeRefreshLayout extends ViewGroup {
private static final long RETURN_TO_ORIGINAL_POSITION_TIMEOUT = 300;
private static final float ACCELERATE_INTERPOLATION_FACTOR = 1.5f;
private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
private static final float PROGRESS_BAR_HEIGHT = 4;
private static final float MAX_SWIPE_DISTANCE_FACTOR = .6f;
private static final int REFRESH_TRIGGER_DISTANCE = 120;
private SwipeProgressBar mProgressBar; //the thing that shows progress is going
private View mTarget; //the content that gets pulled down
private int mOriginalOffsetTop;
private OnRefreshListener mListener;
private MotionEvent mDownEvent;
private int mFrom;
private boolean mRefreshing = false;
private int mTouchSlop;
private float mDistanceToTriggerSync = -1;
private float mPrevY;
private int mMediumAnimationDuration;
private float mFromPercentage = 0;
private float mCurrPercentage = 0;
private int mProgressBarHeight;
private int mCurrentTargetOffsetTop;
// Target is returning to its start offset because it was cancelled or a
// refresh was triggered.
private boolean mReturningToStart;
private final DecelerateInterpolator mDecelerateInterpolator;
private final AccelerateInterpolator mAccelerateInterpolator;
private static final int[] LAYOUT_ATTRS = new int[] {
android.R.attr.enabled
};
private final Animation mAnimateToStartPosition = new Animation() {
#Override
public void applyTransformation(float interpolatedTime, Transformation t) {
int targetTop = 0;
if (mFrom != mOriginalOffsetTop) {
targetTop = (mFrom + (int)((mOriginalOffsetTop - mFrom) * interpolatedTime));
}
int offset = targetTop - mTarget.getTop();
final int currentTop = mTarget.getTop();
if (offset + currentTop < 0) {
offset = 0 - currentTop;
}
setTargetOffsetTopAndBottom(offset);
}
};
private Animation mShrinkTrigger = new Animation() {
#Override
public void applyTransformation(float interpolatedTime, Transformation t) {
float percent = mFromPercentage + ((0 - mFromPercentage) * interpolatedTime);
mProgressBar.setTriggerPercentage(percent);
}
};
private final AnimationListener mReturnToStartPositionListener = new BaseAnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
// Once the target content has returned to its start position, reset
// the target offset to 0
mCurrentTargetOffsetTop = 0;
}
};
private final AnimationListener mShrinkAnimationListener = new BaseAnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
mCurrPercentage = 0;
}
};
private final Runnable mReturnToStartPosition = new Runnable() {
#Override
public void run() {
mReturningToStart = true;
animateOffsetToStartPosition(mCurrentTargetOffsetTop + getPaddingTop(),
mReturnToStartPositionListener);
}
};
// Cancel the refresh gesture and animate everything back to its original state.
private final Runnable mCancel = new Runnable() {
#Override
public void run() {
mReturningToStart = true;
// Timeout fired since the user last moved their finger; animate the
// trigger to 0 and put the target back at its original position
if (mProgressBar != null) {
mFromPercentage = mCurrPercentage;
mShrinkTrigger.setDuration(mMediumAnimationDuration);
mShrinkTrigger.setAnimationListener(mShrinkAnimationListener);
mShrinkTrigger.reset();
mShrinkTrigger.setInterpolator(mDecelerateInterpolator);
startAnimation(mShrinkTrigger);
}
animateOffsetToStartPosition(mCurrentTargetOffsetTop + getPaddingTop(),
mReturnToStartPositionListener);
}
};
/**
* Simple constructor to use when creating a SwipeRefreshLayout from code.
* #param context
*/
public SwipeRefreshLayout(Context context) {
this(context, null);
}
/**
* Constructor that is called when inflating SwipeRefreshLayout from XML.
* #param context
* #param attrs
*/
public SwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMediumAnimationDuration = getResources().getInteger(
android.R.integer.config_mediumAnimTime);
setWillNotDraw(false);
mProgressBar = new SwipeProgressBar(this);
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mProgressBarHeight = (int) (metrics.density * PROGRESS_BAR_HEIGHT);
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
mAccelerateInterpolator = new AccelerateInterpolator(ACCELERATE_INTERPOLATION_FACTOR);
final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
setEnabled(a.getBoolean(0, true));
a.recycle();
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
removeCallbacks(mCancel);
removeCallbacks(mReturnToStartPosition);
}
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(mReturnToStartPosition);
removeCallbacks(mCancel);
}
private void animateOffsetToStartPosition(int from, AnimationListener listener) {
mFrom = from;
mAnimateToStartPosition.reset();
mAnimateToStartPosition.setDuration(mMediumAnimationDuration);
mAnimateToStartPosition.setAnimationListener(listener);
mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);
mTarget.startAnimation(mAnimateToStartPosition);
}
/**
* Set the listener to be notified when a refresh is triggered via the swipe
* gesture.
*/
public void setOnRefreshListener(SwipeActivity swipeActivity) {
mListener = swipeActivity;
}
private void setTriggerPercentage(float percent) {
if (percent == 0f) {
// No-op. A null trigger means it's uninitialized, and setting it to zero-percent
// means we're trying to reset state, so there's nothing to reset in this case.
mCurrPercentage = 0;
return;
}
mCurrPercentage = percent;
mProgressBar.setTriggerPercentage(percent);
}
/**
* Notify the widget that refresh state has changed. Do not call this when
* refresh is triggered by a swipe gesture.
*
* #param refreshing Whether or not the view should show refresh progress.
*/
public void setRefreshing(boolean refreshing) {
if (mRefreshing != refreshing) {
ensureTarget();
mCurrPercentage = 0;
mRefreshing = refreshing;
if (mRefreshing) {
mProgressBar.start();
} else {
mProgressBar.stop();
}
}
}
/**
* Set the four colors used in the progress animation. The first color will
* also be the color of the bar that grows in response to a user swipe
* gesture.
*
* #param colorRes1 Color resource.
* #param colorRes2 Color resource.
* #param colorRes3 Color resource.
* #param colorRes4 Color resource.
*/
public void setColorScheme(int colorRes1, int colorRes2, int colorRes3, int colorRes4) {
ensureTarget();
final Resources res = getResources();
final int color1 = res.getColor(colorRes1);
final int color2 = res.getColor(colorRes2);
final int color3 = res.getColor(colorRes3);
final int color4 = res.getColor(colorRes4);
mProgressBar.setColorScheme(color1, color2, color3,color4);
}
/**
* #return Whether the SwipeRefreshWidget is actively showing refresh
* progress.
*/
public boolean isRefreshing() {
return mRefreshing;
}
private void ensureTarget() {
// Don't bother getting the parent height if the parent hasn't been laid out yet.
if (mTarget == null) {
if (getChildCount() > 1 && !isInEditMode()) {
throw new IllegalStateException(
"SwipeRefreshLayout can host only one direct child");
}
mTarget = getChildAt(0);
mOriginalOffsetTop = mTarget.getTop() + getPaddingTop();
}
if (mDistanceToTriggerSync == -1) {
if (getParent() != null && ((View)getParent()).getHeight() > 0) {
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mDistanceToTriggerSync = (int) Math.min(
((View) getParent()) .getHeight() * MAX_SWIPE_DISTANCE_FACTOR,
REFRESH_TRIGGER_DISTANCE * metrics.density);
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
mProgressBar.draw(canvas);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();
mProgressBar.setBounds(0, 0, width, mProgressBarHeight);
if (getChildCount() == 0) {
return;
}
final View child = getChildAt(0);
final int childLeft = getPaddingLeft();
final int childTop = mCurrentTargetOffsetTop + getPaddingTop();
final int childWidth = width - getPaddingLeft() - getPaddingRight();
final int childHeight = height - getPaddingTop() - getPaddingBottom();
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() > 1 && !isInEditMode()) {
throw new IllegalStateException("SwipeRefreshLayout can host only one direct child");
}
if (getChildCount() > 0) {
getChildAt(0).measure(
MeasureSpec.makeMeasureSpec(
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
MeasureSpec.EXACTLY));
}
}
/**
* #return Whether it is possible for the child view of this layout to
* scroll up. Override this if the child view is a custom view.
*/
public boolean canChildScrollUp() {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (mTarget instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTarget;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return mTarget.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(mTarget, -1);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
ensureTarget();
boolean handled = false;
if (mReturningToStart && ev.getAction() == MotionEvent.ACTION_DOWN) {
mReturningToStart = false;
}
if (isEnabled() && !mReturningToStart && !canChildScrollUp()) {
handled = onTouchEvent(ev);
}
return !handled ? super.onInterceptTouchEvent(ev) : handled;
}
#Override
public void requestDisallowInterceptTouchEvent(boolean b) {
// Nope.
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
boolean handled = false;
switch (action) {
case MotionEvent.ACTION_DOWN:
mCurrPercentage = 0;
mDownEvent = MotionEvent.obtain(event);
mPrevY = mDownEvent.getY();
break;
case MotionEvent.ACTION_MOVE:
if (mDownEvent != null && !mReturningToStart) {
final float eventY = event.getY();
float yDiff = eventY - mDownEvent.getY();
if (yDiff > mTouchSlop) {
// User velocity passed min velocity; trigger a refresh
if (yDiff > mDistanceToTriggerSync) {
// User movement passed distance; trigger a refresh
startRefresh();
handled = true;
break;
} else {
// Just track the user's movement
setTriggerPercentage(
mAccelerateInterpolator.getInterpolation(
yDiff / mDistanceToTriggerSync));
float offsetTop = yDiff;
if (mPrevY > eventY) {
offsetTop = yDiff - mTouchSlop;
}
updateContentOffsetTop((int) (offsetTop));
if (mPrevY > eventY && (mTarget.getTop() < mTouchSlop)) {
// If the user puts the view back at the top, we
// don't need to. This shouldn't be considered
// cancelling the gesture as the user can restart from the top.
removeCallbacks(mCancel);
} else {
updatePositionTimeout();
}
mPrevY = event.getY();
handled = true;
}
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mDownEvent != null) {
mDownEvent.recycle();
mDownEvent = null;
}
break;
}
return handled;
}
private void startRefresh() {
removeCallbacks(mCancel);
mReturnToStartPosition.run();
setRefreshing(true);
mListener.onRefresh();
}
private void updateContentOffsetTop(int targetTop) {
final int currentTop = mTarget.getTop();
if (targetTop > mDistanceToTriggerSync) {
targetTop = (int) mDistanceToTriggerSync;
} else if (targetTop < 0) {
targetTop = 0;
}
setTargetOffsetTopAndBottom(targetTop - currentTop);
}
private void setTargetOffsetTopAndBottom(int offset) {
mTarget.offsetTopAndBottom(offset);
mCurrentTargetOffsetTop = mTarget.getTop();
}
private void updatePositionTimeout() {
removeCallbacks(mCancel);
postDelayed(mCancel, RETURN_TO_ORIGINAL_POSITION_TIMEOUT);
}
/**
* Classes that wish to be notified when the swipe gesture correctly
* triggers a refresh should implement this interface.
*/
public interface OnRefreshListener {
public void onRefresh();
}
/**
* Simple AnimationListener to avoid having to implement unneeded methods in
* AnimationListeners.
*/
private class BaseAnimationListener implements AnimationListener {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
}
following is manifest file..
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.swiperefreshlayout"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.swiperefreshlayout.SwipeActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Just copy paste all code in your project and you will get your desired output.

Drag and Drop for listview of views

Hi i am having Listview where each item is having different layout.and i want to perform drag and drop on this listview.i have searched many examples and tried but all works for listview of strings or something like that,none is working on listview of views.finally i decided to go with
DevBytes: ListView Cell Dragging and Rearranging this one.i implemented dynaliclistview but it is crashing as this also using strings in listview.Following is my listview adapter
public class ListViewPagerAdapter extends BaseAdapter {
ViewPagerAdapter mViewPagerAdapter;
private Context context;
private int selectedIndex;
FragmentManager mFragmentManager;
static ViewPager vp;
LayoutInflater inflater;
private ArrayList<Integer> mContent;
public ListViewPagerAdapter(Context context,FragmentManager fg)
{
super();
this.context = context;
mFragmentManager = fg;
}
#Override
public int getCount() {
return 4;
}
public void setSelectedIndex(int position) {
selectedIndex = position;
notifyDataSetChanged();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if (convertView == null) {
inflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if(position==0)
{
convertView = inflater.inflate(R.layout.titlebar, null);
}
}
if(position==0)
{
convertView = inflater.inflate(R.layout.titlebar, null);
}
if(position==1)
{LayoutInflater inflater1 = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater1.inflate(R.layout.calendarwidget_layout, null);
}
if(position==2)
{
LayoutInflater inflater2 = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater2.inflate(R.layout.view_pager_list_view, null);
vp = (ViewPager) convertView.findViewById(R.id.list_pager);
mViewPagerAdapter = new ViewPagerAdapter(mFragmentManager);
vp.setAdapter(mViewPagerAdapter);
}
if(position==3)
{
LayoutInflater inflater2 = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater2.inflate(R.layout.view_pager_list_view, null);
vp = (ViewPager) convertView.findViewById(R.id.list_pager);
mViewPagerAdapter = new ViewPagerAdapter(mFragmentManager);
vp.setAdapter(mViewPagerAdapter);
mViewPagerAdapter.notifyDataSetChanged();
}
return convertView;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
}
and following is code for dynamiclisview (same as from mentioned example)
public class DynamicListView extends ListView {
private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15;
private final int MOVE_DURATION = 150;
private final int LINE_THICKNESS = 15;
public ArrayList<String> mCheeseList;
private int mLastEventY = -1;
private int mDownY = -1;
private int mDownX = -1;
private int mTotalOffset = 0;
private boolean mCellIsMobile = false;
private boolean mIsMobileScrolling = false;
private int mSmoothScrollAmountAtEdge = 0;
private final int INVALID_ID = -1;
private long mAboveItemId = INVALID_ID;
private long mMobileItemId = INVALID_ID;
private long mBelowItemId = INVALID_ID;
private BitmapDrawable mHoverCell;
private Rect mHoverCellCurrentBounds;
private Rect mHoverCellOriginalBounds;
private final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private boolean mIsWaitingForScrollFinish = false;
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
public DynamicListView(Context context) {
super(context);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void init(Context context) {
setOnItemLongClickListener(mOnItemLongClickListener);
setOnScrollListener(mScrollListener);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
mSmoothScrollAmountAtEdge = (int)(SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density);
}
/**
* Listens for long clicks on any items in the listview. When a cell has
* been selected, the hover cell is created and set up.
*/
private AdapterView.OnItemLongClickListener mOnItemLongClickListener =
new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos, long id) {
mTotalOffset = 0;
int position = pointToPosition(mDownX, mDownY);
int itemNum = position - getFirstVisiblePosition();
View selectedView = getChildAt(itemNum);
mMobileItemId = getAdapter().getItemId(position);
mHoverCell = getAndAddHoverView(selectedView);
selectedView.setVisibility(INVISIBLE);
mCellIsMobile = true;
updateNeighborViewsForID(mMobileItemId);
return true;
}
};
/**
* Creates the hover cell with the appropriate bitmap and of appropriate
* size. The hover cell's BitmapDrawable is drawn on top of the bitmap every
* single time an invalidate call is made.
*/
private BitmapDrawable getAndAddHoverView(View v) {
int w = v.getWidth();
int h = v.getHeight();
int top = v.getTop();
int left = v.getLeft();
Bitmap b = getBitmapWithBorder(v);
BitmapDrawable drawable = new BitmapDrawable(getResources(), b);
mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);
drawable.setBounds(mHoverCellCurrentBounds);
return drawable;
}
/** Draws a black border over the screenshot of the view passed in. */
private Bitmap getBitmapWithBorder(View v) {
Bitmap bitmap = getBitmapFromView(v);
Canvas can = new Canvas(bitmap);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(LINE_THICKNESS);
paint.setColor(Color.BLACK);
can.drawBitmap(bitmap, 0, 0, null);
can.drawRect(rect, paint);
return bitmap;
}
/** Returns a bitmap showing a screenshot of the view passed in. */
private Bitmap getBitmapFromView(View v) {
Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas (bitmap);
v.draw(canvas);
return bitmap;
}
/**
* Stores a reference to the views above and below the item currently
* corresponding to the hover cell. It is important to note that if this
* item is either at the top or bottom of the list, mAboveItemId or mBelowItemId
* may be invalid.
*/
private void updateNeighborViewsForID(long itemID) {
int position = getPositionForID(itemID);
ListViewPagerAdapter adapter = ((ListViewPagerAdapter)getAdapter());
mAboveItemId = adapter.getItemId(position - 1);
mBelowItemId = adapter.getItemId(position + 1);
}
/** Retrieves the view in the list corresponding to itemID */
public View getViewForID (long itemID) {
int firstVisiblePosition = getFirstVisiblePosition();
ListViewPagerAdapter adapter = ((ListViewPagerAdapter)getAdapter());
for(int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
int position = firstVisiblePosition + i;
long id = adapter.getItemId(position);
if (id == itemID) {
return v;
}
}
return null;
}
/** Retrieves the position in the list corresponding to itemID */
public int getPositionForID (long itemID) {
View v = getViewForID(itemID);
if (v == null) {
return -1;
} else {
return getPositionForView(v);
}
}
/**
* dispatchDraw gets invoked when all the child views are about to be drawn.
* By overriding this method, the hover cell (BitmapDrawable) can be drawn
* over the listview's items whenever the listview is redrawn.
*/
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mHoverCell != null) {
mHoverCell.draw(canvas);
}
}
#Override
public boolean onTouchEvent (MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mDownX = (int)event.getX();
mDownY = (int)event.getY();
mActivePointerId = event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
if (mActivePointerId == INVALID_POINTER_ID) {
break;
}
int pointerIndex = event.findPointerIndex(mActivePointerId);
mLastEventY = (int) event.getY(pointerIndex);
int deltaY = mLastEventY - mDownY;
if (mCellIsMobile) {
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left,
mHoverCellOriginalBounds.top + deltaY + mTotalOffset);
mHoverCell.setBounds(mHoverCellCurrentBounds);
invalidate();
handleCellSwitch();
mIsMobileScrolling = false;
handleMobileCellScroll();
return false;
}
break;
case MotionEvent.ACTION_UP:
touchEventsEnded();
break;
case MotionEvent.ACTION_CANCEL:
touchEventsCancelled();
break;
case MotionEvent.ACTION_POINTER_UP:
/* If a multitouch event took place and the original touch dictating
* the movement of the hover cell has ended, then the dragging event
* ends and the hover cell is animated to its corresponding position
* in the listview. */
pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
touchEventsEnded();
}
break;
default:
break;
}
return super.onTouchEvent(event);
}
/**
* This method determines whether the hover cell has been shifted far enough
* to invoke a cell swap. If so, then the respective cell swap candidate is
* determined and the data set is changed. Upon posting a notification of the
* data set change, a layout is invoked to place the cells in the right place.
* Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can
* offset the cell being swapped to where it previously was and then animate it to
* its new position.
*/
private void handleCellSwitch() {
final int deltaY = mLastEventY - mDownY;
int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;
View belowView = getViewForID(mBelowItemId);
View mobileView = getViewForID(mMobileItemId);
View aboveView = getViewForID(mAboveItemId);
boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop());
if (isBelow || isAbove) {
final long switchItemID = isBelow ? mBelowItemId : mAboveItemId;
View switchView = isBelow ? belowView : aboveView;
final int originalItem = getPositionForView(mobileView);
if (switchView == null) {
updateNeighborViewsForID(mMobileItemId);
return;
}
swapElements(mCheeseList, originalItem, getPositionForView(switchView));
((BaseAdapter) getAdapter()).notifyDataSetChanged();
mDownY = mLastEventY;
final int switchViewStartTop = switchView.getTop();
mobileView.setVisibility(View.VISIBLE);
switchView.setVisibility(View.INVISIBLE);
updateNeighborViewsForID(mMobileItemId);
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#SuppressLint("NewApi")
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this);
View switchView = getViewForID(switchItemID);
mTotalOffset += deltaY;
int switchViewNewTop = switchView.getTop();
int delta = switchViewStartTop - switchViewNewTop;
switchView.setTranslationY(delta);
ObjectAnimator animator = ObjectAnimator.ofFloat(switchView,
View.TRANSLATION_Y, 0);
animator.setDuration(MOVE_DURATION);
animator.start();
return true;
}
});
}
}
private void swapElements(ArrayList arrayList, int indexOne, int indexTwo) {
Object temp = arrayList.get(indexOne);
arrayList.set(indexOne, arrayList.get(indexTwo));
arrayList.set(indexTwo, temp);
}
/**
* Resets all the appropriate fields to a default state while also animating
* the hover cell back to its correct location.
*/
private void touchEventsEnded () {
final View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile|| mIsWaitingForScrollFinish) {
mCellIsMobile = false;
mIsWaitingForScrollFinish = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
// If the autoscroller has not completed scrolling, we need to wait for it to
// finish in order to determine the final location of where the hover cell
// should be animated to.
if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
mIsWaitingForScrollFinish = true;
return;
}
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop());
ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds",
sBoundEvaluator, mHoverCellCurrentBounds);
hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
invalidate();
}
});
hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
setEnabled(false);
}
#Override
public void onAnimationEnd(Animator animation) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
setEnabled(true);
invalidate();
}
});
hoverViewAnimator.start();
} else {
touchEventsCancelled();
}
}
/**
* Resets all the appropriate fields to a default state.
*/
private void touchEventsCancelled () {
View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
invalidate();
}
mCellIsMobile = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
}
/**
* This TypeEvaluator is used to animate the BitmapDrawable back to its
* final location when the user lifts his finger by modifying the
* BitmapDrawable's bounds.
*/
private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() {
public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
return new Rect(interpolate(startValue.left, endValue.left, fraction),
interpolate(startValue.top, endValue.top, fraction),
interpolate(startValue.right, endValue.right, fraction),
interpolate(startValue.bottom, endValue.bottom, fraction));
}
public int interpolate(int start, int end, float fraction) {
return (int)(start + fraction * (end - start));
}
};
/**
* Determines whether this listview is in a scrolling state invoked
* by the fact that the hover cell is out of the bounds of the listview;
*/
private void handleMobileCellScroll() {
mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
}
/**
* This method is in charge of determining if the hover cell is above
* or below the bounds of the listview. If so, the listview does an appropriate
* upward or downward smooth scroll so as to reveal new items.
*/
public boolean handleMobileCellScroll(Rect r) {
int offset = computeVerticalScrollOffset();
int height = getHeight();
int extent = computeVerticalScrollExtent();
int range = computeVerticalScrollRange();
int hoverViewTop = r.top;
int hoverHeight = r.height();
if (hoverViewTop <= 0 && offset > 0) {
smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
return true;
}
if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
return true;
}
return false;
}
public void setCheeseList(ArrayList<String> cheeseList) {
mCheeseList = cheeseList;
}
/**
* This scroll listener is added to the listview in order to handle cell swapping
* when the cell is either at the top or bottom edge of the listview. If the hover
* cell is at either edge of the listview, the listview will begin scrolling. As
* scrolling takes place, the listview continuously checks if new cells became visible
* and determines whether they are potential candidates for a cell swap.
*/
private AbsListView.OnScrollListener mScrollListener = new AbsListView.OnScrollListener () {
private int mPreviousFirstVisibleItem = -1;
private int mPreviousVisibleItemCount = -1;
private int mCurrentFirstVisibleItem;
private int mCurrentVisibleItemCount;
private int mCurrentScrollState;
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
mCurrentFirstVisibleItem = firstVisibleItem;
mCurrentVisibleItemCount = visibleItemCount;
mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem
: mPreviousFirstVisibleItem;
mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount
: mPreviousVisibleItemCount;
checkAndHandleFirstVisibleCellChange();
checkAndHandleLastVisibleCellChange();
mPreviousFirstVisibleItem = mCurrentFirstVisibleItem;
mPreviousVisibleItemCount = mCurrentVisibleItemCount;
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
mScrollState = scrollState;
isScrollCompleted();
}
/**
* This method is in charge of invoking 1 of 2 actions. Firstly, if the listview
* is in a state of scrolling invoked by the hover cell being outside the bounds
* of the listview, then this scrolling event is continued. Secondly, if the hover
* cell has already been released, this invokes the animation for the hover cell
* to return to its correct position after the listview has entered an idle scroll
* state.
*/
private void isScrollCompleted() {
if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) {
if (mCellIsMobile && mIsMobileScrolling) {
handleMobileCellScroll();
} else if (mIsWaitingForScrollFinish) {
touchEventsEnded();
}
}
}
/**
* Determines if the listview scrolled up enough to reveal a new cell at the
* top of the list. If so, then the appropriate parameters are updated.
*/
public void checkAndHandleFirstVisibleCellChange() {
if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
/**
* Determines if the listview scrolled down enough to reveal a new cell at the
* bottom of the list. If so, then the appropriate parameters are updated.
*/
public void checkAndHandleLastVisibleCellChange() {
int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount;
int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount;
if (currentLastVisibleItem != previousLastVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
};
}
And following is list.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<com.bin.widget.DynamicListView
android:id="#+id/campaignListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#0000"
>
</com.bin.widget.DynamicListView>
</RelativeLayout>
please help me out...thanks in advance
HI I finally solved this problem myself,above code works by making few changes in adapter class of listview.In adapter's public long getItemId(int position) make necessary changes so that it will give you id of passed positions view.Dont just return position. Also,in dynamicListview class after swapping position refresh of listview is being done so in listadapter's getview() method,we need to make changes accordingly.
That's it,then it works like charm.Hope this helps somebody else too.

how to fill adapter to viewpage fully without going aside?

I am trying to change viewpage rotation 90 to get vertical swapping. but my adapter going aside. i am unable fix it. help me to fit layout correctly.
Here is my view pager
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_alignParentTop="true"
android:layout_width="800dp"
android:layout_height="480dp"
android:background="#a07fe0">
</android.support.v4.view.ViewPager>
Here is my layout of adapter
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ff0000"
android:layout_centerInParent="true"
android:orientation="horizontal"
android:rotation="270">
<ImageView
android:id="#+id/screen"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="start"
android:src="#drawable/makescr1"/>
</LinearLayout>
Use This class.
public class VerticalPager extends ViewGroup {
public static final String TAG = "VerticalPager";
private static final int INVALID_SCREEN = -1;
public static final int SPEC_UNDEFINED = -1;
private static final int TOP = 0;
private static final int BOTTOM = 1;
/**
* The velocity at which a fling gesture will cause us to snap to the next screen
*/
private static final int SNAP_VELOCITY = 1000;
private int pageHeight;
private int measuredHeight;
private boolean mFirstLayout = true;
private int mCurrentPage;
private int mNextPage = INVALID_SCREEN;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mTouchSlop;
private int mMaximumVelocity;
private float mLastMotionY;
private float mLastMotionX;
private final static int TOUCH_STATE_REST = 0;
private final static int TOUCH_STATE_SCROLLING = 1;
private int mTouchState = TOUCH_STATE_REST;
private boolean mAllowLongPress;
private Set<OnScrollListener> mListeners = new HashSet<OnScrollListener>();
VerticalPageChange mpageChangeListener;
/**
* Used to inflate the Workspace from XML.
*
* #param context The application's context.
* #param attrs The attribtues set containing the Workspace's customization values.
*/
public VerticalPager(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public VerticalPager(Context context, AttributeSet attrs,
VerticalPageChange mpageChangeListener) {
this(context, attrs, 0);
this.mpageChangeListener=mpageChangeListener;
}
/**
* Used to inflate the Workspace from XML.
*
* #param context The application's context.
* #param attrs The attribtues set containing the Workspace's customization values.
* #param defStyle Unused.
*/
public VerticalPager(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.com_deezapps_widget_HorizontalPager);
//pageHeightSpec = a.getDimensionPixelSize(R.styleable.com_deezapps_widget_HorizontalPager_pageWidth, SPEC_UNDEFINED);
//a.recycle();
init(context);
}
/**
* Initializes various states for this workspace.
*/
private void init(Context context) {
mScroller = new Scroller(getContext(), new DecelerateInterpolator());
mCurrentPage = 0;
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
/**
* Returns the index of the currently displayed page.
*
* #return The index of the currently displayed page.
*/
int getCurrentPage() {
return mCurrentPage;
}
/**
* Sets the current page.
*
* #param currentPage
*/
public void setCurrentPage(int currentPage) {
mCurrentPage = Math.max(0, Math.min(currentPage, getChildCount()));
scrollTo(getScrollYForPage(mCurrentPage), 0);
invalidate();
}
public int getPageHeight() {
return pageHeight;
}
// public void setPageHeight(int pageHeight) {
// this.pageHeightSpec = pageHeight;
// }
/**
* Gets the value that getScrollX() should return if the specified page is the current page (and no other scrolling is occurring).
* Use this to pass a value to scrollTo(), for example.
* #param whichPage
* #return
*/
private int getScrollYForPage(int whichPage) {
int height = 0;
for(int i = 0; i < whichPage; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
height += child.getHeight();
}
}
return height - pageHeightPadding();
}
#Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
} else if (mNextPage != INVALID_SCREEN) {
mCurrentPage = mNextPage;
mNextPage = INVALID_SCREEN;
clearChildrenCache();
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
// ViewGroup.dispatchDraw() supports many features we don't need:
// clip to padding, layout animation, animation listener, disappearing
// children, etc. The following implementation attempts to fast-track
// the drawing dispatch by drawing only what we know needs to be drawn.
final long drawingTime = getDrawingTime();
// todo be smarter about which children need drawing
final int count = getChildCount();
for (int i = 0; i < count; i++) {
drawChild(canvas, getChildAt(i), drawingTime);
}
for (OnScrollListener mListener : mListeners) {
int adjustedScrollY = getScrollY() + pageHeightPadding();
mListener.onScroll(adjustedScrollY);
if (adjustedScrollY % pageHeight == 0) {
mListener.onViewScrollFinished(adjustedScrollY / pageHeight);
}
}
}
int pageHeightPadding() {
return ((getMeasuredHeight() - pageHeight) / 2);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
pageHeight = getMeasuredHeight();
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(pageHeight, MeasureSpec.UNSPECIFIED));
}
if (mFirstLayout) {
scrollTo(getScrollYForPage(mCurrentPage), 0);
mFirstLayout = false;
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
measuredHeight = 0;
final int count = getChildCount();
int height;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
if(i == 0) {
child.getHeight();
child.layout(0, measuredHeight, right - left, measuredHeight + (int)(pageHeight*.96));
measuredHeight += (pageHeight*.96);
} else {
height = pageHeight * (int)Math.ceil((double)child.getMeasuredHeight()/(double)pageHeight);
height = Math.max(pageHeight, height);
child.layout(0, measuredHeight, right - left, measuredHeight + height);
measuredHeight += height;
}
}
}
}
#Override
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
int screen = indexOfChild(child);
if (screen != mCurrentPage || !mScroller.isFinished()) {
return true;
}
return false;
}
#Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
int focusableScreen;
try
{
if (mNextPage != INVALID_SCREEN) {
focusableScreen = mNextPage;
} else {
focusableScreen = mCurrentPage;
}
getChildAt(focusableScreen).requestFocus(direction, previouslyFocusedRect);
}
catch(Exception e)
{
e.printStackTrace();
}
return false;
}
#Override
public boolean dispatchUnhandledMove(View focused, int direction) {
if (direction == View.FOCUS_LEFT) {
if (getCurrentPage() > 0) {
snapToPage(getCurrentPage() - 1);
return true;
}
} else if (direction == View.FOCUS_RIGHT) {
if (getCurrentPage() < getChildCount() - 1) {
snapToPage(getCurrentPage() + 1);
return true;
}
}
return super.dispatchUnhandledMove(focused, direction);
}
#Override
public void addFocusables(ArrayList<View> views, int direction) {
getChildAt(mCurrentPage).addFocusables(views, direction);
if (direction == View.FOCUS_LEFT) {
if (mCurrentPage > 0) {
getChildAt(mCurrentPage - 1).addFocusables(views, direction);
}
} else if (direction == View.FOCUS_RIGHT){
if (mCurrentPage < getChildCount() - 1) {
getChildAt(mCurrentPage + 1).addFocusables(views, direction);
}
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//Log.d(TAG, "onInterceptTouchEvent::action=" + ev.getAction());
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
* scrolling there.
*/
/*
* Shortcut the most recurring case: the user is in the dragging
* state and he is moving his finger. We want to intercept this
* motion.
*/
final int action = ev.getAction();
if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) {
//Log.d(TAG, "onInterceptTouchEvent::shortcut=true");
return true;
}
final float y = ev.getY();
final float x = ev.getX();
switch (action) {
case MotionEvent.ACTION_MOVE:
/*
* mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
* whether the user has moved far enough from his original down touch.
*/
if (mTouchState == TOUCH_STATE_REST) {
checkStartScroll(x, y);
}
break;
case MotionEvent.ACTION_DOWN:
// Remember location of down touch
mLastMotionX = x;
mLastMotionY = y;
mAllowLongPress = true;
/*
* If being flinged and user touches the screen, initiate drag;
* otherwise don't. mScroller.isFinished should be false when
* being flinged.
*/
mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Release the drag
clearChildrenCache();
mTouchState = TOUCH_STATE_REST;
break;
}
/*
* The only time we want to intercept motion events is if we are in the
* drag mode.
*/
return mTouchState != TOUCH_STATE_REST;
}
private void checkStartScroll(float x, float y) {
/*
* Locally do absolute value. mLastMotionX is set to the y value
* of the down event.
*/
final int xDiff = (int) Math.abs(x - mLastMotionX);
final int yDiff = (int) Math.abs(y - mLastMotionY);
boolean xMoved = xDiff > mTouchSlop;
boolean yMoved = yDiff > mTouchSlop;
if (xMoved || yMoved) {
if (yMoved) {
// Scroll if the user moved far enough along the X axis
mTouchState = TOUCH_STATE_SCROLLING;
enableChildrenCache();
}
// Either way, cancel any pending longpress
if (mAllowLongPress) {
mAllowLongPress = false;
// Try canceling the long press. It could also have been scheduled
// by a distant descendant, so use the mAllowLongPress flag to block
// everything
final View currentScreen = getChildAt(mCurrentPage);
currentScreen.cancelLongPress();
}
}
}
void enableChildrenCache() {
setChildrenDrawingCacheEnabled(true);
setChildrenDrawnWithCacheEnabled(true);
}
void clearChildrenCache() {
setChildrenDrawnWithCacheEnabled(false);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
final int action = ev.getAction();
final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
/*
* If being flinged and user touches, stop the fling. isFinished
* will be false if being flinged.
*/
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
// Remember where the motion event started
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
if (mTouchState == TOUCH_STATE_REST) {
checkStartScroll(y, x);
} else if (mTouchState == TOUCH_STATE_SCROLLING) {
// Scroll to follow the motion event
int deltaY = (int) (mLastMotionY - y);
mLastMotionY = y;
// Apply friction to scrolling past boundaries.
final int count = getChildCount();
if (getScrollY() < 0 || getScrollY() + pageHeight > getChildAt(count - 1).getBottom()) {
deltaY /= 2;
}
scrollBy(0, deltaY);
}
break;
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocityY = (int) velocityTracker.getYVelocity();
final int count = getChildCount();
// check scrolling past first or last page?
if(getScrollY() < 0) {
snapToPage(0);
} else if(getScrollY() > measuredHeight - pageHeight) {
snapToPage(count - 1, BOTTOM);
} else {
for(int i = 0; i < count; i++) {
final View child = getChildAt(i);
if(child.getTop() < getScrollY() &&
child.getBottom() > getScrollY() + pageHeight) {
// we're inside a page, fling that bitch
mNextPage = i;
mScroller.fling(getScrollX(), getScrollY(), 0, -velocityY, 0, 0, child.getTop(), child.getBottom() - getHeight());
invalidate();
break;
} else if(child.getBottom() > getScrollY() && child.getBottom() < getScrollY() + getHeight()) {
// stuck in between pages, oh snap!
if(velocityY < -SNAP_VELOCITY) {
snapToPage(i + 1);
} else if(velocityY > SNAP_VELOCITY) {
snapToPage(i, BOTTOM);
} else if(getScrollY() + pageHeight/2 > child.getBottom()) {
snapToPage(i + 1);
} else {
snapToPage(i, BOTTOM);
}
break;
}
}
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
mTouchState = TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
}
return true;
}
private void snapToPage(final int whichPage, final int where) {
enableChildrenCache();
boolean changingPages = whichPage != mCurrentPage;
mNextPage = whichPage;
View focusedChild = getFocusedChild();
if (focusedChild != null && changingPages && focusedChild == getChildAt(mCurrentPage)) {
focusedChild.clearFocus();
}
final int delta;
if(getChildAt(whichPage).getHeight() <= pageHeight || where == TOP) {
delta = getChildAt(whichPage).getTop() - getScrollY();
} else {
delta = getChildAt(whichPage).getBottom() - pageHeight - getScrollY();
}
mScroller.startScroll(0, getScrollY(), 0, delta, 400);
invalidate();
mpageChangeListener.onPageChange(whichPage);
}
public void snapToPage(final int whichPage) {
snapToPage(whichPage, TOP);
// mpageChangeListener.onPageChange(whichPage);
}
#Override
protected Parcelable onSaveInstanceState() {
final SavedState state = new SavedState(super.onSaveInstanceState());
state.currentScreen = mCurrentPage;
return state;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
if (savedState.currentScreen != INVALID_SCREEN) {
mCurrentPage = savedState.currentScreen;
}
}
public void scrollUp() {
if (mNextPage == INVALID_SCREEN && mCurrentPage > 0 && mScroller.isFinished()) {
snapToPage(mCurrentPage - 1);
}
}
public void scrollDown() {
if (mNextPage == INVALID_SCREEN && mCurrentPage < getChildCount() - 1 && mScroller.isFinished()) {
snapToPage(mCurrentPage + 1);
}
}
public int getScreenForView(View v) {
int result = -1;
if (v != null) {
ViewParent vp = v.getParent();
int count = getChildCount();
for (int i = 0; i < count; i++) {
if (vp == getChildAt(i)) {
return i;
}
}
}
return result;
}
/**
* #return True is long presses are still allowed for the current touch
*/
public boolean allowLongPress() {
return mAllowLongPress;
}
public static class SavedState extends BaseSavedState {
int currentScreen = -1;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentScreen = in.readInt();
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(currentScreen);
}
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
public void addOnScrollListener(OnScrollListener listener) {
mListeners.add(listener);
}
public void removeOnScrollListener(OnScrollListener listener) {
mListeners.remove(listener);
}
/**
* Implement to receive events on scroll position and page snaps.
*/
public static interface OnScrollListener {
/**
* Receives the current scroll X value. This value will be adjusted to assume the left edge of the first
* page has a scroll position of 0. Note that values less than 0 and greater than the right edge of the
* last page are possible due to touch events scrolling beyond the edges.
* #param scrollX Scroll X value
*/
void onScroll(int scrollX);
/**
* Invoked when scrolling is finished (settled on a page, centered).
* #param currentPage The current page
*/
void onViewScrollFinished(int currentPage);
}
public interface VerticalPageChange
{
public void onPageChange(int position);
}
}
i have add page dynamically. inside getView() of BaseAdapter.
final VerticalPager verticalPage = new VerticalPager(Act_ItemView.this, null, mVerticalPagechangeListener);
// setDotIndicatorView(p.arr_images.size());
for (int i = 0; i < p.arr_images.size(); i++)
{
final String image_url = p.arr_images.get(i).image_method;
PhotoView imageView = new PhotoView(Act_ItemView.this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
imageView.setAllowParentInterceptOnEdge(true);
// imageView.setScaleType(ScaleType.CENTER_CROP);
imageLoader1.displayImage(image_url, imageView, options1, animateFirstListener1);
verticalPage.setHorizontalScrollBarEnabled(false);
verticalPage.addView(imageView);
verticalPage.setTag(i);
}
linearLayoutMain.addView(verticalPage);
here is listner implemented
VerticalPager.VerticalPageChange mVerticalPagechangeListener = new VerticalPager.VerticalPageChange()
{
#Override
public void onPageChange(int position)
{
try
{
int pagePosition1 = viewPager.getCurrentItem();
setindicator(position);
array_index[pagePosition1] = position;
} catch (Exception e)
{
e.printStackTrace();
}
}
};

How to load only new items in pull to refresh custom listview?

I need to load only new items on pull to refresh, remaining loaded items should move down after the new items are loaded. I am loading 10,10 items in load more once again if I do pull to refresh I want all loaded items on top with newly updated item.
How to do that?
((PullAndLoadListView)getListView()).setOnRefreshListener(new OnRefreshListener(){public void onRefresh(){}}
I would definitely take a look at Chris Banes' implementation of pull-to-refresh. His code does not only include this interaction style for ListView, but also GridView and WebView.
Especially the latter will be of interest in your case, since it's an example implementation of pull-to-refresh for a view that does not use an adapter for its content. If you look at the source code, you'll see that every concrete pull-to-refreh view in Banes' project extends from a generic PullToRefreshBase, which contains most of the logic for animation and refreshing. The benefit of having that base class is that doing the same thing for any other type of view, e.g. a TextView, should be pretty straightforward.
The only drawback of this approach is that the implementation is a wrapper for other views, meaning you'll have write a couple of extra lines to get the actual view. So it's not a full drop-in replacement. However, its functionality and features far exceed that little inconvenience.
EDITED :
Look at the Below Code i have implemented
in your Main JAVA File :
PullToRefreshListView listview;
listview = (PullToRefreshListView) findViewById(R.id.airpost_listView);
listview.setOnRefreshListener(new OnRefreshListener() {
public void onRefresh() {
// TODO Auto-generated method stub
new GetPost().execute(); // AsyncTask where you can put your logic when to call the listview for getting new data or let it be same as before
}
});
Listview Defined in xml File:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/bhavesh"
android:padding="5dp" >
<com.FlightMate.AirpostTab.PullToRefreshListView
android:id="#+id/airpost_listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:cacheColorHint="#android:color/transparent"
android:divider="#00000000" />
</LinearLayout>
Here is PullToRefreshListView :
package com.FlightMate.AirpostTab;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
public class PullToRefreshListView extends PullToRefreshBase<ListView> {
public PullToRefreshListView(Context context) {
super(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected final ListView createAdapterView(Context context,
AttributeSet attrs) {
ListView lv = new ListView(context, attrs);
// Set it to this so it can be used in ListActivity/ListFragment
lv.setId(android.R.id.list);
return lv;
}
}
here is PullToRefreshBase :
package com.FlightMate.AirpostTab;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import com.FlightMate.R;
public abstract class PullToRefreshBase<T extends AbsListView> extends
LinearLayout implements OnTouchListener, OnScrollListener {
private final class SmoothScrollRunnable implements Runnable {
static final int ANIMATION_DURATION_MS = 190;
static final int ANIMATION_FPS = 1000 / 60;
private final Interpolator interpolator;
private final int scrollToY;
private final int scrollFromY;
private final Handler handler;
private boolean continueRunning = true;
private long startTime = -1;
private int currentY = -1;
public SmoothScrollRunnable(Handler handler, int fromY, int toY) {
this.handler = handler;
this.scrollFromY = fromY;
this.scrollToY = toY;
this.interpolator = new AccelerateDecelerateInterpolator();
}
// #Override
public void run() {
/**
* Only set startTime if this is the first time we're starting, else
* actually calculate the Y delta
*/
if (startTime == -1) {
startTime = System.currentTimeMillis();
} else {
/**
* We do do all calculations in long to reduce software float
* calculations. We use 1000 as it gives us good accuracy and
* small rounding errors
*/
long normalizedTime = (1000 * (System.currentTimeMillis() - startTime))
/ ANIMATION_DURATION_MS;
normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);
final int deltaY = Math
.round((scrollFromY - scrollToY)
* interpolator
.getInterpolation(normalizedTime / 1000f));
this.currentY = scrollFromY - deltaY;
setHeaderScroll(currentY);
}
// If we're not at the target Y, keep going...
if (continueRunning && scrollToY != currentY) {
handler.postDelayed(this, ANIMATION_FPS);
}
}
public void stop() {
this.continueRunning = false;
this.handler.removeCallbacks(this);
}
};
// ===========================================================
// Constants
// ===========================================================
static final int PULL_TO_REFRESH = 0;
static final int RELEASE_TO_REFRESH = PULL_TO_REFRESH + 1;
static final int REFRESHING = RELEASE_TO_REFRESH + 1;
static final int EVENT_COUNT = 3;
public static final int MODE_PULL_DOWN_TO_REFRESH = 0x1;
public static final int MODE_PULL_UP_TO_REFRESH = 0x2;
public static final int MODE_BOTH = 0x3;
// ===========================================================
// Fields
// ===========================================================
private int state = PULL_TO_REFRESH;
private int mode = MODE_PULL_DOWN_TO_REFRESH;
private int currentMode;
private boolean disableScrollingWhileRefreshing = true;
private T adapterView;
private boolean isPullToRefreshEnabled = true;
private LoadingLayout headerLayout;
private LoadingLayout footerLayout;
private int headerHeight;
private final Handler handler = new Handler();
private OnTouchListener onTouchListener;
private OnRefreshListener onRefreshListener;
private OnScrollListener onScrollListener;
private OnLastItemVisibleListener onLastItemVisibleListener;
private int lastSavedFirstVisibleItem = -1;
private SmoothScrollRunnable currentSmoothScrollRunnable;
private float startY = -1;
private final float[] lastYs = new float[EVENT_COUNT];
// ===========================================================
// Constructors
// ===========================================================
public PullToRefreshBase(Context context) {
this(context, null);
}
public PullToRefreshBase(Context context, int mode) {
this(context);
this.mode = mode;
}
public PullToRefreshBase(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
// ===========================================================
// Getter & Setter
// ===========================================================
/**
* Get the Wrapped AdapterView. Anything returned here has already been
* added to the content view.
*
* #return The AdapterView which is currently wrapped
*/
public final T getAdapterView() {
return adapterView;
}
/**
* Whether Pull-to-Refresh is enabled
*
* #return enabled
*/
public final boolean isPullToRefreshEnabled() {
return isPullToRefreshEnabled;
}
public void setDisableScrollingWhileRefreshing(
boolean disableScrollingWhileRefreshing) {
this.disableScrollingWhileRefreshing = disableScrollingWhileRefreshing;
}
/**
* Mark the current Refresh as complete. Will Reset the UI and hide the
* Refreshing View
*/
public final void onRefreshComplete() {
resetHeader();
}
public final void setOnLastItemVisibleListener(
OnLastItemVisibleListener listener) {
onLastItemVisibleListener = listener;
}
public final void setOnRefreshListener(OnRefreshListener listener) {
onRefreshListener = listener;
}
/**
* A mutator to enable/disable Pull-to-Refresh for the current AdapterView
*
* #param enable
* Whether Pull-To-Refresh should be used
*/
public final void setPullToRefreshEnabled(boolean enabled) {
this.isPullToRefreshEnabled = enabled;
}
public final void setReleaseLabel(String releaseLabel) {
if (null != headerLayout) {
headerLayout.setReleaseLabel(releaseLabel);
}
if (null != footerLayout) {
footerLayout.setReleaseLabel(releaseLabel);
}
}
public final void setPullLabel(String pullLabel) {
if (null != headerLayout) {
headerLayout.setPullLabel(pullLabel);
}
if (null != footerLayout) {
footerLayout.setPullLabel(pullLabel);
}
}
public final void setRefreshingLabel(String refreshingLabel) {
if (null != headerLayout) {
headerLayout.setRefreshingLabel(refreshingLabel);
}
if (null != footerLayout) {
footerLayout.setRefreshingLabel(refreshingLabel);
}
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
public final void setOnScrollListener(OnScrollListener listener) {
onScrollListener = listener;
}
#Override
public final void setOnTouchListener(OnTouchListener listener) {
onTouchListener = listener;
}
public final void onScroll(final AbsListView view,
final int firstVisibleItem, final int visibleItemCount,
final int totalItemCount) {
if (null != onLastItemVisibleListener) {
// detect if last item is visible
if (visibleItemCount > 0 && visibleItemCount < totalItemCount
&& (firstVisibleItem + visibleItemCount == totalItemCount)) {
// only process first event
if (firstVisibleItem != lastSavedFirstVisibleItem) {
lastSavedFirstVisibleItem = firstVisibleItem;
onLastItemVisibleListener.onLastItemVisible();
}
}
}
if (null != onScrollListener) {
onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
totalItemCount);
}
}
public final void onScrollStateChanged(final AbsListView view,
final int scrollState) {
if (null != onScrollListener) {
onScrollListener.onScrollStateChanged(view, scrollState);
}
}
// #Override
public final boolean onTouch(View view, MotionEvent ev) {
if (isPullToRefreshEnabled) {
// Returning true here stops the ListView being scrollable while we
// refresh
if (state == REFRESHING && disableScrollingWhileRefreshing) {
return true;
} else if (onAdapterViewTouch(view, ev)) {
return true;
}
}
if (null != onTouchListener) {
return onTouchListener.onTouch(view, ev);
}
return false;
}
/**
* This is implemented by derived classes to return the created AdapterView.
* If you need to use a custom AdapterView (such as a custom ListView),
* override this method and return an instance of your custom class.
*
* Be sure to set the ID of the view in this method, especially if you're
* using a ListActivity or ListFragment.
*
* #param context
* #param attrs
* AttributeSet from wrapped class. Means that anything you
* include in the XML layout declaration will be routed to the
* AdapterView
* #return New instance of the AdapterView
*/
protected abstract T createAdapterView(Context context, AttributeSet attrs);
// ===========================================================
// Methods
// ===========================================================
protected final void resetHeader() {
state = PULL_TO_REFRESH;
initializeYsHistory();
startY = -1;
if (null != headerLayout) {
headerLayout.reset();
}
if (null != footerLayout) {
footerLayout.reset();
}
smoothScrollTo(0);
}
private void init(Context context, AttributeSet attrs) {
setOrientation(LinearLayout.VERTICAL);
// Styleables from XML
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.PullToRefresh);
mode = a.getInteger(R.styleable.PullToRefresh_mode,
MODE_PULL_DOWN_TO_REFRESH);
// AdapterView
// By passing the attrs, we can add ListView/GridView params via XML
adapterView = this.createAdapterView(context, attrs);
adapterView.setOnTouchListener(this);
adapterView.setOnScrollListener(this);
addView(adapterView, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, 0, 1.0f));
// Loading View Strings
String pullLabel = context
.getString(R.string.pull_to_refresh_pull_label);
String refreshingLabel = context
.getString(R.string.pull_to_refresh_refreshing_label);
String releaseLabel = context
.getString(R.string.pull_to_refresh_release_label);
// Add Loading Views
if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
headerLayout = new LoadingLayout(context,
MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel,
refreshingLabel);
addView(headerLayout, 0, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
measureView(headerLayout);
headerHeight = headerLayout.getMeasuredHeight();
}
if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) {
footerLayout = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH,
releaseLabel, pullLabel, refreshingLabel);
addView(footerLayout, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
measureView(footerLayout);
headerHeight = footerLayout.getMeasuredHeight();
}
// Styleables from XML
if (a.hasValue(R.styleable.PullToRefresh_headerTextColor)) {
final int color = a.getColor(
R.styleable.PullToRefresh_headerTextColor, Color.BLACK);
if (null != headerLayout) {
headerLayout.setTextColor(color);
}
if (null != footerLayout) {
footerLayout.setTextColor(color);
}
}
if (a.hasValue(R.styleable.PullToRefresh_headerBackground)) {
this.setBackgroundResource(a.getResourceId(
R.styleable.PullToRefresh_headerBackground, Color.WHITE));
}
if (a.hasValue(R.styleable.PullToRefresh_adapterViewBackground)) {
adapterView.setBackgroundResource(a.getResourceId(
R.styleable.PullToRefresh_adapterViewBackground,
Color.WHITE));
}
a.recycle();
// Hide Loading Views
switch (mode) {
case MODE_BOTH:
setPadding(getPaddingLeft(), -headerHeight, getPaddingRight(),
-headerHeight);
break;
case MODE_PULL_UP_TO_REFRESH:
setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
-headerHeight);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
setPadding(getPaddingLeft(), -headerHeight, getPaddingRight(),
getPaddingBottom());
break;
}
// If we're not using MODE_BOTH, then just set currentMode to current
// mode
if (mode != MODE_BOTH) {
currentMode = mode;
}
}
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
int lpHeight = p.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
private boolean onAdapterViewTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
updateEventStates(event);
if (isPullingToRefresh() && startY == -1) {
startY = event.getY();
// Need to set current Mode if we're using both
if (mode == MODE_BOTH) {
if (isUserDraggingDownwards()) {
currentMode = MODE_PULL_DOWN_TO_REFRESH;
} else if (isUserDraggingUpwards()) {
currentMode = MODE_PULL_UP_TO_REFRESH;
}
}
return false;
}
if (startY != -1 && !adapterView.isPressed()) {
pullEvent(event, startY);
return true;
}
break;
case MotionEvent.ACTION_UP:
initializeYsHistory();
startY = -1;
if (state == RELEASE_TO_REFRESH) {
setRefreshing();
if (onRefreshListener != null) {
onRefreshListener.onRefresh();
}
} else {
smoothScrollTo(0);
}
break;
}
return false;
}
private void pullEvent(MotionEvent event, float firstY) {
float averageY = average(lastYs);
final int height;
switch (currentMode) {
case MODE_PULL_UP_TO_REFRESH:
height = (int) Math.max(firstY - averageY, 0);
setHeaderScroll(height);
break;
case MODE_PULL_DOWN_TO_REFRESH:
default:
height = (int) Math.max(averageY - firstY, 0);
setHeaderScroll(-height);
break;
}
if (state == PULL_TO_REFRESH && headerHeight < height) {
state = RELEASE_TO_REFRESH;
if (null != headerLayout) {
headerLayout.releaseToRefresh();
}
if (null != footerLayout) {
footerLayout.releaseToRefresh();
}
} else if (state == RELEASE_TO_REFRESH && headerHeight >= height) {
state = PULL_TO_REFRESH;
if (null != headerLayout) {
headerLayout.pullToRefresh();
}
if (null != footerLayout) {
footerLayout.pullToRefresh();
}
}
}
private void setHeaderScroll(int y) {
scrollTo(0, y);
}
private void setRefreshing() {
state = REFRESHING;
if (null != headerLayout) {
headerLayout.refreshing();
}
if (null != footerLayout) {
footerLayout.refreshing();
}
switch (currentMode) {
case MODE_PULL_DOWN_TO_REFRESH:
smoothScrollTo(-headerHeight);
break;
case MODE_PULL_UP_TO_REFRESH:
smoothScrollTo(headerHeight);
break;
}
}
private float average(float[] ysArray) {
float avg = 0;
for (int i = 0; i < EVENT_COUNT; i++) {
avg += ysArray[i];
}
return avg / EVENT_COUNT;
}
private void initializeYsHistory() {
for (int i = 0; i < EVENT_COUNT; i++) {
lastYs[i] = 0;
}
}
private void updateEventStates(MotionEvent event) {
for (int i = 0, z = event.getHistorySize(); i < z; i++) {
this.updateEventStates(event.getHistoricalY(i));
}
this.updateEventStates(event.getY());
}
private void updateEventStates(float y) {
for (int i = 0; i < EVENT_COUNT - 1; i++) {
lastYs[i] = lastYs[i + 1];
}
lastYs[EVENT_COUNT - 1] = y;
}
private boolean isPullingToRefresh() {
if (isPullToRefreshEnabled && state != REFRESHING) {
switch (mode) {
case MODE_PULL_DOWN_TO_REFRESH:
return isFirstItemVisible() && isUserDraggingDownwards();
case MODE_PULL_UP_TO_REFRESH:
return isLastItemVisible() && isUserDraggingUpwards();
case MODE_BOTH:
return (isFirstItemVisible() && isUserDraggingDownwards())
|| (isLastItemVisible() && isUserDraggingUpwards());
}
}
return false;
}
private boolean isFirstItemVisible() {
if (this.adapterView.getCount() == 0) {
return true;
} else if (adapterView.getFirstVisiblePosition() == 0) {
return adapterView.getChildAt(0).getTop() >= adapterView.getTop();
} else {
return false;
}
}
private boolean isLastItemVisible() {
final int count = this.adapterView.getCount();
if (count == 0) {
return true;
} else if (adapterView.getLastVisiblePosition() == count - 1) {
return true;
} else {
return false;
}
}
private boolean isUserDraggingDownwards() {
return this.isUserDraggingDownwards(0, EVENT_COUNT - 1);
}
private boolean isUserDraggingDownwards(int from, int to) {
return lastYs[from] != 0 && lastYs[to] != 0
&& Math.abs(lastYs[from] - lastYs[to]) > 10
&& lastYs[from] < lastYs[to];
}
private boolean isUserDraggingUpwards() {
return this.isUserDraggingUpwards(0, EVENT_COUNT - 1);
}
private boolean isUserDraggingUpwards(int from, int to) {
return lastYs[from] != 0 && lastYs[to] != 0
&& Math.abs(lastYs[to] - lastYs[from]) > 10
&& lastYs[to] < lastYs[from];
}
private void smoothScrollTo(int y) {
if (null != currentSmoothScrollRunnable) {
currentSmoothScrollRunnable.stop();
}
this.currentSmoothScrollRunnable = new SmoothScrollRunnable(handler,
getScrollY(), y);
handler.post(currentSmoothScrollRunnable);
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static interface OnRefreshListener {
public void onRefresh();
}
public static interface OnLastItemVisibleListener {
public void onLastItemVisible();
}
}
Hope it will Help you out from your Problem. let me know if you are still finding any difficulties.

Categories

Resources