标签:
先看主布局activity_main.xml
<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:background="@color/white" tools:context=".MainActivity" > <com.imooc.listviewfrashdemo1.ReFlashListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/white" android:cacheColorHint="#00000000" android:dividerHeight="5dip" /> </RelativeLayout>
<?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:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="10dip" android:paddingTop="10dip" > <LinearLayout android:id="@+id/layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/tip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉可以刷新!" /> <TextView android:id="@+id/lastupdate_time" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <ImageView android:id="@+id/arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/layout" android:layout_marginRight="20dip" android:src="@drawable/pull_to_refresh_arrow" /> <ProgressBar android:id="@+id/progress" style="?android:attr/progressBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/layout" android:layout_marginRight="20dip" android:visibility="gone" /> </RelativeLayout> </LinearLayout>
item_layout.xml
<?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="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="60dip" android:gravity="center_vertical" android:background="@drawable/app_item_bg" android:orientation="horizontal" > <ImageView android:id="@+id/item3_apkiv" android:layout_width="50dip" android:layout_height="50dip" android:background="@drawable/test_icon" android:layout_marginLeft="10dip" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginLeft="10dip" android:orientation="vertical" > <TextView android:id="@+id/item3_apkname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="应用程序名字" android:textColor="@color/black" android:textSize="18dip" /> <TextView android:id="@+id/item3_apkinfo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dip" android:text="应用程序信息" android:textSize="14dip" /> </LinearLayout> <Button android:layout_width="60dip" android:layout_height="30dip" android:background="@drawable/ic_launcher" android:id="@+id/item3_dlbtn" android:layout_marginRight="10dip" android:text="安装" /> </LinearLayout> <TextView android:id="@+id/item3_apkdes" android:layout_width="fill_parent" android:layout_height="30dip" android:layout_marginLeft="5dip" android:layout_marginRight="5dip" android:gravity="center_vertical" android:text="应用程序描述" android:textSize="14dip" /> </LinearLayout>
接下来看bean类
ApkEntity
package com.imooc.listviewfrashdemo1; public class ApkEntity { private String name; private String des; private String info; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDes() { return des; } public void setDes(String des) { this.des = des; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } }
MainActivity
package com.imooc.listviewfrashdemo1; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import com.example.listviewfrashdemo1.R; import com.imooc.listviewfrashdemo1.ReFlashListView.IReflashListener; public class MainActivity extends Activity implements IReflashListener { ArrayList<ApkEntity> apk_list; MyAdapter adapter; ReFlashListView listview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 加载布局--只有一个listView setContentView(R.layout.activity_main); // 设置数据 setData(); //填充数据 showList(apk_list); } /** * 设置数据源 */ private void setData() { apk_list = new ArrayList<ApkEntity>(); for (int i = 0; i < 10; i++) { ApkEntity entity = new ApkEntity(); entity.setName("默认数据"); entity.setInfo("50w用户"); entity.setDes("这是一个神奇的应用"); apk_list.add(entity); } } private void showList(ArrayList<ApkEntity> apk_list) { if (adapter == null) { listview = (ReFlashListView) findViewById(R.id.listview); //为本类设置监听,然后implements IReflashListener listview.setInterface(this); adapter = new MyAdapter(this, apk_list); //如果适配器为null,设置适配器即可 listview.setAdapter(adapter); } else { //如果适配器不为null,就更新数据源,进行notifyDataSetChanged() adapter.onDateChange(apk_list); } } /** * 实现刷新操作的回调方法 */ @Override public void onReflush () { Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { // 获取最新数据 setReflashData(); // 通知界面显示 showList(apk_list); // 通知listview 刷新数据完毕!!!!!!!!!!!!!! listview.reflashComplete(); } }, 2000); } private void setReflashData() { for (int i = 0; i < 2; i++) { ApkEntity entity = new ApkEntity(); entity.setName("刷新数据"); entity.setDes("这是一个神奇的应用"); entity.setInfo("50w用户"); apk_list.add(0, entity); } } }
MyAdapter
package com.imooc.listviewfrashdemo1; import java.util.ArrayList; import com.example.listviewfrashdemo1.R; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class MyAdapter extends BaseAdapter { ArrayList<ApkEntity> apk_list; LayoutInflater inflater; public MyAdapter(Context context, ArrayList<ApkEntity> apk_list) { this.apk_list = apk_list; this.inflater = LayoutInflater.from(context); } public void onDateChange(ArrayList<ApkEntity> apk_list) { this.apk_list = apk_list; this.notifyDataSetChanged(); } @Override public int getCount() { return apk_list.size(); } @Override public Object getItem(int position) { return apk_list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ApkEntity entity = apk_list.get(position); ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.item_layout, null); holder.name_tv = (TextView) convertView .findViewById(R.id.item3_apkname); holder.des_tv = (TextView) convertView .findViewById(R.id.item3_apkdes); holder.info_tv = (TextView) convertView .findViewById(R.id.item3_apkinfo); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } holder.name_tv.setText(entity.getName()); holder.des_tv.setText(entity.getDes()); holder.info_tv.setText(entity.getInfo()); return convertView; } class ViewHolder { TextView name_tv; TextView des_tv; TextView info_tv; } }接下来看自定义listview类了(里面代码详细)
ReFlashListView
package com.imooc.listviewfrashdemo1; import java.text.SimpleDateFormat; import java.util.Date; 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.ViewGroup; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import com.example.listviewfrashdemo1.R; /** * 隐藏头布局--先测量父布局,获取头布局高度,设置padding,然后隐藏头布局,listview在添加头布局 * 设置监听事件 * 判断ontouch时间 * 设置监听加载刷新的数据 */ public class ReFlashListView extends ListView implements OnScrollListener { View header;// 顶部布局文件; int headerHeight;// 顶部布局文件的高度; int firstVisibleItem;// 当前第一个可见的item的位置; int scrollState;// listview 当前滚动状态; boolean isRemark;// 标记,当前是在listview最顶端摁下的; int startY;// 摁下时的Y值; int state;// 当前的状态; final int NONE = 0;// 正常状态; final int PULL = 1;// 提示下拉状态; final int RELESE = 2;// 提示释放状态; final int REFLASHING = 3;// 刷新状态; IReflashListener iReflushListener;//刷新数据的接口 /** * 三个构造方法,并且初始化视图 */ public ReFlashListView(Context context) { super(context); initView(context); } public ReFlashListView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public ReFlashListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } /** * 初始化界面,添加顶部布局文件到 listview */ private void initView(Context context) { LayoutInflater inflater = LayoutInflater.from(context); header = inflater.inflate(R.layout.header_layout, null); //先测量父布局,不然headerHeight为0 measureView(header); //获取头布局文件的高度 headerHeight = header.getMeasuredHeight(); Log.i("tag", "headerHeight = " + headerHeight); //隐藏头布局文件 topPadding(-headerHeight); //listview添加头布局 this.addHeaderView(header); //设置滑动监听 this.setOnScrollListener(this); } /** * 通知父布局,占用的宽,高; */ private void measureView(View view) { ViewGroup.LayoutParams p = view.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } /** * 因为listView不限制高度。child有多高,listView就给它多高的空间 * 但是listView是限制宽度的,所以需要getChildMeasureSpec */ int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); int height; //获取itme的高度值 int tempHeight = p.height; if (tempHeight > 0) { height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY); } else { height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } view.measure(width, height); } /** * 设置header 布局 上边距;--站在父布局的角度看待问题 */ private void topPadding(int topPadding) { header.setPadding(header.getPaddingLeft(), topPadding, header.getPaddingRight(), header.getPaddingBottom()); header.invalidate(); } /** * 实现接口方法 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.firstVisibleItem = firstVisibleItem; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { this.scrollState = scrollState; } /** * 实现touch方法 */ @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { /** * 如果手指按下,如果firstVisibleItem == 0就设置标记为true,代表是在最顶端按下的 * 并且获取按下的坐标Y轴距离 */ case MotionEvent.ACTION_DOWN: if (firstVisibleItem == 0) { isRemark = true; startY = (int) ev.getY(); } break; case MotionEvent.ACTION_MOVE: /** * 判断移动过程操作; */ onMove(ev); break; case MotionEvent.ACTION_UP: if (state == RELESE) { state = REFLASHING; // 加载最新数据; reflashViewByState(); iReflushListener.onReflush(); } else if (state == PULL) { state = NONE; isRemark = false; reflashViewByState(); } break; } return super.onTouchEvent(ev); } /** * 当手指按下 */ private void onMove(MotionEvent ev) { //如果不是在listview在最顶端时候按下的,直接返回,不做处理 if (!isRemark) { return; } int tempY = (int) ev.getY(); //获取移动的距离 int space = tempY - startY; //获取最新的头布局的padding值 int topPadding = space - headerHeight; switch (state) { /** * 判断刷新箭头的状态值 */ case NONE: //如果稍微移动就改成状态是--下拉可以刷新 if (space > 0) { //如果是正常状态,就修改状态为下拉可以刷新 state = PULL; //根据当前状态,改变界面显示; reflashViewByState(); } break; case PULL: //重绘最新的头布局隐藏程度 topPadding(topPadding); //如果比头布局高度还大于30就直接改变状态值 if (space-headerHeight> 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) { //修改状态为--松开可以刷新 state = RELESE; reflashViewByState(); } break; case RELESE: //重绘最新的头布局隐藏程度 topPadding(topPadding); if (space-headerHeight < 30) { //改变状态--下拉可以刷新 state = PULL; reflashViewByState(); } else if (space <= 0) { //当space<=0,即可见的item索引不是0 state = NONE; //还原 isRemark = false; reflashViewByState(); } break; } } /** * 根据当前状态,改变界面显示; */ private void reflashViewByState() { TextView tip = (TextView) header.findViewById(R.id.tip); ImageView arrow = (ImageView) header.findViewById(R.id.arrow); ProgressBar progress = (ProgressBar) header.findViewById(R.id.progress); RotateAnimation anim = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); anim.setDuration(500); anim.setFillAfter(true); RotateAnimation anim1 = new RotateAnimation(180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); anim1.setDuration(500); anim1.setFillAfter(true); switch (state) { case NONE: arrow.clearAnimation(); topPadding(-headerHeight); 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: topPadding(50); arrow.setVisibility(View.GONE); progress.setVisibility(View.VISIBLE); tip.setText("正在刷新..."); arrow.clearAnimation(); break; } } /** * 获取完数据; */ public void reflashComplete() { //将刷新状态还原成正常状态 state = NONE; //还原状态 isRemark = false; reflashViewByState(); TextView lastupdatetime = (TextView) header .findViewById(R.id.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); } public void setInterface(IReflashListener iReflushListener){ this.iReflushListener = iReflushListener; } /** * 刷新数据接口 * @author Administrator */ public interface IReflashListener{ public void onReflush(); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u013210620/article/details/47349049