欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義ListView實現(xiàn)下拉刷新上拉加載更多

 更新時間:2022年10月09日 09:29:08   作者:TMusketeer  
Listview現(xiàn)在用的很少了,基本都是使用Recycleview,但是不得不說Listview具有劃時代的意義,我們可以自己添加下拉刷新,上拉加載更多功能。本文就來利用自定義ListView實現(xiàn)下拉刷新上拉加載更多效果,需要的可以參考一下

Listview現(xiàn)在用的很少了,基本都是使用Recycleview,但是不得不說Listview具有劃時代的意義,拓展性很強,我們可以自己添加下拉刷新,上拉加載更多功能。他和recycleview不同,他生來具有addHeaderView和addFooterView的功能,這也導致同樣都是列表控件,實現(xiàn)上拉下拉的方式缺截然不同。

效果圖

1、創(chuàng)建刷新控件

public class MyListview extends ListView {


    public MyListview(Context context) {
        this(context,null);
    }

    public MyListview(Context context, AttributeSet attrs) {
        this(context,attrs,0);
    }

    public MyListview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    public void init(Context context) {


    }

1.1、創(chuàng)建頭部View

頭部樣式,我寫的是最簡單的,根據(jù)業(yè)務需求來定,下拉的時候無非就是幾種

  • 產品logo作為箭頭轉動的icon
  • 添加刷新時間
  • 加入其他具有特色的動效

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center"
    tools:ignore="MissingDefaultResource">
    <ProgressBar
        android:layout_width="20dp"
        android:layout_height="match_parent"
        style="?android:attr/progressBarStyle"
        android:layout_marginEnd="10dp"
        android:indeterminateTint="#E8AD56"
        />
    <TextView
        android:id="@+id/header_text"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:text="我是頭部"
        android:gravity="center"
        android:textColor="#E8AD56"/>
</LinearLayout>

樣式寫好后,我們需要添加到我們控件中,addHeaderView就起到作用了

public void init(Context context) {
    //添加頭部
    viewHeader = View.inflate(context, R.layout.view_header, null);
    viewHeader.measure(0, 0);
    //讓系統(tǒng)自動檢測頭部高度
    heightHeader = viewHeader.getMeasuredHeight();
    header_text = viewHeader.findViewById(R.id.header_text);
    viewHeader.setPadding(0, -heightHeader, 0, 0);
    this.addHeaderView(viewHeader);
}

一些控件我定義成全局的是因為下面會用到。setPadding可以設置顯示位置,左上右下,上為負數(shù)就是隱藏在頂部。我們需要手指下拉去控制他緩慢顯示,就用到了OnTouchListener,我們實現(xiàn)OnTouch方法做一些事件的分發(fā)處理。

1.2、下拉事件

public class MyListview extends ListView implements View.OnTouchListener{
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }
   public void init(Context context){
       setOnTouchListener(this);
   }
}

注意:別忘記了setOnTouchListener在init中添加

這時候我們需要對event的down,move,up事件進行邏輯處理,當手指按在屏幕時會觸發(fā)事件,一個down事件,0~無數(shù)次move事件,一個up事件,這里面著重對move事件做處理,我們記錄一下down事件的Y,因為是上下拉動,沒必要計算X。然后diffY就是手指滑動的距離,我們需要處理一下這個值,因為值太大,而且值是整數(shù),會讓我們下拉的時候產生錯亂,我們本意是讓其從-100到0緩慢滑出(比如頭部高度是100,從隱藏到顯示就是-100到0),小伙伴都可以試試viewHeader.setPadding(0, diffY, 0, 0);和viewHeader.setPadding(0, paddY, 0, 0);效果是不一樣的,diff/3是讓其有種阻尼的感覺,不然的話會很塊就被拉出來了。還有事件消費的話一定要return true。

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downY = (int) event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            moveY = (int) event.getY();
            diffY = moveY - downY;
            //滑動的距離
            paddY = - heightHeader + diffY / 3;
            viewHeader.setPadding(0, paddY, 0, 0);
            return true;
            //break;
        case MotionEvent.ACTION_UP:

            break;
    }
    return false;
}

我們下面要做下拉時給人的反饋,我們下拉時有3種狀態(tài)分別是

  • 開始刷新  (下拉距離不超過100)
  • 釋放刷新   (下拉距離超過100)
  • 刷新中    (手指釋放,up事件處理)

//屬性-開始刷新狀態(tài)
private final int PULL_REFRESH_STATE = 0;
private final int PULL_REFRESH_RELEASE = 1;//釋放刷新
private final int PULL_REFRESHING = 2;//正在刷新
private int pull_current_state = PULL_REFRESH_STATE;//當前狀態(tài)
public void updateHeaderState() {
    switch (pull_current_state) {
        //開始
        case PULL_REFRESH_STATE:
            header_text.setText("開始刷新");
            viewHeader.setPadding(0, -heightHeader, 0, 0);
            break;
        //釋放
        case PULL_REFRESH_RELEASE:
            header_text.setText("釋放刷新");
            break;
        //正在
        case PULL_REFRESHING:
            header_text.setText("刷新中.......");
            viewHeader.setPadding(0, 0, 0, 0);
            break;

    }
}

我們只需要判斷是否處于刷新中,如果不是,則計算是不是第一個item可見并且滑動距離大于0,證明手指滑動了。然后不同滑出高度顯示不同的文字即可。

@Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                moveY = (int) event.getY();
                diffY = moveY - downY;
                //滑動的距離
                paddY = - heightHeader + diffY / 3;
                //如果是正在刷新中不做任何操作
                if (pull_current_state == PULL_REFRESHING) {
                    return false;
                }
//                下拉//第一條,并且滑動距離大于0
                if (getFirstVisiblePosition() == 0 && diffY > 0) {
                    if (paddY > 0 && pull_current_state != PULL_REFRESH_RELEASE) {
                        //釋放刷新
                        pull_current_state = PULL_REFRESH_RELEASE;
                        updateHeaderState();
                    } else if (paddY < 0 && pull_current_state != PULL_REFRESH_STATE) {
                        pull_current_state = PULL_REFRESH_STATE;
                        header_text.setText("開始刷新");
                        updateHeaderState();
                    }
                    viewHeader.setPadding(0, paddY, 0, 0);
                    return true;
                }

                break;
            case MotionEvent.ACTION_UP:
                if (pull_current_state == PULL_REFRESH_STATE) {
                    updateHeaderState();
                } else if (pull_current_state == PULL_REFRESH_RELEASE) {
                    pull_current_state = PULL_REFRESHING;
                    updateHeaderState();
                }
                break;
        }
        return false;
    }

1.3、接口回調

我們需要狀態(tài)根據(jù)業(yè)務來動態(tài)調整,在可以刷新的時候做一些邏輯處理,同時處理完了,調整狀態(tài)。

public void setPullDownFinish() {
    pull_current_state = PULL_REFRESH_STATE;
    viewHeader.setPadding(0, -heightHeader, 0, 0);
}
public IPullDownRefreshService iPullDownRefreshService;
public interface IPullDownRefreshService {
    void onPullDownRefresh();//下拉刷新

    void onLoadMore();//上拉加載更多刷新
}

public void setOnRefreshListener(IPullDownRefreshService iPullDownRefreshService) {
    this.iPullDownRefreshService = iPullDownRefreshService;
}

準備工作做好后,我們在更新狀態(tài)的地方調用

public void updateHeaderState() {
    switch (pull_current_state) {
        //開始
        case PULL_REFRESH_STATE:
            break;
        //釋放
        case PULL_REFRESH_RELEASE:
            break;
        //正在
        case PULL_REFRESHING:
            header_text.setText("刷新中.......");
            viewHeader.setPadding(0, 0, 0, 0);
            if (iPullDownRefreshService != null) {
                iPullDownRefreshService.onPullDownRefresh();
            }
            break;

    }
}

Activity中使用,來一個3秒刷新完成

mBinding.listview.setOnRefreshListener(new MyListview.IPullDownRefreshService() {
            @Override
            public void onPullDownRefresh() {
                refreshSuccess();
                Toast.makeText(ActivityRefresh.this, "下拉-加載中.....", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onLoadMore() {
                Toast.makeText(ActivityRefresh.this, "more-加載中.....", Toast.LENGTH_SHORT).show();
            }
        });

    CountDownTimer countDownTimer;
    public void refreshSuccess() {
        if (countDownTimer == null) {
            countDownTimer = new CountDownTimer(3000, 1000) {

                @Override
                public void onTick(long millisUntilFinished) {

                }

                @Override
                public void onFinish() {
                    mBinding.listview.setPullDownFinish();
                    countDownTimer.cancel();
                    countDownTimer = null;
                }
            }.start();
        }
    }

到這下拉刷新就結束了。

上拉加載更多也是如此

2、上拉加載更多

2.1、底部樣式

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center"
    tools:ignore="MissingDefaultResource">
    <ProgressBar
        android:id="@+id/footer_prggress"
        android:layout_width="20dp"
        android:layout_height="match_parent"
        style="?android:attr/progressBarStyle"
        android:layout_marginEnd="10dp"
        android:indeterminateTint="#E8AD56"
        />
    <TextView
        android:id="@+id/footer_text"
        android:layout_width="wrap_content"
        android:layout_height="70dp"
        android:text="正在加載更多"
        android:gravity="center"
        android:textColor="#E8AD56"/>

</LinearLayout>

2.2、布局添加

public void init(Context context) {
    viewFooter = View.inflate(context, R.layout.view_footer, null);
    viewFooter.measure(0, 0);
    footer_text = viewFooter.findViewById(R.id.footer_text);
    footer_prggress = viewFooter.findViewById(R.id.footer_prggress);
    heightFooter = viewFooter.getMeasuredHeight();
    viewFooter.setPadding(0, -heightFooter, 0, 0);
    this.addFooterView(viewFooter);
}

到這里也布局算是添加完畢了,加載更多實現(xiàn)方式不同,我羅列兩種

  • 結合OnTouchListener
  • 結合OnScrollListener

方式一

這里我先說方式一,因為我們下拉也是用的OnTouchListener,上拉加載也有幾種狀態(tài),有加載中,還有暫無數(shù)據(jù),普遍大家會寫, 已經到底了~,一直顯示在最底部,提示用戶沒數(shù)據(jù)了,從而我們控件的上拉事件不可觸發(fā)狀態(tài)。

private final int MORE_LOAD_STATE = 10;
private final int MORE_LOADING = 11;
private final int MORE_NO = 12;//已加載全部數(shù)據(jù)
private int more_current_state = MORE_LOAD_STATE;//當前狀態(tài)

只有一點需要注意paddFooterY = paddFooterY > heightFooter ? 0 : paddFooterY;來判斷不能滑出底部的高度。

@Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                moveY = (int) event.getY();
                diffY = moveY - downY;
                //滑動的距離
                paddFooterY = heightFooter - diffY/3 ;  
                //上拉加載更多
                if (getLastVisiblePosition() == getCount() - 1 && more_current_state != MORE_NO) {
                    if( more_current_state!=MORE_LOADING){
                        more_current_state = MORE_LOADING;
                        if (iPullDownRefreshService != null) {
                            iPullDownRefreshService.onLoadMore();
                        }
                    }
                    paddFooterY = paddFooterY > heightFooter ? 0 : paddFooterY;
                    viewFooter.setPadding(0,paddFooterY , 0, 0);
                     return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return false;
    }

方式二

public class MyListview extends ListView implements View.OnTouchListener, AbsListView.OnScrollListener{
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        //沒有滾動,或者已經用戶觸摸滾動動畫結束
        if(scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_FLING){
            //最后一個可見
            if(getLastVisiblePosition() == getCount()-1){
                viewFooter.setPadding(0,0,0,0);
                if(iPullDownRefreshService!=null){
                    iPullDownRefreshService.onLoadMore();
                }
            }
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

}

注意:在init方法中添加

public void init(Context context) {
    setOnTouchListener(this);
    ......
    this.setOnScrollListener(this);
}

到此這篇關于Android自定義ListView實現(xiàn)下拉刷新上拉加載更多的文章就介紹到這了,更多相關Android ListView下拉刷新上拉加載內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論