我是CoordinatorLayout
的新手,这是我在CoordinatorLayout
中遇到的一种非常奇怪的行为。我有一个ImageView
(或者更具体地说是ImageView
的子类名为CircleImageView
(它将中心的个人资料图片存放在此处))作为CoordinatorLayout
的子项之一。我已将此CircleImageView
锚定到AppbarLayout
(这是CoordinatorLayout
的另一个孩子)。这是我的整个布局:
到目前为止一切顺利。我目前能够滚动AppbarLayout
和NestedScrollView
移动。但是,当我们向上滚动并决定依赖自定义CoordinatorLayour.Behavior
时,我想到动画配置文件图片向右移动。我最终得到了一个尝试翻译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;
}
}
答案 0 :(得分:2)
# Deny user1 from all hosts but host1
DenyUsers user1@!host1,*
# Allow all users from any host that are not denied yet
AllowUsers *@*
解决它(我不记得相同问题的链接):
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:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CollapsingImageBehavior">
<attr name="collapsedTarget" format="integer"></attr>
</declare-styleable>
</resources>
<?xml version="1.0" encoding="utf-8"?>
答案 1 :(得分:1)
根据这个答案:https://stackoverflow.com/a/40023161/6248491
声明包含 CollapsingToolbarLayout
与父母提升相关的小提琴
尝试将AppBarLayout
提升为0dp。此外,CircleImageView
应保持更高(更高)的高度,以便不会在顶部“提升”。
希望这会有所帮助。如果有效,请告诉我。
答案 2 :(得分:1)
去年我不得不做类似的事情。
AvatarImageBehavior
基于the GitHub project by Saul Molinero (saulmm)
您可以注意到,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);
}
}
答案 3 :(得分:1)
我终于弄明白了。我将问题缩小到自定义行为(显然),问题是子视图(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;
}
}
你可以看到它比通过LayoutParams
操纵属性的 @ Eselfar 答案更简单。(我还没有测试过他的答案,因为我的答案动画有点不同)
逻辑非常简单:按CircleImageView
收缩的比例翻译AppBarLayout
。