Skip to content

Commit

Permalink
2.0 init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
imallan committed Aug 24, 2016
1 parent 254fc02 commit c549cf0
Show file tree
Hide file tree
Showing 13 changed files with 361 additions and 141 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ android {

defaultConfig {
applicationId "uk.co.imallan.jellyrefreshlayout"
minSdkVersion 19
minSdkVersion 21
targetSdkVersion 24
versionCode 1
versionName "1.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,43 @@
package uk.co.imallan.jellyrefreshlayout;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import uk.co.imallan.jellyrefresh.JellyRefreshLayout;
import uk.co.imallan.jellyrefresh.PullToRefreshLayout;

public class MainActivity extends AppCompatActivity {

private JellyRefreshLayout mJellyLayout;

@SuppressLint("InflateParams")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setTitle("Jelly");
final PullToRefreshLayout jellyLayout = (PullToRefreshLayout) findViewById(R.id.jelly_refresh);
jellyLayout.setPullToRefreshListener(new PullToRefreshLayout.PullToRefreshListener() {
mJellyLayout = (JellyRefreshLayout) findViewById(R.id.jelly_refresh);
mJellyLayout.setPullToRefreshListener(new PullToRefreshLayout.PullToRefreshListener() {
@Override
public void onRefresh(PullToRefreshLayout pullToRefreshLayout) {
pullToRefreshLayout.postDelayed(new Runnable() {
@Override
public void run() {
jellyLayout.finishRefreshing();
mJellyLayout.setRefreshing(false);
}
}, 3000);
}
});
// new JellyRefreshLayout.JellyRefreshListener() {
// @Override
// public void onRefresh(final JellyRefreshLayout jellyRefreshLayout) {
// jellyRefreshLayout.postDelayed(new Runnable() {
// @Override
// public void run() {
// jellyRefreshLayout.finishRefreshing();
// }
// }, 3000);
// }
// });
View loadingView = LayoutInflater.from(this).inflate(R.layout.view_loading, null);
mJellyLayout.setLoadingView(loadingView);
}

@Override
Expand All @@ -57,7 +55,19 @@ public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
if (id == R.id.action_refresh) {
mJellyLayout.post(new Runnable() {
@Override
public void run() {
mJellyLayout.setRefreshing(true);
}
});
mJellyLayout.postDelayed(new Runnable() {
@Override
public void run() {
mJellyLayout.setRefreshing(false);
}
}, 3000);
return true;
}

Expand Down
9 changes: 6 additions & 3 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
Expand All @@ -20,9 +21,11 @@
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:elevation="4dp"
android:text="@string/loading">
<!--android:textColor="@android:color/white"-->
<!--app:jellyColor="@color/primary">-->
android:text="@string/loading"
app:headerHeight="48dp"
app:jellyColor="@color/primary"
app:pullHeight="160dp"
app:triggerHeight="108dp">

<ScrollView
android:layout_width="match_parent"
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/res/layout/view_loading.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="Loading..."
android:textColor="@android:color/white"
android:textSize="20sp"/>
12 changes: 8 additions & 4 deletions app/src/main/res/menu/menu_main.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="@+id/action_refresh"
android:orderInCategory="100"
android:title="@string/action_refresh"
app:showAsAction="never"/>
</menu>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
<string name="loading">Loading…</string>
<string name="action_settings">Settings</string>
<string name="lorem_ipsum">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras congue magna felis, ac maximus velit fringilla non. Curabitur eleifend velit risus. Donec tincidunt arcu id enim faucibus, ac maximus neque fringilla. In egestas sed ipsum et commodo. Duis tincidunt sollicitudin libero eget semper. Ut fermentum quam id ipsum dictum, eu pulvinar nunc maximus. Praesent erat tellus, finibus vel nulla accumsan, condimentum fermentum ligula. Nullam finibus posuere porttitor. In dui dolor, gravida ac nisi sit amet, rutrum fringilla ex. Curabitur eu lorem sed magna dignissim egestas. Duis viverra dui quis mauris auctor, sed feugiat arcu aliquet. Maecenas feugiat ac odio ac finibus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc ultricies placerat ante, id semper sem convallis et. Praesent finibus maximus elementum. Phasellus sed malesuada massa. Etiam eleifend diam maximus, ultricies enim et, congue ligula. Vestibulum at accumsan diam, vitae vehicula tellus. Curabitur ut nibh commodo, condimentum enim id, semper nisi. Aenean at eleifend diam. Ut consectetur eleifend urna ut euismod. Proin convallis gravida ligula id placerat. Aenean facilisis magna ut odio eleifend dictum. Suspendisse faucibus, ipsum eu varius cursus, orci ante luctus turpis, eget egestas justo augue id orci. Donec tincidunt laoreet neque. Vivamus pharetra erat orci, non rhoncus nunc placerat at. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse potenti. Vivamus accumsan metus ut finibus blandit. Quisque aliquet quam in tempus auctor. Suspendisse nibh tortor, dapibus vel quam accumsan, gravida ornare velit. Ut ut nunc pulvinar, pharetra ipsum quis, aliquet turpis. Nam eu massa lacus. Pellentesque quis tortor ipsum. Ut condimentum, purus sit amet maximus efficitur, ex sem lacinia quam, eget convallis dui leo a dui. Mauris posuere purus mauris, quis tristique diam hendrerit ut. Praesent tempus purus sed risus aliquet ultrices. Cras vitae maximus metus, quis convallis eros. Cras dignissim nisl ut magna efficitur convallis. In faucibus leo quis sollicitudin feugiat. Proin nec dui justo. Fusce in porta quam. Morbi ac tincidunt sem. Donec venenatis suscipit nulla, ut porta nibh tincidunt tincidunt. Curabitur et aliquet arcu, ut pharetra neque. Nam sagittis rutrum ante ut ultrices. Sed placerat felis vitae mauris ornare interdum. Cras non dolor convallis, tempus odio quis, finibus tortor. Nunc placerat sit amet lacus in ornare. Maecenas ultricies augue in magna placerat posuere. Interdum et malesuada fames ac ante ipsum primis in faucibus. Suspendisse venenatis nisl et velit venenatis tempus. Sed sed urna at turpis dictum fringilla volutpat ac erat. Cras efficitur orci tincidunt, rhoncus ante at, interdum est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur dapibus est a nulla porttitor, sed scelerisque nunc facilisis. Proin tempus, mauris et condimentum maximus, mi risus tempor nisi, non posuere justo libero vel arcu. Praesent commodo feugiat orci ac volutpat. Nullam vulputate pulvinar mauris id pellentesque.</string>
<string name="action_refresh">Refresh</string>
</resources>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'me.tatarka:gradle-retrolambda:3.2.0'
classpath 'me.tatarka:gradle-retrolambda:3.2.5'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand Down
2 changes: 2 additions & 0 deletions jellyrefresh/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.0'

retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:2.3.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,20 @@
import android.support.annotation.ColorInt;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;

public class JellyLayout extends FrameLayout {
private static final String TAG = "JellyLayout";
class JellyLayout extends FrameLayout {

private Paint mPaint;
private Path mPath;
@ColorInt
private int mColor = Color.GRAY;
// FIXME: 23/08/2016 hardcoded
private int mHeaderHeight = 200;
private int mPullHeight = 400;
private ViewOutlineProvider mViewOutlineProvider;
private float mPointX;
float mHeaderHeight = 0;
float mPullHeight = 0;

public JellyLayout(Context context) {
this(context, null);
Expand Down Expand Up @@ -71,34 +68,38 @@ public void setPointX(float pointX) {
if (needInvalidate) invalidate();
}


@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final int width = canvas.getWidth();
Log.d(TAG, "onDraw: height: " + getHeight());

mHeaderHeight = getHeight() / 2;
mPullHeight = getHeight();
drawPulling(canvas);
}

private void drawPulling(Canvas canvas) {

final int width = canvas.getWidth();
final float mDisplayX = (mPointX - width / 2f) * 0.5f + width / 2f;
mPaint.setColor(mColor);

float mDisplayX = (mPointX - width / 2f) * 0.5f + width / 2f;
int headerHeight = (int) mHeaderHeight;
int pullHeight = (int) mPullHeight;

mPath.rewind();
mPath.moveTo(0, 0);
mPath.lineTo(0, mHeaderHeight);
mPath.quadTo(mDisplayX, mPullHeight, width, mHeaderHeight);
mPath.lineTo(0, headerHeight);
mPath.quadTo(mDisplayX, pullHeight, width, headerHeight);
mPath.lineTo(width, 0);
mPath.close();

canvas.drawPath(mPath, mPaint);

canvas.drawLine(0, mPullHeight, width, mPullHeight, mPaint);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setOutlineProvider(mViewOutlineProvider);
}

}

public void setHeaderHeight(float headerHeight) {
mHeaderHeight = headerHeight;
}
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,141 @@
package uk.co.imallan.jellyrefresh;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

public class JellyRefreshLayout extends PullToRefreshLayout {
public class JellyRefreshLayout extends PullToRefreshLayout implements PullToRefreshLayout.PullToRefreshPullingListener {

private JellyLayout mJellyLayout;
private View mLoadingView;

public JellyRefreshLayout(Context context) {
super(context);
init();
this(context, null);
}

public JellyRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
this(context, attrs, 0);
}

public JellyRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
resolveAttributes(attrs);
}

private void resolveAttributes(@Nullable AttributeSet attrs) {
if (attrs == null) return;
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.JellyRefreshLayout);
try {
int color = a.getColor(R.styleable.JellyRefreshLayout_jellyColor, Color.WHITE);
float height = a.getDimension(R.styleable.JellyRefreshLayout_headerHeight, mHeaderHeight);
float pullHeight = a.getDimension(R.styleable.JellyRefreshLayout_pullHeight, mPullHeight);
float triggerHeight = a.getDimension(R.styleable.JellyRefreshLayout_pullHeight, mTriggerHeight);
mJellyLayout.setColor(color);
mHeaderHeight = height;
mPullHeight = pullHeight;
mTriggerHeight = triggerHeight;
} finally {
a.recycle();
}
}

@Override
public void setRefreshing(boolean refreshing) {
if (refreshing) {
post(() -> mJellyLayout.setPointX(mJellyLayout.getWidth() / 2));
}
super.setRefreshing(refreshing);
}

private void init() {
JellyLayout jellyLayout = new JellyLayout(getContext());
mJellyLayout = new JellyLayout(getContext());

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
jellyLayout.setElevation(getElevation());
mJellyLayout.setElevation(getElevation());
}
setHeaderView(jellyLayout);
setPullingListener(new PullToRefreshPullingListener() {
@Override
public void onPulling(PullToRefreshLayout pullToRefreshLayout, float fraction, float pointXPosition) {
jellyLayout.setPointX(pointXPosition);
}

@Override
public void onReleasing(PullToRefreshLayout pullToRefreshLayout, float fraction) {

}
});
setHeaderView(mJellyLayout);
setPullingListener(this);
}

@Override
protected void onStateChanged(@State int newState) {
switch (newState) {
case STATE_REFRESHING:
if (mLoadingView != null) {
mLoadingView.setVisibility(VISIBLE);
}
break;
case STATE_REFRESHING_SETTLING:
if (mLoadingView != null) {
mLoadingView.setVisibility(VISIBLE);
mLoadingView.setTranslationY(mPullHeight);
mLoadingView.animate().translationY(0).setDuration(150).start();
}
break;
case STATE_DRAGGING:
case STATE_IDLE:
case STATE_SETTLING:
case STATE_RELEASING:
if (mLoadingView != null) {
mLoadingView.setVisibility(INVISIBLE);
}
break;
}
}

@Override
public void onPulling(float fraction, float pointXPosition) {
mJellyLayout.setPointX(pointXPosition);
}

@Override
public void onTranslationYChanged(float translationY) {
switch (getState()) {
case STATE_DRAGGING:
case STATE_RELEASING:
mJellyLayout.mHeaderHeight = Math.min(translationY / 2, mHeaderHeight);
mJellyLayout.mPullHeight = translationY;
break;
case STATE_REFRESHING:
mJellyLayout.mHeaderHeight = mHeaderHeight;
mJellyLayout.mPullHeight = mHeaderHeight;
break;
case STATE_SETTLING:
mJellyLayout.mHeaderHeight = translationY;
mJellyLayout.mPullHeight = translationY;
break;
case STATE_REFRESHING_SETTLING:
mJellyLayout.mHeaderHeight = mHeaderHeight;
if (translationY > mHeaderHeight) {
float dy = translationY - mHeaderHeight;
float acceleratedHeight = translationY - 2 * dy;
mJellyLayout.mPullHeight = Math.max(mHeaderHeight, acceleratedHeight);
} else {
mJellyLayout.mPullHeight = mHeaderHeight;
}
break;
case STATE_IDLE:
mJellyLayout.mHeaderHeight = 0;
mJellyLayout.mPullHeight = 0;
break;
}
mJellyLayout.postInvalidate();
}

public void setLoadingView(View view) {
FrameLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
mJellyLayout.addView(view, params);
view.setVisibility(INVISIBLE);
mLoadingView = view;
}
}
Loading

0 comments on commit c549cf0

Please sign in to comment.