[英]CoordinatorLayout: View disappears with custom behavior
我是CoordinatorLayout
的新手,這是我在CoordinatorLayout
遇到的一個非常奇怪的行為。我有一個ImageView
(或更具體地講是一個稱為CircleImageView
的ImageView
的子類(在此處居中配置文件圖片) )作為孩子之一的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項目
如您CircleImageView
, CircleImageView
是布局的最后一個元素。 也許這是你的問題? 希望能幫助到你。
片段的布局
<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.