diff --git a/library/src/main/java/lumenghz/com/pullrefresh/PullToRefreshView.java b/library/src/main/java/lumenghz/com/pullrefresh/PullToRefreshView.java
index a6d9c8e..d380085 100644
--- a/library/src/main/java/lumenghz/com/pullrefresh/PullToRefreshView.java
+++ b/library/src/main/java/lumenghz/com/pullrefresh/PullToRefreshView.java
@@ -22,6 +22,7 @@
import lumenghz.com.pullrefresh.refresh_view.BaseRefreshView;
import lumenghz.com.pullrefresh.refresh_view.RocketRefreshView;
+import lumenghz.com.pullrefresh.refresh_view.SunRefreshView;
import lumenghz.com.pullrefresh.util.Utils;
/**
@@ -30,10 +31,12 @@
*/
public class PullToRefreshView extends ViewGroup {
private static final int DRAG_MAX_DISTANCE = 120;
+ private static final int DRAW_MAX_DISTANCE_SUN = 140;
private static final float DRAG_RATE = .5f;
private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
- public static final int STYPE_ROCKET = 0;
+ public static final int TYPE_ROCKET = 0;
+ public static final int TYPE_SUN = 1;
public static final int MAX_OFFSET_ANIMATION_DURATION = 700;
private static final int INVALID_POINTER = -1;
@@ -78,27 +81,38 @@ public PullToRefreshView(Context context) {
public PullToRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PullToRefreshView);
- final int type = a.getInteger(R.styleable.PullToRefreshView_lrefresh, STYPE_ROCKET);
+ final int type = a.getInteger(R.styleable.PullToRefreshView_lrefresh, TYPE_ROCKET);
a.recycle();
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
- mTotalDragDistance = Utils.convertDpToPixel(context, DRAG_MAX_DISTANCE);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mRefreshView = new ImageView(context);
- setRefreshStyle(type);
+ setRefreshStyle(context, type);
addView(mRefreshView);
setWillNotDraw(false);
ViewCompat.setChildrenDrawingOrderEnabled(this, true);
}
- private void setRefreshStyle(int type) {
+ /**
+ * Set landscape's height dynamically because different landscape suitable different heights.
+ *
+ * @param context context
+ * @param type type of theme which chosen by user
+ * @see {@link #mTotalDragDistance = Utils.convertDpToPixel} in this method
+ */
+ private void setRefreshStyle(Context context, int type) {
setRefreshing(false);
switch (type) {
- case STYPE_ROCKET:
+ case TYPE_ROCKET:
mBaseRefreshView = new RocketRefreshView(getContext(), this);
+ mTotalDragDistance = Utils.convertDpToPixel(context, DRAG_MAX_DISTANCE);
+ break;
+ case TYPE_SUN:
+ mBaseRefreshView = new SunRefreshView(getContext(), this);
+ mTotalDragDistance = Utils.convertDpToPixel(context, DRAW_MAX_DISTANCE_SUN);
break;
default:
throw new InvalidParameterException("Type is not exists");
diff --git a/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/AnimationFractory.java b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/AnimationFactory.java
similarity index 75%
rename from library/src/main/java/lumenghz/com/pullrefresh/refresh_view/AnimationFractory.java
rename to library/src/main/java/lumenghz/com/pullrefresh/refresh_view/AnimationFactory.java
index 811017b..4123f74 100644
--- a/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/AnimationFractory.java
+++ b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/AnimationFactory.java
@@ -4,17 +4,20 @@
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
/**
* @author lumeng on 2016-06-16.
* jiahehz@gmail.com
*/
-public class AnimationFractory {
+public class AnimationFactory {
private static final int ANIMATION_FIRE_BURN_DURATION = 180;
private static final int ANIMATION_FIRE_SCALE_DURATION = 100;
+ private static final int ANIMATION_SUN_ROTATE_DURATION = 1000;
private static final Interpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
private static final Interpolator DECELERATE_INTERPOLATOR = new AccelerateDecelerateInterpolator();
+ private static final Interpolator NORMAL_INTERPOLATOR = new LinearInterpolator();
Animation getFireScale(Animation animation) {
configureAnimation(animation,
@@ -38,6 +41,17 @@ Animation getFireBurn(Animation animation) {
return animation;
}
+ Animation getSunRotate(Animation animation) {
+ configureAnimation(animation,
+ NORMAL_INTERPOLATOR,
+ ANIMATION_SUN_ROTATE_DURATION,
+ 0,
+ Animation.RESTART,
+ Animation.INFINITE);
+
+ return animation;
+ }
+
private void configureAnimation(Animation animation, Interpolator interpolator, int duration, int startOffset, int repeatMode, int repeatCount) {
animation.setInterpolator(interpolator);
animation.setDuration(duration);
diff --git a/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/BaseRefreshView.java b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/BaseRefreshView.java
index 2cd434a..a59b89e 100644
--- a/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/BaseRefreshView.java
+++ b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/BaseRefreshView.java
@@ -10,6 +10,7 @@
import android.os.Build;
import lumenghz.com.pullrefresh.PullToRefreshView;
+import lumenghz.com.pullrefresh.util.Utils;
/**
* @author lumeng on 2016-06-16.
@@ -31,6 +32,14 @@ protected Context getContext() {
public abstract void offsetTopAndBottom(int offset);
+ protected abstract void initialDimens(int viewWidth);
+
+ protected abstract void setupAnimations();
+
+ protected int getPixel(int dp) {
+ return Utils.convertDpToPixel(getContext(), dp);
+ }
+
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void invalidateDrawable(Drawable who) {
diff --git a/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/RocketRefreshView.java b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/RocketRefreshView.java
index 2a84345..1cb5095 100644
--- a/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/RocketRefreshView.java
+++ b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/RocketRefreshView.java
@@ -83,7 +83,8 @@ public void run() {
});
}
- private void initialDimens(int viewWidth) {
+ @Override
+ protected void initialDimens(int viewWidth) {
if (viewWidth <= 0 || viewWidth == mScreenWidth) return;
mScreenWidth = viewWidth;
@@ -267,8 +268,9 @@ public boolean isRunning() {
return false;
}
- private void setupAnimations() {
- AnimationFractory animationFractory = new AnimationFractory();
+ @Override
+ protected void setupAnimations() {
+ AnimationFactory animationFractory = new AnimationFactory();
mFireBurnAnimation = animationFractory.getFireBurn(new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
diff --git a/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/SunRefreshView.java b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/SunRefreshView.java
new file mode 100644
index 0000000..e6e7ad8
--- /dev/null
+++ b/library/src/main/java/lumenghz/com/pullrefresh/refresh_view/SunRefreshView.java
@@ -0,0 +1,257 @@
+package lumenghz.com.pullrefresh.refresh_view;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.util.Log;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import lumenghz.com.pullrefresh.PullToRefreshView;
+import lumenghz.com.pullrefresh.R;
+
+/**
+ * @author lumeng on 2016-07-01.
+ */
+public class SunRefreshView extends BaseRefreshView {
+ private static final float HEIGHT_RATIO = 1.0f;
+ private static final float BUILDING_INITIAL_SCALE = 1.0f;
+ private static final float BUILDING_FINAL_SCALE = 1.2f;
+
+ private PullToRefreshView mParent;
+
+ private Matrix mMatrix;
+
+ private Context mContext;
+
+ private Animation mSunAnimation;
+
+ private Bitmap mSun;
+ private Bitmap mBuilding;
+
+ private Paint mBackgroundPaint;
+
+ private boolean isRefreshing = false;
+ private boolean isSunRise = true;
+
+ private float mBuildingTopOffset;
+
+ private float mSunRotateAngle;
+ private float mPercent;
+
+ private int mSunWidth;
+ private int mSunHeight;
+
+ /**
+ * height of landscape
+ */
+ private int mSenceHeight;
+ /**
+ * width of landscape
+ */
+ private int mScreenWidth;
+ /**
+ * distance between bottom of landscape and top of landscape
+ */
+ private int mTop;
+ /**
+ * max distance between bottom of landscape and top of landscape
+ */
+ private int totalDistance;
+
+ public SunRefreshView(Context context, final PullToRefreshView layout) {
+ super(context, layout);
+
+ mParent = layout;
+ mMatrix = new Matrix();
+ mContext = getContext();
+ setupAnimations();
+ setupPaint();
+ layout.post(new Runnable() {
+ @Override
+ public void run() {
+ initialDimens(layout.getWidth());
+ }
+ });
+ }
+
+ @Override
+ protected void initialDimens(int viewWidth) {
+ if (viewWidth <= 0 || viewWidth == mScreenWidth) return;
+
+ createBitmaps();
+
+ mScreenWidth = viewWidth;
+ mSenceHeight = (int) (HEIGHT_RATIO * mScreenWidth);
+
+ mTop = -mParent.getTotalDragDistance();
+ totalDistance = -mTop;
+
+ mBuildingTopOffset = -mTop - mBuilding.getHeight();
+
+ mSunWidth = mSun.getWidth();
+ mSunHeight = mSun.getHeight();
+ }
+
+ private void createBitmaps() {
+ mSun = CreateBitmapFactory.getBitmapFromImage(R.drawable.sun, mContext);
+ mBuilding = CreateBitmapFactory.getBitmapFromImage(R.drawable.home_title_building_hz, mContext);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mScreenWidth <= 0) return;
+
+ final int saveCount = canvas.save();
+
+ canvas.translate(0, mTop);
+ canvas.clipRect(0, -mTop, mScreenWidth, mParent.getTotalDragDistance());
+ canvas.drawRect(0, -mTop, mScreenWidth, mParent.getTotalDragDistance(), mBackgroundPaint);
+
+ drawBuilding(canvas);
+ drawSun(canvas);
+
+ canvas.restoreToCount(saveCount);
+ }
+
+ /**
+ * Draw building
+ *
+ * @param canvas canvas
+ */
+ private void drawBuilding(Canvas canvas) {
+ final Matrix matrix = mMatrix;
+ matrix.reset();
+
+ float dragPercent = Math.min(1f, Math.abs(mPercent));
+
+ float buildingScale;
+
+ buildingScale = BUILDING_INITIAL_SCALE + (BUILDING_FINAL_SCALE - BUILDING_INITIAL_SCALE) * dragPercent;
+ matrix.preScale(buildingScale, buildingScale);
+
+ final float offsetX = mScreenWidth / 2
+ - mBuilding.getWidth() / 2
+ + (1f - buildingScale) * mBuilding.getWidth() / 2;
+ final float offsetY = mBuildingTopOffset;
+
+ matrix.postTranslate(offsetX, offsetY);
+ canvas.drawBitmap(mBuilding, matrix, null);
+ }
+
+ /**
+ * Draw sun
+ *
+ * @param canvas canvas
+ */
+ private void drawSun(Canvas canvas) {
+ final Matrix matrix = mMatrix;
+ matrix.reset();
+
+ float dragPercent = Math.min(1f, Math.abs(mPercent));
+
+ final float offsetX = isRefreshing ? mScreenWidth / 2 * (2 - dragPercent) - mSunWidth / 2 : (mScreenWidth * dragPercent - mSunWidth) / 2;
+ final float offsetY = totalDistance * func(dragPercent);
+
+ matrix.preRotate(mSunRotateAngle == 0.0f ? (360 * dragPercent) : mSunRotateAngle, mSunWidth / 2, mSunHeight / 2);
+ matrix.postTranslate(offsetX, offsetY);
+ canvas.drawBitmap(mSun, matrix, null);
+ }
+
+ @Override
+ protected void setupAnimations() {
+ AnimationFactory factory = new AnimationFactory();
+ mSunAnimation = factory.getSunRotate(new Animation() {
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ mSunRotateAngle = 720 * setVariable(interpolatedTime);
+ }
+ });
+ mSunAnimation.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ resetOrigins();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+ }
+ });
+ }
+
+ private void setupPaint() {
+ mBackgroundPaint = new Paint();
+ mBackgroundPaint.setColor(Color.rgb(251, 66, 49));
+ mBackgroundPaint.setStyle(Paint.Style.FILL);
+ }
+
+ @Override
+ public void setBounds(int left, int top, int right, int bottom) {
+ super.setBounds(left, top, right, mSenceHeight + top);
+ }
+
+ @Override
+ public void setPercent(float percent, boolean invalidate) {
+ setPercent(percent);
+ }
+
+ private void setPercent(float percent) {
+ this.mPercent = percent;
+ }
+
+ @Override
+ public void offsetTopAndBottom(int offset) {
+ mTop += offset;
+ invalidateSelf();
+ }
+
+ @Override
+ public void start() {
+ isRefreshing = true;
+ mSunAnimation.reset();
+
+ mParent.startAnimation(mSunAnimation);
+ }
+
+ @Override
+ public void stop() {
+ mParent.clearAnimation();
+ isRefreshing = false;
+ }
+
+ @Override
+ public boolean isRunning() {
+ return false;
+ }
+
+ private float setVariable(float value) {
+ invalidateSelf();
+ return value;
+ }
+
+ private void resetOrigins() {
+ setPercent(0);
+ mSunRotateAngle = 0.0f;
+ isSunRise = true;
+ }
+
+ /**
+ * This is sun's moving-equation
+ * (y-3.1)² (x-1.8)²
+ * -------- + -------- = 1
+ * 3.3*3.3 2*2
+ *
+ * @param degree x value in the equation
+ * @return y value int the equation
+ */
+ public float func(float degree) {
+ return -(float) Math.sqrt((1.00 - Math.pow(degree - 2.32, 2) / 7.29) * 5.9049) + 2.20f;
+ }
+}
diff --git a/library/src/main/res/drawable-xhdpi/home_title_building_cq.png b/library/src/main/res/drawable-xhdpi/home_title_building_cq.png
new file mode 100755
index 0000000..f548dda
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/home_title_building_cq.png differ
diff --git a/library/src/main/res/drawable-xhdpi/home_title_building_cs.png b/library/src/main/res/drawable-xhdpi/home_title_building_cs.png
new file mode 100755
index 0000000..34d8617
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/home_title_building_cs.png differ
diff --git a/library/src/main/res/drawable-xhdpi/home_title_building_default.png b/library/src/main/res/drawable-xhdpi/home_title_building_default.png
new file mode 100755
index 0000000..641e9dd
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/home_title_building_default.png differ
diff --git a/library/src/main/res/drawable-xhdpi/home_title_building_fz.png b/library/src/main/res/drawable-xhdpi/home_title_building_fz.png
new file mode 100755
index 0000000..244f3b9
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/home_title_building_fz.png differ
diff --git a/library/src/main/res/drawable-xhdpi/home_title_building_hz.png b/library/src/main/res/drawable-xhdpi/home_title_building_hz.png
new file mode 100755
index 0000000..29ac77a
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/home_title_building_hz.png differ
diff --git a/library/src/main/res/drawable-xhdpi/home_title_refresh_text15.png b/library/src/main/res/drawable-xhdpi/home_title_refresh_text15.png
new file mode 100755
index 0000000..029c225
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/home_title_refresh_text15.png differ
diff --git a/library/src/main/res/drawable-xhdpi/sun.png b/library/src/main/res/drawable-xhdpi/sun.png
new file mode 100755
index 0000000..381733d
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/sun.png differ
diff --git a/library/src/main/res/drawable-xhdpi/weather_hori_line.png b/library/src/main/res/drawable-xhdpi/weather_hori_line.png
new file mode 100755
index 0000000..4946814
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/weather_hori_line.png differ
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
index 935b076..a71c917 100644
--- a/library/src/main/res/values/attrs.xml
+++ b/library/src/main/res/values/attrs.xml
@@ -3,6 +3,7 @@
+
\ No newline at end of file
diff --git a/sample/src/main/res/layout/fragment_listview.xml b/sample/src/main/res/layout/fragment_listview.xml
index c72ac00..0f6032e 100644
--- a/sample/src/main/res/layout/fragment_listview.xml
+++ b/sample/src/main/res/layout/fragment_listview.xml
@@ -10,7 +10,7 @@
android:id="@+id/pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:lrefresh="rocket"
+ app:lrefresh="sun"
>
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
\ No newline at end of file
diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher.png b/sample/src/main/res/mipmap-hdpi/ic_launcher.png
index 2a1b0a7..d20b458 100644
Binary files a/sample/src/main/res/mipmap-hdpi/ic_launcher.png and b/sample/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher.png b/sample/src/main/res/mipmap-mdpi/ic_launcher.png
index bf97b7b..c8b8311 100644
Binary files a/sample/src/main/res/mipmap-mdpi/ic_launcher.png and b/sample/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
index 9b1f833..cc73b3d 100644
Binary files a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png and b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
index ccbbe74..5bac4dd 100644
Binary files a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index 65900ce..67f4141 100644
Binary files a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml
index e17005e..1b6235b 100644
--- a/sample/src/main/res/values/colors.xml
+++ b/sample/src/main/res/values/colors.xml
@@ -2,7 +2,7 @@
#2B2E4A
#2B2E4A
- #E84545
+ #e1e0e0
#6fa7d7
#ca703f