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 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();
}
}
}
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 lists;
public MyAdapter(Context context,List 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
head_view.xml
item.xml
源码下载:
点击打开链接