<?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="match_parent"
android:gravity="center"
>
<ImageView
android:id="@+id/image_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/indicator_arrow"
/>
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@mipmap/indicate_rotate"
android:visibility="invisible"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toRightOf="@id/image_arrow"
>
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="下拉刷新"
/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="20dp"
android:text="最後刷新2016-6-17"
/>
</LinearLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ProgressBar
android:id="@+id/itme1bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:indeterminateDrawable="@mipmap/indicate_rotate"
android:visibility="visible"
/>
<TextView
android:id="@+id/itme1textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff00"
android:layout_marginLeft="30dp"
android:textStyle="bold"
android:textSize="25sp"
android:text="加載更多........"
/>
</LinearLayout>
package com.example.administrator.app4;
import android.content.Context;
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.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* Created by Administrator on 2016/6/17 0017.
* <p/>
* 自定義ListView,把佈局加載到ListView中
*/
public class PullListView extends ListView {
private ImageView image_arrow;//箭頭圖片(頂部、底部)
private ProgressBar progressBar,itme1bar;//進度條(頂部)
private TextView tv_state, tv_time,itme1textview;//頂部顯示的文字、底部
private int headerHeight;//添加的頂部佈局高度
private View headerView;//添加的佈局(View對象,頂部)
private View footerView;//底部佈局
private boolean isComplete = false;//判斷是否拖動到底部了
public PullListView(Context context) {
super(context);
init();
}
public PullListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
initHeaderView();//初始化頂部View
initFooterView();//底部View
initAnimation();//動畫的方法
this.setOnScrollListener(//ListrView添加滑動事件
new OnScrollListener() {
@Override//開始和結束拖地時會調用該方法
public void onScrollStateChanged(AbsListView view, int scrollState) {
//停止拖地 到底部
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && isComplete) {
//加載更多的數據
footerView.setPadding(0, 0, 0, 0);
if (pullRefreshInterface != null) {
itme1textview.setText("正在加載更多......");
itme1bar.setVisibility(VISIBLE);//顯示進度條
itme1bar.startAnimation(animationBar);//設置進度條啓動動畫
pullRefreshInterface.onMore();
}
}
}
@Override//拖地的過程中會調用該方法
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
isComplete = firstVisibleItem + visibleItemCount == totalItemCount;//到底了
}
}
);
}
private void initFooterView() {//底部佈局View
LayoutInflater inflater = LayoutInflater.from(getContext());
footerView = inflater.inflate(R.layout.itme1, null);
itme1bar= (ProgressBar) footerView.findViewById(R.id.itme1bar);
itme1textview= (TextView) footerView.findViewById(R.id.itme1textview);//找到底部的控件
footerView.measure(0, 0);//強制執行該方法,測量控件大小
int footer_height = footerView.getMeasuredHeight();
//設置內邊距(隱藏)
footerView.setPadding(0,-footer_height,0,0);
//把View對象添加到ListView的底部
this.addFooterView(footerView);
}
private void initHeaderView() {//頂部View
LayoutInflater inflater = LayoutInflater.from(getContext());
headerView = inflater.inflate(R.layout.itme, null);
image_arrow = (ImageView) headerView.findViewById(R.id.image_arrow);
progressBar = (ProgressBar) headerView.findViewById(R.id.progressbar);
tv_state = (TextView) headerView.findViewById(R.id.tv_state);
tv_time = (TextView) headerView.findViewById(R.id.tv_time);
//獲取佈局的高度
headerView.measure(0, 0);
headerHeight = headerView.getMeasuredHeight();
headerView.setPadding(0, -headerHeight, 0, 0);//設置內邊距,不可見
this.addHeaderView(headerView);//把View對象加載到ListView的頂部
}
private float down_y;//點擊的Y座標
//定義表示ListView狀態的常量
private final int PULLREFRESH = 0;//下拉刷新
private final int RELLRESH = 1;//鬆開刷新
private final int RELLRESHING = 2;//正在刷新
private int currentState = PULLREFRESH;//記錄當前狀態(初始化爲下拉刷新)
private int paddingTop = 0;
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {//判斷ListView的狀態
case MotionEvent.ACTION_DOWN://按下狀態
down_y = ev.getY();//獲得按下的Y座標(高度)
break;
case MotionEvent.ACTION_MOVE://移動狀態
float y = ev.getY();
//往下拉(獲得用戶往下拉的距離,高度)
int length = (int) (y - down_y);
paddingTop = length - headerHeight;//往下拉的距離和頂部View的內邊距
//正在刷新
if (currentState == RELLRESHING) {
break;
}
//大於頂部View的高度
if (paddingTop > -headerHeight && getFirstVisiblePosition() == 0) {
headerView.setPadding(0, paddingTop, 0, 0);//設置頂部的內邊距
//下拉刷新
if (paddingTop >= 0 && currentState == PULLREFRESH) {//正在刷新
currentState = RELLRESH;//鬆開刷新
refreshState(); //鬆開刷新
} else if (paddingTop < 0 && currentState == RELLRESH) {
currentState = PULLREFRESH;//正在刷新
refreshState();//處理事件的方法
}
return true;//ListView不用處理滑動事件
}
break;
case MotionEvent.ACTION_UP://鬆開狀態
if (currentState == PULLREFRESH) {//下拉刷新
headerView.setPadding(0, -headerHeight, 0, 0);
} else if (currentState == RELLRESH) {//鬆開刷新
currentState = RELLRESHING;//正在刷新
refreshState();
if (pullRefreshInterface!=null) {//接口對象不爲空
pullRefreshInterface.onPull();//調用自己的方法
}
}
}
return super.onTouchEvent(ev);//不消費此次觸屏事件
}
private PullRefreshInterface pullRefreshInterface;//接口對象
private RotateAnimation animationUp,animationDown,animationBar;//旋轉的補間動畫對象
public void setPullRefreshInterface(PullRefreshInterface pullRefreshInterface) {
this.pullRefreshInterface = pullRefreshInterface;
}
public interface PullRefreshInterface {//回調的接口
public void onPull();
public void onMore();
}
private void refreshState() {//修改界面的顯示
switch (currentState) {//當前狀態
case PULLREFRESH://下拉刷新
tv_state.setText("下拉刷新");
//圖片控件開始執行動畫
image_arrow.startAnimation(animationDown);
break;
case RELLRESH://鬆開刷新
tv_state.setText("鬆開刷新");
image_arrow.startAnimation(animationUp);
break;
case RELLRESHING://正在刷新
tv_state.setText("正在刷新");
headerView.setPadding(0, 0, 0, 0);//設置內邊距(完全顯示)
//動畫取消、箭頭消失
image_arrow.clearAnimation();//取消動畫
image_arrow.setVisibility(INVISIBLE);//隱藏控件
//進度條顯示
progressBar.setVisibility(VISIBLE);
progressBar.startAnimation(animationBar);//啓動動畫
progressBar.setIndeterminate(true);
break;
}
}
public void initAnimation(){
//創建旋轉動畫
animationUp=new RotateAnimation(0,-180,
RotateAnimation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
animationUp.setDuration(1000);
animationUp.setFillAfter(true);
animationDown=new RotateAnimation(-180,-360,
RotateAnimation.RELATIVE_TO_SELF,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
animationDown.setDuration(1000);
animationDown.setFillAfter(true);
//進度條的旋轉
animationBar=new RotateAnimation(
0,360,RotateAnimation.RELATIVE_TO_PARENT,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
animationBar.setDuration(1000);
animationBar.setFillAfter(true);
animationBar.setRepeatCount(Animation.INFINITE);//無限循環
}
public void complete(boolean isPull){
if(isPull){
currentState=PULLREFRESH;//下拉刷新
tv_state.setText("下拉刷新");
tv_time.setText("2016-6-18");
progressBar.clearAnimation();//取消動畫
progressBar.setVisibility(INVISIBLE);//進度條隱藏
headerView.setPadding(0,-headerHeight,0,0);//隱藏頂部View
}else{//隱藏底部View
itme1textview.setText("加載更多.......");
itme1bar.clearAnimation();//取消動畫
itme1bar.setVisibility(INVISIBLE);//隱藏進度條
footerView.setPadding(0, -footerView.getMeasuredHeight(),0,0);
}
}
}
在主UI的XML文件中使用自定義的ListView
<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.administrator.app4.MainActivity">
<com.example.administrator.app4.PullListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
package com.example.administrator.app4;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* 下拉刷新上拉加載
* 自定義的ListView
*/
public class MainActivity extends AppCompatActivity {
private PullListView listView;//自定義的ListView
private List<String> strs;//適配器需要的數據
private ArrayAdapter adapter;//適配器
private int connt1=1,connt2=1;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
int what=msg.what;//獲取發送過來的空消息
if(what==1){
//下拉刷新完成(添加到集合裏面,最上面)
strs.add(0, "第"+connt1+"次下拉刷新的新數據哦!");
adapter.notifyDataSetChanged();//提醒控件更新顯示
connt1++;
//下拉刷新需要改變狀態
listView.complete(true);
}else if(what==2){
//加載更多數據(底部的View)
for(int i=0;i<10;i++){
strs.add("第"+connt2+"次,加載更多的數據"+(i+1)+"號");
}
connt2++;//自增
adapter.notifyDataSetChanged();//通知更新
listView.complete(false);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView= (PullListView) findViewById(R.id.listview);
init();
adapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1,strs);
listView.setAdapter(adapter);//設置適配器
setOnList();//設置監聽
}
private void setOnList() {
listView.setPullRefreshInterface(//回調ListView裏面的接口
new PullListView.PullRefreshInterface() {
@Override
public void onPull() {
//執行具體的操作
new Thread(){//創建子線程
@Override
public void run() {
try {
Thread.sleep(3000);//線程休眠
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(1);//發送空消息回主線程(增加上面的內容)
}
}.start();//啓動線程
}
@Override
public void onMore() {
new Thread(){//創建線程
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(2);//發送空消息(增加下面的內容)
}
}.start();//開啓線程
}
}
);
}
private void init() {//初始化集合
strs=new ArrayList<String>();
for(int i=0;i<30;i++){
strs.add("List原來的第"+(i+1)+"條數據");
}
}
}