Activity从RecyclerView拦截DragEvent

时间:2014-12-22 21:06:06

标签: android

我希望获得Google+个人资料页面效果(请查看随附的GIF)

enter image description here

我取得的成就

到目前为止,我已经实现了:滚动到底部(向上拖动)时,标题图像将缩小,SlidingTab将固定在ActionBar下方。就像GIF的前半部分一样

但是我无法做到相反:当RecyclerView到达第一个孩子时,它会停止发送onScrolled事件,并且标题视图无法展开。

相关文件

继承我的布局文件:

<android.support.v4.widget.DrawerLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:animateLayoutChanges="true"
    android:fitsSystemWindows="false"
    tools:context=".ProfileActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/profile_header_background_image"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/header"
            android:layout_alignParentTop="true"
            android:adjustViewBounds="true"
            android:scaleType="centerCrop"
            tools:src="@drawable/ic_launcher" />

        <LinearLayout
            android:id="@+id/header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:orientation="vertical">

            <include
                android:id="@+id/toolbar"
                layout="@layout/toolbar_actionbar_layout" />

            <include
                android:id="@+id/profile_bio_view"
                layout="@layout/profile_header" />
        </LinearLayout>


        <SlidingTabLayout
            android:id="@+id/profile_sliding_tags"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/header" />

        <android.support.v4.view.ViewPager
            android:id="@+id/profile_viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentBottom="true"
            android:layout_below="@+id/profile_sliding_tags" />
    </RelativeLayout>


    <include layout="@layout/drawer_navigation_layout" />

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

ViewPager&#39; RecyclerView内,我做了这个:

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            Bus.post(new ProfileScrolledEvent(recyclerView.getChildAt(0).getTop(), state, dy));
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            state = newState;
            // intercept the touch event if scroll state=0 (IDLE)
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                Bus.post(new ProfileScrolledEvent(recyclerView.getChildAt(0).getTop(), state, 0));
                recyclerView.getParent().getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                recyclerView.getParent().getParent().requestDisallowInterceptTouchEvent(false);
            }
        }
    });

因此,当RecyclerView滚动时,我可以将滚动的像素发布到活动中,并在我的活动中:

@Subscribe
    public void onProfileScrolledEvent(ProfileScrolledEvent event) {
        // FIXME: can scroll with shrink header, but the header will not expand as expected
        int scrollState = event.getScrollState();
        int pixels = event.getScrolledPixels();
        int recyclerViewTop = event.getRecyclerViewTop();
        if (pixels == 0 && scrollState == 0) {
            //TODO intercept the touch event
            shouldIntercept = true;
        } else {
            shouldIntercept = false;
            scrollProfile(recyclerViewTop);
        }
        LogUtil.debug("Bus event. top: " + recyclerViewTop + " state: " + scrollState + " pixels: " + pixels);

    }

    private void scrollProfile(int pixels) {
        ViewGroup.LayoutParams headerParams = profileBioView.getLayoutParams();
        headerParams.height = profileBioView.getHeight() + pixels / 2;
        currentHeaderHeight = headerParams.height;
        LogUtil.debug("currentHeaderHeight: " + currentHeaderHeight +
                "\n profileBioView.getHeight: " + profileBioView.getHeight() +
                "\n background.getHeight: " + headerBackground.getHeight());
        ViewGroup.LayoutParams imageParams = headerBackground.getLayoutParams();
        imageParams.height = headerParams.height;

        if (headerParams.height <= 0) {
            headerBackground.setVisibility(View.INVISIBLE);
        } else {
            headerBackground.setVisibility(View.VISIBLE);
            slidingTabLayout.setTranslationY(pixels / 2);

            if (headerParams.height > origHeaderHeight) {
                headerParams.height = origHeaderHeight;
                imageParams.height = origHeaderHeight;
            }
            profileBioView.setLayoutParams(headerParams);
            headerBackground.setLayoutParams(imageParams);
        }
    }

问题

问题是,当RecyclerView到达其第一个孩子时,onScrolled事件停止,ScrollState变为IDLE。此时,我想通知父活动拦截TouchEvent并继续移动标题视图。但是,当我尝试在活动中注册GestureListener时,它根本就没有被调用。

那么还有更好的方法吗?或者是否可以在特定条件下拦截孩子TouchEvent

仅供参考:我使用Otto Bus发布消息,请点击此处:http://square.github.io/otto/

0 个答案:

没有答案