Coder Social home page Coder Social logo

jeasonlzy / headerviewpager Goto Github PK

View Code? Open in Web Editor NEW
767.0 24.0 178.0 4.54 MB

具有共同头部的 ViewPager,支持与ListView,GridView,ScrollView,WebView,RecyclerView 嵌套使用。具有连续的滑动事件 和 滑动监听, 支持下拉刷新。

Java 100.00%

headerviewpager's Introduction

HeaderViewPager

###具有共同头部的 ViewPager,支持与ListView,GridView,ScrollView,WebView,RecyclerView 嵌套使用。具有连续的滑动事件 和 滑动监听, 支持下拉刷新。

该项目参考了:https://github.com/cpoopc/ScrollableLayout 喜欢原作的可以去使用。相比原项目,代码更简单易懂,扩展性更高,欢迎大家下载体验本项目,如果使用过程中遇到什么问题,欢迎反馈。

演示

image image image

1.用法

该项目和我github上其他的view相关的项目已经一起打包上传到jCenter仓库中(源码地址 https://github.com/jeasonlzy0216/ViewCore ),使用的时候可以直接使用compile依赖,用法如下 ###该项目中使用到的大部分自定义控件,均来源于上述仓库

	compile 'com.lzy.widget:view-core:0.2.1'

或者使用

    compile project(':header_viewpager')

2.实现原理

把自定义控件 HeaderViewPagerLayoutdispatchTouchEvent 方法进行重写,根据手势方向决定是否分发事件,同时使用 Scroller 滚动内部视图,达到滑动的连续性。 具体详细代码,实例代码中会有详细注释。

3.代码参考

1.布局解析

  • 自定义控件HeaderViewPagerLayout作为根布局
  • 无论控件具有多少个子View,只有第一个子View会被自定义控件按头部解析,所以,如果头部有多个View,可以使用ViewGroup包裹,例如下面实例使用的是LinearLayout包裹(头部是一个ViewPager和Indicator指示器),除了第一个View会被滑出去外,其余布局均不会被滑出。
  • 如果滑动时,想让布局滑动到一定距离后停止么可以在xml布局中加入自定义属性app:hvp_topOffset="50dp",值的大小表示距离顶部多少距离停止滑动
  • 在头部滑动的过程中,可以使用setOnScrollListener设置滑动监听,动态改变头部据或者其他布局的动画

###例如布局中做如下布局:

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

    <com.lzy.widget.HeaderViewPager
        android:id="@+id/scrollableLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:hvp_topOffset="50dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="200dp">

            <com.lzy.widget.loop.LoopViewPager
                android:id="@+id/pagerHeader"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:lvp_delayTime="2000"
                app:lvp_isAutoLoop="true"/>

            <com.lzy.widget.tab.CircleIndicator
                android:id="@+id/ci"
                android:layout_width="match_parent"
                android:layout_height="20dp"
                android:layout_alignParentBottom="true"
                android:background="#4000"
                app:ci_normalRadiusColor="#FFF"
                app:ci_selectedRadiusColor="#FFF"/>
        </RelativeLayout>

        <com.lzy.widget.tab.PagerSlidingTabStrip
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@mipmap/bg_menu_normal"
            android:textSize="16sp"
            app:pstsDividerColor="#00000000"
            app:pstsIndicatorColor="#2DA4F0"
            app:pstsIndicatorHeight="2dp"
            app:pstsShouldExpand="false"
            app:pstsTextAllCaps="false"
            app:pstsUnderlineHeight="2dp"/>

        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </com.lzy.widget.HeaderViewPager>

    <include
        android:id="@+id/titleBar"
        layout="@layout/include_titlebar"/>
</FrameLayout>

2.对于自定义控件,需要做如下初始化

	scrollableLayout.setCurrentScrollableContainer(fragments.get(0));
    viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            scrollableLayout.setCurrentScrollableContainer(fragments.get(position));
        }
    });

3.如果需要对滑动过程进行监听,可以使用如下代码,currentY 表示当前滑过的距离,maxY表示当前可以滑动的最大距离,有了这两个参数,就可以对任意布局,做任何动画了。例如如下代码就是实现 视差动画效果的代码。

	scrollableLayout.setOnScrollListener(new HeaderViewPagerLayout.OnScrollListener() {
        @Override
        public void onScroll(int currentY, int maxY) {
            image.setTranslationY(currentY / 2);
        }
    });

headerviewpager's People

Contributors

jeasonlzy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

headerviewpager's Issues

嵌套RecyclerView 导致,RecyclerView滑动速率发生突变

首先感谢作者开源这么棒的项目。我在使用中遇见了一个问题。
伪代码

image

测试机型:很多,都出现了
系统版本:6.0.1 5.1.1 其他的没测试
描述:此时效果正常,上下正常联动,但是RecyclerView 滑动时,滑动fling,松手后,会有明显速度加快的情况发生。

补充:从下往上滑,头部完全滑出去后,上滑RecyclerView会出现速度变快的问题(滑动开始时速度加快)。
从上往下滑,速率正常。

空指针异常

You should call ScrollableHelper.setCurrentScrollableContainer() to set ScrollableContainer.
按照你说的写的 我设置了这个属性,还报这个错误

LoopviewPager click listener not working

Hi guys,
now only i seen this library.its awesome.
But here in loop viewpager.i click on the image but its didn't trigger a click event.
i tried all ways.but no luck
Can u plz help me
Thanks.

第一个控件没有完全滑出

我的布局文件如下,第一个 RelativeLayout的内容并没有完全滑出,只有一半的内容滑出界面
<com.lzy.widget.HeaderViewPager
android:background="@color/white"
android:id="@+id/scrollableLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:hvp_topOffset="50dp">

    <RelativeLayout>

        <ImageView />

        <RelativeLayout>

            <TextView />

            <TextView />

            <TextView />

        </RelativeLayout>

        <Button/>

    </RelativeLayout>

请问如何解决

若HeaderView不显示,则不能固定Tabs栏?

HeaderViewPager在项目中没有HeaderView的时候,我们无法做到Tab栏固定。
解决:
1.在onMeasure和dispatchTouchEvent判断mHeaderView是否存在
2.如果不存在,在onMeasure不增加HeaderViewPager的高度,并重新设置滑动最大距离,以及dispatchTouchEvent直接可以让滑动事件让子View消费。
不知这种方案是否使用各种情况。

HeaderScrollHelper isRecyclerViewTop

private boolean isRecyclerViewTop(RecyclerView recyclerView) {
if (recyclerView != null) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
int firstVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
View childAt = recyclerView.getChildAt(0);
if (childAt == null || (firstVisibleItemPosition == 0 && childAt.getTop() == 0)) {
return true;
}
}
}
return false;
}
这个方法中 置灰的地方 如果rv中加了间距 这里会判断不准确,是否可以提供 设置间距的api 在这里减去对应的值

搞了四个小时发现一个bug

当recyclerview的item布局是cardview的时候 ,滑上去拉不下来!! 不下来!!!
记住,就是cardView!坑死我了。

滑动冲突

如果viewpager中每个fragment的数据都是动态获取的,RecyclerView的滑动就和外面的冲突了

Glide加载多张网络图片,CircleIndicator不居中显示。。。帮忙指点一下。。。

private class HeaderAdapter extends PagerAdapter {

    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        ImageView imageView = new ImageView(AircraftInfoActivity.this.getApplicationContext());
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        //  imageView.setImageResource(images[position]);

        if (imagesUrl.size() > 0) {
            
            Glide.with(AircraftInfoActivity.this)
                    .load(imagesUrl.get(position))
                    .placeholder(R.drawable.ic_loading) 
                    .error(R.drawable.ic_fail) 
                    .into(imageView);

            container.addView(imageView);
            imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                }
            });
            return imageView;

        } else {
            return null;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }

    @Override

    public int getCount() {
        return imagesUrl.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

滑动惯性问题

使用的recycleview 头部滑入或划出都有惯性 比如稍微往下拉一点 松手就又退回去了, 拉多一点松手 就全部滑下来了。 这种惯性能屏蔽吗?

hvp_topOffset没有效果

app:hvp_topOffset="50dp" 这个属性没什么效果。设置和不设置没有区别,这是怎么回事。

recyclerview 当自定义了或者加了自定义分割线后滑动上去后无法滑动上来(已解决)

这个主要是由于isRecyclerViewTop此方法做判断时由于一些情况下顶部距离可能不为0时导致滑动可能不会触发向下滑动 所以需要固定配置,因人而异配置方法可能不同我的配置方法是:
加一个顶部偏移值

先修改这个HeaderScrollHelper类下的方法:

/**
     * 顶部偏移值,主要是给isRecyclerViewTop此方法做判断时由于一些情况下顶部距离可能不为0 所以需要固定配置
     */
    private int topOffsetHeight = 0;

修改滑动内容适配器:

public void setCurrentScrollableContainer(ScrollableContainer scrollableContainer, int topOffsetHeight) {
        this.mCurrentScrollableContainer = scrollableContainer;
        this.topOffsetHeight = topOffsetHeight;
    }

源方法isRecyclerViewTop改为这样:

  private boolean isRecyclerViewTop(RecyclerView recyclerView) {
        if (recyclerView != null) {
            RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
            if (layoutManager instanceof LinearLayoutManager) {
                int firstVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
                View childAt = recyclerView.getChildAt(0);
                RecyclerView.ItemDecoration itemDecoration = recyclerView.getItemDecorationAt(0);
                if (childAt == null ||
                        (firstVisibleItemPosition == 0 && (childAt.getTop() == topOffsetHeight || childAt.getTop() == 0))) {
                    return true;
                }
            }
        }
        return false;
    }

然后是修改此HeaderViewPager类下的方法(我修改了一个方法并且加了一个方法):

   public void setCurrentScrollableContainer(HeaderScrollHelper.ScrollableContainer scrollableContainer, int topOffset) {
        mScrollable.setCurrentScrollableContainer(scrollableContainer, topOffset);
    }

    public void setCurrentScrollableContainer(HeaderScrollHelper.ScrollableContainer scrollableContainer) {
        mScrollable.setCurrentScrollableContainer(scrollableContainer, 0);
    }

然后就是特例的一些界面特例处理

                    headerViewPager.setCurrentScrollableContainer((HeaderViewPagerFragment) fragmentList.get(position),
                            DensityUtil.dip2px(CustomerDetailActivity.this, 30));
                } else {
                    headerViewPager.setCurrentScrollableContainer((HeaderViewPagerFragment) fragmentList.get(position));
                }

至此应该能解决大部分问题了

HeaderScrollHelper中的isTop()可不可以稍微开放点啊

作者你好,如题,HeaderScrollHelper中的isTop()是否可以稍微开放点,比如我是用的RecyclerView,但是LayoutManager是用的GridLayoutManager,而库中只对LinearLayoutManager做了判断,其他的都是返回false。建议是否可以在接口ScrollableContainer中添加一个方法:isTop( ),让我们自己可以在对应的页面给你返回一个值

嵌套RecyclerView 导致,RecyclerView滑动速率发生突变

首先感谢作者开源这么棒的项目。我在使用中遇见了一个问题。
`伪代码

...

`

测试机型:很多,都出现了
系统版本:6.0.1 5.1.1 其他的没测试
描述:此时效果正常,上下正常联动,但是RecyclerView 滑动时,滑动fling,松手后,会有明显速度加快的情况发生。

看代码发现的事件传递的疑问

hi,jeasonlzy,首先感谢你提供的这么棒的开源库,我在看代码有个地方不太明白,请指教:

在HeaderViewPager的142行:
/**
* 这里要注意,对于垂直滑动来说,给出以下三个条件
* 头部没有固定,允许滑动的View处于第一条可见,当前按下的点在头部区域
* 三个条件满足一个即表示需要滚动当前布局,否者不处理,将事件交给子View去处理
*/
if (verticalScrollFlag && (!isStickied() || mScrollable.isTop() || isClickHead)) {
//如果是向下滑,则deltaY小于0,对于scrollBy来说
//正值为向上和向左滑,负值为向下和向右滑,这里要注意
scrollBy(0, (int) (deltaY + 0.5));
invalidate();
}

进入if之后,表示我们需要移动整个容器布局,所以直接滚动容器。

但是这里并没有return,所以这里不管条件如何,这个事件还是会传递到子view中去,如果这个子view是listview,在整体容器滚动的同时,为什么listview自己不会滚动呢?

使用RecyclerView模板压入方式

View view = layoutInflater.inflate(R.layout.item_product, null);
View view = layoutInflater.inflate(R.layout.item_product, parent);
第一种可以正常使用,当parent不为空时向上可以正常滑动,但是滑到顶后,上面收起来的内容就拉不下来了

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.