簡體   English   中英

CoordinatorLayout:視圖因自定義行為而消失

[英]CoordinatorLayout: View disappears with custom behavior

我是CoordinatorLayout的新手,這是我在CoordinatorLayout遇到的一個非常奇怪的行為。我有一個ImageView (或更具體地講是一個稱為CircleImageViewImageView的子類(在此處居中配置文件圖片) )作為孩子之一的CoordinatorLayout 我已經將此CircleImageView錨定到AppbarLayout (這是CoordinatorLayout另一個子級)。 這是我的整個布局:

到目前為止,一切都很好。 我目前能夠滾動AppbarLayout ,並且NestedScrollView移動。 但是,當我向上滾動並決定依賴自定義CoordinatorLayour.Behavior ,我想到了對Profile圖片進行動畫處理的權利。 最后,我嘗試了一個自定義行為,嘗試翻譯CircleImageView 它尚不完整,但是應該可以平移視圖,除非現在, CircleImageView隨着自定義行為的引入而完全消失了。

這可能是什么原因?

注意 :我嘗試用ImageView替換CircleImageView,並且行為保持不變。


這是供參考的布局:

<?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"
    android:fitsSystemWindows="false">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/main.appbar"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:fitsSystemWindows="false"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            </android.support.v7.widget.Toolbar>

            <android.support.v7.widget.AppCompatImageView
                android:id="@+id/imageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|end"
                android:layout_marginBottom="24dp"
                android:layout_marginEnd="24dp"
                android:layout_marginRight="24dp"
                android:layout_weight="1"
                android:tint="@color/white"
                app:srcCompat="@drawable/ic_settings_24px" />

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


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

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/profile_pic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="4dp"
           app:layout_behavior="com.learncity.learner.account.profile.ProfilePicBehavior"
        android:src="@drawable/avatar_boy_2"
        app:layout_anchor="@id/main.appbar"
        app:layout_anchorGravity="bottom|center" />

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">


            <TextView
                android:id="@+id/user_name"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="64dp"
                android:lineSpacingExtra="8dp"
                android:padding="@dimen/activity_horizontal_margin"
                android:text="@string/account_person_name_label"
                android:textAlignment="center"
                android:textSize="40sp"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <android.support.v7.widget.AppCompatImageView
                android:id="@+id/id_phone_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="24dp"
                android:layout_marginStart="24dp"
                android:layout_marginTop="8dp"
                android:tint="@color/colorPrimary"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/user_name"
                app:srcCompat="@drawable/ic_phone_black_24dp" />

            <TextView
                android:id="@+id/id_phone_no"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="16dp"
                android:layout_marginStart="16dp"
                android:text="Phone No"
                app:layout_constraintBottom_toBottomOf="@+id/id_phone_icon"
                app:layout_constraintLeft_toRightOf="@+id/id_phone_icon"
                app:layout_constraintTop_toTopOf="@+id/id_phone_icon"
                app:layout_constraintVertical_bias="0.571" />


            <android.support.v7.widget.AppCompatImageView
                android:id="@+id/id_email_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="24dp"
                android:layout_marginStart="24dp"
                android:layout_marginTop="8dp"
                android:tint="@color/colorPrimary"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/id_phone_icon"
                app:srcCompat="@drawable/ic_email_black_24dp" />

            <TextView
                android:id="@+id/id_email_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="16dp"
                android:layout_marginStart="16dp"
                android:text="Email Id"
                app:layout_constraintBottom_toBottomOf="@+id/id_email_icon"
                app:layout_constraintLeft_toRightOf="@+id/id_email_icon"
                app:layout_constraintTop_toTopOf="@+id/id_email_icon" />

            <View
                style="@style/Divider"
                android:layout_marginEnd="8dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/id_email_icon" />

        </android.support.constraint.ConstraintLayout>

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


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

和自定義行為:( 我知道計算可能不正確,但是我正在嘗試制作初始的原始動畫

public class ProfilePicBehavior extends CoordinatorLayout.Behavior<CircleImageView>{


    public ProfilePicBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) {
        // Translate the CircleImageView to the right
        // Calculate first, what fraction the AppBarLayout has shrunk by
        float proportion = dependency.getHeight() / 200f;
        // Translate the child by this proportion
        float translationX = parent.getWidth() * proportion;
        child.setTranslationX(translationX);

        return true;
    }
}

幾個月前,我也遇到了同樣的問題。 我通過以下自定義CoordinatorLayout.Behavior解決了這個問題(我不記得相同問題的鏈接):

public class CollapsingImageBehavior extends CoordinatorLayout.Behavior<View> {

private final static int X = 0;
private final static int Y = 1;
private final static int WIDTH = 2;
private final static int HEIGHT = 3;

private int mTargetId;

private int[] mView;

private int[] mTarget;

public CollapsingImageBehavior() {
}

public CollapsingImageBehavior(Context context, AttributeSet attrs) {

    if (attrs != null) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CollapsingImageBehavior);
        mTargetId = a.getResourceId(R.styleable.CollapsingImageBehavior_collapsedTarget, 0);
        a.recycle();
    }

    if (mTargetId == 0) {
        throw new IllegalStateException("collapsedTarget attribute not specified on view for behavior");
    }
}

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
    return dependency instanceof AppBarLayout;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {

    setup(parent, child);

    AppBarLayout appBarLayout = (AppBarLayout) dependency;

    int range = appBarLayout.getTotalScrollRange();
    float factor = -appBarLayout.getY() / range;

    int left = mView[X] + (int) (factor * (mTarget[X] - mView[X]));
    int top = mView[Y] + (int) (factor * (mTarget[Y] - mView[Y]));
    int width = mView[WIDTH] + (int) (factor * (mTarget[WIDTH] - mView[WIDTH]));
    int height = mView[HEIGHT] + (int) (factor * (mTarget[HEIGHT] - mView[HEIGHT]));

    CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
    lp.width = width;
    lp.height = height;
    child.setLayoutParams(lp);
    child.setX(left);
    child.setY(top);

    return true;
}

private void setup(CoordinatorLayout parent, View child) {

    if (mView != null) return;

    mView = new int[4];
    mTarget = new int[4];

    mView[X] = (int) child.getX();
    mView[Y] = (int) child.getY();
    mView[WIDTH] = child.getWidth();
    mView[HEIGHT] = child.getHeight();

    View target = parent.findViewById(mTargetId);
    if (target == null) {
        throw new IllegalStateException("target view not found");
    }

    mTarget[WIDTH] += target.getWidth();
    mTarget[HEIGHT] += target.getHeight();

    View view = target;
    while (view != parent) {
        mTarget[X] += (int) view.getX();
        mTarget[Y] += (int) view.getY();
        view = (View) view.getParent();
    }

}
}

您必須添加一個自定義樣式的attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CollapsingImageBehavior">
    <attr name="collapsedTarget" format="integer"></attr>
</declare-styleable>
</resources>

之后,您可以如下定義xml:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.AppBarLayout
    android:id="@+id/main.appbar"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:fitsSystemWindows="false"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            <Space
                android:id="@+id/circle_collapsed_target"
                android:layout_width="40dp"
                android:layout_height="40dp" />
        </android.support.v7.widget.Toolbar>

        <android.support.v7.widget.AppCompatImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_marginBottom="24dp"
            android:layout_marginEnd="24dp"
            android:layout_marginRight="24dp"
            android:layout_weight="1"
            app:srcCompat="@drawable/ic_tab_angel" />


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


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

<ImageView
    android:id="@+id/profile_pic"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_gravity="top|center_horizontal"
    android:layout_marginTop="220dp"
    android:elevation="4dp"
    android:src="@mipmap/icon_app"
    app:collapsedTarget="@id/circle_collapsed_target"
    app:layout_behavior="com.kp_corp.angelalarm.activity.CollapsingImageBehavior" />
<!---->

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/user_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="64dp"
            android:lineSpacingExtra="8dp"
            android:padding="@dimen/activity_horizontal_margin"
            android:text="Test"
            android:textAlignment="center"
            android:textSize="40sp"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />


    </android.support.constraint.ConstraintLayout>

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

根據此答案: https : //stackoverflow.com/a/40023161/6248491

這說明包含的 CollapsingToolbarLayout 擺弄着父母的身高

嘗試將AppBarLayout高度設為0dp。 另外, CircleImageView應該具有更多(更高)的高程,以便不會在頂部 “抬高”

希望這可以幫助。 讓我知道它是否有效。

去年我不得不做類似的事情。

AvatarImageBehavior基於Saul Molinero(saulmm)的GitHub項目

如您CircleImageViewCircleImageView是布局的最后一個元素。 也許這是你的問題? 希望能幫助到你。

片段的布局

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:custom="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:ignore="RtlHardcoded">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/main_appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/main.collapsing"
            android:layout_width="match_parent"
            android:layout_height="550dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:id="@+id/iv_product_background"
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:scaleType="centerCrop"
                android:tint="#11000000"
                app:layout_collapseMode="parallax"/>

            <FrameLayout
                android:id="@+id/main_framelayout_title"
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:layout_gravity="bottom|center_horizontal"
                android:background="@color/white"
                android:orientation="vertical"
                app:layout_collapseMode="parallax">

                <LinearLayout
                    android:id="@+id/main_linearlayout_title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/tv_product_title_open"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:gravity="bottom|center"
                        tools:text="Title"
                        android:textColor="@android:color/white"
                        android:textSize="30sp"/>

                    <TextView
                        android:id="@+id/tv_product_tagline"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:layout_marginTop="4dp"
                        android:gravity="center"
                        android:paddingEnd="@dimen/standard_margin_space"
                        android:paddingStart="@dimen/standard_margin_space"
                        tools:text="Tagline"
                        android:textColor="@android:color/white"/>

                </LinearLayout>
            </FrameLayout>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>


    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:scrollbars="none"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:id="@+id/products_view_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"/>
    </android.support.v4.widget.NestedScrollView>

    <android.support.v7.widget.Toolbar
        android:id="@+id/main_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        app:layout_anchor="@id/main_framelayout_title"
        app:theme="@style/ThemeOverlay.AppCompat.Dark"
        app:title="">

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

        <TextView
            android:id="@+id/tv_product_title_closed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="71dp"
            android:gravity="center_vertical"
            tools:text="Title"
            android:textColor="@android:color/white"
            android:textSize="26sp"/>

        <!--</LinearLayout>-->
    </android.support.v7.widget.Toolbar>

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/iv_product_avatar"
        android:layout_width="@dimen/product_avatar_width"
        android:layout_height="@dimen/product_avatar_width"
        android:layout_gravity="top|center_horizontal"
        android:layout_marginTop="235dp"
        android:src="@drawable/img_products_total16_avatar"
        app:border_color="@color/grey"
        app:border_width="0dp"
        app:layout_behavior="com.myname.AvatarImageBehavior"/>

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

AvatarImageBehavior

public class AvatarImageBehavior extends CoordinatorLayout.Behavior<CircleImageView> {

    private final static String TAG = AvatarImageBehavior.class.getSimpleName();
    private final Context mContext;

    private boolean isInitialized = false;

    private float mStartX;
    private float mMaxXMove;

    private float mStartY;
    private float mMaxYMove;

    private float mMaxScroll;

    private float mStartHeight;
    private float mMaxHeightChange;

    private float mFinalHeight;
    private float mFinalX;
    private float mFinalY;

    public AvatarImageBehavior(Context context, AttributeSet attrs) {
        mContext = context;
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) {
        return dependency instanceof Toolbar;
    }

    private void initProperties(CircleImageView child, View dependency) {
        mMaxScroll = dependency.getY();

        mStartHeight = child.getHeight();
        mFinalHeight = mContext.getResources().getDimensionPixelOffset(R.dimen.product_avatar_final_width);
        mMaxHeightChange = mStartHeight - mFinalHeight;

        mStartX = child.getX();
        mFinalX = mContext.getResources().getDimensionPixelOffset(R.dimen.product_avatar_margin_left);
        mMaxXMove = mStartX - mFinalX;

        mStartY = child.getY();
        mFinalY = (dependency.getHeight() - mFinalHeight) / 2f;
        mMaxYMove = mStartY - mFinalY;

        isInitialized = true;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) {

        if (!isInitialized)
            initProperties(child, dependency);

        final float currScrollDist = dependency.getY();

        if (currScrollDist == 0) {
            setParams(child, (int) mFinalX, (int) mFinalY, (int) mFinalHeight);
        } else if (currScrollDist == mMaxScroll) { // reset the values if the scroll is at the max
            setParams(child, (int) mStartX, (int) mStartY, (int) mStartHeight);
        } else {
            float scrollFactor = currScrollDist / mMaxScroll;
            float factor = 1f - scrollFactor;

            float currX = mStartX - (mMaxXMove * factor);
            float currY = mStartY - (mMaxYMove * factor);
            float currHeight = mStartHeight - (mMaxHeightChange * factor);

            setParams(child, (int) currX, (int) currY, (int) currHeight);
        }

        return true;
    }

    private void setParams(CircleImageView view, int xPos, int yPos, int height) {
        view.setX(xPos);
        view.setY(yPos);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) view.getLayoutParams();
        lp.width = height;
        lp.height = height;
        view.setLayoutParams(lp);
    }
}

我終於想通了。 我將問題縮小為自定義行為(很明顯),問題是子視圖( CircleImageView )的翻譯異常值。

這是微調值后的自定義行為:

public class ProfilePicBehavior extends CoordinatorLayout.Behavior<CircleImageView>{

    private int mDependencyHeight;
    private int mProfilePicMargin;
    private int mActionBarHeight;

    public ProfilePicBehavior(Context context) {
        init(context);
    }

    public ProfilePicBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context){

        mDependencyHeight = (int)context.getResources()
                .getDimension(R.dimen.appbarlayout_learner_home_height);

        mProfilePicMargin = (int)ViewUtils.dpToPx(context, 8f);

        mActionBarHeight = (int)ActivityUtils.getActionBarHeight(context);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) {

        if(dependency instanceof AppBarLayout){
            return true;
        }
        return false;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) {
        // Translate the CircleImageView to the right
        // Calculate first, what fraction the AppBarLayout has shrunk by
        int bottom = dependency.getBottom();
        int top = dependency.getTop();
        int viewHeight = bottom;

        float proportion = Math.min(1, 1 - ((viewHeight - mActionBarHeight) / (float)(mDependencyHeight - mActionBarHeight)));
        // Translate the child by this proportion
        float translationX = (parent.getWidth()/2 - child.getWidth()/2 - mProfilePicMargin) * proportion;
        float translationY = (child.getHeight()/2 - mProfilePicMargin) * proportion;

        child.setTranslationX(translationX);
        child.setTranslationY(translationY);

        return true;
    }
}

您會發現它比@Eselfar的答案要簡單得多,后者通過LayoutParams操作屬性(盡管我的動畫有點不同,但我尚未測試他的答案)

邏輯非常簡單: AppBarLayout縮小的比例轉換CircleImageView

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM