Last active
August 29, 2015 14:09
-
-
Save fdoyle/6f9f8d217565d7fea4fd to your computer and use it in GitHub Desktop.
PullToRefreshLayout - Because guidelines are for scrubs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.derp.android.view; | |
import android.animation.Animator; | |
import android.content.Context; | |
import android.support.v4.widget.SwipeRefreshLayout; | |
import android.util.AttributeSet; | |
import android.view.LayoutInflater; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.widget.FrameLayout; | |
import android.widget.TextView; | |
import com.derp.android.R; | |
public class PullToRefreshLayout extends FrameLayout { | |
SwipeRefreshLayout.OnRefreshListener listener; | |
View child; | |
View prompt; | |
TextView promptText; | |
View promptIcon; | |
public PullToRefreshLayout(Context context) { | |
super(context); | |
setup(); | |
} | |
public PullToRefreshLayout(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
setup(); | |
} | |
public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
setup(); | |
} | |
public void setup() { | |
LayoutInflater.from(getContext()).inflate(R.layout.pull_to_refresh_background, this, true); | |
listener = new SwipeRefreshLayout.OnRefreshListener() { | |
@Override | |
public void onRefresh() { | |
throw new IllegalStateException("Add a listener"); | |
} | |
}; | |
} | |
public void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener) { | |
this.listener = listener; | |
} | |
@Override | |
protected void onFinishInflate() { | |
super.onFinishInflate(); | |
child = getChildAt(1); | |
prompt = getChildAt(0); | |
prompt.setVisibility(GONE); | |
promptText = (TextView) prompt.findViewById(R.id.ptr_text); | |
promptIcon = prompt.findViewById(R.id.ptr_icon); | |
} | |
Float lastY; | |
@Override | |
public boolean onInterceptTouchEvent(MotionEvent ev) { | |
View child = getChildAt(1); | |
float currentY = ev.getY(); | |
switch (ev.getAction()) { | |
case MotionEvent.ACTION_POINTER_DOWN: | |
return false; | |
case MotionEvent.ACTION_MOVE: | |
if (lastY == null) | |
lastY = currentY; | |
if (lastY < currentY && !child.canScrollVertically(-1)) { | |
lastY = currentY; | |
return true; | |
} else { | |
lastY = currentY; | |
return false; | |
} | |
case MotionEvent.ACTION_UP: | |
default: | |
lastY = null; | |
return false; | |
} | |
} | |
@Override | |
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { | |
//no | |
} | |
Float startY; | |
@Override | |
public boolean onTouchEvent(MotionEvent ev) { | |
float currentY = ev.getY(); | |
switch (ev.getAction()) { | |
case MotionEvent.ACTION_POINTER_DOWN: | |
break; | |
case MotionEvent.ACTION_MOVE: | |
if (startY == null) | |
startY = ev.getY(); | |
float delta = currentY - startY; | |
if (delta < 0) { | |
animateToStart(); | |
return false; | |
} | |
animateToPosition(delta); | |
if (isPulledFarEnough()) { | |
promptText.setText(R.string.ptr_release); | |
} else { | |
promptText.setText(R.string.ptr_pull); | |
} | |
break; | |
case MotionEvent.ACTION_UP: | |
case MotionEvent.ACTION_CANCEL: | |
animateToStart(); | |
if (isPulledFarEnough()) { | |
if (listener != null) | |
listener.onRefresh(); | |
} | |
startY = null; | |
break; | |
} | |
return true; | |
} | |
public boolean isPulledFarEnough() { | |
return prompt.getTranslationY() > 0; | |
} | |
private void animateToPosition(float position) { | |
prompt.setVisibility(View.VISIBLE); | |
child.animate().translationY(position).setDuration(0).start(); | |
prompt.animate().translationY(position - prompt.getHeight()).setDuration(0).setListener(null).start(); | |
promptIcon.setRotation(position / 2); | |
} | |
private void animateToStart() { | |
child.animate().translationY(0).setDuration(200).start(); | |
prompt.animate().translationY(0 - prompt.getHeight()).setDuration(200).setListener(new Animator.AnimatorListener() { | |
@Override | |
public void onAnimationStart(Animator animation) { | |
} | |
@Override | |
public void onAnimationEnd(Animator animation) { | |
if (prompt != null) | |
prompt.setVisibility(View.GONE); | |
} | |
@Override | |
public void onAnimationCancel(Animator animation) { | |
} | |
@Override | |
public void onAnimationRepeat(Animator animation) { | |
} | |
}).start(); | |
promptIcon.setRotation(0); | |
} | |
} | |
========================== | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:orientation="vertical" | |
android:padding="10dp" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content"> | |
<TextView | |
android:id="@+id/ptr_text" | |
android:text="@string/ptr_pull" | |
android:textSize="30sp" | |
android:layout_gravity="center" | |
android:gravity="center" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" /> | |
<ImageView | |
android:id="@+id/ptr_icon" | |
android:layout_gravity="center" | |
android:src="@drawable/refresh" | |
android:layout_width="48dp" | |
android:layout_height="48dp" /> | |
</LinearLayout> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment