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) {
}
}
}
Related
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.
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();
}
}
};
I have used this tutorial https://code.google.com/p/range-seek-bar/#Example_usage_as_Integer_range?.
Encountered runtime error of my activity stopped. Would like to seek help from you. I attempted to correct the following compile errors as listed below.
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, context);
Context cannot be resolved to a variable
I tried adding changing context to this.
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
TAG cannot be resolved to a variable.
I tried adding "protected static final String TAG = null;" to main activity.
ViewGroup layout = (ViewGroup) findViewById(<your-layout-id>)
Does the layout id refer to my main_activity.xml in my layout?
Really grateful for your feedback.
MainActivity.Java
package com.example.rangeseekbargooglecode;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.ViewGroup;
import com.example.rangeseekbargooglecode.RangeSeekBar.OnRangeSeekBarChangeListener;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String TAG = null;
// create RangeSeekBar as Integer range between 20 and 75
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, this);
seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
#Override
public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
// handle changed range values
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
}
});
// add RangeSeekBar to pre-defined layout
ViewGroup layout = (ViewGroup) findViewById(R.layout.activity_main);
layout.addView(seekBar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
activity_main.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" >
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="109dp" />
</RelativeLayout>
Edited Code to allow TextView to display range.
public class MainActivity extends Activity {
private TextView textview;
protected static final String TAG = "com.example.gto_doubleseekbar";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.textView1);
// create RangeSeekBar as Integer range between 20 and 75
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, this);
seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
#Override
public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
// handle changed range values
String powerranger = "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue;
Log.i(TAG, powerranger);
textview.setText(powerranger);
}
});
// add RangeSeekBar to pre-defined layout
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.activity_main,null);
layout.addView(seekBar);
setContentView(layout);
}
RangeSeekBar seekBar = new RangeSeekBar(20, 75, context); 1. Context cannot be resolved to a variable
this must work:
RangeSeekBar seekBar = new RangeSeekBar(20, 75, this);
Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue); 2. TAG cannot be resolved to a variable. I tried adding "protected static final String TAG = null;" to main activity.
Don't set it to null. Usually you use the app or component name, e.g.
protected static final String TAG = "MyApp";
ViewGroup layout = (ViewGroup) findViewById() 3. Does the layout id refer to my main_activity.xml in my layout?
Use this:
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService (Context.LAYOUT_INFLATER_SERVICE);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.activity_main,null);
layout.addView(seekBar);
setContentView(layout);
Try to implement custom RangeSeekBar.
xml file:
<com.doondoz.utility.common_function.RangeSeekBar
android:id="#+id/seekBarPrice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:left_index="0"
android:layout_weight="0.90" />
java file:
RangeSeekBar.java
public class RangeSeekBar extends View {
private static final int DEFAULT_HEIGHT = 70;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_TICK_COUNT = 100;
private Thumb leftThumb, rightThumb;
private Thumb pressedThumb = null;
private SeekBar seekBar;
private Paint thumbPaint;
private OnRangeSeekBarChangerListener mListener;
private int mTickCount;
private int mLeftIndex = 0;
private int mRightIndex;
private int mThumbColor;
private int mThumbNormalRadius;
private int mThumbPressedRadius;
public RangeSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public RangeSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public RangeSeekBar(Context context) {
super(context);
}
#SuppressWarnings("deprecation")
private void init(Context context, AttributeSet attrs) {
Resources resources = getResources();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RangeSeekBar);
try {
mTickCount = typedArray.getInteger(R.styleable.RangeSeekBar_tick_count, DEFAULT_TICK_COUNT);
mRightIndex = mTickCount - 1;
mThumbColor = typedArray.getColor(R.styleable.RangeSeekBar_thumb_color, getResources().getColor(R.color.thumb_default));
mThumbNormalRadius = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_thumb_normal_radius, 12);
mThumbPressedRadius = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_thumb_pressed_radius, 16);
mLeftIndex = typedArray.getInteger(R.styleable.RangeSeekBar_left_index, 0);
mRightIndex = typedArray.getInteger(R.styleable.RangeSeekBar_right_index, mRightIndex);
if (mLeftIndex < 0)
throw new IllegalArgumentException("Left index must be >= 0");
if (mRightIndex > mTickCount)
throw new IllegalArgumentException("Right index must be <= tick count");
} finally {
typedArray.recycle();
}
setUp();
}
private void setUp() {
thumbPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
thumbPaint.setStyle(Paint.Style.FILL);
thumbPaint.setColor(mThumbColor);
leftThumb = new Thumb(0, 0, thumbPaint, mThumbNormalRadius, mThumbPressedRadius);
rightThumb = new Thumb(0, 0, thumbPaint, mThumbNormalRadius, mThumbPressedRadius);
seekBar = new SeekBar(0, 0, 0, Color.BLACK, 1, mThumbColor, 3);
seekBar.setTickNumb(mTickCount);
}
public void setOnRangeBarChangeListener(OnRangeSeekBarChangerListener onRangeBarChangeListener) {
mListener = onRangeBarChangeListener;
}
/**
* Set number of ticks
*
* #param tickCount Default is 100
*/
public void setTickCount(int tickCount) {
mTickCount = tickCount;
seekBar.setTickNumb(mTickCount);
invalidate();
}
/**
* Set thumb's color
*
* #param thumbColor Default is orange
*/
public void setThumbColor(int thumbColor) {
mThumbColor = thumbColor;
thumbPaint.setColor(mThumbColor);
invalidate();
}
/**
* Set thumb's normal radius
*
* #param thumbRadius Default is 6dp
*/
public void setThumbNormalRadius(float thumbRadius) {
mThumbNormalRadius = (int) (thumbRadius*getResources().getDisplayMetrics().density);
leftThumb.radius = mThumbNormalRadius;
rightThumb.radius = mThumbNormalRadius;
invalidate();
}
/**
* Set thumb's pressed radius
*
* #param thumbPressedRadius Default is 8dp
*/
public void setThumbPressedRadius(float thumbPressedRadius) {
mThumbPressedRadius = (int) (thumbPressedRadius*getResources().getDisplayMetrics().density);
leftThumb.pressedRadius = mThumbPressedRadius;
rightThumb.pressedRadius = mThumbPressedRadius;
invalidate();
}
/**
* Set index for the Left Thumb
*
* #param leftIndex Default is 0
*/
public void setLeftIndex(int leftIndex) {
if (leftIndex < 0) {
throw new IllegalArgumentException("Left index must be >= 0");
}
mLeftIndex = leftIndex;
leftThumb.setIndex(seekBar, mLeftIndex);
invalidate();
}
/**
* Set index for the Right thumb
*
* #param rightIndex Default is 99
*/
public void setRightIndex(int rightIndex) {
if (rightIndex > mTickCount) {
throw new IllegalArgumentException("Left index must be <= tick count");
}
mRightIndex = rightIndex;
leftThumb.setIndex(seekBar, mRightIndex);
invalidate();
}
/**
* Get left index
*
* #return int
*/
public int getLeftIndex() {
return mLeftIndex;
}
/**
* Get right index
*
* #return int
*/
public int getRightIndex() {
return mRightIndex;
}
/**
* Get number of tick
*
* #return int
*/
public int getTickCount() {
return mTickCount;
}
#Override
protected synchronized void onDraw(Canvas canvas) {
seekBar.draw(canvas, leftThumb, rightThumb);
leftThumb.draw(canvas);
rightThumb.draw(canvas);
if (pressedThumb != null && pressedThumb.isAnimating) {
invalidate();
}
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height, width;
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(heightSize, DEFAULT_HEIGHT);
} else {
height = DEFAULT_HEIGHT;
}
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
width = Math.min(widthSize, DEFAULT_WIDTH);
} else {
width = DEFAULT_WIDTH;
}
setMeasuredDimension(width, height);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
pressedThumb = checkThumbPressed(eventX, eventY);
if (pressedThumb == null) {
return super.onTouchEvent(event);
}
pressedThumb.setPressed(true);
invalidate();
setPressed(true);
return true;
case MotionEvent.ACTION_MOVE:
onActionMove(eventX);
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (pressedThumb == null) {
return super.onTouchEvent(event);
}
onActionUp();
break;
}
return super.onTouchEvent(event);
}
private void onActionUp() {
pressedThumb.onActionUp(seekBar);
invalidate();
}
private void onActionMove(float eventX) {
if (eventX >= seekBar.leftX && eventX <= seekBar.rightX) {
pressedThumb.x = eventX;
invalidate();
if (leftThumb.x > rightThumb.x) {
final Thumb temp = leftThumb;
leftThumb = rightThumb;
rightThumb = temp;
}
int leftIndex = seekBar.getNearestTick(leftThumb);
int rightIndex = seekBar.getNearestTick(rightThumb);
if (mLeftIndex != leftIndex || mRightIndex != rightIndex) {
mLeftIndex = leftIndex;
mRightIndex = rightIndex;
if (mListener != null) {
mListener.onIndexChange(this, mLeftIndex, mRightIndex);
}
}
}
}
private Thumb checkThumbPressed(float eventX, float eventY) {
Thumb result = null;
boolean isLeftThumbPressed = leftThumb.isInTargetZone(eventX, eventY);
boolean isRightThumbPressed = rightThumb.isInTargetZone(eventX, eventY);
if (isLeftThumbPressed && isRightThumbPressed) {
result = (eventX / getWidth() >= 0.5f) ? leftThumb : rightThumb;
} else if (isLeftThumbPressed) {
result = leftThumb;
} else if (isRightThumbPressed) {
result = rightThumb;
}
return result;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
leftThumb.x = (getPaddingLeft() + 20 + leftThumb.normalRadius / 2);
leftThumb.y = (h + getPaddingTop() + getPaddingBottom()) / 2;
rightThumb.y = leftThumb.y;
rightThumb.x = (w - getPaddingRight() - 20 - rightThumb.normalRadius / 2);
seekBar.leftX = leftThumb.x;
seekBar.rightX = rightThumb.x;
seekBar.y = leftThumb.y;
leftThumb.setIndex(seekBar, mLeftIndex);
rightThumb.setIndex(seekBar, mRightIndex);
}
#Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
SavedState state = new SavedState(super.onSaveInstanceState());
state.tickCount = mTickCount;
state.leftIndex = mLeftIndex;
state.rightIndex = mRightIndex;
state.thumbColor = mThumbColor;
state.thumbNormalRadius = mThumbNormalRadius;
state.thumbPressedRadius = mThumbPressedRadius;
bundle.putParcelable(SavedState.STATE,state);
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
SavedState savedState = bundle.getParcelable(SavedState.STATE);
mTickCount = savedState.tickCount;
mThumbColor = savedState.thumbColor;
mThumbNormalRadius = savedState.thumbNormalRadius;
mThumbPressedRadius = savedState.thumbPressedRadius;
mLeftIndex = savedState.leftIndex;
mRightIndex = savedState.rightIndex;
super.onRestoreInstanceState(savedState.getSuperState());
return;
}
super.onRestoreInstanceState(SavedState.EMPTY_STATE);
}
public interface OnRangeSeekBarChangerListener {
void onIndexChange(RangeSeekBar rangeBar, int leftIndex, int rightIndex);
}
static class SavedState extends BaseSavedState {
static final String STATE = "RangeSeekBar.STATE";
int tickCount;
int leftIndex;
int rightIndex;
int thumbColor;
int thumbNormalRadius;
int thumbPressedRadius;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
}
public static final Creator<SavedState> CREATOR =
new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
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.
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.