Tap to refresh is visible all the time and gap is still visible on list view

喜你入骨 提交于 2019-12-03 09:15:53

Use this code instead

public class PullToRefreshListView extends ListView implements OnScrollListener {

//  private static final int TAP_TO_REFRESH = 1;
private static final int PULL_TO_REFRESH = 2;
private static final int RELEASE_TO_REFRESH = 3;
protected static final int REFRESHING = 4;

protected static final String TAG = "PullToRefreshListView";

private OnRefreshListener mOnRefreshListener;

/**
 * Listener that will receive notifications every time the list scrolls.
 */
private OnScrollListener mOnScrollListener;
protected LayoutInflater mInflater;

// header
private RelativeLayout mRefreshView;
private TextView mRefreshViewText;
private ImageView mRefreshViewImage;
private ProgressBar mRefreshViewProgress;
private TextView mRefreshViewLastUpdated;

protected int mCurrentScrollState;
protected int mRefreshState;

private RotateAnimation mFlipAnimation;
private RotateAnimation mReverseFlipAnimation;

private int mRefreshViewHeight;
private int mRefreshOriginalTopPadding;
private int mLastMotionY;

private boolean mBounceHack;

public PullToRefreshListView(Context context) {
    super(context);
    init(context);
}

public PullToRefreshListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public PullToRefreshListView(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

protected void init(Context context) {
    // Load all of the animations we need in code rather than through XML
    mFlipAnimation = new RotateAnimation(0, -180,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    mFlipAnimation.setInterpolator(new LinearInterpolator());
    mFlipAnimation.setDuration(250);
    mFlipAnimation.setFillAfter(true);
    mReverseFlipAnimation = new RotateAnimation(-180, 0,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f,
            RotateAnimation.RELATIVE_TO_SELF, 0.5f);
    mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
    mReverseFlipAnimation.setDuration(250);
    mReverseFlipAnimation.setFillAfter(true);

    mInflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // header
    mRefreshView = (RelativeLayout) mInflater.inflate(
            R.layout.pull_to_refresh_header, this, false);
    mRefreshViewText = (TextView) mRefreshView
            .findViewById(R.id.pull_to_refresh_text);
    mRefreshViewImage = (ImageView) mRefreshView
            .findViewById(R.id.pull_to_refresh_image);
    mRefreshViewProgress = (ProgressBar) mRefreshView
            .findViewById(R.id.pull_to_refresh_progress);
    mRefreshViewLastUpdated = (TextView) mRefreshView
            .findViewById(R.id.pull_to_refresh_updated_at);

    mRefreshViewImage.setMinimumHeight(50);
    mRefreshView.setOnClickListener(new OnClickRefreshListener());
    mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();

    mRefreshState = PULL_TO_REFRESH;

    addHeaderView(mRefreshView);

    super.setOnScrollListener(this);

    measureView(mRefreshView);
    mRefreshViewHeight = mRefreshView.getMeasuredHeight();
}

@Override
protected void onAttachedToWindow() {
    //have to ask super to attach to window, otherwise it won't scroll in jelly bean.
    super.onAttachedToWindow();
    setSelection(1);
}

@Override
public void setAdapter(ListAdapter adapter) {
    super.setAdapter(adapter);

    setSelection(1);
}

/**
 * Set the listener that will receive notifications every time the list
 * scrolls.
 * 
 * @param l
 *            The scroll listener.
 */
@Override
public void setOnScrollListener(AbsListView.OnScrollListener l) {
    mOnScrollListener = l;
}

/**
 * Register a callback to be invoked when this list should be refreshed.
 * 
 * @param onRefreshListener
 *            The callback to run.
 */
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
    mOnRefreshListener = onRefreshListener;
}

/**
 * Set a text to represent when the list was last updated.
 * 
 * @param lastUpdated
 *            Last updated at.
 */
public void setLastUpdated(CharSequence lastUpdated) {
    if (lastUpdated != null) {
        mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
        mRefreshViewLastUpdated.setText(lastUpdated);
    } else {
        mRefreshViewLastUpdated.setVisibility(View.GONE);
    }
}

@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
    final int y = (int) event.getY();
    mBounceHack = false;

    switch (event.getAction()) {
    case MotionEvent.ACTION_UP:
        if (!isVerticalScrollBarEnabled()) {
            setVerticalScrollBarEnabled(true);
        }
        if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
            if ((mRefreshView.getBottom() >= mRefreshViewHeight || mRefreshView
                    .getTop() >= 0) && mRefreshState == RELEASE_TO_REFRESH) {
                // Initiate the refresh
                mRefreshState = REFRESHING;
                prepareForRefresh();
                onRefresh();
            } else if (mRefreshView.getBottom() < mRefreshViewHeight
                    || mRefreshView.getTop() <= 0) {
                // Abort refresh and scroll down below the refresh view
                resetHeader();
                setSelection(1);
            }
        }
        break;
    case MotionEvent.ACTION_DOWN:
        mLastMotionY = y;
        break;
    case MotionEvent.ACTION_MOVE:
        applyHeaderPadding(event);
        break;
    }
    return super.onTouchEvent(event);
}

private void applyHeaderPadding(MotionEvent ev) {
    // getHistorySize has been available since API 1
    int pointerCount = ev.getHistorySize();

    for (int p = 0; p < pointerCount; p++) {
//          if (mRefreshState == RELEASE_TO_REFRESH) {
            if (isVerticalFadingEdgeEnabled()) {
                setVerticalScrollBarEnabled(false);
            }

            int historicalY = (int) ev.getHistoricalY(p);

            // Calculate the padding to apply, we divide by 1.7 to
            // simulate a more resistant effect during pull.
            int topPadding = (int) (((historicalY - mLastMotionY) - mRefreshViewHeight) / 1.7);

            mRefreshView.setPadding(mRefreshView.getPaddingLeft(),
                    topPadding, mRefreshView.getPaddingRight(),
                    mRefreshView.getPaddingBottom());
        }
//      }
}

/**
 * Sets the header padding back to original size.
 */
private void resetHeaderPadding() {
    mLastMotionY = 0;
    mRefreshView.setPadding(mRefreshView.getPaddingLeft(),
            mRefreshOriginalTopPadding, mRefreshView.getPaddingRight(),
            mRefreshView.getPaddingBottom());
}

/**
 * Resets the header to the original state.
 */
private void resetHeader() {
//      if (mRefreshState != TAP_TO_REFRESH) {
        mRefreshState = PULL_TO_REFRESH;

        resetHeaderPadding();

        // Set refresh view text to the pull label
        mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
        // Replace refresh drawable with arrow drawable
        mRefreshViewImage
                .setImageResource(R.drawable.ic_pulltorefresh_arrow);
        // Clear the full rotation animation
        mRefreshViewImage.clearAnimation();
        // Hide progress bar and arrow.
        mRefreshViewImage.setVisibility(View.GONE);
        mRefreshViewProgress.setVisibility(View.GONE);
//      }
}

private void measureView(View child) {
    ViewGroup.LayoutParams p = child.getLayoutParams();
    if (p == null) {
        p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
    }

    int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
    int lpHeight = p.height;
    int childHeightSpec;
    if (lpHeight > 0) {
        childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
                MeasureSpec.EXACTLY);
    } else {
        childHeightSpec = MeasureSpec.makeMeasureSpec(0,
                MeasureSpec.UNSPECIFIED);
    }
    child.measure(childWidthSpec, childHeightSpec);
}

public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
    // When the refresh view is completely visible, change the text to say
    // "Release to refresh..." and flip the arrow drawable.
    if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
            && mRefreshState != REFRESHING) {
        if (firstVisibleItem == 0) {
            mRefreshViewImage.setVisibility(View.VISIBLE);
            if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20 || mRefreshView
                    .getTop() >= 0) && mRefreshState != RELEASE_TO_REFRESH) {
                mRefreshViewText
                        .setText(R.string.pull_to_refresh_release_label);
                mRefreshViewImage.clearAnimation();
                mRefreshViewImage.startAnimation(mFlipAnimation);
                mRefreshState = RELEASE_TO_REFRESH;
            } else if (mRefreshView.getBottom() < mRefreshViewHeight + 20
                    && mRefreshState != PULL_TO_REFRESH) {
                mRefreshViewText
                        .setText(R.string.pull_to_refresh_pull_label);
//                  if (mRefreshState != TAP_TO_REFRESH) {
                    mRefreshViewImage.clearAnimation();
                    mRefreshViewImage.startAnimation(mReverseFlipAnimation);
//                  }
                mRefreshState = PULL_TO_REFRESH;
            }
        } else {
            mRefreshViewImage.setVisibility(View.GONE);
            resetHeader();
        }
    } else if (mCurrentScrollState == SCROLL_STATE_FLING
            && firstVisibleItem == 0 && mRefreshState != REFRESHING) {
        setSelection(1);
        mBounceHack = true;
    } else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
        setSelection(1);
    }

    if (mOnScrollListener != null) {
        mOnScrollListener.onScroll(view, firstVisibleItem,
                visibleItemCount, totalItemCount);
    }
}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    mCurrentScrollState = scrollState;

    if (mCurrentScrollState == SCROLL_STATE_IDLE) {
        mBounceHack = false;
    }

    if (mOnScrollListener != null) {
        mOnScrollListener.onScrollStateChanged(view, scrollState);
    }

}

public void prepareForRefresh() {
    resetHeaderPadding();

    mRefreshViewImage.setVisibility(View.GONE);
    // We need this hack, otherwise it will keep the previous drawable.
    mRefreshViewImage.setImageDrawable(null);
    mRefreshViewProgress.setVisibility(View.VISIBLE);

    // Set refresh view text to the refreshing label
    mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);

    mRefreshState = REFRESHING;
}

public void onRefresh() {
    Log.d(TAG, "onRefresh");

    if (mOnRefreshListener != null) {
        mOnRefreshListener.onRefresh();
    }
}

/**
 * Resets the list to a normal state after a refresh.
 * 
 * @param lastUpdated
 *            Last updated at.
 */
public void onRefreshComplete(CharSequence lastUpdated) {
    setLastUpdated(lastUpdated);
    onRefreshComplete();
}

/**
 * Resets the list to a normal state after a refresh.
 */
public void onRefreshComplete() {
    Log.d(TAG, "onRefreshComplete");

    resetHeader();

    // If refresh view is visible when loading completes, scroll down to
    // the next item.
    if (mRefreshView.getBottom() > 0) {
        invalidateViews();
        setSelection(1);
    }
}

/**
 * Invoked when the refresh view is clicked on. This is mainly used when
 * there's only a few items in the list and it's not possible to drag the
 * list.
 */
private class OnClickRefreshListener implements OnClickListener {

    public void onClick(View v) {
        if (mRefreshState != REFRESHING) {
            prepareForRefresh();
            onRefresh();
        }
    }

}

/**
 * Interface definition for a callback to be invoked when list should be
 * refreshed.
 */
public interface OnRefreshListener {
    /**
     * Called when the list should be refreshed.
     * <p>
     * A call to {@link PullToRefreshListView #onRefreshComplete()} is
     * expected to indicate that the refresh has completed.
     */
    public void onRefresh();
}

}

also set the visibility to gone in the pull_to_refresh_header.xml in your library layout if you have it (android:id="@+id/pull_to_refresh_text")

<TextView
    android:id="@+id/pull_to_refresh_text"
    android:text="@string/pull_to_refresh_pull_label"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:textStyle="bold"
    android:paddingTop="5dip"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:gravity="center"
    android:visibility="gone"
    />

enjoy!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!