仿知乎滑动隐藏与显示ToolBar,SwipRefreshLayout刷新

本文介绍如何实现仿知乎的滑动隐藏与显示ToolBar,利用SwipeRefreshLayout刷新功能。通过调整布局文件的clipToPadding和clipChildren属性,监听RecyclerView滚动,并自定义OnScrollListener,实现ToolBar的动态显示和隐藏。同时,解决SwipeRefreshLayout下拉刷新时小圆圈被ToolBar遮挡的问题。完整代码可在优快云找到。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直接上效果图:

这里写图片描述
下拉刷新采用谷歌官方刷新控件
上拉加载采用git上的一个控件

一、设置ToolBar及伪沉浸式上一篇就说过,这里不再讲解了。
这个demo必须的依赖:

    compile 'com.github.fangx:haorefresh:1.0'
    compile 'com.wang.avi:library:1.0.1'
    compile 'com.android.support:design:24.1.0'

二、布局文件:

<?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:background="#1ee4d8"
    android:clipToPadding="true"
    android:fitsSystemWindows="true"
    tools:context="com.example.ceshi.MainActivity">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
    >

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

            <me.fangx.haorefresh.HaoRecyclerView
                android:id="@+id/ce_shi_lv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipChildren="false"
                android:clipToPadding="false"
                android:paddingTop="?attr/actionBarSize"
               >
            </me.fangx.haorefresh.HaoRecyclerView>

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

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right|bottom"
            android:layout_marginBottom="56dp"
            android:layout_marginRight="56dp"
            android:background="@color/colorAccent"/>
    </FrameLayout>
    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="#1ee4d8">
    </android.support.v7.widget.Toolbar>
</FrameLayout>

其中注意这两句话:
clipToPadding就是说控件的绘制区域是否在padding里面的,true的情况下如果你设置了padding那么绘制的区域就往里 缩,clipChildren是指子控件是否超过padding区域,这两个属性默认是true的,所以在设置了padding情况下,默认滚动是在 padding内部的,要达到上面的效果主要把这两个属性设置了false那么这样子控件就能画到padding的区域了。

  android:clipChildren="false"
  android:clipToPadding="false"
  android:paddingTop="?attr/actionBarSize"

item的简单布局为了测试:

<?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="wrap_content"
              android:orientation="vertical">

    <TextView
        android:text="小明"
        android:padding="24dp"
        android:id="@+id/ce_shi_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

三、监听RecyclerView的addOnScrollListener 中new一个自定义的OnScrollListener来判断移动到某个位置执行隐藏或者显示的方法。

public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {

    private static final int SCROLL_DISTANCE = 50;
    private int totalScrollDistance;
    private boolean isShow = true;

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        int firstVisableItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
        //当第一个item存在界面上时就不触发隐藏、显示操作
        if (firstVisableItem == 0) {
            return;
        }
        if ((dy > 0 && isShow) || (dy < 0 && !isShow)) {
            totalScrollDistance += dy;
        }
        if (totalScrollDistance > SCROLL_DISTANCE && isShow) {
            hide();
            isShow = false;
            totalScrollDistance = 0;
        } else if (totalScrollDistance < -SCROLL_DISTANCE && !isShow) {
            show();
            isShow = true;
            totalScrollDistance = 0;
        }
    }

    public abstract void hide();

    public abstract void show();

}

把隐藏或显示写在下面两个方法里面

 mRecyclerView.addOnScrollListener(new HidingScrollListener() {
            @Override
            public void hide() {

     //如果想向下隐藏可以采用这种                       //button.animate().translationY(button.getHeight()+getMarginBottom(button)).setInterpolator(new FastOutSlowInInterpolator());

                button.hide();
                mToolBar.animate().translationY(-mToolBar.getHeight()).setInterpolator(new AccelerateDecelerateInterpolator());
            }

            @Override
            public void show() { 
       //如果想向下隐藏可以采用这种                 //button.animate().translationY(0).setInterpolator(new FastOutSlowInInterpolator());

                button.show();
                mToolBar.animate().translationY(0).setInterpolator(new AccelerateDecelerateInterpolator());
            }
        });


    /*
     *获取控件在布局中的高度
     */
    private int getMarginBottom(View v) {
        int marginBottom = 0;
        final ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
        if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
            marginBottom = ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin;
        }
        return marginBottom;
    }

这里注意一下,看布局文件我们的SwipeRefreshLayout直接顶着状态栏,下拉刷新话,默认的小圆圈高度的位置正好会被这个ToolBar遮挡住,效果就不好了,这里我们可以调节一下小圆圈的高度,这样就不会被ToolBar遮挡住了,400是根据情况设定的。

 refresh.setProgressViewEndTarget(false,400);

上拉加载,我们也看到了,借用github上。上拉加载动画借用上边的,一句话就可以改变他的样式,上边搜搜这个wang.avi,很多样式。

 mRecyclerView= (HaoRecyclerView) findViewById(R.id.ce_shi_lv);
        LinearLayoutManager line=new LinearLayoutManager(this);
        line.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(line);

        ProgressView progressView=new ProgressView(this);
       //下面这一句话就可以改变他的样式,大伙可以试一试。 progressView.setIndicatorId(ProgressView.BallRotate);
        progressView.setIndicatorColor(0xff69b3e0);
        mRecyclerView.setFootLoadingView(progressView);

//加载完后显示的文字
        TextView textView=new TextView(this);
        textView.setText("已经到底了");
        mRecyclerView.setFootEndView(textView);
        mRecyclerView.setLoadMoreListener(new LoadMoreListener() {
            @Override
            public void onLoadMore() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {

                        if (mList.size()>=30){
                            mRecyclerView.loadMoreEnd();
                            return;
                        }else {
                            getData();
                        }
                        mAdapter.notifyDataSetChanged();
                        mRecyclerView.loadMoreComplete();
                    }
                },2000);
            }
        });

另外,RecyclerView本事没有Item的点击事件,这个HaoRecyclerView也已经帮我们封装好了。

//已经封装好的点击事件
        mRecyclerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(MainActivity.this, "click-----position" + i, Toast.LENGTH_SHORT).show();
            }
        });

完整代码我会发在优快云上。
地址:http://download.youkuaiyun.com/detail/kuaizilanqiu/9623884

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值