天天看點

Android之listview下拉重新整理

       很久沒有更新了,老是忘記,哈哈。。。。。

      那麼今天就說一說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();

    }  

}

好了,到這裡下拉重新整理的操作就是完成了,我把全部的代碼都貼在上面了,其中會有注釋,希望你們能看明白。

因為曾經的我也為這個問題難為過,找了好多但都是一點,有的需要自己去嘗試怎麼跟自己寫的融合,很麻煩。是以我明白自己找到的代碼如果不能運作,還報一大堆的錯誤是多麼的坑人,我會盡量的把所有的代碼都給你們展示出來,希望你們看的高興。

就到這裡了。^-^         ^-^            ^-^