Android问题集:SwipeRefreshLayout下拉不显示进度圈

Posted 王梵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android问题集:SwipeRefreshLayout下拉不显示进度圈相关的知识,希望对你有一定的参考价值。

问题

今天有一个新需求,要求在列表中没数据时,显示一个text,提示用户。列表是用ListView+SwipeRefreshLayout实现的,刚接手项目不久,看了下代码后就开始动手了。结果发现,当EmptyView(就是一个TextView)显示时,下拉刷新时,看不到进度圈,只有在松开时才会看到一下,而列表中有数据时,则下拉顺畅。

有图有真相,下面就是问题图,注意无数据时的下拉。

实现

我手撸了个demo,重现了这个问题。
先来看下xml,如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">


    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh_layout_demo"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ListView
                android:id="@+id/lv_swipe_refresh_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

            <TextView
                android:id="@+id/tv_empty_swipe_refresh_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="没有item可展示"
                android:gravity="center"
                android:visibility="gone"/>
        </FrameLayout>
    </android.support.v4.widget.SwipeRefreshLayout>

</LinearLayout>

很简单,就是FrameLayout中放一个ListView和一个TextView,当没有数据时,显示TextView,当有数据时显示ListView。
下面是代码

public class MainActivity extends Activity 

    SwipeRefreshLayout mSwipeRefreshLayout;
    ListView mListView;
    TextView mTextView;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout_demo);
        mListView = (ListView) findViewById(R.id.lv_swipe_refresh_layout);
        mTextView = (TextView) findViewById(R.id.tv_empty_swipe_refresh_layout);
        mTextView.setOnTouchListener(new View.OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
                if(event.getAction() == MotionEvent.ACTION_DOWN)
                    return true;
                
                return false;
            
        );

        init();
    



    private void init() 
        loadData();
        refresh();
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() 
            @Override
            public void onRefresh() 
                loadData();
                mHandler.sendEmptyMessageDelayed(1, 1000);
            
        );
    

    boolean flag = true;
    private List<String> mDatas = new ArrayList<>();

    private void loadData() 
        if (flag) 
            for (int i = 0; i < 100; i++) 
                int num = (int) (Math.random() * 100);
                mDatas.add("-------" + num + "---------");
            
         else 
            mDatas.clear();
        

        flag = !flag;

    

    ArrayAdapter<String> mAdapter;
    private void refresh()
        boolean isEmpty = mDatas.size() == 0;
        mListView.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
        mTextView.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
        if (isEmpty) 
            mTextView.setText("没有数据,再刷新试试,有惊喜哦~~");
         else 
            if(mAdapter == null)
                mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mDatas);
                mListView.setAdapter(mAdapter);
             else 
                mAdapter.notifyDataSetChanged();
            
        
    



    Handler mHandler = new Handler(new Handler.Callback() 
        @Override
        public boolean handleMessage(Message msg) 

            switch (msg.what) 
                case 1:
                    refresh();
                    if (mSwipeRefreshLayout.isRefreshing()) 
                        mSwipeRefreshLayout.setRefreshing(false);
                    
                    break;
            

            return true;
        
    );

解决

之前我在自己的Demo集中测试过,发现并没有这个问题,详细比对了demo和正式项目中的代码,没在代码上发现不同,上网查了一下,在一篇博客中找到了思路,果断比对demo和正式项目中的v4包,2个果然不一样。

  • demo中是: ‘com.android.support:support-v4:26.0.0-alpha1’
  • 正式项目中是: ‘com.android.support:support-v4:23.3.0’。

将正式项目中的v4包版本调到26,就可以正常运行了。效果如下

造成问题的原因

问题解决了,但还要深究一下其中的原因。debug源码,最终发现,当ListView显示,下拉刷新时,SwipeRefreshLayout的down事件被子View消费了,当Move时,才会调用自身的onTouchEvent方法。
而当ListView不显示,显示TextView时,SwipeRefreshLayout的down事件没有被子View消费,需要调用自己的onTouchEvent方法 。这个就是导致问题的原因。
根据上面的原因,可以有一种解决方式,如下

mTextView.setOnTouchListener(new View.OnTouchListener() 
    @Override
    public boolean onTouch(View v, MotionEvent event) 
        if(event.getAction() == MotionEvent.ACTION_DOWN)
            return true;
        
        return false;
    
);

经过测试,确定该方法是可行的。
至于为什么26.0.0版本的v4包可行,因为看不到源码,无法得知。

以上是关于Android问题集:SwipeRefreshLayout下拉不显示进度圈的主要内容,如果未能解决你的问题,请参考以下文章

我将如何下载 *** android 数据集?

android问题笔记集

结果集到 Android 光标

加载程序集 Xamarin.Android.Support.v4 时出现异常

android中的图例和字段集

Android MediaCodec 的程序集容器