Skip to content

Instantly share code, notes, and snippets.

@fdoyle
Last active August 29, 2015 14:09
Show Gist options
  • Save fdoyle/6f9f8d217565d7fea4fd to your computer and use it in GitHub Desktop.
Save fdoyle/6f9f8d217565d7fea4fd to your computer and use it in GitHub Desktop.
PullToRefreshLayout - Because guidelines are for scrubs.
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