完美解决!隐藏listview的headerView,实现动态下拉,(仿ios)

来源:互联网 发布:mac有迅雷吗 编辑:程序博客网 时间:2024/05/22 02:13

这两天在做项目的 时候遇到了这个问题,发现网上也有人提出了这个问题,但是根本没有人去解决,可能是问题太简单了。我在这里贴上我的代码,以往对大家有帮助。

首先,实现的效果,希望是这样的。




网上也给出了一些解决方案,但是根本没有实现动态的下拉呀。(下面贴出网上解决方案的截图)



接下来再来描述一下问题。我要实现的是listview的headerview 一开始是隐藏的。我把它拉下来,它就可见了,(自己写的。由于是公司的代码,不能贴出完整项目,还是希望对大家有帮助)

/** * 下拉出现顶部HeaderView * */public class PullShowHeaderListView extends ListView {    private View mHeaderView;    private int startY = -1;// 滑动起点的y坐标    private int mHeaderViewHeight;//headerview 的高    private static final int STATE_PULLING_DOWN = 0;//下拉状态    private static final int STATE_PULLING_UP = 1;//上拉状态    private int pulling_state = -1;    public PullShowHeaderListView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public PullShowHeaderListView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public PullShowHeaderListView(Context context) {        this(context, null, 0);    }    /**     * 初始化头布局     * init headerView in your code, init header Id first     */    public void initHeaderView(Context context, int layoutId) {        mHeaderView = View.inflate(context, layoutId, null);        this.addHeaderView(mHeaderView, null, false);        //这样可以让HeaderView不可点击        mHeaderView.measure(0, 0);        mHeaderViewHeight = mHeaderView.getMeasuredHeight();//我这里得到的结果是152        mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏头布局1        mHeaderView.setVisibility(View.GONE);// 隐藏头布局2    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN://                startY = -1;// 重置                startY = (int) ev.getRawY();                Log.i("---->PullShowHeaderListView", "startY " + startY);                Log.i("---->PullShowHeaderListView", "getFirstVisiblePosition " + getFirstVisiblePosition());                if (getFirstVisiblePosition() == 0 && mHeaderView.getPaddingTop() != 0) {//在第一个条目可见的情况下,将headerview置为visible,但是隐藏起来                    mHeaderView.setVisibility(View.VISIBLE);//mHeaderView.getPaddingTop() 如果等于0表示headerView完全可见(也就是我们已经把它拉下来了,此时不需要进行操作)                    mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);                    Log.i("---->PullShowHeaderListView", " visible,but hide");                } else if (getFirstVisiblePosition() != 0) {                    mHeaderView.setVisibility(View.GONE);                    mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);                    Log.i("---->PullShowHeaderListView", "not visible,and hide");                }                break;            case MotionEvent.ACTION_MOVE:                if (mHeaderView.getVisibility() != View.VISIBLE) { //保证下面代码是在,headerview置为visible的情况下才进行操作,                    break;                } else {                    int endY = (int) ev.getRawY();//得到滑动中的距离                    int dy = endY - startY;// 移动偏移量                    Log.i("---->PullShowHeaderListView", "endY -startY" + dy);                    int padding = 0;                    if (dy > 10 && mHeaderView.getPaddingTop() != 0 && pulling_state != STATE_PULLING_UP) {  // 当手指向下滑动了一定的距离(并且此时的headerView并不是完全可见的)                        pulling_state = STATE_PULLING_DOWN;                        padding = getPadding(dy);//控制padding大小在0到-mHeaderViewHeight之间                        mHeaderView.setPadding(0, padding, 0, 0);                        Log.i("---->PullShowHeaderListView", "down padding of the headerView" + padding);                    }                    if (dy < -10 && mHeaderView.getPaddingTop() != -mHeaderViewHeight && pulling_state != STATE_PULLING_DOWN) {//当手指向上滑动了一定的距离(并且此时的headerView并不是完全隐藏的)                        pulling_state = STATE_PULLING_UP;                        padding = getPadding(dy);//控制padding大小在0到-mHeaderViewHeight之间                        mHeaderView.setPadding(0, padding, 0, 0);                        Log.i("---->PullShowHeaderListView", "up padding of the headerView" + padding);                    }                }                break;            case MotionEvent.ACTION_UP:                if (mHeaderView.getPaddingTop() <= -mHeaderViewHeight / 2) {                    mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏                    mHeaderView.setVisibility(View.GONE);                    Log.i("---->PullShowHeaderListView", "more than 1/2,hiding");                } else if (mHeaderView.getPaddingTop() > -mHeaderViewHeight / 2) {                    mHeaderView.setPadding(0, 0, 0, 0);// 显示                    mHeaderView.setVisibility(View.VISIBLE);                    Log.i("---->PullShowHeaderListView", "less than 1/2,show");                }                startY = -1;// 重置                pulling_state = -1;                break;            default:                break;        }        return super.onTouchEvent(ev);//        return false;    }    private int getPadding(int dy) {        int padding = 0;        if (pulling_state == STATE_PULLING_DOWN) {//dy为正数,此时必须限定padding范围为-150~0            padding = dy - mHeaderViewHeight;            if (padding > 0) {                padding = 0;            }        } else if (pulling_state == STATE_PULLING_UP) {//dy为负数,此时必须限定padding范围为0~-150            padding = dy;            if (padding < -mHeaderViewHeight) {                padding = -mHeaderViewHeight;            }        }        return padding;    }    public View getHeaderView() {        return mHeaderView;    }    /**     * 拦截事件。确保在item上面的click不消耗事件,从而在上面可以下拉     */    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        return true;    }}

好了,接下来,就是在布局文件中引用这个自定义的view。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <com.view.PullShowHeaderListView        android:id="@+id/list_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:listSelector="@drawable/list_item_selector"        android:drawSelectorOnTop="true" /></FrameLayout>

在自己的activity里面可以引用了:

 <pre name="code" class="java">        list_view = (PullShowHeaderListView) view.findViewById(R.id.list_view);//添加了隐藏HeaderView的ListView        list_view.initHeaderView(mContext, R.layout.header_view);        list_view.setOnItemClickListener(new MyOnItemClickListener());        list_view.setOnItemLongClickListener(new MyOnItemLongClickLister());

好了,里面的headerview是我自定义的一个布局。你可以自定义一个自己的布局。

整个自定义view主要实现的就是下拉和上拉以及隐藏和显示headerview的情况。

讲讲我自己遇到的问题。需要注意的情况:

由于自定义了OnTouchEvent,大家可以看看事件分发的一些问题。你会发现在空白区域是可以把listview下拉的,但是在我们的listview的item上面,就无法下拉。这是因为我们的item的click消耗了事件的传递。我也就在OnInterceTouchEvent中返回true,代表不让我们的item得到事件。所以实现了item上面也可以下拉。

这是后就注意了,item就不可以自定义click事件,但是我们可以定义ListView的ItemClickLIstener和ItemLongClickListener呀。

最后贴两个讲解非常棒的事件分发机制的大神帖:

http://blog.csdn.net/guolin_blog/article/details/9097463/

http://blog.csdn.net/xiaanming/article/details/21696315

希望对大家有帮助

0 0
原创粉丝点击