主函数代码:
import android.content.Context; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import java.sql.Date; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener, View.OnTouchListener { private ListView mLv; private MainAdapter mAdapter; private View headView; private int headViewHeight;//顶部布局文件的高度; private int firstVisibleItem;//当前界面第一个可见的item位置 int state;//当前的状态 final int NONE = 0;//正常状态 final int PULL = 1;//提示下拉刷新状态 final int RELESE = 2;//松开释放状态 final int REFLASHING = 3;//正在刷新状态 int scrollState;//当前滚动状态 boolean isRemark;//标记 当前是在最顶端按下的; int startY;//按下时的Y轴位置 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLv = (ListView) findViewById(R.id.lv_main); mAdapter = new MainAdapter(this); mLv.setAdapter(mAdapter); headView = LayoutInflater.from(this).inflate(R.layout.head_lv_main, null); measureView(headView); headViewHeight = headView.getMeasuredHeight(); Log.d("tag", "headViewHeight = " + headViewHeight); topPadding(-headViewHeight); mLv.addHeaderView(headView); mLv.setOnScrollListener(this); mLv.setOnTouchListener(this); } //通知父布局占用的宽和高 private void measureView(View view) { ViewGroup.LayoutParams p = view.getLayoutParams(); if (p == null) { p = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); int height; int tempHeight = p.height; if (tempHeight > 0) { height = View.MeasureSpec.makeMeasureSpec(tempHeight, View.MeasureSpec.EXACTLY); } else { height = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); } view.measure(width, height); } //设置头布局上边距 private void topPadding(int topPadding) { headView.setPadding(headView.getPaddingLeft(), topPadding, headView.getPaddingRight(), headView.getPaddingBottom()); headView.invalidate(); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { this.scrollState = scrollState; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.firstVisibleItem = firstVisibleItem; } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (firstVisibleItem == 0) { isRemark = true; startY = (int) event.getY(); } break; case MotionEvent.ACTION_MOVE: onMove(event); break; case MotionEvent.ACTION_UP: if (state == RELESE) { state = REFLASHING; //加载最新数据 reflashViewByState(); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mAdapter.addData(addNewData()); reflashComplete(); } },2000); } else if (state == PULL) { state = NONE; isRemark = false; reflashViewByState(); } break; } return false; } public void reflashComplete() { state = NONE; isRemark = false; reflashViewByState(); TextView lastUpdateTime = (TextView) headView.findViewById(R.id.tv_lastUpdate_time); SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss"); Date date = new Date(System.currentTimeMillis()); String time = format.format(date); lastUpdateTime.setText(time); } //判断移动过程中操作 private void onMove(MotionEvent event) { if (!isRemark) { return; } int tempY = (int) event.getY(); int space = tempY - startY; int topPadding = space - headViewHeight; switch (state) { case NONE: if (space > 0) { state = PULL; reflashViewByState(); } break; case PULL: topPadding(topPadding); if (space > headViewHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) { state = RELESE; reflashViewByState(); } break; case RELESE: topPadding(topPadding); if (space < headViewHeight + 30) { state = PULL; reflashViewByState(); } else if (space <= 0) { state = NONE; isRemark = false; reflashViewByState(); } break; case REFLASHING: break; } } //根据当前状态,改变界面显示 private void reflashViewByState() { TextView tip = (TextView) headView.findViewById(R.id.tv_tip); ImageView arrow = (ImageView) headView.findViewById(R.id.iv_head); ProgressBar progress = (ProgressBar) headView.findViewById(R.id.progress); RotateAnimation anim = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); anim.setDuration(500); anim.setFillAfter(true); RotateAnimation anim1 = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); anim1.setDuration(500); anim1.setFillAfter(true); switch (state) { case NONE: arrow.clearAnimation(); topPadding(-headViewHeight); break; case PULL: arrow.setVisibility(View.VISIBLE); progress.setVisibility(View.GONE); tip.setText("下拉可以刷新"); arrow.clearAnimation(); arrow.setAnimation(anim1); break; case RELESE: arrow.setVisibility(View.VISIBLE); progress.setVisibility(View.GONE); tip.setText("松开可以刷新"); arrow.clearAnimation(); arrow.setAnimation(anim); break; case REFLASHING: arrow.clearAnimation(); topPadding(50); arrow.setVisibility(View.GONE); progress.setVisibility(View.VISIBLE); tip.setText("正在刷新...."); break; } } public List<String> addNewData(){ ArrayList<String> data = new ArrayList<>(); for (int i = 0; i < 3; i++) { data.add("新" + i); } return data; } class MainAdapter extends BaseAdapter { private List<String> data; private Context context; public MainAdapter(Context context) { this.context = context; init(); } private void init() { data = new ArrayList<>(); for (int i = 0; i < 60; i++) { data.add("第" + i + "条"); } notifyDataSetChanged(); } public void addData(List<String> data){ this.data.addAll(0,data); notifyDataSetChanged(); } @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { MyViewHolder myViewHolder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.item_lv_main, null); myViewHolder = new MyViewHolder(convertView); myViewHolder.textView = (TextView) convertView.findViewById(R.id.tv_item_main); convertView.setTag(myViewHolder); } else { myViewHolder = (MyViewHolder) convertView.getTag(); } myViewHolder.textView.setText(data.get(position)); return convertView; } class MyViewHolder { TextView textView; public MyViewHolder(View convertView) { textView = (TextView) convertView.findViewById(R.id.tv_item_main); } } }
}
主函数布局文件代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <ListView android:id="@+id/lv_main" android:layout_width="match_parent" android:layout_height="match_parent" />
</RelativeLayout>
item布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tv_item_main"/> </LinearLayout>
头布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="10dp" android:paddingBottom="10dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:id="@+id/ll_head" android:gravity="center" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_tip" android:text="下拉可以刷新"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_lastUpdate_time" /> </LinearLayout> <ImageView android:layout_marginRight="20dp" android:layout_toLeftOf="@id/ll_head" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/iv_head" android:src="@mipmap/ic_launcher"/> <ProgressBar android:layout_marginRight="20dp" android:layout_toLeftOf="@id/ll_head" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/progress" style="?android:attr/progressBarStyleSmall" android:visibility="gone"/> </RelativeLayout> </LinearLayout>
主函数代码:
import android.content.Context; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import java.sql.Date; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener, View.OnTouchListener { private ListView mLv; private MainAdapter mAdapter; private View headView; private int headViewHeight;//顶部布局文件的高度; private int firstVisibleItem;//当前界面第一个可见的item位置 int state;//当前的状态 final int NONE = 0;//正常状态 final int PULL = 1;//提示下拉刷新状态 final int RELESE = 2;//松开释放状态 final int REFLASHING = 3;//正在刷新状态 int scrollState;//当前滚动状态 boolean isRemark;//标记 当前是在最顶端按下的; int startY;//按下时的Y轴位置 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLv = (ListView) findViewById(R.id.lv_main); mAdapter = new MainAdapter(this); mLv.setAdapter(mAdapter); headView = LayoutInflater.from(this).inflate(R.layout.head_lv_main, null); measureView(headView); headViewHeight = headView.getMeasuredHeight(); Log.d("tag", "headViewHeight = " + headViewHeight); topPadding(-headViewHeight); mLv.addHeaderView(headView); mLv.setOnScrollListener(this); mLv.setOnTouchListener(this); } //通知父布局占用的宽和高 private void measureView(View view) { ViewGroup.LayoutParams p = view.getLayoutParams(); if (p == null) { p = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); int height; int tempHeight = p.height; if (tempHeight > 0) { height = View.MeasureSpec.makeMeasureSpec(tempHeight, View.MeasureSpec.EXACTLY); } else { height = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); } view.measure(width, height); } //设置头布局上边距 private void topPadding(int topPadding) { headView.setPadding(headView.getPaddingLeft(), topPadding, headView.getPaddingRight(), headView.getPaddingBottom()); headView.invalidate(); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { this.scrollState = scrollState; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.firstVisibleItem = firstVisibleItem; } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (firstVisibleItem == 0) { isRemark = true; startY = (int) event.getY(); } break; case MotionEvent.ACTION_MOVE: onMove(event); break; case MotionEvent.ACTION_UP: if (state == RELESE) { state = REFLASHING; //加载最新数据 reflashViewByState(); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mAdapter.addData(addNewData()); reflashComplete(); } },2000); } else if (state == PULL) { state = NONE; isRemark = false; reflashViewByState(); } break; } return false; } public void reflashComplete() { state = NONE; isRemark = false; reflashViewByState(); TextView lastUpdateTime = (TextView) headView.findViewById(R.id.tv_lastUpdate_time); SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss"); Date date = new Date(System.currentTimeMillis()); String time = format.format(date); lastUpdateTime.setText(time); } //判断移动过程中操作 private void onMove(MotionEvent event) { if (!isRemark) { return; } int tempY = (int) event.getY(); int space = tempY - startY; int topPadding = space - headViewHeight; switch (state) { case NONE: if (space > 0) { state = PULL; reflashViewByState(); } break; case PULL: topPadding(topPadding); if (space > headViewHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) { state = RELESE; reflashViewByState(); } break; case RELESE: topPadding(topPadding); if (space < headViewHeight + 30) { state = PULL; reflashViewByState(); } else if (space <= 0) { state = NONE; isRemark = false; reflashViewByState(); } break; case REFLASHING: break; } } //根据当前状态,改变界面显示 private void reflashViewByState() { TextView tip = (TextView) headView.findViewById(R.id.tv_tip); ImageView arrow = (ImageView) headView.findViewById(R.id.iv_head); ProgressBar progress = (ProgressBar) headView.findViewById(R.id.progress); RotateAnimation anim = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); anim.setDuration(500); anim.setFillAfter(true); RotateAnimation anim1 = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); anim1.setDuration(500); anim1.setFillAfter(true); switch (state) { case NONE: arrow.clearAnimation(); topPadding(-headViewHeight); break; case PULL: arrow.setVisibility(View.VISIBLE); progress.setVisibility(View.GONE); tip.setText("下拉可以刷新"); arrow.clearAnimation(); arrow.setAnimation(anim1); break; case RELESE: arrow.setVisibility(View.VISIBLE); progress.setVisibility(View.GONE); tip.setText("松开可以刷新"); arrow.clearAnimation(); arrow.setAnimation(anim); break; case REFLASHING: arrow.clearAnimation(); topPadding(50); arrow.setVisibility(View.GONE); progress.setVisibility(View.VISIBLE); tip.setText("正在刷新...."); break; } } public List<String> addNewData(){ ArrayList<String> data = new ArrayList<>(); for (int i = 0; i < 3; i++) { data.add("新" + i); } return data; } class MainAdapter extends BaseAdapter { private List<String> data; private Context context; public MainAdapter(Context context) { this.context = context; init(); } private void init() { data = new ArrayList<>(); for (int i = 0; i < 60; i++) { data.add("第" + i + "条"); } notifyDataSetChanged(); } public void addData(List<String> data){ this.data.addAll(0,data); notifyDataSetChanged(); } @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { MyViewHolder myViewHolder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.item_lv_main, null); myViewHolder = new MyViewHolder(convertView); myViewHolder.textView = (TextView) convertView.findViewById(R.id.tv_item_main); convertView.setTag(myViewHolder); } else { myViewHolder = (MyViewHolder) convertView.getTag(); } myViewHolder.textView.setText(data.get(position)); return convertView; } class MyViewHolder { TextView textView; public MyViewHolder(View convertView) { textView = (TextView) convertView.findViewById(R.id.tv_item_main); } } }
}
主函数布局文件代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <ListView android:id="@+id/lv_main" android:layout_width="match_parent" android:layout_height="match_parent" />
</RelativeLayout>
item布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tv_item_main"/> </LinearLayout>
头布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="10dp" android:paddingBottom="10dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:id="@+id/ll_head" android:gravity="center" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_tip" android:text="下拉可以刷新"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_lastUpdate_time" /> </LinearLayout> <ImageView android:layout_marginRight="20dp" android:layout_toLeftOf="@id/ll_head" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/iv_head" android:src="@mipmap/ic_launcher"/> <ProgressBar android:layout_marginRight="20dp" android:layout_toLeftOf="@id/ll_head" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/progress" style="?android:attr/progressBarStyleSmall" android:visibility="gone"/> </RelativeLayout> </LinearLayout>