亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

android下拉刷新ListView的介紹和實(shí)現(xiàn)代碼

 更新時(shí)間:2013年04月21日 21:26:09   作者:  
在當(dāng)下,列表組件不帶下拉刷新的都不好意思叫列表。第一次完成列表的下拉刷新功能的時(shí)候,直接在Activity中實(shí)現(xiàn),雖然功能上是實(shí)現(xiàn)了,總體上感覺(jué)很亂。所以第二次用到的時(shí)候,就想著封裝成一個(gè)組件,實(shí)現(xiàn)和Activity的解耦。

    大致上,我們發(fā)現(xiàn),下拉刷新的列表和一般列表的區(qū)別是,當(dāng)滾動(dòng)條在頂端的時(shí)候,再往下拉動(dòng)就會(huì)把整個(gè)列表拉下來(lái),顯示出松開(kāi)刷新的提示。由此可以看出,在構(gòu)建這個(gè)下拉刷新的組件的時(shí)候,只用繼承ListView,然后重寫(xiě)onTouchEvent就能實(shí)現(xiàn)。還有就是要能在xml布局文件中引用,還需要一個(gè)參數(shù)為Context,AttributeSet的構(gòu)造函數(shù)。

  表面上的功能大概就這些了。另一方面,刷新的行為似乎還沒(méi)有定義,在刷新前做什么,刷新時(shí)要做什么,刷新完成后要做什么,這些行為寫(xiě)入一個(gè)接口中,然后讓組件去實(shí)現(xiàn)。

  在整個(gè)組件的實(shí)現(xiàn)中,主體部分自然是onTouchEvent的部分。這里需要做一些說(shuō)明,在ListView中,數(shù)據(jù)的滾動(dòng)和ListView.scrollTo的行為是不一樣的。數(shù)據(jù)的滾動(dòng)是大概適配器的事。所以在不滿足下拉整個(gè)列表的條件下,onTouchEvent 應(yīng)該返回super.onTouchEvent(ev),讓ListView組件原本的OnTouchEvent去處理。

  考慮到組件的id和表頭的布局需要事先定義,同時(shí)我想把這個(gè)組件應(yīng)用于多個(gè)項(xiàng)目里,所以就把這個(gè)組件作為一個(gè)Library去實(shí)現(xiàn)。

     下面就是具體的實(shí)現(xiàn)代碼。

  首先來(lái)看一下表頭的布局文件chenzong_push_refresh_header.xml:

復(fù)制代碼 代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="40dip"
       >
    <ImageView
        android:layout_width="30dip"
        android:layout_height="40dip"
        android:background="@drawable/arrow_down"
           android:layout_alignParentLeft="true"
        android:id="@+id/push_refresh_header_img"
        android:layout_marginLeft="10dip"
        />
    <ProgressBar
        android:layout_width="40dip"
        android:layout_height="40dip"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="10dip"
        android:id="@+id/push_refresh_header_pb"
        style="@android:style/Widget.ProgressBar.Inverse"
        android:visibility="gone"/>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:orientation="vertical"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="最近一次更新在:"
            android:textColor="#000000"
            />
        <TextView
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:id="@+id/push_refresh_header_date"
            android:textColor="#000000"
            android:text="2013-03-04 08:03:38"/>
    </LinearLayout>
</RelativeLayout>

       箭頭、processBar和最近的一次刷新時(shí)間,表頭文件就這三個(gè)元素。

       刷新的行為接口RefreshOperation的代碼:

復(fù)制代碼 代碼如下:

public interface RefreshOperation {
    public void OnRefreshStart();
    public void OnRefreshing();
    public void OnRefreshEnd();
}

     列表拉下來(lái)時(shí),箭頭翻轉(zhuǎn)的動(dòng)畫(huà)arrow_rotate.xml:

復(fù)制代碼 代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:fromDegrees="0"
    android:toDegrees="180"
    android:duration="300"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fillAfter="true"
    android:repeatCount="0">

</rotate>

      這些文件和一些資源文件備齊了之后,接下來(lái)就是下拉刷新列表PushRefreshList的具體實(shí)現(xiàn):

復(fù)制代碼 代碼如下:

package com.chenzong;

import java.util.Calendar;

import com.doall.pushrefreshlist.R;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ListView;
import android.widget.TextView;


public class PushRefreshList extends ListView implements RefreshOperation{

    private int header_layout=R.layout.chenzong_push_refresh_header;
    //表頭文件
    private int arrow_down=R.drawable.arrow_down;
    //箭頭往下的資源
    private int arrow_up=R.drawable.arrow_up;
    //箭頭往上的資源
    private int img=R.id.push_refresh_header_img;
    //顯示箭頭的控件id
    private int pb=R.id.push_refresh_header_pb;
    //刷新時(shí)的進(jìn)度條
    private int startPoint=0;
    //觸摸的起始點(diǎn)
    private RefreshOperation refresh;
    //刷新行為的對(duì)象
    private Animation animation=null;
    private Context context;
    private View headerView;
    private int minPushHeight;

   
    private final String TAG="pushRefresh";

    public PushRefreshList(Context cotext, AttributeSet attrs) {
        super(context, attrs);
        View empty=new View(context);
        //判斷是否到列表的頂端,通常要用到this.getFirstVisiblePosition(),這里創(chuàng)建一個(gè)高度的為零View,加到headerView和數(shù)據(jù)之間
        this.addHeaderView(empty);
        LayoutInflater inflater=LayoutInflater.from(context);
        headerView=inflater.inflate(header_layout, null);
        this.addHeaderView(headerView);
        this.setRefreshOperation(this);
        this.context=context;

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        this.minPushHeight=headerView.getMeasuredHeight();
        //獲取下拉刷新的觸發(fā)高度
        super.onLayout(changed, l, t, r, b);
    }

    private boolean canHandleEvent(int dy)
    {
        return (dy<0&&this.getFirstVisiblePosition()==0&&!isPbVisible());
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        int action=ev.getAction();
        switch(action)
        {
        case MotionEvent.ACTION_DOWN:
            startPoint=(int)ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            int dy=startPoint-(int)ev.getY();
            if(canHandleEvent(dy))
            {
                if(animation==null)
                {
                    if(Math.abs(this.getScrollY())>=this.minPushHeight)
                    {   
                        animation=AnimationUtils.loadAnimation(context, R.anim.arrow_rotate);
                        View mView=headerView.findViewById(img);
                        mView.startAnimation(animation);
                        this.setScrollbarFadingEnabled(true);
                    }
                }
                this.scrollTo(0,dy/2);   
                return true;
            }
            break;
        case MotionEvent.ACTION_UP:

                this.setScrollbarFadingEnabled(false);
                if(animation!=null)
                {
                    setImgBackgroundUp();
                    switchCompent(View.INVISIBLE,View.VISIBLE);
                    this.scrollTo(0,-minPushHeight);
                    PushRefreshList.this.refresh.OnRefreshStart();
                    new Thread(mRunnable).start();
                    animation=null;
                }
                else
                    this.scrollTo(0,0);
            break;
        }
        return super.onTouchEvent(ev);
    }

    private Runnable mRunnable=new Runnable()
    {

        @Override
        public void run() {
            PushRefreshList.this.refresh.OnRefreshing();
            mHandler.obtainMessage().sendToTarget();
        }
    };

    private Handler mHandler=new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            PushRefreshList.this.refresh.OnRefreshEnd();
            PushRefreshList.this.scrollTo(0, 0);
            PushRefreshList.this.setImgBackgroundDown();
            PushRefreshList.this.switchCompent(View.VISIBLE, View.GONE);
            TextView tv=(TextView)headerView.findViewById(R.id.push_refresh_header_date);
            tv.setText(this.getDateStr());
        }

        private String getDateStr()
        {
            Calendar ca=Calendar.getInstance();
            int year=ca.get(Calendar.YEAR);
            int month=ca.get(Calendar.MONTH);
            int date=ca.get(Calendar.DATE);
            int hour=ca.get(Calendar.HOUR);
            int mintes=ca.get(Calendar.MINUTE);
            int second=ca.get(Calendar.SECOND);
            return year+"-"+(month+1)+"-"+date+" "+hour+":"+mintes+":"+second;
        }
    };

    private void switchCompent(int imgStatus,int pbStatus)
    {
        View img=headerView.findViewById(R.id.push_refresh_header_img);
        img.clearAnimation();
        //執(zhí)行了動(dòng)畫(huà)的控件如果不調(diào)用clearAnimation,setVisibility(View.GONE)會(huì)失效
        img.setVisibility(imgStatus);
        headerView.findViewById(R.id.push_refresh_header_pb).setVisibility(pbStatus);
    }

    private boolean isPbVisible()
    {
        return View.VISIBLE==headerView.findViewById(R.id.push_refresh_header_pb).getVisibility();
    }

    private void setImgBackgroundUp()
    {
        View mView=headerView.findViewById(this.img);
        mView.setBackgroundResource(arrow_up);
    }

    private void setImgBackgroundDown()
    {
        View mView=headerView.findViewById(this.img);
        mView.setBackgroundResource(arrow_down);
    }

    public void setRefreshOperation(RefreshOperation refresh)
    {
        this.refresh=refresh;
    }

    @Override
    public void OnRefreshStart() {

    }

    @Override
    public void OnRefreshing() {

    }

    @Override
    public void OnRefreshEnd() {
    }

相關(guān)文章

  • android自定義ImageView仿圖片上傳示例

    android自定義ImageView仿圖片上傳示例

    本篇文章主要介紹了android自定義ImageView仿圖片上傳,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-01-01
  • Android自定義View實(shí)現(xiàn)時(shí)鐘效果

    Android自定義View實(shí)現(xiàn)時(shí)鐘效果

    這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Android仿微信選擇圖片和拍照功能

    Android仿微信選擇圖片和拍照功能

    這篇文章主要為大家詳細(xì)介紹了Android仿微信選擇圖片和拍照功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android zip文件下載和解壓實(shí)例

    Android zip文件下載和解壓實(shí)例

    這篇文章主要介紹了Android zip文件下載和解壓實(shí)例,有需要的朋友可以參考一下
    2014-01-01
  • Android自定義View中Paint、Rect、Canvas介紹(一)

    Android自定義View中Paint、Rect、Canvas介紹(一)

    這篇文章主要為大家詳細(xì)介紹了Android自定義View中Paint、Rect、Canvas的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android AlertDialog多種創(chuàng)建方式案例詳解

    Android AlertDialog多種創(chuàng)建方式案例詳解

    這篇文章主要介紹了Android AlertDialog多種創(chuàng)建方式案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • PagerSlidingTabStrip制作Android帶標(biāo)簽的多界面滑動(dòng)切換

    PagerSlidingTabStrip制作Android帶標(biāo)簽的多界面滑動(dòng)切換

    這篇文章主要介紹了使用PagerSlidingTabStrip制作Android帶標(biāo)簽的多界面滑動(dòng)切換效果的方法,PagerSlidingTabStrip是GitHub上的一個(gè)開(kāi)源項(xiàng)目,調(diào)用這個(gè)庫(kù)可以少寫(xiě)不少代碼XD 需要的朋友可以參考下
    2016-04-04
  • Android編程設(shè)計(jì)模式之原型模式實(shí)例詳解

    Android編程設(shè)計(jì)模式之原型模式實(shí)例詳解

    這篇文章主要介紹了Android編程設(shè)計(jì)模式之原型模式,結(jié)合實(shí)例形式詳細(xì)分析了Android設(shè)計(jì)模式之原型模式的概念、原理、定義、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-12-12
  • Android 3D旋轉(zhuǎn)動(dòng)畫(huà)效果實(shí)現(xiàn)分解

    Android 3D旋轉(zhuǎn)動(dòng)畫(huà)效果實(shí)現(xiàn)分解

    如何實(shí)現(xiàn)View的3D旋轉(zhuǎn)效果,實(shí)現(xiàn)的主要原理就是圍繞Y軸旋轉(zhuǎn),同時(shí)在Z軸方面上有一個(gè)深入的縮放,具體實(shí)現(xiàn)代碼如下,感興趣的朋友可以參考下哈
    2013-06-06
  • Android文件讀寫(xiě)的幾種方式

    Android文件讀寫(xiě)的幾種方式

    文件讀寫(xiě)作為Android四大數(shù)據(jù)存儲(chǔ)方式之一,又分為內(nèi)部存儲(chǔ)和外部存儲(chǔ)兩種,下面這篇文章主要給大家介紹了關(guān)于Android文件讀寫(xiě)的幾種方式,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06

最新評(píng)論