【问题标题】:Listview Pull to refresh Library and adding Header viewListview 拉动刷新库并添加标题视图
【发布时间】:2025-12-03 13:55:01
【问题描述】:

我做了拉刷新列表视图 为此我制作了自定义组件列表视图 添加标题视图时我遇到了问题

或者任何朋友可以告诉我为什么会这样。或者一些朋友在此之前做过

当轻微滚动时,我需要在列表视图中添加搜索栏的标题,如果滚动更多,则像拉动刷新一样工作

请检查以下课程

package com.app.refreshableList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.app.XXXXXX.R;
import com.google.android.gms.internal.el;

public class RefreshableListView extends ListView {

Boolean isScrool = false;
private View mHeaderContainer = null;
private View mHeaderView = null;
private ImageView mArrow = null;
private ProgressBar mProgress = null;
private TextView mText = null;
private float mY = 0;
private float mHistoricalY = 0;
private int mHistoricalTop = 0;
private int mInitialHeight = 0;
private boolean mFlag = false;
private boolean mArrowUp = false;
private boolean mIsRefreshing = false;
private int mHeaderHeight = 0;
private OnRefreshListener mListener = null;

private static final int REFRESH = 0;
private static final int NORMAL = 1;
private static final int HEADER_HEIGHT_DP = 62;
private static final String TAG = RefreshableListView.class.getSimpleName();

private ListViewObserver mObserver;
private View mTrackedChild;
private int mTrackedChildPrevPosition;
private int mTrackedChildPrevTop;
OnTouchListener touch;

View vHeader;

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);
    if (mTrackedChild == null) {
        if (getChildCount() > 0) {
            mTrackedChild = getChildInTheMiddle();
            mTrackedChildPrevTop = mTrackedChild.getTop();
            mTrackedChildPrevPosition = getPositionForView(mTrackedChild);
        }
    } else {
        boolean childIsSafeToTrack = mTrackedChild.getParent() == this
                && getPositionForView(mTrackedChild) == mTrackedChildPrevPosition;
        if (childIsSafeToTrack) {
            int top = mTrackedChild.getTop();
            if (mObserver != null) {
                float deltaY = top - mTrackedChildPrevTop;
                mObserver.onScroll(deltaY);

            }
            mTrackedChildPrevTop = top;
        } else {
            mTrackedChild = null;
        }
    }

}

private View getChildInTheMiddle() {
    return getChildAt(getChildCount() / 2);
}

public void setObserver(ListViewObserver observer) {
    mObserver = observer;
}

public RefreshableListView(final Context context) {
    super(context);
    initialize();
}

public RefreshableListView(final Context context, final AttributeSet attrs) {
    super(context, attrs);
    initialize();
}

public RefreshableListView(final Context context, final AttributeSet attrs,
        final int defStyle) {
    super(context, attrs, defStyle);
    initialize();
}

public void setOnRefreshListener(final OnRefreshListener l) {
    mListener = l;
}

@Override
public void setOnTouchListener(OnTouchListener l) {
    // TODO Auto-generated method stub
    super.setOnTouchListener(l);
}

public void completeRefreshing() {
    mProgress.setVisibility(View.INVISIBLE);
    mArrow.setVisibility(View.VISIBLE);
    mHandler.sendMessage(mHandler.obtainMessage(NORMAL, mHeaderHeight, 0));
    mIsRefreshing = false;
    invalidateViews();
}

@Override
public boolean onInterceptTouchEvent(final MotionEvent ev) {
    switch (ev.getAction()) {
    case MotionEvent.ACTION_DOWN:
        mHandler.removeMessages(REFRESH);
        mHandler.removeMessages(NORMAL);
        mY = mHistoricalY = ev.getY();
        if (mHeaderContainer.getLayoutParams() != null) {
            mInitialHeight = mHeaderContainer.getLayoutParams().height;
        }
        // if (isScrool == true) {
        //
        // } else {
        // isScrool = true;
        // addHeaderView(vHeader);
        // // setSelectionAfterHeaderView();
        // // Animation anim =
        // // AnimationUtils.loadAnimation(
        // // getContext(), R.anim.bounce_animation);
        // // startAnimation(anim);
        // // setSelectionAfterHeaderView();
        // // setOverScrollMode(View.OVER_SCROLL_NEVER);
        // // setSelectionFromTop(0, 0);
        // // smoothScrollToPosition(getChildAt(0).getTop()
        // // - vHeader.getHeight());
        // // bottom_layout.setVisibility(View.VISIBLE);
        // }
        break;
    }
    return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(final MotionEvent ev) {
    switch (ev.getAction()) {
    case MotionEvent.ACTION_MOVE:
        mHistoricalTop = getChildAt(0).getTop();
        break;
    case MotionEvent.ACTION_UP:
        if (!mIsRefreshing) {
            if (mArrowUp) {
                startRefreshing();
                mHandler.sendMessage(mHandler.obtainMessage(REFRESH,
                        (int) (ev.getY() - mY) / 2 + mInitialHeight, 0));
            } else {
                if (getChildAt(0).getTop() == 0) {
                    mHandler.sendMessage(mHandler.obtainMessage(NORMAL,
                            (int) (ev.getY() - mY) / 2 + mInitialHeight, 0));
                }
            }
        } else {
            mHandler.sendMessage(mHandler.obtainMessage(REFRESH,
                    (int) (ev.getY() - mY) / 2 + mInitialHeight, 0));
        }
        mFlag = false;
        break;

    }
    return super.onTouchEvent(ev);
}

@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
        int scrollY, int scrollRangeX, int scrollRangeY,
        int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
    // TODO Auto-generated method stub

    Log.e("overscrolled", deltaX + "//" + deltaY + "//" + scrollX + "//"
            + scrollY + "//");

    return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
            scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY,
            isTouchEvent);
}

@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_MOVE
            && getFirstVisiblePosition() == 0) {
        float direction = ev.getY() - mHistoricalY;
        int height = (int) (ev.getY() - mY) / 2 + mInitialHeight;
        if (height < 0) {
            height = 0;
        }

        float deltaY = Math.abs(mY - ev.getY());
        ViewConfiguration config = ViewConfiguration.get(getContext());
        if (deltaY > config.getScaledTouchSlop()) {

            // Scrolling downward
            if (direction > 0) {
                // Refresh bar is extended if top pixel of the first item is
                // visible
                if (getChildAt(0) != null) {
                    if (getChildAt(0).getTop() == 0) {
                        if (mHistoricalTop < 0) {

                            // mY = ev.getY(); // TODO works without
                            // this?mHistoricalTop = 0;
                        }
                        if (isScrool == true) {

                        } else {
                            isScrool = true;
                            addHeaderView(vHeader);

                            Handler hn = new Handler();

                            hn.postDelayed(new Runnable() {

                                @Override
                                public void run() {
                                    // TODO Auto-generated method stub
                                    smoothScrollByOffset(1);

                                }
                            }, 50);
                        }
                        // Animation anim =
                        // AnimationUtils.loadAnimation(
                        // getContext(), R.anim.bounce_animation);
                        // startAnimation(anim);
                        // setSelectionAfterHeaderView();
                        // setOverScrollMode(View.OVER_SCROLL_NEVER);
                        // setSelectionFromTop(0, 0);
                        // smoothScrollToPosition(getChildAt(0).getTop()
                        // - vHeader.getHeight());
                        // bottom_layout.setVisibility(View.VISIBLE);
                        // }
                        // Extends refresh bar

                        /*****
                         * commented by me on 10-09-2014
                         */
                        Log.e("selected index ",
                                String.valueOf(getScrollY()) + "//"
                                        + getMaxScrollAmount() + "//"
                                        + getAdapter().getCount());
                        setHeaderHeight(height);

                        // Stop list scroll to prevent the list from
                        // overscrolling
                        ev.setAction(MotionEvent.ACTION_CANCEL);
                        mFlag = false;
                    }
                }

            } else if (direction < 0) {
                // Scrolling upward

                // Refresh bar is shortened if top pixel of the first item
                // is
                // visible
                if (getChildAt(0) != null) {
                    if (getChildAt(0).getTop() == 0) {
                        setHeaderHeight(height);

                        // If scroll reaches top of the list, list scroll is
                        // enabled
                        if (getChildAt(1) != null
                                && getChildAt(1).getTop() <= 1 && !mFlag) {
                            ev.setAction(MotionEvent.ACTION_DOWN);
                            mFlag = true;
                        }
                    }
                }
            }
        }

        mHistoricalY = ev.getY();
    }
    try {
        return super.dispatchTouchEvent(ev);
    } catch (Exception e) {
        return false;
    }
}

@Override
public boolean performItemClick(final View view, final int position,
        final long id) {
    if (position == 0) {
        // This is the refresh header element
        return true;
    } else {
        return super.performItemClick(view, position - 1, id);
    }
}

private void initialize() {

    LayoutInflater inflator = (LayoutInflater) getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    vHeader = inflator.inflate(R.layout.search_header, null);
    LayoutInflater inflater = (LayoutInflater) getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mHeaderContainer = inflater.inflate(R.layout.refreshable_list_header,
            null);
    mHeaderView = mHeaderContainer
            .findViewById(R.id.refreshable_list_header);
    mArrow = (ImageView) mHeaderContainer
            .findViewById(R.id.refreshable_list_arrow);
    mProgress = (ProgressBar) mHeaderContainer
            .findViewById(R.id.refreshable_list_progress);
    mText = (TextView) mHeaderContainer
            .findViewById(R.id.refreshable_list_text);
    addHeaderView(mHeaderContainer);

    mHeaderHeight = (int) (HEADER_HEIGHT_DP * getContext().getResources()
            .getDisplayMetrics().density);

    setHeaderHeight(0);
}

private void setHeaderHeight(final int height) {
    if (height <= 1) {
        mHeaderView.setVisibility(View.GONE);
    } else {
        mHeaderView.setVisibility(View.VISIBLE);
    }

    // Extends refresh bar
    LayoutParams lp = (LayoutParams) mHeaderContainer.getLayoutParams();
    if (lp == null) {
        lp = new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.WRAP_CONTENT);
    }
    lp.height = height;
    mHeaderContainer.setLayoutParams(lp);

    // Refresh bar shows up from bottom to top
    LinearLayout.LayoutParams headerLp = (LinearLayout.LayoutParams) mHeaderView
            .getLayoutParams();
    if (headerLp == null) {
        headerLp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.WRAP_CONTENT);
    }

    headerLp.topMargin = -mHeaderHeight + height;

    mHeaderView.setLayoutParams(headerLp);

    if (!mIsRefreshing) {
        // If scroll reaches the trigger line, start refreshing
        if (height > mHeaderHeight && !mArrowUp) {
            mArrow.startAnimation(AnimationUtils.loadAnimation(
                    getContext(), R.anim.rotate));
            mText.setText("Release to update");
            rotateArrow();
            mArrowUp = true;
        } else if (height < mHeaderHeight && mArrowUp) {
            mArrow.startAnimation(AnimationUtils.loadAnimation(
                    getContext(), R.anim.rotate));
            mText.setText("Pull down to update");
            rotateArrow();
            mArrowUp = false;

        } else {

        }
    }
}

private void rotateArrow() {
    Drawable drawable = mArrow.getDrawable();
    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    canvas.save();
    canvas.rotate(180.0f, canvas.getWidth() / 2.0f,
            canvas.getHeight() / 2.0f);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight());
    drawable.draw(canvas);
    canvas.restore();
    mArrow.setImageBitmap(bitmap);
}

private void startRefreshing() {
    mArrow.setVisibility(View.INVISIBLE);
    mProgress.setVisibility(View.VISIBLE);
    mText.setText("Loading...");
    mIsRefreshing = true;

    if (mListener != null) {
        mListener.onRefresh(this);
    }
    setSelection(0);
}

private final Handler mHandler = new Handler() {

    @Override
    public void handleMessage(final Message msg) {
        super.handleMessage(msg);

        int limit = 0;
        switch (msg.what) {
        case REFRESH:
            limit = mHeaderHeight;
            break;
        case NORMAL:
            limit = 0;
            break;
        }

        // Elastic scrolling
        if (msg.arg1 >= limit) {
            setHeaderHeight(msg.arg1);
            int displacement = (msg.arg1 - limit) / 10;
            if (displacement == 0) {
                mHandler.sendMessage(mHandler.obtainMessage(msg.what,
                        msg.arg1 - 1, 0));
            } else {
                mHandler.sendMessage(mHandler.obtainMessage(msg.what,
                        msg.arg1 - displacement, 0));
            }
        }
    }

};

public interface OnRefreshListener {
    public void onRefresh(RefreshableListView listView);
}

public static interface ListViewObserver {
    public void onScroll(float deltaY);
}
}

这里是我的代码,我在其中添加标题以进行搜索,但是当我添加 listview 时,芳香地向下滚动。 我确实调试了很多,但无法弄清楚。

    // Scrolling downward
            if (direction > 0) {
                // Refresh bar is extended if top pixel of the first item is
                // visible
                if (getChildAt(0) != null) {
                    if (getChildAt(0).getTop() == 0) {
                        if (mHistoricalTop < 0) {

                            // mY = ev.getY(); // TODO works without
                            // this?mHistoricalTop = 0;
                        }
                        if (isScrool == true) {

                        } else {
                            isScrool = true;
                            // adding header.
                            addHeaderView(vHeader);

                            Handler hn = new Handler();

                            hn.postDelayed(new Runnable() {

                                @Override
                                public void run() {
                                    // TODO Auto-generated method stub
                                    smoothScrollByOffset(1);

                                }
                            }, 50);
                        }
                        // Extends refresh bar

                        /*****
                         * commented by me on 10-09-2014
                         */
                        Log.e("selected index ",
                                String.valueOf(getScrollY()) + "//"
                                        + getMaxScrollAmount() + "//"
                                        + getAdapter().getCount());
                        setHeaderHeight(height);

                        // Stop list scroll to prevent the list from
                        // overscrolling
                        ev.setAction(MotionEvent.ACTION_CANCEL);
                        mFlag = false;
                    }
                }

【问题讨论】:

    标签: android listview android-listview android-custom-view


    【解决方案1】:

    我对你的代码做了一些修改,它对我有用

    请检查以下课程

    公共类 RefreshableListView 扩展 ListView {

    private TextView search_text;
    private Button distance_spinner;
    Boolean isScrool = false;
    Boolean isFirst = false;
    private View mHeaderContainer = null;
    private View mHeaderView = null;
    private ImageView mArrow = null;
    private ProgressBar mProgress = null;
    private TextView mText = null;
    private float mY = 0;
    private float mHistoricalY = 0;
    private int mHistoricalTop = 0;
    private int mInitialHeight = 0;
    private boolean mFlag = false;
    private boolean mArrowUp = false;
    private boolean mIsRefreshing = false;
    private int mHeaderHeight = 0;
    private OnRefreshListener mListener = null;
    
    private static final int REFRESH = 0;
    private static final int NORMAL = 1;
    private static final int HEADER_HEIGHT_DP = 62;
    @SuppressWarnings("unused")
    private static final String TAG = RefreshableListView.class.getSimpleName();
    
    OnTouchListener touch;
    
    public static View vHeader;
    View vheaders;
    
    public RefreshableListView(final Context context) {
        super(context);
        initialize();
    }
    
    public RefreshableListView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }
    
    public RefreshableListView(final Context context, final AttributeSet attrs,
            final int defStyle) {
        super(context, attrs, defStyle);
        initialize();
    }
    
    public void setOnRefreshListener(final OnRefreshListener l) {
        mListener = l;
    }
    
    @Override
    public void setOnTouchListener(OnTouchListener l) {
        super.setOnTouchListener(l);
    }
    
    public void completeRefreshing() {
        mProgress.setVisibility(View.INVISIBLE);
        mArrow.setVisibility(View.VISIBLE);
        mHandler.sendMessage(mHandler.obtainMessage(NORMAL, mHeaderHeight, 0));
        mIsRefreshing = false;
        invalidateViews();
    }
    
    @Override
    public boolean onInterceptTouchEvent(final MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mHandler.removeMessages(REFRESH);
            mHandler.removeMessages(NORMAL);
            mY = mHistoricalY = ev.getY();
            if (mHeaderContainer.getLayoutParams() != null) {
                mInitialHeight = mHeaderContainer.getLayoutParams().height;
            }
    
            break;
        }
        return super.onInterceptTouchEvent(ev);
    }
    
    @Override
    public boolean onTouchEvent(final MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_MOVE:
            mHistoricalTop = getChildAt(0).getTop();
            break;
        case MotionEvent.ACTION_UP:
            if (!mIsRefreshing) {
                if (mArrowUp) {
                    startRefreshing();
                    mHandler.sendMessage(mHandler.obtainMessage(REFRESH,
                            (int) (ev.getY() - mY) / 2 + mInitialHeight, 0));
                } else {
                    if (getChildAt(0).getTop() == 0) {
                        mHandler.sendMessage(mHandler.obtainMessage(NORMAL,
                                (int) (ev.getY() - mY) / 2 + mInitialHeight, 0));
                    }
                }
            } else {
                mHandler.sendMessage(mHandler.obtainMessage(REFRESH,
                        (int) (ev.getY() - mY) / 2 + mInitialHeight, 0));
            }
            mFlag = false;
            break;
    
        }
        return super.onTouchEvent(ev);
    }
    
    @Override
    public boolean dispatchTouchEvent(final MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_MOVE
                && getFirstVisiblePosition() == 0) {
            float direction = ev.getY() - mHistoricalY;
            int height = (int) (ev.getY() - mY) / 2 + mInitialHeight;
            if (height < 0) {
                height = 0;
            }
    
            float deltaY = Math.abs(mY - ev.getY());
            ViewConfiguration config = ViewConfiguration.get(getContext());
            if (deltaY > config.getScaledTouchSlop()) {
    
                // Scrolling downward
                if (direction > 0) {
                    // Refresh bar is extended if top pixel of the first item is
                    // visible
                    if (getChildAt(0) != null) {
                        if (getChildAt(0).getTop() == 0) {
                            if (mHistoricalTop < 0) {
    
                                // mY = ev.getY();
                                // this?mHistoricalTop = 0;
                            }
    
                            // Animation anim =
                            // AnimationUtils.loadAnimation(
                            // getContext(), R.anim.bounce_animation);
                            // startAnimation(anim);
                            // setSelectionAfterHeaderView();
                            // setOverScrollMode(View.OVER_SCROLL_NEVER);
                            // setSelectionFromTop(0, 0);
                            // smoothScrollToPosition(getChildAt(0).getTop()
                            // - vHeader.getHeight());
                            // bottom_layout.setVisibility(View.VISIBLE);
                            // }
                            // Extends refresh bar
                            if (isScrool == true) {
    
                                if (search_text.getVisibility() == 0
                                        && distance_spinner.getVisibility() == 0) {
    
                                } else {
                                    search_text.setVisibility(View.VISIBLE);
                                    distance_spinner
                                            .setVisibility(View.VISIBLE);
                                }
                            } else {
                                isScrool = true;
                                // Extends refresh bar
    
                                search_text.setVisibility(View.VISIBLE);
                                distance_spinner.setVisibility(View.VISIBLE);
    
                            }
    
                            setHeaderHeight(height);
    
                            // Stop list scroll to prevent the list from
                            // overscrolling
                            ev.setAction(MotionEvent.ACTION_CANCEL);
                            mFlag = false;
                        }
                    }
    
                } else if (direction < 0) {
                    // Scrolling upward
    
                    // Refresh bar is shortened if top pixel of the first item
                    // is
                    // visible
                    if (getChildAt(0) != null) {
                        if (getChildAt(0).getTop() == 0) {
                            setHeaderHeight(height);
    
                            // If scroll reaches top of the list, list scroll is
                            // enabled
                            if (getChildAt(1) != null
                                    && getChildAt(1).getTop() <= 1 && !mFlag) {
                                ev.setAction(MotionEvent.ACTION_DOWN);
                                mFlag = true;
                            }
                        }
                    }
                }
            }
    
            mHistoricalY = ev.getY();
        }
        try {
            return super.dispatchTouchEvent(ev);
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public boolean performItemClick(final View view, final int position,
            final long id) {
        if (position == 0) {
            // This is the refresh header element
            return true;
        } else {
            return super.performItemClick(view, position - 1, id);
        }
    }
    
    private void initialize() {
    
        LayoutInflater inflator = (LayoutInflater) getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        vHeader = inflator.inflate(R.layout.search_header, null);
        LayoutInflater inflater = (LayoutInflater) getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mHeaderContainer = inflater.inflate(R.layout.refreshable_list_header,
                null);
        vheaders = vHeader.findViewById(R.id.search_layout);
    
        mHeaderView = mHeaderContainer
                .findViewById(R.id.refreshable_list_header);
        mArrow = (ImageView) mHeaderContainer
                .findViewById(R.id.refreshable_list_arrow);
        mProgress = (ProgressBar) mHeaderContainer
                .findViewById(R.id.refreshable_list_progress);
        mText = (TextView) mHeaderContainer
                .findViewById(R.id.refreshable_list_text);
        addHeaderView(mHeaderContainer);
    
        search_text = (TextView) vheaders.findViewById(R.id.editText1);
        distance_spinner = (Button) vheaders.findViewById(R.id.button1);
        search_text.setVisibility(View.GONE);
        distance_spinner.setVisibility(View.GONE);
        addHeaderView(vheaders);
    
        mHeaderHeight = (int) (HEADER_HEIGHT_DP * getContext().getResources()
                .getDisplayMetrics().density);
    
        setHeaderHeight(0);
    }
    
    public View getHeaderview() {
        return vHeader;
    
    }
    
    private void setHeaderHeight(final int height) {
        if (height <= 1) {
            mHeaderView.setVisibility(View.GONE);
        } else {
            mHeaderView.setVisibility(View.VISIBLE);
    
        }
    
        // Extends refresh bar
        LayoutParams lp = (LayoutParams) mHeaderContainer.getLayoutParams();
        if (lp == null) {
            lp = new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT);
        }
        lp.height = height;
        mHeaderContainer.setLayoutParams(lp);
    
        // Refresh bar shows up from bottom to top
        LinearLayout.LayoutParams headerLp = (LinearLayout.LayoutParams) mHeaderView
                .getLayoutParams();
        if (headerLp == null) {
            headerLp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT);
        }
    
        headerLp.topMargin = -mHeaderHeight + height;
    
        mHeaderView.setLayoutParams(headerLp);
    
        if (!mIsRefreshing) {
            // If scroll reaches the trigger line, start refreshing
            if (height > mHeaderHeight && !mArrowUp) {
                mArrow.startAnimation(AnimationUtils.loadAnimation(
                        getContext(), R.anim.rotate));
                mText.setText("Release to update");
                rotateArrow();
                mArrowUp = true;
            } else if (height < mHeaderHeight && mArrowUp) {
                mArrow.startAnimation(AnimationUtils.loadAnimation(
                        getContext(), R.anim.rotate));
                mText.setText("Pull down to update");
                rotateArrow();
                mArrowUp = false;
    
            } else {
    
            }
        }
    }
    
    private void rotateArrow() {
        Drawable drawable = mArrow.getDrawable();
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.save();
        canvas.rotate(180.0f, canvas.getWidth() / 2.0f,
                canvas.getHeight() / 2.0f);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        canvas.restore();
        mArrow.setImageBitmap(bitmap);
    }
    
    public void startRefreshing() {
        mArrow.setVisibility(View.INVISIBLE);
        mProgress.setVisibility(View.VISIBLE);
        mText.setText("Loading...");
        mIsRefreshing = true;
    
        if (mListener != null) {
            mListener.onRefresh(this);
        }
        setSelection(0);
    }
    
    private final Handler mHandler = new Handler() {
    
        @Override
        public void handleMessage(final Message msg) {
            super.handleMessage(msg);
    
            int limit = 0;
            switch (msg.what) {
            case REFRESH:
                limit = mHeaderHeight;
                break;
            case NORMAL:
                limit = 0;
                break;
            }
    
            // Elastic scrolling
            if (msg.arg1 >= limit) {
                setHeaderHeight(msg.arg1);
                int displacement = (msg.arg1 - limit) / 10;
                if (displacement == 0) {
                    mHandler.sendMessage(mHandler.obtainMessage(msg.what,
                            msg.arg1 - 1, 0));
                } else {
                    mHandler.sendMessage(mHandler.obtainMessage(msg.what,
                            msg.arg1 - displacement, 0));
                }
            }
        }
    
    };
    
    public interface OnRefreshListener {
        public void onRefresh(RefreshableListView listView);
    }
    
    public static interface ListViewObserver {
        public void onScroll(float deltaY);
    }
    

    }

    【讨论】:

      【解决方案2】:

      Chris Banes 制作了一个 Library,它将满足您的需求。

      你可以在这里找到它:https://github.com/chrisbanes/ActionBar-PullToRefresh

      请注意,此项目仍在开发中,因此当前 API 可能会更改。

      或者正如下面在评论中所说的,你可以给我们这个

      https://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html

      步骤:

      1) 创建布局

      view must be scrollable, such a ScrollView or a ListView. As a simple example:
      <android.support.v4.widget.SwipeRefreshLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/swipe_container"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
      
          <ScrollView
              android:layout_width="match_parent"
              android:layout_height="match_parent">
      
              <TextView
                  android:text="@string/hello_world"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginTop="16dp"
                  android:gravity="center"/>
          </ScrollView>
      
      </android.support.v4.widget.SwipeRefreshLayout>
      

      2) 使用代码

      @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.activity_main);
      
                  swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
                  swipeLayout.setOnRefreshListener(this);
                  swipeLayout.setColorScheme(android.R.color.holo_blue_bright, 
                  android.R.color.holo_green_light, 
                  android.R.color.holo_orange_light, 
                  android.R.color.holo_red_light);
              }
      
      
              @Override public void onRefresh() {
              new Handler().postDelayed(new Runnable() {
              @Override public void run() {
              swipeLayout.setRefreshing(false);
               }
           }, 5000);
       }
      

      取自这里:http://antonioleiva.com/swiperefreshlayout/

      【讨论】:

      • Chris 的库已弃用,最好使用这个:developer.android.com/reference/android/support/v4/widget/…
      • 不,我不需要这个库。因为在我的活动中我使用主题无标题栏
      • @Ciprian 有什么例子吗
      • @Ciprian 我使用了可滑动布局,但是当我添加 headerview 时。列表视图向下滚动并且滚动不起作用
      • @Umesh 我不明白你的问题