Aspsine/SwipeToLoadLayout

SwipeToLoadLayout.setSwipeStyle方法 belw属性不起作用

tancolo opened this issue · 3 comments

问题描述:

版本: 1.0.4
不论是@Aspsine 提供的Demo, 还是自己实际使用时, 发现问题。
使用Recycleview 以及 ListView 将对应的SwipeToLoadLayout布局设置为 app:swipe_style="blew" 不起作用,使用的还是CLASSIC Style。

重现方法:

  • 1.导入官方demo
  • 2.进入app -> Twitter Style -> RECYCLEVIEW Tab
  • 3.下拉刷新,默认是classic模式 (下拉刷新过程中,滑动recycleview可以进入刷新view之下)
  • 4.修改fragment包目录下的 TwitterRecyclerFragment.java 对应的布局文件 fragment_twitter_recycler.xml 将app:swipe_style="classic" 改为 app:swipe_style="blew"
  • 5.再次编译测试,发现还是跟 classic 一样的效果, 而改用其他的效果 style,[above, scale] 有效果。

奇怪点:

Demo提供了使用java代码修改样式的实例,菜单-> Set Header Footer Via Java -> Style选择 Blow, Header Style,Footer Style默认为 Twitter Style, 发现 blew效果是可以看到!
查看布局文件 fragment_nav_java_code.xml

<LinearLayout 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:orientation="vertical">

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

    <com.aspsine.swipetoloadlayout.SwipeToLoadLayout
        android:id="@+id/swipeToLoadLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#e3e3e3"
        tools:context="com.aspsine.swipetoloadlayout.demo.fragment.NavJavaCodeFragment">

        <ListView
            android:id="@id/swipe_target"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:background="@color/white"/>

    </com.aspsine.swipetoloadlayout.SwipeToLoadLayout>
</LinearLayout>

Demo,然后再代码中动态 添加Header, Footer, 以及设置对应的Style, 相关代码:

view = mInflater.inflate(R.layout.layout_classic_footer, swipeToLoadLayout, false); -> changeFooter
view = mInflater.inflate(R.layout.layout_twitter_header, swipeToLoadLayout, false); -> changeHeader
swipeToLoadLayout.setSwipeStyle(SwipeToLoadLayout.STYLE.BLEW); -> changeStyle

代码分析

不论是设置属性 app:swipe_style="classic" 还是代码控制 swipeToLoadLayout.setSwipeStyle(SwipeToLoadLayout.STYLE.BLEW) 都会执行到 SwipeToLoadLayout.java中的

public void setSwipeStyle(int style) {
        this.mStyle = style;
        requestLayout();
    }

而mStyle在哪里使用,关键是在 layoutChildren中使用,其中涉及到 Headerview,FooterView, targetView位置的确定。这段代码,没有搞清楚作者的实现逻辑。
疑惑的代码如下:

if (mHeaderView != null) {
            ...
            switch (mStyle) {
                case STYLE.CLASSIC:
                    // classic
                    headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
                    break;
                case STYLE.ABOVE:
                    // classic
                    headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
                    break;
                case STYLE.BLEW: //问题点???
                    // blew
                    headerTop = paddingTop + lp.topMargin;
                    break;
                case STYLE.SCALE:
                    // scale
                    headerTop = paddingTop + lp.topMargin - mHeaderHeight / 2 + mHeaderOffset / 2;
                    break;
                default:
                    // classic
                    headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
                    break;
            }
            final int headerRight = headerLeft + headerView.getMeasuredWidth();
            final int headerBottom = headerTop + headerView.getMeasuredHeight();
            headerView.layout(headerLeft, headerTop, headerRight, headerBottom);
        }
		
		// layout target
        if (mTargetView != null) {
            ...

            switch (mStyle) {
                case STYLE.CLASSIC:
                    // classic
                    targetTop = paddingTop + lp.topMargin + mTargetOffset;
                    break;
                case STYLE.ABOVE:
                    // above
                    targetTop = paddingTop + lp.topMargin;
                    break;
                case STYLE.BLEW: //问题点???
                    // classic
                    targetTop = paddingTop + lp.topMargin + mTargetOffset;
                    break;
                case STYLE.SCALE:
                    // classic
                    targetTop = paddingTop + lp.topMargin + mTargetOffset;
                    break;
                default:
                    // classic
                    targetTop = paddingTop + lp.topMargin + mTargetOffset;
                    break;
            }
            final int targetRight = targetLeft + targetView.getMeasuredWidth();
            final int targetBottom = targetTop + targetView.getMeasuredHeight();
            targetView.layout(targetLeft, targetTop, targetRight, targetBottom);
        }
		
		// layout footer
        if (mFooterView != null) {
            ...
            switch (mStyle) {
                case STYLE.CLASSIC:
                    // classic
                    footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
                    break;
                case STYLE.ABOVE:
                    // classic
                    footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
                    break;
                case STYLE.BLEW: //问题点???
                    // blew
                    footerBottom = height - paddingBottom - lp.bottomMargin;
                    break;
                case STYLE.SCALE:
                    // scale
                    footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight / 2 + mFooterOffset / 2;
                    break;
                default:
                    // classic
                    footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
                    break;
            }
            final int footerTop = footerBottom - footerView.getMeasuredHeight();
            final int footerRight = footerLeft + footerView.getMeasuredWidth();

            footerView.layout(footerLeft, footerTop, footerRight, footerBottom);
        }

总感觉 case BLEW: 的处理跟其他的差别很大

作者要是能看到,还请核实下代码,若有可能,可以简单介绍下 layoutChildren 考虑的逻辑。
谢谢!

你好,经过测试,修改fragment_twitter_recycler.xml app:swipe_style="blew"是有效果的。

请观察,classic的header是从上面拉出来的。而blew模式下,header是被盖在recyclerView下面的。

<com.aspsine.swipetoloadlayout.SwipeToLoadLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/swipeToLoadLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/style_window_background"
    app:swipe_style="blew"
    tools:context="com.aspsine.swipetoloadlayout.demo.fragment.TwitterRecyclerFragment">

    <include
        android:id="@id/swipe_refresh_header"
        layout="@layout/layout_twitter_header" />

    <android.support.v7.widget.RecyclerView
        android:id="@id/swipe_target"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false" />

    <include
        android:id="@id/swipe_load_more_footer"
        layout="@layout/layout_classic_footer" />
</com.aspsine.swipetoloadlayout.SwipeToLoadLayout>
// layout header
if (mHeaderView != null) {
    final View headerView = mHeaderView;
    MarginLayoutParams lp = (MarginLayoutParams) headerView.getLayoutParams();
    final int headerLeft = paddingLeft + lp.leftMargin;
    final int headerTop;
    switch (mStyle) {
        case STYLE.CLASSIC:
            // classic
            headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
            break;
        case STYLE.ABOVE:
            // classic
            headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
            break;
        case STYLE.BLEW:
            // blew
            headerTop = paddingTop + lp.topMargin; // blew 模式下,下拉过程中,header 的位置一直保持不变。
            break;
        case STYLE.SCALE:
            // scale
            headerTop = paddingTop + lp.topMargin - mHeaderHeight / 2 + mHeaderOffset / 2;
            break;
        default:
            // classic
            headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
            break;
    }
    final int headerRight = headerLeft + headerView.getMeasuredWidth();
    final int headerBottom = headerTop + headerView.getMeasuredHeight();
    headerView.layout(headerLeft, headerTop, headerRight, headerBottom);
}


// layout target
if (mTargetView != null) {
    final View targetView = mTargetView;
    MarginLayoutParams lp = (MarginLayoutParams) targetView.getLayoutParams();
    final int targetLeft = paddingLeft + lp.leftMargin;
    final int targetTop;

    switch (mStyle) {
        case STYLE.CLASSIC:
            // classic
            targetTop = paddingTop + lp.topMargin + mTargetOffset;
            break;
        case STYLE.ABOVE:
            // above
            targetTop = paddingTop + lp.topMargin;
            break;
        case STYLE.BLEW:
            // classic
            targetTop = paddingTop + lp.topMargin + mTargetOffset; // blew 模式下,下拉过程中,targetView 就像classic的模式一下一样,下拉需要增大顶部间距,这样就可以漏出header; 上拉过程中,target需要减少顶部间距为负值,这样就可以漏出footer
            break;
        case STYLE.SCALE:
            // classic
            targetTop = paddingTop + lp.topMargin + mTargetOffset;
            break;
        default:
            // classic
            targetTop = paddingTop + lp.topMargin + mTargetOffset;
            break;
    }
    final int targetRight = targetLeft + targetView.getMeasuredWidth();
    final int targetBottom = targetTop + targetView.getMeasuredHeight();
    targetView.layout(targetLeft, targetTop, targetRight, targetBottom);
}

// layout footer
if (mFooterView != null) {
    final View footerView = mFooterView;
    MarginLayoutParams lp = (MarginLayoutParams) footerView.getLayoutParams();
    final int footerLeft = paddingLeft + lp.leftMargin;
    final int footerBottom;
    switch (mStyle) {
        case STYLE.CLASSIC:
            // classic
            footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
            break;
        case STYLE.ABOVE:
            // classic
            footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
            break;
        case STYLE.BLEW:
            // blew
            footerBottom = height - paddingBottom - lp.bottomMargin; // blew 模式下,下拉过程中,footer位置不变
            break;
        case STYLE.SCALE:
            // scale
            footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight / 2 + mFooterOffset / 2;
            break;
        default:
            // classic
            footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
            break;
    }
    final int footerTop = footerBottom - footerView.getMeasuredHeight();
    final int footerRight = footerLeft + footerView.getMeasuredWidth();

    footerView.layout(footerLeft, footerTop, footerRight, footerBottom);
}

@Aspsine 将header view, footer view添加其他颜色,区别与整体颜色。
发现确实,如你所说, classic style, header & recycleview一起,blew style,header 在最上面,Recyclerview 在下拉的过程中会跟header分离。
为止,录制了 2个小视频,你可以看下! 一个是修改你的demo,一个是我自己的demo
http://pan.baidu.com/s/1i4LduxZ
http://pan.baidu.com/s/1qY8UbNY

所以,BELW 的含义,其实是在下拉的过程中,header view其实是在 recycleview的下面。
但是 从视频效果上看,你的比我的好看多了,我的还会闪烁一下! 这应该是我Recyclerview底部透明的缘故?

是的,recyclerview背景透明的缘故。