SwipeRefreshLayout(Android的下拉刷新组件)

SwipeRefreshLayout(Android的下拉刷新组件)

public class SwipeRefreshLayout 
extends ViewGroup implements NestedScrollingParent, NestedScrollingChild

只要用户可以通过垂直滑动手势刷新视图的内容,就应该使用SwipeRefreshLayout。 实例化此视图的活动应该添加一个OnRefreshListener,以便在刷新刷新手势完成时通知它。 SwipeRefreshLayout将在每次手势再次完成时通知侦听器; 监听者负责正确确定何时实际启动其内容的刷新。 如果听众确定不应该刷新,则必须调用setRefreshing(false)来取消刷新的任何可视指示。 如果活动希望仅显示进度动画,则应调用setRefreshing(true)。 要禁用手势和进度动画,请在视图上调用setEnabled(false)。

该布局应该是由于手势而被刷新的视图的父级,并且只能支持一个直接的孩子。 此视图也将作为手势的目标,并将被强制匹配此布局中提供的宽度和高度。 SwipeRefreshLayout不提供辅助功能事件; 相反,必须提供菜单项以允许在使用该手势的任何地方刷新内容。

SwipeRefreshLayout类中两个重要的接口:

  • interface SwipeRefreshLayout.OnChildScrollUpCallback
    • 希望覆盖canChildScrollUp()方法行为的类应该实现此接口。
  • interface SwipeRefreshLayout.OnRefreshListener
    • 希望在滑动手势正确触发刷新时收到通知的类应实现此接口。

SwipeRefreshLayout类中的常用方法:

#

  • void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)
    • 将侦听器设置为在通过滑动手势触发刷新时收到通知。

判断刷新状态

  • boolean isRefreshing()
    • 判断刷新状态

通知窗口小部件刷新状态已更改。

  • void setRefreshing(boolean refreshing)
    • 通知窗口小部件刷新状态已更改。

设置刷新时进度动画的颜色

  • void setColorScheme(int… colors)
    • API方法22.0.0中已弃用此方法。使用setColorSchemeResources(int)
  • void setColorSchemeColors(int… colors)
    • 设置进度动画中使用的颜色。
  • void setColorSchemeResources(int… colorResIds)
    • 从颜色资源设置进度动画中使用的颜色资源。

设置刷新时进度旋转光盘的背景颜色

  • void setProgressBackgroundColor(int colorRes)
    • API方法22.0.0中已弃用此方法。使用setProgressBackgroundColorSchemeResource(int)
  • void setProgressBackgroundColorSchemeColor(int color)
    • 设置进度旋转光盘的背景颜色。
  • void setProgressBackgroundColorSchemeResource(int colorRes)
    • 设置进度旋转光盘的背景颜色。

设置刷新指示器的位置

  • void setProgressViewEndTarget(boolean scale, int end)
    • 刷新指示器静止位置始终位于更新内容的顶部附近。
  • void setProgressViewOffset(boolean scale, int start, int end)
    • 刷新指示符起始和休息位置总是位于更新内容的顶部附近。

关于SwipeRefreshLayout的详细介绍官方API

SwipeRefreshLayout与ListFragment的结合使用实例:

public class CustomSwipeRefreshFragment extends ListFragment {

    private static final int LIST_ITEM_COUNT = 20;
    private SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Create the list fragment's content view by calling the super method
        View listFragmentView=super.onCreateView(inflater, container, savedInstanceState);

        // Now create a SwipeRefreshLayout to wrap the fragment's content view
        mSwipeRefreshLayout=new ListFragmentSwipeRefreshLayout(container.getContext());

        // Add the list fragment's content view to the SwipeRefreshLayout, making sure that it fills
        // the SwipeRefreshLayout
        mSwipeRefreshLayout.addView(listFragmentView,ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);

        // Make sure that the SwipeRefreshLayout will fill the fragment
        mSwipeRefreshLayout.setLayoutParams(
                new ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT));

        /**
         * Create an ArrayAdapter to contain the data for the ListView. Each item in the ListView
         * uses the system-defined simple_list_item_1 layout that contains one TextView.
         */
        ListAdapter adapter = new ArrayAdapter<>(
                getActivity(),
                android.R.layout.simple_list_item_1,
                android.R.id.text1,
                Cheeses.randomList(LIST_ITEM_COUNT));

        // Set the adapter between the ListView and its backing data.
        setListAdapter(adapter);

        //设置下拉刷新监听器
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                initiateRefresh();
            }
        });

        return mSwipeRefreshLayout;
    }

    /**
     * 调用DummyBackgroundTask().execute()方法开始在后台刷新数据
     * 通过将刷新过程抽象为单一方法,该应用程序允许SwipeGestureLayout onRefresh()方法和“刷新”操作项目刷新内容。
     */
    private void initiateRefresh() {
        new DummyBackgroundTask().execute();
    }

    /**
     * 当AsyncTask完成时,它调用onRefreshComplete(),更新ListAdapter中的数据,并关闭进度条。
     * @param result
     */
    private void onRefreshComplete(List<String> result) {
        // Remove all items from the ListAdapter, and then replace them with the new items
        ArrayAdapter<String> adapter = (ArrayAdapter<String>) getListAdapter();
        adapter.clear();
        for (String cheese : result) {
            adapter.add(cheese);
        }

        Toast.makeText(getActivity(), "刷新成功", Toast.LENGTH_SHORT).show();

        // 停止刷新指示
        mSwipeRefreshLayout.setRefreshing(false);
    }

    /**
     * 在ListFragment中使用SwipeRefreshLayout的子类。 
     * 原因是因为SwipeRefreshLayout只支持一个单独的子View,它希望是一个触发刷新的子View。
     * 在我们的例子中,布局的子View是ListFragment#onCreateView(LayoutInflater,ViewGroup,Bundle)返回的内容视图,
     * 它是ViewGroup。 要启用ListView对“swipe-to-refresh”支持,我们需要覆盖默认行为,并在手势可能时正确发出信号。 
     * 这是通过重写#canChildScrollUp()方法来完成的。
     */
    private class ListFragmentSwipeRefreshLayout extends SwipeRefreshLayout {

        public ListFragmentSwipeRefreshLayout(Context context) {
            super(context);
        }

        /**
         * 如上所述,当可以进行“swipe-to-refresh”时,我们需要重写此方法以正确发出信号。
         * @return true if the {@link android.widget.ListView} is visible and can scroll up.
         */
        @Override
        public boolean canChildScrollUp() {
            final ListView listView=getListView();
            if (listView.getVisibility()==VISIBLE){
                return canListViewScrollUp(listView);
            }else {
                return true;
            }
        }

    }

    /**
     * 异步线程刷新数据
     */
    private class DummyBackgroundTask extends AsyncTask<Void, Void, List<String>> {

        static final int TASK_DURATION = 3 * 1000; // 3 seconds

        @Override
        protected List<String> doInBackground(Void... params) {
            // Sleep for a small amount of time to simulate a background-task
            try {
                Thread.sleep(TASK_DURATION);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // Return a new random list of cheeses
            return Cheeses.randomList(LIST_ITEM_COUNT);
        }

        @Override
        protected void onPostExecute(List<String> result) {
            super.onPostExecute(result);

            // Tell the Fragment that the refresh has completed
            onRefreshComplete(result);
        }

    }

    // BEGIN_INCLUDE (check_list_can_scroll)
    /**
     * 检查{@link ListView}是否可以从当前位置向上滚动的实用方法。
     * 处理平台版本差异,在需要时提供向后兼容的功能。
     */
    private static boolean canListViewScrollUp(ListView listView) {
        if (android.os.Build.VERSION.SDK_INT >= 14) {
            // For ICS and above we can call canScrollVertically() to determine this
            return ViewCompat.canScrollVertically(listView, -1);
        } else {
            // Pre-ICS we need to manually check the first visible item and the child view's top
            // value
            return listView.getChildCount() > 0 &&
                    (listView.getFirstVisiblePosition() > 0
                            || listView.getChildAt(0).getTop() < listView.getPaddingTop());
        }
    }
    // END_INCLUDE (check_list_can_scroll)

}

在布局中使用SwipeRefreshLayout

布局

<android.support.v4.widget.SwipeRefreshLayout
    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"/

</android.support.v4.widget.SwipeRefreshLayout>

Activity

public class MainActivity extends AppCompatActivity {

    private SwipeRefreshLayout mSwipeRefreshLayout;
    private ListView mListView;
    private int LIST_ITEM_COUNT=20;
    private ArrayAdapter mAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_layout);
        mListView = (ListView) findViewById(R.id.lv_next);

        mAdapter = new ArrayAdapter<>(
                this,
                android.R.layout.simple_list_item_1,
                android.R.id.text1,
                Cheeses.randomList(LIST_ITEM_COUNT));
        mListView.setAdapter(mAdapter);

        mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_light,
                android.R.color.holo_red_light,android.R.color.holo_orange_light,
                android.R.color.holo_green_light);
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                initiateRefresh();
            }
        });
    }

    private void initiateRefresh() {
        new DummyBackgroundTask().execute();
    }

    private void onRefreshComplete(List<String> result) {
        // Remove all items from the ListAdapter, and then replace them with the new items
        mAdapter.clear();
        for (String cheese : result) {
            mAdapter.add(cheese);
        }

        Toast.makeText(this, "刷新成功", Toast.LENGTH_SHORT).show();

        // Stop the refreshing indicator
        mSwipeRefreshLayout.setRefreshing(false);
    }

    /**
     * 异步线程刷新数据
     */
    private class DummyBackgroundTask extends AsyncTask<Void, Void, List<String>> {

        static final int TASK_DURATION = 3 * 1000; // 3 seconds

        @Override
        protected List<String> doInBackground(Void... params) {
            // Sleep for a small amount of time to simulate a background-task
            try {
                Thread.sleep(TASK_DURATION);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // Return a new random list of cheeses
            return Cheeses.randomList(LIST_ITEM_COUNT);
        }

        @Override
        protected void onPostExecute(List<String> result) {
            super.onPostExecute(result);

            // Tell the Fragment that the refresh has completed
            onRefreshComplete(result);
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值