2017-05-10 49 views
1

我在Android应用程序中创建滚动活动。该活动具有带视差效​​果的CollapsingToolbarLayout。CollapsingToolbarLayout滚动问题 - 有时在滚动时卡住

当我将appbarlayout下方的布局向上滚动时,它会顺利地上升,appbarlayout将折叠到标题。ImageView和TextView将转到标题。当我将布局向下滚动时,它们都会回到起点。

的错误是在这里:

当我运行在某些设备上的活动

,有时当我滚动起来,布局将stucked有上下几秒钟,然后回到去顶。 当我在其他设备上运行该活动时,它会好的,没有发生任何错误。

这个bug的演示:https://share.weiyun.com/1d797a4a92580e1595eacb226f9a92a3

这里的布局:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout 
    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:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="nczz.cn.helloworld.ScrollingActivity" 
    > 
    <android.support.design.widget.AppBarLayout 
     android:id="@+id/app_bar" 
     android:layout_width="match_parent" 
     android:layout_height="@dimen/app_bar_height" 
     android:background="#FA7199" 
     app:layout_scrollFlags="scroll|enterAlways" 
     android:theme="@style/AppTheme.AppBarOverlay"> 

     <nczz.cn.widget.CollapsingImageTextLayout 
      android:id="@+id/imageTextLayout" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      app:layout_scrollFlags="scroll|exitUntilCollapsed" 
      app:title_id="@+id/test_title" 
      app:text_id="@+id/test_text" 
      app:img_scale="0.6" 
      app:text_scale="0.6" 
      app:text_margin_left="110dp" 
      app:img_id="@+id/test_img" 
      app:img_margin_left="55dp" 
      > 
      <LinearLayout 
       android:id="@+id/test_title" 
       android:layout_width="match_parent" 
       android:layout_height="80dp" 
       android:background="#FA7199" 
       android:gravity="center_vertical" 
       android:orientation="horizontal" 
       > 
       <ImageView 
        android:id="@+id/return_btn" 
        android:layout_width="15dp" 
        android:layout_height="15dp" 
        android:layout_marginLeft="20dp" 
        android:layout_centerVertical="true" 
        android:src="@drawable/left" /> 
      </LinearLayout> 

      <ImageView 
       android:id="@+id/test_img" 
       android:layout_width="80dp" 
       android:layout_height="80dp" 
       android:scaleType="fitXY" 
       android:src="@mipmap/ic_launcher" 
       android:layout_centerInParent="true" 
       android:layout_marginBottom="30dp" 
       /> 

      <TextView 
       android:id="@+id/test_text" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_below="@+id/test_img" 
       android:text="MoveText" 
       android:textSize="20sp" 
       android:textColor="@android:color/white" 
       android:layout_marginTop="-20dp" 
       android:layout_marginLeft="50dp" 
       android:layout_centerInParent="true" 
       /> 

     </nczz.cn.widget.CollapsingImageTextLayout> 

    </android.support.design.widget.AppBarLayout> 
    <include 
     android:id="@+id/includelayout" 
     layout="@layout/content_scrolling"/> 

</android.support.design.widget.CoordinatorLayout> 

这里是CollapsingImageTextLayout:

package nczz.cn.widget; 

import android.content.Context; 
import android.content.res.TypedArray; 
import android.support.annotation.NonNull; 
import android.support.design.widget.AppBarLayout; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.ViewParent; 
import android.widget.RelativeLayout; 

import nczz.cn.helloworld.R; 


/** 
* Created by yahui.hu on 2017/4/21. 
*/ 

public class CollapsingImageTextLayout extends RelativeLayout { 

    private AppBarLayout.OnOffsetChangedListener mOffsetChangedListener; 

    private int mTitleId, mTextId, mImageId; 
    private int mTitleMarginLeft, mTitleMarginTop, mImgMarginLeft, mImgMarginTop; 
    private float mTextScale, mImgScale; 
    private View mTitle, mImg, mText; 
    private boolean isGetView = true; 
    private int mTitleHeight = 0; 


    public CollapsingImageTextLayout(Context context) { 
     this(context, null); 
    } 

    public CollapsingImageTextLayout(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public CollapsingImageTextLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     TypedArray a = context.obtainStyledAttributes(attrs, 
       R.styleable.CollapsingImageLayout, defStyleAttr, 0); 
     mTitleId = a.getResourceId(R.styleable.CollapsingImageLayout_title_id, 0); 
     mTextId = a.getResourceId(R.styleable.CollapsingImageLayout_text_id, 0); 
     mImageId = a.getResourceId(R.styleable.CollapsingImageLayout_img_id, 0); 
     mTextScale = a.getFloat(R.styleable.CollapsingImageLayout_text_scale, 0.4f); 
     mImgScale = a.getFloat(R.styleable.CollapsingImageLayout_img_scale, 0.4f); 
     mTitleMarginLeft = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_text_margin_left, 0); 
     mTitleMarginTop = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_text_margin_top, 0); 
     mImgMarginLeft = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_img_margin_left, 0); 
     mImgMarginTop = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_img_margin_top, 0); 
     a.recycle(); 

    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     getView(); 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    } 

    private void getView() { 
     if (!isGetView) { 
      return; 
     } 
     if (mTitleId != 0) { 
      mTitle = findViewById(mTitleId); 
     } 

     if (mTextId != 0) { 
      mText = findViewById(mTextId); 
     } 

     if (mImageId != 0) { 
      mImg = findViewById(mImageId); 
     } 
     isGetView = false; 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     super.onLayout(changed, l, t, r, b); 

     if (mTitle != null) { 
      getViewOffsetHelper(mTitle).onViewLayout(0, 0); 
      setMinimumHeight(getHeightWithMargins(mTitle)); 
      mTitleHeight = mTitle.getHeight(); 
      this.bringChildToFront(mTitle); 
     } 

     if (mImg != null) { 
      getViewOffsetHelper(mImg).onViewLayout(mImgMarginLeft, mImgMarginTop); 
      this.bringChildToFront(mImg); 
     } 

     if (mText != null) { 
      getViewOffsetHelper(mText).onViewLayout(mTitleMarginLeft, mTitleMarginTop); 
      this.bringChildToFront(mText); 
     } 
    } 

    static ViewHelper getViewOffsetHelper(View view) { 
     ViewHelper offsetHelper = (ViewHelper) view.getTag(R.id.view_helper); 
     if (offsetHelper == null) { 
      offsetHelper = new ViewHelper(view); 
      view.setTag(R.id.view_helper, offsetHelper); 
     } 
     return offsetHelper; 
    } 


    private static int getHeightWithMargins(@NonNull final View view) { 
     final ViewGroup.LayoutParams lp = view.getLayoutParams(); 
     if (lp instanceof MarginLayoutParams) { 
      final MarginLayoutParams mlp = (MarginLayoutParams) lp; 
      return view.getHeight() + mlp.topMargin + mlp.bottomMargin; 
     } 
     return view.getHeight(); 
    } 

    @Override 
    protected void onAttachedToWindow() { 
     super.onAttachedToWindow(); 
     ViewParent viewParent = getParent(); 
     if (viewParent instanceof AppBarLayout) { 
      if (mOffsetChangedListener == null) mOffsetChangedListener = new OffsetListenerImp(); 
      ((AppBarLayout) viewParent).addOnOffsetChangedListener(mOffsetChangedListener); 
     } 
    } 

    @Override 
    protected void onDetachedFromWindow() { 
     ViewParent viewParent = getParent(); 
     if (viewParent instanceof AppBarLayout) { 
      ((AppBarLayout) viewParent).removeOnOffsetChangedListener(mOffsetChangedListener); 
     } 
     super.onDetachedFromWindow(); 
    } 


    final int getMaxOffsetForPinChild(View child) { 
     final ViewHelper offsetHelper = getViewOffsetHelper(child); 
     final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 
     return getHeight() 
       - offsetHelper.getLayoutTop() 
       - child.getHeight() 
       - lp.bottomMargin; 
    } 

    static int constrain(int amount, int low, int high) { 
     return amount < low ? low : (amount > high ? high : amount); 
    } 

    static int constrain(int amount, int low) { 
     return amount < low ? low : amount; 
    } 

    private void setTopAndBottomOffset(View child, int verticalOffset) { 
     ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper); 
     viewHelper.setTopAndBottomOffset(
       constrain(-verticalOffset, 0, getMaxOffsetForPinChild(child))); 
     Log.e("setTopAndBottomOffset",""+-verticalOffset); 
    } 

    private void setTopAndBottomOffset(View child, int verticalOffset, float scale) { 
     ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper); 
     viewHelper.setTopAndBottomOffset(
       constrain(-verticalOffset - getMaxOffset(viewHelper, scale), 
         0)); 
     //Log.e("setTopAndBottomOffset",""+-verticalOffset); 
    } 

    private void setLeftAndRightOffset(View child, int verticalOffset, float scale) { 
     ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper); 
     int maxOffsetDistance = getMaxOffset(viewHelper, scale); 
     int maxLeft = viewHelper.getLayoutLeft() 
       + (viewHelper.getViewWidth() - viewHelper.getScaleViewWidth(scale)) 
       - viewHelper.getMarginTitleLeft(); 
     int realOffset = (int) (maxLeft * 1.0f/(maxOffsetDistance * 1.0f) * verticalOffset); 
     realOffset = constrain(realOffset, -maxLeft, maxLeft); 
     viewHelper.setLeftAndRightOffset(realOffset); 
     // Log.e("setLeftAndRightOffset",""+realOffset); 
    } 

    private void setViewScale(View child, int verticalOffset, float scale) { 
     ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper); 
     int maxOffsetDistance = getMaxOffset(viewHelper, scale); 
     float realScale = -verticalOffset - maxOffsetDistance > 0 ? scale : verticalOffset == 0 ? 1f : 0f; 
     if (realScale == 0) { 
      realScale = (maxOffsetDistance + verticalOffset * (1 - scale))/(maxOffsetDistance * 1f); 
     } 
     viewHelper.setViewOffsetScale(realScale); 
    } 

    private int getMaxOffset(ViewHelper viewHelper, float scale) { 
     int scaleViewHeight = (int) (scale * viewHelper.getViewHeight()); 
     int offsetTitleDistance = scaleViewHeight >= mTitleHeight ? 0 : (mTitleHeight - scaleViewHeight)/2; 
     int marginTop = viewHelper.getMarginTitleTop() >= offsetTitleDistance ? offsetTitleDistance : viewHelper.getMarginTitleTop(); 
     return viewHelper.getLayoutBottom() - viewHelper.getScaleViewHeight(scale) - offsetTitleDistance - marginTop; 
    } 

    private class OffsetListenerImp implements AppBarLayout.OnOffsetChangedListener { 
     @Override 
     public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { 
      if (mTitle != null) { 
       setTopAndBottomOffset(mTitle, verticalOffset); 
      } 
      if (mText != null) { 
       setTopAndBottomOffset(mText, verticalOffset, mTextScale); 
       setLeftAndRightOffset(mText, verticalOffset, mTextScale); 
       setViewScale(mText, verticalOffset, mTextScale); 
      } 
      if (mImg != null) { 
       setTopAndBottomOffset(mImg, verticalOffset, mImgScale); 
       setLeftAndRightOffset(mImg, verticalOffset, mImgScale); 
       setViewScale(mImg, verticalOffset, mImgScale); 
      } 
     } 
    } 

    public void setImgTitleMarginTop(int top) { 
     if (mImg != null) { 
      getViewOffsetHelper(mImg).setMarginTitleTop(top); 
     } 
    } 

    public void setImgTitleMarginLeft(int left) { 
     if (mImg != null) { 
      getViewOffsetHelper(mImg).setMarginTitleLeft(left); 
     } 
    } 

    public void setTextTitleMarginTop(int top) { 
     if (mText != null) { 
      getViewOffsetHelper(mText).setMarginTitleTop(top); 
     } 
    } 

    public void setImgTextMarginLeft(int left) { 
     if (mText != null) { 
      getViewOffsetHelper(mText).setMarginTitleLeft(left); 
     } 
    } 
} 

这里是content_scolling.xml:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v4.widget.NestedScrollView 
    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:layout_width="match_parent" 
    android:background="#cccccc" 
    android:layout_height="match_parent" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior" 
    tools:context="nczz.cn.helloworld.ScrollingActivity" 
    tools:showIn="@layout/activity_scrolling"> 
    <TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/large_text" /> 

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

这里是java:

package nczz.cn.helloworld; 

import android.app.Activity; 
import android.content.Intent; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.Window; 
import android.view.WindowManager; 
import android.widget.LinearLayout; 

public class ScrollingActivity extends Activity { 
    LinearLayout titleTxt; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(R.layout.activity_scrolling); 
     initViews(); 
     setTitleBarHeight(); 
    } 

    private void initViews(){ 
     titleTxt= (LinearLayout) findViewById(R.id.test_title); 
    } 


    private void setTitleBarHeight(){ 
     WindowManager manager=getWindowManager(); 
     int height=manager.getDefaultDisplay().getHeight(); 
     ViewGroup.LayoutParams params=titleTxt.getLayoutParams(); 
     params.height=height/12; 
     titleTxt.setLayoutParams(params); 
    } 
} 

回答

0

我不知道但你可以根据视图嵌套滚动型

viewlayoutInsidescrollview.setNestedScrollingEnabled(false); 

里面的java类

+0

感谢使用下面的代码,但它不工作的人 – lee