Android 5.0 之SwipeRefreshLayout

来源:互联网 发布:手机暖宝宝软件 编辑:程序博客网 时间:2024/05/22 05:00

下拉刷新是一种比较常用的效果,Android 5.0之前官方并未提供类似的控件,App中主要是用的第三方库,例如PullToRefresh,ActionBar-PullToRefresh等。刚好现在项目中需要处理 Android 5.0 材质设计部分的东西,就顺带学习下这部分。

大体介绍一下;

  1. SwipeRefreshLayout是Google在support v4 19.1版本的library更新的一个下拉刷新控件 (android-support-v4.jar)
  2. 目前只支持下拉刷新,不支持上拉加载更多的操作(需要自行进行扩展)
  3. 作为官方自带的控件,相对能能够保证比较好的通用性及风格(这里不包括各种自家定制的系统 L)
  4. SwipeRefreshLayout继承于ViewGroup,ViewGroup中可以包含其他不同控件,so UI定制起来也相对比较容易
  5. 使用起来比较方便,可以很容易的实现Google Now的刷新效果

        SwipeRefreshLayout布局中目前只能包含一个子布局,使用侦听机制来通知刷新事件。例如当用户使用下拉手势时,SwipeRefreshLayout会触发OnRefreshListener,然后刷新事件会在onRefresh()方法中进行处理。当需要结束刷新的时候,可以调用setRefreshing(false)。如果要禁用手势和进度动画,调用setEnabled(false)即可。

 

接下来介绍一下其大体使用方法:

1.布局文件(示例代码)

<?xml version="1.0"encoding="utf-8"?>
<FrameLayout 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">
 
    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/id_explore_swipe_ly"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#ffffff">
 
        <ListView
            android:id="@+id/id_listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </ListView>
    </android.support.v4.widget.SwipeRefreshLayout>
 
</FrameLayout>

2.java逻辑代码:

首先需要实现 SwipeRefreshLayout.OnRefreshListener  接口,然后重写方法 onRefresh():

@Override
publicvoid onRefresh() {
    newHandler().postDelayed(newRunnable() {
 
        @Override
        publicvoid run() {
            // 设置SwipeRefreshLayout当前是否处于刷新状态,一般是在请求数据的时候设置为true,在数据被加载到View中后,设置为false。
            mSwipeRefreshLayout.setRefreshing(false);
        }
    },3000);
}

现在我们初始化该控件:

publicvoid initSwipeRefreshParameters() {
    // 设置进度条的颜色变化,最多可以设置4种颜色
 mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_dark, android.R.color.holo_green_light,
            android.R.color.holo_orange_light, android.R.color.holo_red_light);
    // 设置下拉监听,当用户下拉的时候会去执行回调
    mSwipeRefreshLayout.setOnRefreshListener(this);
    // 调整进度条距离屏幕顶部的距离
    mSwipeRefreshLayout.setProgressViewOffset(false,0,
            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,24, getResources().getDisplayMetrics()));
}

以上是基本用法,现在来大体介绍一下定制支持上拉加载的部分,演示图示:


首先实现SwipeRefreshLayout的重写:

publicclass mySwipeRefreshLayoutextends SwipeRefreshLayoutimplements OnScrollListener {
 
    privateint mTouchSlop;
    privateListView mListView;
    privateOnLoadListener mOnLoadListener;
    privateView mListViewFooter;
    privateint mYDown;
    privateint mLastY;
    privateboolean isLoading = false;
 
    publicmySwipeRefreshLayout(Context context) {
        this(context,null);
    }
 
    publicmySwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
 
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
 
        mListViewFooter = LayoutInflater.from(context).inflate(R.layout.listview_footer,null, false);
    }
 
    @Override
    protectedvoid onLayout(booleanchanged, int left, int top, int right, intbottom) {
        super.onLayout(changed, left, top, right, bottom);
 
        // 初始化ListView对象
        if(mListView == null) {
            getListView();
        }
    }
 
    privatevoid getListView() {
        intchilds = getChildCount();
        if(childs > 0) {
            View childView = getChildAt(0);
            if(childView instanceofListView) {
                mListView = (ListView) childView;
                // 设置滚动监听器给ListView, 使得滚动的情况下也可以自动加载
                mListView.setOnScrollListener(this);
            }
        }
    }
 
    publicvoid setListView(ListView list) {
        this.mListView = list;
        setLoading(true);
        this.mListView.setOnScrollListener(this);
    }
 
    @Override
    publicboolean dispatchTouchEvent(MotionEvent event) {
        finalint action = event.getAction();
 
        switch(action) {
            caseMotionEvent.ACTION_DOWN:
                mYDown = (int) event.getRawY();
                break;
            caseMotionEvent.ACTION_MOVE:
                mLastY = (int) event.getRawY();
                break;
            caseMotionEvent.ACTION_UP:
                if(canLoad()) {
                    loadData();
                }
                break;
            default:
                break;
        }
 
        returnsuper.dispatchTouchEvent(event);
    }
 
    /**
     * @方法说明:是否可以加载更多, 条件是到了最底部, listview不在加载中, 且为上拉操作.
     */
    privateboolean canLoad() {
        returnisBottom() && !isLoading && isPullUp();
    }
 
    /**
     * @方法说明:判断是否到了最底部
     */
    privateboolean isBottom() {
        if(mListView != null&& mListView.getAdapter() != null) {
            returnmListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() -1);
        }
        returnfalse;
    }
 
    /**
     * @方法说明:是否是上拉操作
     */
    privateboolean isPullUp() {
        return(mYDown - mLastY) >= mTouchSlop;
    }
 
    /**
     * @方法说明: 如果到了最底部,而且是上拉操作.那么执行onLoad方法
     */  
    privatevoid loadData() {
        if(mOnLoadListener != null) {
            mOnLoadListener.onLoad();
        }
        // 设置状态
        setLoading(true);
    }
 
    /**
     * @方法说明:设置刷新
     */
    publicvoid setLoading(booleanloading) {
        isLoading = loading;
        if(mListView != null&& mListView.getFooterViewsCount() > 0)
            mListView.removeFooterView(mListViewFooter);
        if(isLoading) {
            if(mListView != null&& mListView.getFooterViewsCount() <= 0)
                mListView.addFooterView(mListViewFooter);
        }else {
            mYDown =0;
            mLastY =0;
        }
    }
 
    publicvoid setOnLoadListener(OnLoadListener loadListener) {
        mOnLoadListener = loadListener;
    }
 
    @Override
    publicvoid onScrollStateChanged(AbsListView view,int scrollState) {
    }
 
    @Override
    publicvoid onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount) {
        if(isFastDoubleClick(100))
            return;
 
        // 滚动时到了最底部也可以加载更多
        isLoading =false;
        if(canLoad()) {
            loadData();
        }
    }
 
    publicView getmListViewFooter() {
        returnmListViewFooter;
    }
 
    /**
     * @类描述:加载更多的监听器
     */
    publicstatic interfaceOnLoadListener {
        publicvoid onLoad();
    }
 
    privatestatic long lastClickTime;
 
    publicstatic booleanisFastDoubleClick(longtimes) {
        longtime = System.currentTimeMillis();
        longtimeD = time - lastClickTime;
        if(0 < timeD && timeD < times) {
            returntrue;
        }
        lastClickTime = time;
        returnfalse;
    }
}

MainActivity.java

publicclass MainActivity extends Activity {
    privatemydapter adapter;
 
    @Override
    protectedvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        setContentView(R.layout.main);
        adapter =new mydapter();
 
        // 获取RefreshLayout实例
        finalmySwipeRefreshLayout myRefreshListView = (mySwipeRefreshLayout) findViewById(R.id.swipe_layout);
 
        // 获取listview实例
        ListView listView = (ListView) findViewById(R.id.listview);
        myRefreshListView.setListView(listView);
        listView.setAdapter(adapter);
 
        // 设置进度条的颜色变化,最多可以设置4种颜色
   myRefreshListView.setColorSchemeResources(android.R.color.holo_green_dark, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);
        // 设置下拉刷新监听器
        myRefreshListView.setOnRefreshListener(newOnRefreshListener() {
 
            @Override
            publicvoid onRefresh() {
                Toast.makeText(MainActivity.this,"refresh", Toast.LENGTH_SHORT).show();
                myRefreshListView.postDelayed(newRunnable() {
 
                    @Override
                    publicvoid run() {
                        // 更新完后调用该方法结束刷新
                        myRefreshListView.setRefreshing(false);
 
                        adapter.getData().clear();
                        // 模拟一些数据
                        for(int i = 0; i < 20; i++) {
                            adapter.addData("liu hhh "+ i);
                        }
                    }
                },1000);
            }
        });
 
        // 加载监听器
        myRefreshListView.setOnLoadListener(newOnLoadListener() {
 
            @Override
            publicvoid onLoad() {
                myRefreshListView.postDelayed(newRunnable() {
                    @Override
                    publicvoid run() {
                        // 加载完后调用该方法
                        adapter.addData(newDate().toGMTString());
                        adapter.notifyDataSetChanged();
                        myRefreshListView.setLoading(false);
                    }
                },1500);
            }
        });
    }
 
    classmydapter extendsBaseAdapter {
        List<String> datas =new ArrayList<String>();
 
        publicmydapter() {
            // 模拟一些数据
            for(int i = 0; i < 20; i++) {
                datas.add("item - "+ i);
            }
        }
 
        publicvoid setData(List<String> data) {
            this.datas = data;
            notifyDataSetChanged();
        }
 
        publicvoid addData(String str) {
            this.datas.add(str);
            notifyDataSetChanged();
        }
 
        publicList<String> getData() {
            returndatas;
        }
 
        @Override
        publicint getCount() {
            returndatas.size();
        }
 
        @Override
        publicObject getItem(intposition) {
            returndatas.get(position);
        }
 
        @Override
        publiclong getItemId(intposition) {
            returnposition;
        }
 
        @Override
        publicView getView(intposition, View convertView, ViewGroup parent) {
            if(convertView == null) {
                convertView = MainActivity.this.getLayoutInflater().inflate(R.layout.item,null);
            }
 
            TextView tv = (TextView) convertView.findViewById(R.id.text);
            tv.setText(datas.get(position));
 
            returnconvertView;
        }
    }
}

listView_footer:

<?xmlversion="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@color/very_light_gray"
    android:gravity="center"
    android:layout_gravity="center_horizontal"
    android:paddingBottom="10dip"
    android:paddingTop="10dip" >
 
    <ProgressBar
        android:id="@+id/pull_to_refresh_load_progress"
        style="@android:style/Widget.ProgressBar.Small.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:indeterminate="true"
        android:paddingRight="10dp" />
 
    <TextView
        android:id="@+id/pull_to_refresh_loadmore_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:layout_toRightOf="@+id/pull_to_refresh_load_progress"
        android:paddingTop="5dip"
        android:text="@string/loading"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@android:color/darker_gray"
        android:textSize="14sp"
        android:textStyle="bold" />
 
</RelativeLayout>

main.xml

<?xmlversion="1.0" encoding="utf-8"?>
<com.example.demo.mySwipeRefreshLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>
 
</com.example.demo.mySwipeRefreshLayout>

item.xml:

<?xmlversion="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:padding="10dp"
        android:text="wo lai le"
        android:background="@color/very_light_gray"/>
     
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@android:color/white"/>
 
</LinearLayout>

0 0
原创粉丝点击