仿微博的弹性listview

最近项目需求做一个仿微博的弹性listview,找了很多大家的分享,并没有找到完全符合自己需求的代码,自己在某位热于分享的前辈(看了太多例子,忘记是谁了,请见谅)的代码基础上做了改善,现在记录一下。

public class PullListView extends ListView implements AbsListView.OnScrollListener {


    private static final String TAG = "PullListView";


    //下拉因子,实现下拉时的延迟效果
    private static final float PULL_FACTOR = 0.5f;




    //记录刚开始下拉时的触摸位置的Y坐标
    private int startY;
    private int mlastY;
    private int y;


    //第一个可见条目的索引
    private int firstItemIndex;


    //用于实现下拉弹性效果的headView
    private View headView2;
    private View headView;


    private int currentScrollState;


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


    public PullListView(Context context, AttributeSet attr) {
        super(context, attr);
        init(context);
    }


    /**
     * 初始化
     *
     * @param context
     */
    private void init(Context context) {
        //创建PullListView的headview
        headView2 = new View(this.getContext());
        //默认白色背景,可以改变颜色, 也可以设置背景图片
        headView2.setBackgroundColor(Color.WHITE);
        //默认高度为0
        headView2.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.FILL_PARENT, 0));


        this.addHeaderView(headView2);
        headView = View.inflate(context, R.layout.activity_main, null);
        headView.setPadding(0, dp2px(this.getContext(), -50), 0, dp2px(this.getContext(), -50));
        int mScaledTouchSlop = ViewConfiguration.get(getContext())
                .getScaledTouchSlop();
        this.addHeaderView(headView);
        this.setOnScrollListener(this);
    }




    /**
     * 覆盖onTouchEvent方法,实现下拉回弹效果
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (firstItemIndex == 0) {
            y = (int) event.getRawY();
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //记录下拉起点状态
                startY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int moveY = y - mlastY; //位移
                if (moveY > 0) {
                    int offset = (int) ((y - startY) * PULL_FACTOR);
                    Log.i(TAG, "headView.getLayoutParams().height" + headView.getMeasuredHeight());
                    Log.i(TAG, "headView" + headView.getTop());


                    if (headView.getPaddingTop() >= 0 && headView.getPaddingBottom() >= 0) {
                        int top = offset - (dp2px(this.getContext(), 300) - dp2px(this.getContext(), 200));
                        headView.setPadding(0, 0, 0, 0);
                        headView2.setLayoutParams(new AbsListView.LayoutParams(MATCH_PARENT, top));
                    } else {
                        headView.setPadding(0, offset + dp2px(this.getContext(), -50), 0, offset + dp2px(this.getContext(), -50));
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                resetPosition();
                break;
        }
        mlastY = y;
        return super.onTouchEvent(event);
    }


    private void resetPosition() {
        headView2.setLayoutParams(new AbsListView.LayoutParams(MATCH_PARENT, 0));
        ValueAnimator anim = ValueAnimator.ofInt(headView.getPaddingTop(), dp2px(this.getContext(), -50));
        anim.setDuration(200);
        anim.start();
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                headView.setPadding(0, (Integer) animation.getAnimatedValue(), 0, (Integer) animation.getAnimatedValue());
            }
        });
    }




    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
    }


    public int dp2px(Context ctx, float dp) {
        float density = ctx.getResources().getDisplayMetrics().density;
        int px = (int) (dp * density + 0.5f);// 4.9->5 4.4->4
        return px;
    }


    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        currentScrollState = scrollState;
    }


    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        firstItemIndex = firstVisibleItem;
    }
}

猜你喜欢

转载自blog.csdn.net/sinat_21693123/article/details/50684642