android中的下拉刷新

1.目前主要的下拉刷新大致分为三种实现方式:


    a.比较通用的,像官方SwipeRefreshLayout,github上也有很多种实现,属于在外层包裹。




   b。其实下拉刷新用的最多的还是在listview中,给listview添加head,控制head的padding值




   c。 同上,但是是控制head的高度的


2.下面演示控制head的padding实现下拉刷新

    这种方式并不灵活,比较灵活的是像android-Ultra-Pull-to-Refresh这种,外层包裹的,可以包裹任何view,但是在listview中用head的padding有特殊使用场景比如说,listview 有一个head,而下拉是在这个head的下面的。

                                        



代码:


MainActivity.java

package cn.edu.sxu.www.customerpullrefresh;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {


    private ListView customerlistview;

    private MyAdapter myAdapter;

    private List<String> lists;

    private LinearLayout activity_main;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        activity_main= (LinearLayout) findViewById(R.id.activity_main);
//        customerlistview= (ListView) findViewById(R.id.customerlistview);
        customerlistview=new CustomerListView(this) {
            @Override
            public View addHeadView() {
                TextView textView=new TextView(MainActivity.this);
                textView.setBackgroundColor(Color.parseColor("#ff00ff"));
                textView.setGravity(Gravity.CENTER);
                textView.setText("listview头部");
                AbsListView.LayoutParams params=new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,200);
                textView.setLayoutParams(params);
                addHeaderView(textView);
                return textView;
            }
        };
        customerlistview.setSelector(R.drawable.bg_item);
        activity_main.addView(customerlistview);
        lists=new ArrayList<>();

        for(int i=0;i<20;i++)
        {
            lists.add(""+i);
        }
        myAdapter=new MyAdapter(this,lists);
        customerlistview.setAdapter(myAdapter);
        myAdapter.notifyDataSetChanged();

        customerlistview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String desc = (String) parent.getAdapter().getItem(position);
                MToast.showToast(MainActivity.this,desc);
            }
        });
    }
}



CustomerListView.java

package cn.edu.sxu.www.customerpullrefresh;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ListView;
import android.widget.Scroller;

/**
 * Created by ${huozhenpeng} on 17/6/29.
 * Company : www.miduo.com
 */

public abstract class CustomerListView extends ListView {
    private Context context;

    public CustomerListView(Context context) {
        this(context, null);
    }

    public CustomerListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }

    public abstract View addHeadView();


    public CustomerListView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }


    private View headView;
    private int mHeaderHeight;
    private View firstView;

    private void init() {
        if (headView == null) {
            headView = LayoutInflater.from(context).inflate(R.layout.head_view, null);
        }
        firstView = addHeadView();
        addHeaderView(headView);
        mScrollChecker = new ScrollChecker();
        headView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mHeaderHeight = headView.getMeasuredHeight();
                headView.setPadding(0, -headView.getMeasuredHeight(), 0, 0);
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

    }


    private void setPadding(int paddingTop) {
        if (paddingTop >= 0)
            paddingTop = 0;
        if (paddingTop <= -mHeaderHeight)
            paddingTop = -mHeaderHeight;
        headView.setPadding(0, paddingTop, 0, 0);
    }


    //作用主要是一次下拉还没有结束之后又进行下一次下拉(这种的话,效果会好点,连续。。。。。)
    private int initPadding=-500;
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Y = (int) ev.getY();
                if(runnable!=null)
                {
                    //移除回调,
                    initPadding=headView.getPaddingTop();
                    CustomerListView.this.removeCallbacks(runnable);
                    mScrollChecker.removeCallBacks();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                curY = (int) ev.getY();
                //firstview是区分下拉刷新上面还有没有headview
                if (firstView == null) {
                    if (getFirstVisiblePosition() == 0 && Math.abs(headView.getPaddingTop()) == mHeaderHeight) {
                        if (curY > Y) {
                            setPadding(initPadding + (curY - Y));
                            return true;
                        } else {

                        }
                    } else if (getFirstVisiblePosition() > 0) {

                    } else if (Math.abs(headView.getPaddingTop()) <= mHeaderHeight) {
                        setPadding(initPadding + (curY - Y));
                        return true;
                    }
                } else {
                    if (getFirstVisiblePosition() == 0 && firstView.getBottom() == firstView.getHeight()) {
                        if (curY > Y) {
                            setPadding(initPadding + (curY - Y));
                            return true;
                        } else {

                        }

                    } else {

                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if(firstView!=null)
                {
                    if (Math.abs(headView.getPaddingTop()) < mHeaderHeight&&getFirstVisiblePosition()<2) {
                        onRelease();
                        return true;
                    }
                    else
                    {
                        setPadding(-mHeaderHeight);
                    }
                }
                else
                {
                    if (Math.abs(headView.getPaddingTop()) < mHeaderHeight&&getFirstVisiblePosition()<1) {
                        onRelease();
                        return true;
                    }
                    else
                    {
                        setPadding(-mHeaderHeight);
                    }
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    private int Y;
    private int curY;


    //释放时,contentView的top值
    private int releaseTop;

    private Runnable runnable;

    /**
     * 假设每次让回复到250px的时候执行正在刷新操作
     */
    private void onRelease() {
        releaseTop = headView.getPaddingTop();
        if (Math.abs(headView.getPaddingTop()) <= mHeaderHeight / 2) {
            mScrollChecker.tryToScrollTo(releaseTop + mHeaderHeight / 2, 1000);
            runnable=new Runnable() {
                @Override
                public void run() {
                    //刷新2s后恢复到初始位置
                    //不要用这个,getTop值恢复过程中会变化的
                    mScrollChecker.tryToScrollTo(mHeaderHeight / 2, 1500);
                }
            };
            postDelayed(runnable, 2000);

        } else {
            //相当于不执行刷新
            mScrollChecker.tryToScrollTo(releaseTop + mHeaderHeight, 1500);
        }

    }

    private ScrollChecker mScrollChecker;

    private int oldPadding;

    private boolean finish = true;

    private int currentPadding;

    class ScrollChecker implements Runnable {

        private Scroller mScroller;

        public ScrollChecker() {
            mScroller = new Scroller(getContext());
        }


        @Override
        public void run() {
            finish = !mScroller.computeScrollOffset() || mScroller.isFinished();
            if (!finish) {
                if (headView.getPaddingTop() < -mHeaderHeight) {
                    headView.setPadding(0, -mHeaderHeight, 0, 0);
                } else if (headView.getPaddingTop() > 0) {
                    headView.setPadding(0, -mHeaderHeight, 0, 0);
                } else {
                    currentPadding = -mScroller.getCurrY() + oldPadding;
                    headView.setPadding(0, -mScroller.getCurrY() + oldPadding, 0, 0);
                    post(this);
                }
            }
        }

        public void tryToScrollTo(int to, int duration) {
            oldPadding = headView.getPaddingTop();
            mScroller.startScroll(0, 0, 0, to, duration);
            post(this);
        }

        public void removeCallBacks() {
            removeCallbacks(this);
        }
    }

}




MToast.java

package cn.edu.sxu.www.customerpullrefresh;

import android.content.Context;
import android.view.Gravity;
import android.widget.Toast;

/**
 * 
 * Toast替换
 * 
 */
public class MToast {
	private static Toast mToast;

	public static void showToast(Context context, String text) {
		if (mToast == null) {
			mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
		} else {
			mToast.setText(text);
			mToast.setDuration(Toast.LENGTH_SHORT);
		}
		mToast.setGravity(Gravity.CENTER, 0, 0);
		mToast.show();
	}
	public static void showToast2(Context context, String text) {
		if (mToast == null) {
			mToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
		} else {
			mToast.setText(text);
			mToast.setDuration(Toast.LENGTH_LONG);
		}
		mToast.setGravity(Gravity.CENTER, 0, 0);
		mToast.show();
	}

	public static void cancelToast() {
		if (mToast != null) {
			mToast.cancel();
		}
	}

}


MyAdapter.java
package cn.edu.sxu.www.customerpullrefresh;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * Created by ${huozhenpeng} on 17/6/29.
 * Company : www.miduo.com
 */

public class MyAdapter extends BaseAdapter {
    private Context context;
    private List<String> lists;
    public MyAdapter(Context context,List<String> lists)
    {
        this.context=context;
        this.lists=lists;

    }
    @Override
    public int getCount() {
        return lists.size();
    }

    @Override
    public Object getItem(int position) {
        return lists.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        convertView= LayoutInflater.from(context).inflate(R.layout.item,null);
        TextView textView= (TextView) convertView.findViewById(R.id.text);
        textView.setText(lists.get(position));
        return convertView;
    }
}


activity_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#000000"
        />


</LinearLayout>



head_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <LinearLayout
        android:orientation="vertical"
        android:background="#00ff00"
        android:layout_width="match_parent"
        android:layout_height="500px">
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="200px"
            android:text="头部"
            android:gravity="center"
            android:textColor="#00aabb"
            />
        <ProgressBar
            android:layout_gravity="center"
            android:id="@+id/pb_progress"
            android:layout_width="wrap_content"
            android:layout_height="250px"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            />
    </LinearLayout>

</LinearLayout>







item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:gravity="center"
        />
</RelativeLayout>



源码下载:

点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值