zoukankan      html  css  js  c++  java
  • Android 5.0 之SwipeRefreshLayout

    金田

    下拉刷新是一种比较常用的效果,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
    public void onRefresh() {
        new Handler().postDelayed(new Runnable() {
    
            @Override
            public void run() {
                // 设置SwipeRefreshLayout当前是否处于刷新状态,一般是在请求数据的时候设置为true,在数据被加载到View中后,设置为false。
                mSwipeRefreshLayout.setRefreshing(false); 
            }
        }, 3000);
    }
    

    现在我们初始化该控件:

    public void 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()));
    }
    

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

    图1 上拉加载效果示意图

    首先实现SwipeRefreshLayout的重写:

    public class mySwipeRefreshLayout extends SwipeRefreshLayout implements OnScrollListener {
    
        private int mTouchSlop;
        private ListView mListView;
        private OnLoadListener mOnLoadListener;
        private View mListViewFooter;
        private int mYDown;
        private int mLastY;
        private boolean isLoading = false;
    
        public mySwipeRefreshLayout(Context context) {
            this(context, null);
        }
    
        public mySwipeRefreshLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    
            mListViewFooter = LayoutInflater.from(context).inflate(R.layout.listview_footer, null, false);
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
    
            // 初始化ListView对象
            if (mListView == null) {
                getListView();
            }
        }
    
        private void getListView() {
            int childs = getChildCount();
            if (childs > 0) {
                View childView = getChildAt(0);
                if (childView instanceof ListView) {
                    mListView = (ListView) childView;
                    // 设置滚动监听器给ListView, 使得滚动的情况下也可以自动加载
                    mListView.setOnScrollListener(this);
                }
            }
        }
    
        public void setListView(ListView list) {
            this.mListView = list;
            setLoading(true);
            this.mListView.setOnScrollListener(this);
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            final int action = event.getAction();
    
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    mYDown = (int) event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    mLastY = (int) event.getRawY();
                    break;
                case MotionEvent.ACTION_UP:
                    if (canLoad()) {
                        loadData();
                    }
                    break;
                default:
                    break;
            }
    
            return super.dispatchTouchEvent(event);
        }
    
        /**
         * @方法说明:是否可以加载更多, 条件是到了最底部, listview不在加载中, 且为上拉操作.
         */
        private boolean canLoad() {
            return isBottom() && !isLoading && isPullUp();
        }
    
        /**
         * @方法说明:判断是否到了最底部
         */
        private boolean isBottom() {
            if (mListView != null && mListView.getAdapter() != null) {
                return mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() - 1);
            }
            return false;
        }
    
        /**
         * @方法说明:是否是上拉操作
         */
        private boolean isPullUp() {
            return (mYDown - mLastY) >= mTouchSlop;
        }
    
        /**
         * @方法说明: 如果到了最底部,而且是上拉操作.那么执行onLoad方法
         */   
        private void loadData() {
            if (mOnLoadListener != null) {
                mOnLoadListener.onLoad();
            }
            // 设置状态
            setLoading(true);
        }
    
        /**
         * @方法说明:设置刷新
         */
        public void setLoading(boolean loading) {
            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;
            }
        }
    
        public void setOnLoadListener(OnLoadListener loadListener) {
            mOnLoadListener = loadListener;
        }
    
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (isFastDoubleClick(100))
                return;
    
            // 滚动时到了最底部也可以加载更多
            isLoading = false;
            if (canLoad()) {
                loadData();
            }
        }
    
        public View getmListViewFooter() {
            return mListViewFooter;
        }
    
        /**
         * @类描述:加载更多的监听器
         */
        public static interface OnLoadListener {
            public void onLoad();
        }
    
        private static long lastClickTime;
    
        public static boolean isFastDoubleClick(long times) {
            long time = System.currentTimeMillis();
            long timeD = time - lastClickTime;
            if (0 < timeD && timeD < times) {
                return true;
            }
            lastClickTime = time;
            return false;
        }
    }
    

    MainActivity.java

    public class MainActivity extends Activity {
        private mydapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.main);
            adapter = new mydapter();
    
            // 获取RefreshLayout实例
            final mySwipeRefreshLayout 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(new OnRefreshListener() {
    
                @Override
                public void onRefresh() {
                    Toast.makeText(MainActivity.this, "refresh", Toast.LENGTH_SHORT).show();
                    myRefreshListView.postDelayed(new Runnable() {
    
                        @Override
                        public void run() {
                            // 更新完后调用该方法结束刷新
                            myRefreshListView.setRefreshing(false);
    
                            adapter.getData().clear();
                            // 模拟一些数据
                            for (int i = 0; i < 20; i++) {
                                adapter.addData("liu hhh " + i);
                            }
                        }
                    }, 1000);
                }
            });
    
            // 加载监听器
            myRefreshListView.setOnLoadListener(new OnLoadListener() {
    
                @Override
                public void onLoad() {
                    myRefreshListView.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            // 加载完后调用该方法
                            adapter.addData(new Date().toGMTString());
                            adapter.notifyDataSetChanged();
                            myRefreshListView.setLoading(false);
                        }
                    }, 1500);
                }
            });
        }
    
        class mydapter extends BaseAdapter {
            List<String> datas = new ArrayList<String>();
    
            public mydapter() {
                // 模拟一些数据
                for (int i = 0; i < 20; i++) {
                    datas.add("item - " + i);
                }
            }
    
            public void setData(List<String> data) {
                this.datas = data;
                notifyDataSetChanged();
            }
    
            public void addData(String str) {
                this.datas.add(str);
                notifyDataSetChanged();
            }
    
            public List<String> getData() {
                return datas;
            }
    
            @Override
            public int getCount() {
                return datas.size();
            }
    
            @Override
            public Object getItem(int position) {
                return datas.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @Override
            public View getView(int position, 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));
    
                return convertView;
            }
        }
    }
    

    listView_footer:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns: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

    <?xml version="1.0" encoding="utf-8"?>
    <com.example.demo.mySwipeRefreshLayout xmlns: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:

    <?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" >
    
        <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>
    

    参考链接

    http://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html

    版权所有,转载须注明作者(金田)及出处(原文

  • 相关阅读:
    jira:7.12.3版本搭建(破解版)
    traefik添加多证书
    人肉分析sorted(lst, key=lambda x: (x.isdigit(), x.isdigit() and int(x) % 2 == 0, x.islower(), x.isupper(), x))过程
    jquery实现checkbox全选/反选/取消
    k8s简单集群搭建
    第十二周编程总结
    第十周作业
    第九周编程总结
    第七周编程总结
    第五周编程总结
  • 原文地址:https://www.cnblogs.com/CocoonJin/p/4793827.html
Copyright © 2011-2022 走看看