android 自定义ListView实现下拉刷新
来源:互联网 发布:几个excel表数据合并 编辑:程序博客网 时间:2024/06/05 10:22
这两天突然想弄个下拉刷新的,于是就在网上搜索,找呀找,发现那些都好长,反正我是不怎么看得懂,于是,我就到处寻,果不其然,被我弄懂了。下面我从我得角度向大家详细如何实现的。
ListView 有 两个方法, addFooterView(View view); 和 addHeaderView(View view); 直接传一个布局文件进去调用 。实现下拉刷新,其实就是检测滑动事件来显示或者隐藏头尾布局 . 下面我上全部代码与大家一一解释:
RefreListview.java
package com.qzzhu.refrelist;import java.text.SimpleDateFormat;import java.util.Date;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.widget.AbsListView;import android.widget.ImageView;import android.widget.ListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ProgressBar;import android.widget.TextView;public class RefreListview extends ListView implements OnScrollListener {private View headview; //头布局private View footview;//尾布局private Context context; //上下文private int headHeight; //头布局高度 private int footheight; //尾布局高度private int downY; //触摸事件 按下的Y值private int mYfirstVisibleItem=0;//list显示的头item是第几个itemprivate final int PULL_DOWN_REFRE=0;//下拉刷新private final int RELEASE_REFRE = 1;//释放刷新private final int REFREING = 3;//刷新中private int currentState = PULL_DOWN_REFRE;//当前的状态private ImageView headicon; //头布局里面的空间 箭头private ProgressBar headpb; // 加载控件private TextView headcontent; //头布局里面的控件 文本private TextView headrefretime;//头布局里面的控件 最后更新事件private Animation downAnimation; //下拉刷新动画private Animation upAnimation; //释放刷新动画 private OnRefreChangeListener changeListener; //接口private boolean isMove = false; //是否移动public RefreListview(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;//从这里看起 实例化头文件,把目光先放到该方法上面去initHeadView();initFootView();initAnimation();setOnScrollListener(this);}private void initFootView() { footview = View.inflate(getContext(), R.layout.item_list_footview, null); footview.measure(0, 0); footheight = footview.getMeasuredHeight(); footview.setPadding(0, 0, 0, -footheight); addFooterView(footview);}private void initAnimation() {downAnimation = new RotateAnimation(0,-180,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);downAnimation.setDuration(500);downAnimation.setFillAfter(true);//结束保持动画upAnimation = new RotateAnimation(-180,-360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);upAnimation.setDuration(500);upAnimation.setFillAfter(true);//结束保持动画}private void initHeadView() {//引入一个xml文件headview = View.inflate(context, R.layout.item_list_headview, null);//得到里面的控件headicon=(ImageView) headview.findViewById(R.id.head_icon);headpb = (ProgressBar) headview.findViewById(R.id.head_pb);headcontent = (TextView) headview.findViewById(R.id.head_tvcontent);headrefretime = (TextView) headview.findViewById(R.id.head_refretime);//调用这一句,我们就在listView里面添加了我们自定义的头布局了。但是我们一开始不想它显示的,我们应该把它向上移动头布局高度的距离。但是如何获取头布局的高度呢?addHeaderView(headview);/* * 如果直接调用headview.getHeight();是拿不到高度的,这个前提条件是 界面显示了,所以只能等到0*///要手动得到测量方法,只有通过这个方法,下面的高度才能拿到getMeasuredHeight()//该方法是得到测量方法, headview.measure(0, 0); //调用getMeasuredHeight() 就能拿到当前头布局的高度了 headHeight =headview.getMeasuredHeight();//接下来就是隐藏头布局了,setPadding(<int left, int top,int right,int bottom) // 我们是要向上移,所以就改变第二个参数了,因为超出了屏幕,所以为负值,0代表着刚好完全显示,所以就向上隐藏它的高度了。headview.setPadding(0, -headHeight, 0, 0);//这样初始的时候就会隐藏头布局/下面就开始监听触摸事件了}//复写Touch事件@Overridepublic boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:<span style="white-space:pre"></span>//得到按下的位置,并做成全局变量 downY = (int) ev.getY();break;case MotionEvent.ACTION_MOVE:if (currentState==REFREING) {//如果当前正在刷新的话,拦截当前事件,不让它执行下面的方法break;}int moveY = (int) ev.getY();//得到当前移动的Y值int diff = moveY-downY;//判断是向上滑还是向下滑,我们下拉,肯定要下滑的if (diff>0&&mYfirstVisibleItem==0) {//判断向下滑,并且listview显示的第一个条目的总的第一个条目int padding = -headHeight+diff;//得到偏移量if (padding>0&¤tState==PULL_DOWN_REFRE) {//完全拉出来currentState = RELEASE_REFRE;System.out.println("释放刷新");<span style="white-space:pre"></span>//改变当前状态和布局文字等等方法selectCurrentState();}else if (padding<0&& currentState ==RELEASE_REFRE) {currentState = PULL_DOWN_REFRE;System.out.println("下拉刷新");selectCurrentState();}headview.setPadding(0, padding, 0, 0);return true;}break;case MotionEvent.ACTION_UP:if (currentState ==PULL_DOWN_REFRE) {headview.setPadding(0, -headHeight, 0, 0);}else if (currentState ==RELEASE_REFRE){currentState = REFREING;selectCurrentState();headview.setPadding(0, 0, 0, 0);if (changeListener!=null) {changeListener.pull_down_refresh();}}break;}return super.onTouchEvent(ev);}/** * 各个状态 改变UI的方法 */private void selectCurrentState() {switch (currentState) {case PULL_DOWN_REFRE:headcontent.setText("下拉刷新");headicon.startAnimation(upAnimation);break;case RELEASE_REFRE:headcontent.setText("释放刷新");headicon.startAnimation(downAnimation);break;case REFREING:headcontent.setText("刷新中");headicon.clearAnimation();headicon.setVisibility(View.INVISIBLE);headpb.setVisibility(View.VISIBLE);break;}}/*滚动状态改变调用 public static int SCROLL_STATE_TOUCH_SCROLL = 1; public static int SCROLL_STATE_FLING = 2; * (non-Javadoc) * @see android.widget.AbsListView.OnScrollListener#onScrollStateChanged(android.widget.AbsListView, int) */@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {//显示出来if ((scrollState==SCROLL_STATE_IDLE||scrollState==SCROLL_STATE_FLING)&&getLastVisiblePosition()==getCount()-1) {if (!isMove) {isMove=!isMove;footview.setPadding(0, 0, 0, 0);if (changeListener!=null) {changeListener.loadMove();}setSelection(getCount()-1);//设置当前位置}}}/** * 自定义的监听事件,接受接口 * @param listener */public void setOnListenerChanger(OnRefreChangeListener listener){changeListener = listener; }/** * 滚动时调用 */@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {mYfirstVisibleItem = firstVisibleItem;}/** * 隐藏头布局 刷新结束调用 */public void hideHeadView() {headcontent.setText("下拉刷新");currentState =PULL_DOWN_REFRE;headicon.setVisibility(View.VISIBLE);headpb.setVisibility(View.INVISIBLE);headview.setPadding(0, -headHeight, 0, 0);//这样初始的时候就会隐藏头布局headrefretime.setText("最后更新时间:"+getLastTime());}/** * 获取当前时间 * @return */private String getLastTime() {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return dateFormat.format(new Date());}/** * 隐藏尾布局 刷新结束调用 */public void hideFootView() {isMove =false;headview.setPadding(0, 0, 0,-footheight);//这样初始的时候就会隐藏头布局}}
OnRefreChangeListener.java
package com.qzzhu.refrelist;public interface OnRefreChangeListener {//释放刷新回调的方法void pull_down_refresh();//上啦加载更多void loadMove();}
头布局文件:
<span style="color:#3333ff;"><?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/head_icon" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:background="@drawable/common_listview_headview_red_arrow" /> <ProgressBar android:id="@+id/head_pb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:visibility="invisible" android:indeterminateDrawable="@drawable/custom_bg" /> </FrameLayout><LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center" > <TextView android:id="@+id/head_tvcontent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉刷新" android:textSize="23sp" android:textColor="#ff0000" /> <TextView android:id="@+id/head_refretime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="最后更新时间 2016-5-28" android:textSize="15sp" android:textColor="#77000000" /></LinearLayout></LinearLayout></span>
<span style="color:#3333ff;"><?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" > <ProgressBar android:id="@+id/foot_pb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:indeterminateDrawable="@drawable/custom_bg" /> <TextView android:id="@+id/head_tvcontent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉刷新" android:textSize="23sp" android:textColor="#ff0000" /></LinearLayout>
<pre name="code" class="html">ProgressBar 样式:custom_bg.xml 在drawable文件夹下
<span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="html"><span style="font-family: Arial, Helvetica, sans-serif;"><rotate xmlns:android="http://schemas.android.com/apk/res/android"</span>
android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%" > <shape android:shape="ring" android:innerRadiusRatio="3" android:thicknessRatio="14" android:useLevel="false" > <gradient android:startColor="#ffffff" android:centerColor="#ff6a6a" android:endColor="#ff0000" android:type="sweep" /> </shape></rotate>
MainActivity.javaimport java.util.ArrayList;import java.util.List;import android.support.v7.app.ActionBarActivity;import android.graphics.Color;import android.os.AsyncTask;import android.os.Bundle;import android.os.SystemClock;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;public class MainActivity extends ActionBarActivity {private RefreListview refreListview;private List<String> itemList;private MyAdapter adapter ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); refreListview = (RefreListview) findViewById(R.id.refrelist); itemList = new ArrayList<String>(); for (int i = 0; i < 30; i++) {itemList.add("啦啦啦啦?"+i+"次");} adapter = new MyAdapter(); refreListview.setAdapter(adapter); refreListview.setOnListenerChanger(new OnRefreChangeListener() {@Overridepublic void pull_down_refresh() {new AsyncTask<Void, Void, Void>(){//开始执行的时候调用,此方法 在主线程调用@Overrideprotected void onPreExecute() {//输出测试方法的执行先后和运行所在的线程,运行在主线程中,可以进行修改UI操作System.out.println("onPreExecute"+Thread.currentThread().getName());super.onPreExecute();}//在需要与服务器交互的时候,当onPreExecute被调用之后执行,此方法运行在子线程中,可以进行耗时的操作@Overrideprotected Void doInBackground(Void... params) {// TODO Auto-generated method stubSystemClock.sleep(2000);System.out.println("doInBackground"+Thread.currentThread().getName());itemList.add(0, "新增的条目");return null;}//最后执行,运行在主线程中,可以进行修改UI操作protected void onPostExecute(Void result) {System.out.println("onPostExecute"+Thread.currentThread().getName());adapter.notifyDataSetChanged();refreListview.hideHeadView();super.onProgressUpdate(result);};}.execute(new Void[]{});}@Overridepublic void loadMove() {new AsyncTask<Void, Void, Void>(){protected void onPreExecute() {};@Overrideprotected Void doInBackground(Void... params) {// TODO Auto-generated method stubSystemClock.sleep(2000);itemList.add("新增的条目");return null;}protected void onPostExecute(Void result) {refreListview.hideFootView();adapter.notifyDataSetChanged();super.onProgressUpdate(result);};}.execute(new Void[]{});}}); } private class MyAdapter extends BaseAdapter{@Overridepublic int getCount() {return itemList.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {TextView view =null;if (convertView==null) {view = new TextView(getApplicationContext());}else {view = (TextView) convertView;}view.setText(itemList.get(position));view.setTextColor(Color.BLACK);return view;} }}
整个项目工程Demo 需要的朋友自己下载去研究
0 0
- android 自定义listview实现下拉刷新(一)
- android 自定义ListView实现下拉刷新
- 自定义ListView实现下拉刷新
- 自定义ListView实现下拉刷新
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android 自定义ListView 实现下拉刷新 上拉加载功能
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android自定义ListView实现下拉刷新,效果仿SwipeRefreshLayout
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android下拉刷新ListView实现
- 自定义ListView实现下拉刷新功能
- 自定义listview实现下拉刷新的效果
- Android : 自定义下拉刷新的ListView
- NumPy 索引 迭代 Resheap
- scala学习之Array
- 简述javascript事件委托
- 动态规划1017
- Matlab作图后,使用data cursor实现显示多个点的数据值
- android 自定义ListView实现下拉刷新
- 灵活的坐标系变换:CSS的position定位方式
- 题目23
- MySQL中的多表查询
- 计蒜客 硬币翻转(二进制压缩)
- LeNet5的基本结构
- 题目29
- 《DO圣堂刺客2》国服首测今天拉开
- 两种方法求解逆序对