很久沒有更新了,老是忘記,哈哈。。。。。
那麼今天就說一說listview的下拉重新整理,通過這個我們可以學習到自定義view的一些屬性,還有需要重寫的一些方法,以及這些方法的作用。
雖然現在已經有下拉重新整理的一些成熟的庫了,例如PullToRefresh,有空你們可以去試一下,這個就比較簡單了,隻需調用裡面的方法就可以實作下拉重新整理的功能。
有興趣的朋友可以學習一下。
個人覺得我這個其實有一點點的麻煩,但畢竟是自己剛開始的時候第一次寫的一個自定義view,是以拿出來跟你們分享分享。下面就先貼出我的xml檔案中的代碼吧,必要的地方我會一些注釋的。
這個是首頁面的xml檔案,是自定義listview的包名,
<com.example.reflashlistview.FlashListView
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
這個是listview的item的布局
<?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" >
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="25dp"
android:textColor="#66ff0000"
android:text="文本一"
/>
</LinearLayout>
這個是頭布局的檔案
<?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" >
<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:orientation="vertical"
android:layout_centerInParent="true"
android:id="@+id/linear"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉可以重新整理"
android:id="@+id/update"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/updatetime"
/>
</LinearLayout>
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/xia"
android:id="@+id/image"
android:layout_toLeftOf="@id/linear"
android:layout_marginRight="20dp"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progress"
style="?android:attr/progressBarStyleSmall"
android:visibility="gone"
android:layout_toLeftOf="@id/linear"
android:layout_marginRight="20dp"
/>
</RelativeLayout>
</LinearLayout>
好了,就到正文了,先貼出自定義view的代碼
public class FlashListView extends ListView implements OnScrollListener{
View header;
int headerHeight;
int firstVisibleItem;//目前第一個可見的Item的位置
boolean isRemark;//标記,目前是在listview的最低端嗯下的
int startY;//摁下時的y值
int scrollState;//listview目前滾動的狀态
int state;//目前的狀态
final int NONE=0;//目前狀态
final int PULL=1;//提示下拉狀态
final int RELESE=2;//提示釋放狀态
final int REFLASHING=3;//重新整理狀态
IReflashListener listener;//重新整理資料的接口
private TextView text;
private ProgressBar bar;
private ImageView image;
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
finish();
};
};
//這是要重寫的構造方法
public FlashListView(Context context) {
super(context);
initView(context);
}
public FlashListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public FlashListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
//重新整理完成後讓頭布局繼續隐藏,并恢複到原來的狀态
public void finish(){
if(state==REFLASHING){
state=PULL;
text.setText("下拉重新整理");
bar.setVisibility(View.INVISIBLE);
image.setVisibility(View.VISIBLE);
header.setPadding(0, -headerHeight, 0, 0);
}
}
//初始化界面,添加頂部檔案到listview中
private void initView(Context context){
LayoutInflater inflater = LayoutInflater.from(context);
header=inflater.inflate(R.layout.header, null);
text = (TextView) findViewById(R.id.update);
bar = (ProgressBar) findViewById(R.id.progress);
image = (ImageView) findViewById(R.id.image);
measureView(header);
headerHeight=header.getMeasuredHeight();
topPadding(-headerHeight);//高度是0
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);
}
int width=ViewGroup.getChildMeasureSpec(0, 0, p.width);
int height;
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;
}
//
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
if(firstVisibleItem==0){
isRemark=true;
startY=(int) ev.getY();
reflashViewByState();
}
break;
case MotionEvent.ACTION_MOVE:
onMove(ev);
reflashViewByState();
break;
case MotionEvent.ACTION_UP:
if(state==RELESE){
state=REFLASHING;
reflashViewByState();
//加載最新資料
}else if(state==PULL){
state=NONE;
isRemark=false;
reflashViewByState();
listener.onReflash();
}
break;
}
return super.onTouchEvent(ev);
}
//根據提示目前狀态,改變界面顯示
private void reflashViewByState(){
TextView textview = (TextView) header.findViewById(R.id.update);
ImageView image = (ImageView) header.findViewById(R.id.image);
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:
image.clearAnimation();
topPadding(-headerHeight);
break;
case PULL:
image.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textview.setText("下拉可以重新整理");
image.clearAnimation();
image.setAnimation(anim1);
break;
case RELESE:
image.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textview.setText("松開可以重新整理");
image.clearAnimation();
image.setAnimation(anim);
break;
case REFLASHING:
topPadding(50);
image.setVisibility(View.GONE);
progress.setVisibility(View.VISIBLE);
textview.setText("正在重新整理...");
image.clearAnimation();
break;
}
}
//判斷移動過程中的操作
private void onMove(MotionEvent ev){
if(!isRemark){
return;
}
int tempY=(int) ev.getY();
int space=tempY-startY;
int topPadding =space-headerHeight;
switch (state) {
case NONE:
if(space>0){
state=PULL;
reflashViewByState();
}
break;
case PULL:
topPadding(topPadding);
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){
state=NONE;
isRemark=false;
reflashViewByState();
}
break;
case REFLASHING:
topPadding(topPadding);
if(space<headerHeight+30){
state=PULL;
reflashViewByState();
}else if(space<=0){
state=NONE;
isRemark=false;
reflashViewByState();
}
break;
}
}
//擷取完資料
public void reflashComplete(){
state=NONE;
isRemark=false;
reflashViewByState();
TextView updateTime = (TextView) header.findViewById(R.id.updatetime);
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日hh:mm:ss");
Date date = new Date(System.currentTimeMillis());
String time = format.format(date);
updateTime.setText(time);
}
public void setInterface(IReflashListener listener){
this.listener=listener;
}
//重新整理資料接口
public interface IReflashListener{
public void onReflash();
}
}
然後是在主activity的操作,這裡就比較簡單了
public class MainActivity extends Activity implements IReflashListener{
private FlashListView ll;
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = (FlashListView) findViewById(R.id.ll);
ll.setInterface(this);
ll.setAdapter(new MyAdapter());
}
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return 100;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if(convertView==null){
view=View.inflate(getApplicationContext(), R.layout.item, null);
}else{
view=convertView;
}
ImageView image = (ImageView) view.findViewById(R.id.image);
text = (TextView) view.findViewById(R.id.text);
text.setText("文本"+position);
image.setBackgroundResource(R.drawable.ic_launcher);
return view;
}
}
@Override
public void onReflash() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
ll.reflashComplete();
}
}, 2000);
//擷取最新資料
//通知界面顯示
//通知listview重新整理資料完畢
ll.finish();
}
}
好了,到這裡下拉重新整理的操作就是完成了,我把全部的代碼都貼在上面了,其中會有注釋,希望你們能看明白。
因為曾經的我也為這個問題難為過,找了好多但都是一點,有的需要自己去嘗試怎麼跟自己寫的融合,很麻煩。是以我明白自己找到的代碼如果不能運作,還報一大堆的錯誤是多麼的坑人,我會盡量的把所有的代碼都給你們展示出來,希望你們看的高興。
就到這裡了。^-^ ^-^ ^-^