aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Nurik <roman@nurik.net>2014-10-22 00:04:13 -0400
committerRoman Nurik <roman@nurik.net>2014-10-22 00:04:13 -0400
commitf2e87424ea7cc0c3f8022f984966091ea746a23e (patch)
treee3fc3eb874cf7324a2974166243ce083be07b30b
parentc6d00178d4d0b6d8378c6644c4e9d212acf3d0e3 (diff)
parent1d8ff282225275a06977489ed12d93ac925bca8e (diff)
downloadiosched-f2e87424ea7cc0c3f8022f984966091ea746a23e.tar.gz
Merge pull request #71 from romannurik/master
Update to v21 SwipeRefreshLayout. Also fix nav drawer BACK button bug.
-rw-r--r--android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java34
-rw-r--r--android/src/main/java/com/google/samples/apps/iosched/ui/widget/MultiSwipeRefreshLayout.java1
-rw-r--r--android/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeProgressBar.java267
-rwxr-xr-xandroid/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeRefreshLayout.java596
-rw-r--r--android/src/main/res/values/colors.xml3
-rw-r--r--android/src/main/res/values/dimens.xml3
6 files changed, 30 insertions, 874 deletions
diff --git a/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java b/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java
index ea4f2b8..0d9c6cd 100644
--- a/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java
+++ b/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java
@@ -45,6 +45,7 @@ import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.DrawerLayout;
+import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
@@ -76,7 +77,6 @@ import com.google.samples.apps.iosched.sync.SyncHelper;
import com.google.samples.apps.iosched.ui.debug.DebugActionRunnerActivity;
import com.google.samples.apps.iosched.ui.widget.MultiSwipeRefreshLayout;
import com.google.samples.apps.iosched.ui.widget.ScrimInsetsScrollView;
-import com.google.samples.apps.iosched.ui.widget.SwipeRefreshLayout;
import com.google.samples.apps.iosched.util.AccountUtils;
import com.google.samples.apps.iosched.util.AnalyticsManager;
import com.google.samples.apps.iosched.util.HelpUtils;
@@ -270,11 +270,10 @@ public abstract class BaseActivity extends ActionBarActivity implements
private void trySetupSwipeRefresh() {
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
if (mSwipeRefreshLayout != null) {
- mSwipeRefreshLayout.setColorScheme(
+ mSwipeRefreshLayout.setColorSchemeResources(
R.color.refresh_progress_1,
R.color.refresh_progress_2,
- R.color.refresh_progress_3,
- R.color.refresh_progress_4);
+ R.color.refresh_progress_3);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
@@ -299,11 +298,13 @@ public abstract class BaseActivity extends ActionBarActivity implements
return;
}
- if (mActionBarShown) {
- mSwipeRefreshLayout.setProgressBarTop(mProgressBarTopWhenActionBarShown);
- } else {
- mSwipeRefreshLayout.setProgressBarTop(0);
- }
+ int progressBarStartMargin = getResources().getDimensionPixelSize(
+ R.dimen.swipe_refresh_progress_bar_start_margin);
+ int progressBarEndMargin = getResources().getDimensionPixelSize(
+ R.dimen.swipe_refresh_progress_bar_end_margin);
+ int top = mActionBarShown ? mProgressBarTopWhenActionBarShown : 0;
+ mSwipeRefreshLayout.setProgressViewOffset(false,
+ top + progressBarStartMargin, top + progressBarEndMargin);
}
/**
@@ -435,6 +436,12 @@ public abstract class BaseActivity extends ActionBarActivity implements
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(Gravity.START);
}
+ protected void closeNavDrawer() {
+ if (mDrawerLayout != null) {
+ mDrawerLayout.closeDrawer(Gravity.START);
+ }
+ }
+
/** Populates the navigation drawer with the appropriate items. */
private void populateNavDrawer() {
boolean attendeeAtVenue = PrefUtils.isAttendeeAtVenue(this);
@@ -479,6 +486,15 @@ public abstract class BaseActivity extends ActionBarActivity implements
createNavDrawerItems();
}
+ @Override
+ public void onBackPressed() {
+ if (isNavDrawerOpen()) {
+ closeNavDrawer();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
private void createNavDrawerItems() {
mDrawerItemsListContainer = (ViewGroup) findViewById(R.id.navdrawer_items_list);
if (mDrawerItemsListContainer == null) {
diff --git a/android/src/main/java/com/google/samples/apps/iosched/ui/widget/MultiSwipeRefreshLayout.java b/android/src/main/java/com/google/samples/apps/iosched/ui/widget/MultiSwipeRefreshLayout.java
index 041e1f1..5c82736 100644
--- a/android/src/main/java/com/google/samples/apps/iosched/ui/widget/MultiSwipeRefreshLayout.java
+++ b/android/src/main/java/com/google/samples/apps/iosched/ui/widget/MultiSwipeRefreshLayout.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import com.google.samples.apps.iosched.R;
diff --git a/android/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeProgressBar.java b/android/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeProgressBar.java
deleted file mode 100644
index f12b14e..0000000
--- a/android/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeProgressBar.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.samples.apps.iosched.ui.widget;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.support.v4.view.ViewCompat;
-import android.view.View;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-
-
-/**
- * Custom progress bar that shows a cycle of colors as widening circles that
- * overdraw each other. When finished, the bar is cleared from the inside out as
- * the main cycle continues. Before running, this can also indicate how close
- * the user is to triggering something (e.g. how far they need to pull down to
- * trigger a refresh).
- */
-final class SwipeProgressBar {
-
- // Default progress animation colors are grays.
- private final static int COLOR1 = 0xB3000000;
- private final static int COLOR2 = 0x80000000;
- private final static int COLOR3 = 0x4d000000;
- private final static int COLOR4 = 0x1a000000;
-
- // The duration of the animation cycle.
- private static final int ANIMATION_DURATION_MS = 2000;
-
- // The duration of the animation to clear the bar.
- private static final int FINISH_ANIMATION_DURATION_MS = 1000;
-
- // Interpolator for varying the speed of the animation.
- private static final Interpolator INTERPOLATOR = BakedBezierInterpolator.getInstance();
-
- private final Paint mPaint = new Paint();
- private final RectF mClipRect = new RectF();
- private float mTriggerPercentage;
- private long mStartTime;
- private long mFinishTime;
- private boolean mRunning;
-
- // Colors used when rendering the animation,
- private int mColor1;
- private int mColor2;
- private int mColor3;
- private int mColor4;
- private View mParent;
-
- private Rect mBounds = new Rect();
-
- public SwipeProgressBar(View parent) {
- mParent = parent;
- mColor1 = COLOR1;
- mColor2 = COLOR2;
- mColor3 = COLOR3;
- mColor4 = COLOR4;
- }
-
- /**
- * 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 color1 Integer representation of a color.
- * @param color2 Integer representation of a color.
- * @param color3 Integer representation of a color.
- * @param color4 Integer representation of a color.
- */
- void setColorScheme(int color1, int color2, int color3, int color4) {
- mColor1 = color1;
- mColor2 = color2;
- mColor3 = color3;
- mColor4 = color4;
- }
-
- /**
- * Update the progress the user has made toward triggering the swipe
- * gesture. and use this value to update the percentage of the trigger that
- * is shown.
- */
- void setTriggerPercentage(float triggerPercentage) {
- mTriggerPercentage = triggerPercentage;
- mStartTime = 0;
- ViewCompat.postInvalidateOnAnimation(mParent);
- }
-
- /**
- * Start showing the progress animation.
- */
- void start() {
- if (!mRunning) {
- mTriggerPercentage = 0;
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mRunning = true;
- mParent.postInvalidate();
- }
- }
-
- /**
- * Stop showing the progress animation.
- */
- void stop() {
- if (mRunning) {
- mTriggerPercentage = 0;
- mFinishTime = AnimationUtils.currentAnimationTimeMillis();
- mRunning = false;
- mParent.postInvalidate();
- }
- }
-
- /**
- * @return Return whether the progress animation is currently running.
- */
- boolean isRunning() {
- return mRunning || mFinishTime > 0;
- }
-
- void draw(Canvas canvas) {
- final int width = mBounds.width();
- final int cx = width / 2;
- final int cy = mBounds.top + mBounds.height() / 2;
- boolean drawTriggerWhileFinishing = false;
- int restoreCount = canvas.save();
- canvas.clipRect(mBounds);
- if (mRunning || (mFinishTime > 0)) {
- long now = AnimationUtils.currentAnimationTimeMillis();
- long elapsed = (now - mStartTime) % ANIMATION_DURATION_MS;
- long iterations = (now - mStartTime) / ANIMATION_DURATION_MS;
- float rawProgress = (elapsed / (ANIMATION_DURATION_MS / 100f));
- // If we're not running anymore, that means we're running through
- // the finish animation.
- if (!mRunning) {
- // If the finish animation is done, don't draw anything, and
- // don't repost.
- if ((now - mFinishTime) >= FINISH_ANIMATION_DURATION_MS) {
- mFinishTime = 0;
- return;
- }
- // Otherwise, use a 0 opacity alpha layer to clear the animation
- // from the inside out. This layer will prevent the circles from
- // drawing within its bounds.
- long finishElapsed = (now - mFinishTime) % FINISH_ANIMATION_DURATION_MS;
- float finishProgress = (finishElapsed / (FINISH_ANIMATION_DURATION_MS / 100f));
- float pct = (finishProgress / 100f);
- // Radius of the circle is half of the screen.
- float clearRadius = width / 2 * INTERPOLATOR.getInterpolation(pct);
- mClipRect.set(cx - clearRadius, mBounds.top, cx + clearRadius, mBounds.bottom);
- canvas.saveLayerAlpha(mClipRect, 0, 0);
- // Only draw the trigger if there is a space in the center of
- // this refreshing view that needs to be filled in by the
- // trigger. If the progress view is just still animating, let it
- // continue animating.
- drawTriggerWhileFinishing = true;
- }
- // First fill in with the last color that would have finished drawing.
- if (iterations == 0) {
- canvas.drawColor(mColor1);
- } else {
- if (rawProgress >= 0 && rawProgress < 25) {
- canvas.drawColor(mColor4);
- } else if (rawProgress >= 25 && rawProgress < 50) {
- canvas.drawColor(mColor1);
- } else if (rawProgress >= 50 && rawProgress < 75) {
- canvas.drawColor(mColor2);
- } else {
- canvas.drawColor(mColor3);
- }
- }
- // Then draw up to 4 overlapping concentric circles of varying radii, based on how far
- // along we are in the cycle.
- // progress 0-50 draw mColor2
- // progress 25-75 draw mColor3
- // progress 50-100 draw mColor4
- // progress 75 (wrap to 25) draw mColor1
- if ((rawProgress >= 0 && rawProgress <= 25)) {
- float pct = (((rawProgress + 25) * 2) / 100f);
- drawCircle(canvas, cx, cy, mColor1, pct);
- }
- if (rawProgress >= 0 && rawProgress <= 50) {
- float pct = ((rawProgress * 2) / 100f);
- drawCircle(canvas, cx, cy, mColor2, pct);
- }
- if (rawProgress >= 25 && rawProgress <= 75) {
- float pct = (((rawProgress - 25) * 2) / 100f);
- drawCircle(canvas, cx, cy, mColor3, pct);
- }
- if (rawProgress >= 50 && rawProgress <= 100) {
- float pct = (((rawProgress - 50) * 2) / 100f);
- drawCircle(canvas, cx, cy, mColor4, pct);
- }
- if ((rawProgress >= 75 && rawProgress <= 100)) {
- float pct = (((rawProgress - 75) * 2) / 100f);
- drawCircle(canvas, cx, cy, mColor1, pct);
- }
- if (mTriggerPercentage > 0 && drawTriggerWhileFinishing) {
- // There is some portion of trigger to draw. Restore the canvas,
- // then draw the trigger. Otherwise, the trigger does not appear
- // until after the bar has finished animating and appears to
- // just jump in at a larger width than expected.
- canvas.restoreToCount(restoreCount);
- restoreCount = canvas.save();
- canvas.clipRect(mBounds);
- drawTrigger(canvas, cx, cy);
- }
- // Keep running until we finish out the last cycle.
- ViewCompat.postInvalidateOnAnimation(mParent);
- } else {
- // Otherwise if we're in the middle of a trigger, draw that.
- if (mTriggerPercentage > 0 && mTriggerPercentage <= 1.0) {
- drawTrigger(canvas, cx, cy);
- }
- }
- canvas.restoreToCount(restoreCount);
- }
-
- private void drawTrigger(Canvas canvas, int cx, int cy) {
- mPaint.setColor(mColor1);
- canvas.drawCircle(cx, cy, cx * mTriggerPercentage, mPaint);
- }
-
- /**
- * Draws a circle centered in the view.
- *
- * @param canvas the canvas to draw on
- * @param cx the center x coordinate
- * @param cy the center y coordinate
- * @param color the color to draw
- * @param pct the percentage of the view that the circle should cover
- */
- private void drawCircle(Canvas canvas, float cx, float cy, int color, float pct) {
- mPaint.setColor(color);
- canvas.save();
- canvas.translate(cx, cy);
- float radiusScale = INTERPOLATOR.getInterpolation(pct);
- canvas.scale(radiusScale, radiusScale);
- canvas.drawCircle(0, 0, cx, mPaint);
- canvas.restore();
- }
-
- /**
- * Set the drawing bounds of this SwipeProgressBar.
- */
- void setBounds(int left, int top, int right, int bottom) {
- mBounds.left = left;
- mBounds.top = top;
- mBounds.right = right;
- mBounds.bottom = bottom;
- }
-}
diff --git a/android/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeRefreshLayout.java b/android/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeRefreshLayout.java
deleted file mode 100755
index 903212a..0000000
--- a/android/src/main/java/com/google/samples/apps/iosched/ui/widget/SwipeRefreshLayout.java
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.samples.apps.iosched.ui.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.support.v4.view.MotionEventCompat;
-import android.support.v4.view.ViewCompat;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.Animation;
-import android.view.animation.Animation.AnimationListener;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Transformation;
-import android.widget.AbsListView;
-
-
-/**
- * The SwipeRefreshLayout should be used whenever the user can refresh the
- * contents of a view via a vertical swipe gesture. The activity that
- * instantiates this view should add an OnRefreshListener to be notified
- * whenever the swipe to refresh gesture is completed. The SwipeRefreshLayout
- * will notify the listener each and every time the gesture is completed again;
- * the listener is responsible for correctly determining when to actually
- * initiate a refresh of its content. If the listener determines there should
- * not be a refresh, it must call setRefreshing(false) to cancel any visual
- * indication of a refresh. If an activity wishes to show just the progress
- * animation, it should call setRefreshing(true). To disable the gesture and progress
- * animation, call setEnabled(false) on the view.
- *
- * <p> This layout should be made the parent of the view that will be refreshed as a
- * result of the gesture and can only support one direct child. This view will
- * also be made the target of the gesture and will be forced to match both the
- * width and the height supplied in this layout. The SwipeRefreshLayout does not
- * provide accessibility events; instead, a menu item must be provided to allow
- * refresh of the content wherever this gesture is used.</p>
- */
-public class SwipeRefreshLayout extends ViewGroup {
- private static final String LOG_TAG = SwipeRefreshLayout.class.getSimpleName();
-
- 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 static final int INVALID_POINTER = -1;
-
- 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 int mFrom;
- private boolean mRefreshing = false;
- private int mTouchSlop;
- private float mDistanceToTriggerSync = -1;
- private int mMediumAnimationDuration;
- private float mFromPercentage = 0;
- private float mCurrPercentage = 0;
- private int mProgressBarHeight;
- private int mCurrentTargetOffsetTop;
- private int mProgressBarTop;
-
- private float mInitialMotionY;
- private float mLastMotionY;
- private boolean mIsBeingDragged;
- private int mActivePointerId = INVALID_POINTER;
-
- // 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(OnRefreshListener listener) {
- mListener = listener;
- }
-
- 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();
- }
- }
- }
-
- /**
- * @deprecated Use {@link #setColorSchemeResources(int, int, int, int)}
- */
- @Deprecated
- public void setColorScheme(int colorRes1, int colorRes2, int colorRes3, int colorRes4) {
- setColorSchemeResources(colorRes1, colorRes2, colorRes3, colorRes4);
- }
-
- /**
- * Set the four colors used in the progress animation from color resources.
- * The first color will also be the color of the bar that grows in response
- * to a user swipe gesture.
- */
- public void setColorSchemeResources(int colorRes1, int colorRes2, int colorRes3,
- int colorRes4) {
- final Resources res = getResources();
- setColorSchemeColors(res.getColor(colorRes1), res.getColor(colorRes2),
- res.getColor(colorRes3), res.getColor(colorRes4));
- }
-
- /**
- * 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.
- */
- public void setColorSchemeColors(int color1, int color2, int color3, int color4) {
- ensureTarget();
- 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);
- }
-
- public void setProgressBarTop(int top) {
- mProgressBarTop = top;
- mProgressBar.setBounds(0, mProgressBarTop, getWidth(), mProgressBarTop + mProgressBarHeight);
- }
-
- @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, mProgressBarTop, getWidth(), mProgressBarTop + 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();
-
- final int action = MotionEventCompat.getActionMasked(ev);
-
- if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
- mReturningToStart = false;
- }
-
- if (!isEnabled() || mReturningToStart || canChildScrollUp()) {
- // Fail fast if we're not in a state where a swipe is possible
- return false;
- }
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mLastMotionY = mInitialMotionY = ev.getY();
- mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
- mIsBeingDragged = false;
- mCurrPercentage = 0;
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (mActivePointerId == INVALID_POINTER) {
- Log.e(LOG_TAG, "Got ACTION_MOVE event but don't have an active pointer id.");
- return false;
- }
-
- final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
- if (pointerIndex < 0) {
- Log.e(LOG_TAG, "Got ACTION_MOVE event but have an invalid active pointer id.");
- return false;
- }
-
- final float y = MotionEventCompat.getY(ev, pointerIndex);
- final float yDiff = y - mInitialMotionY;
- if (yDiff > mTouchSlop) {
- mLastMotionY = y;
- mIsBeingDragged = true;
- }
- break;
-
- case MotionEventCompat.ACTION_POINTER_UP:
- onSecondaryPointerUp(ev);
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mIsBeingDragged = false;
- mCurrPercentage = 0;
- mActivePointerId = INVALID_POINTER;
- break;
- }
-
- return mIsBeingDragged;
- }
-
- @Override
- public void requestDisallowInterceptTouchEvent(boolean b) {
- // Nope.
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- final int action = MotionEventCompat.getActionMasked(ev);
-
- if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
- mReturningToStart = false;
- }
-
- if (!isEnabled() || mReturningToStart || canChildScrollUp()) {
- // Fail fast if we're not in a state where a swipe is possible
- return false;
- }
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mLastMotionY = mInitialMotionY = ev.getY();
- mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
- mIsBeingDragged = false;
- mCurrPercentage = 0;
- break;
-
- case MotionEvent.ACTION_MOVE:
- final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
- if (pointerIndex < 0) {
- Log.e(LOG_TAG, "Got ACTION_MOVE event but have an invalid active pointer id.");
- return false;
- }
-
- final float y = MotionEventCompat.getY(ev, pointerIndex);
- final float yDiff = y - mInitialMotionY;
-
- if (!mIsBeingDragged && yDiff > mTouchSlop) {
- mIsBeingDragged = true;
- }
-
- if (mIsBeingDragged) {
- // User velocity passed min velocity; trigger a refresh
- if (yDiff > mDistanceToTriggerSync) {
- // User movement passed distance; trigger a refresh
- startRefresh();
- } else {
- // Just track the user's movement
- setTriggerPercentage(
- mAccelerateInterpolator.getInterpolation(
- yDiff / mDistanceToTriggerSync));
- updateContentOffsetTop((int) (yDiff));
- if (mLastMotionY > y && mTarget.getTop() == getPaddingTop()) {
- // 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();
- }
- }
- mLastMotionY = y;
- }
- break;
-
- case MotionEventCompat.ACTION_POINTER_DOWN: {
- final int index = MotionEventCompat.getActionIndex(ev);
- mLastMotionY = MotionEventCompat.getY(ev, index);
- mActivePointerId = MotionEventCompat.getPointerId(ev, index);
- break;
- }
-
- case MotionEventCompat.ACTION_POINTER_UP:
- onSecondaryPointerUp(ev);
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mIsBeingDragged = false;
- mCurrPercentage = 0;
- mActivePointerId = INVALID_POINTER;
- return false;
- }
-
- return true;
- }
-
- 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);
- }
-
- private void onSecondaryPointerUp(MotionEvent ev) {
- final int pointerIndex = MotionEventCompat.getActionIndex(ev);
- final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
- if (pointerId == mActivePointerId) {
- // This was our active pointer going up. Choose a new
- // active pointer and adjust accordingly.
- final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
- mLastMotionY = MotionEventCompat.getY(ev, newPointerIndex);
- mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
- }
- }
-
- /**
- * 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) {
- }
- }
-}
diff --git a/android/src/main/res/values/colors.xml b/android/src/main/res/values/colors.xml
index cc9a095..d5d91a2 100644
--- a/android/src/main/res/values/colors.xml
+++ b/android/src/main/res/values/colors.xml
@@ -55,8 +55,7 @@
<color name="refresh_progress_1">@color/theme_accent_2</color>
<color name="refresh_progress_2">@color/theme_accent_1</color>
- <color name="refresh_progress_3">@color/theme_primary_dark</color>
- <color name="refresh_progress_4">@color/theme_primary_light</color>
+ <color name="refresh_progress_3">@color/theme_primary</color>
<color name="data_item_background_light">#ffffff</color>
<color name="data_item_lightbg_title">#404040</color>
diff --git a/android/src/main/res/values/dimens.xml b/android/src/main/res/values/dimens.xml
index 91dd3c1..dafa969 100644
--- a/android/src/main/res/values/dimens.xml
+++ b/android/src/main/res/values/dimens.xml
@@ -79,6 +79,9 @@
<dimen name="action_bar_auto_hide_min_y">152dp</dimen>
<dimen name="action_bar_auto_hide_sensivity">48dp</dimen>
+ <dimen name="swipe_refresh_progress_bar_start_margin">-40dp</dimen>
+ <dimen name="swipe_refresh_progress_bar_end_margin">16dp</dimen>
+
<dimen name="browse_sessions_anim_amount">400dp</dimen>
<dimen name="butter_bar_height">64dp</dimen>
<dimen name="filterbar_height">48dp</dimen>