Android 7.0按钮涟漪效应不随按钮布局变化而更新

Android 7.0按钮涟漪效应不随按钮布局变化而更新,android,android-layout,android-animation,android-view,android-button,Android,Android Layout,Android Animation,Android View,Android Button,我正在制作一个生产力应用程序,其中的事件表示为包含事件基本信息的按钮。 该按钮包含在文本视图、选项菜单和开关旁边的RelativeLayout中。父布局的高度设置为包裹内容。看起来是这样的: 您可以单击按钮展开它并显示其他信息。扩展动画是使用自定义动画实现的,该动画会在每次调用applyTransformation(…)时更新按钮的getLayoutParams().height并调用getParent().requestLayout()。这在API级别19(KitKat)设备上运行良好

我正在制作一个生产力应用程序,其中的事件表示为包含事件基本信息的按钮。 该按钮包含在文本视图、选项菜单和开关旁边的RelativeLayout中。父布局的高度设置为包裹内容。看起来是这样的:


您可以单击按钮展开它并显示其他信息。扩展动画是使用自定义动画实现的,该动画会在每次调用applyTransformation(…)时更新按钮的getLayoutParams().height并调用getParent().requestLayout()。这在API级别19(KitKat)设备上运行良好

动画代码:

//The current state of the button which gets updated on animation finish
boolean expanded = false;
@Override
public void onClick(final View v) {
    //Getting references to views
    final RelativeLayout layout = (RelativeLayout) button.getParent();
    final View separator = layout.findViewById(R.id.separator), list = 
layout.findViewById(R.id.notes_list);
    final Button button = (Button) v;
    final RelativeLayout content = (RelativeLayout) layout.findViewById(R.id.relativeLayout);
    final RelativeLayout.LayoutParams lpl = (RelativeLayout.LayoutParams) list.getLayoutParams(), 
            lpsw = (RelativeLayout.LayoutParams) layout.findViewById(R.id.event_switch).getLayoutParams(),
            lp = (RelativeLayout.LayoutParams) button.getLayoutParams();
    //Finished getting references to views
    final int startHeight = lp.height = button.getHeight();
    //Prevents button from automatically resizing to fit its parent when requestLayout is called
    lp.removeRule(RelativeLayout.ALIGN_BOTTOM);
    layout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
            layout.removeOnLayoutChangeListener(this);
            final int goalHeight = GetExpectedHeight(expanded);
            Animation animation = new Animation() {
                float alpha1 = (expanded ? startHeight : goalHeight) - separator.getTop(),
                alpha2 = (expanded ? startHeight : goalHeight) - list.getTop();
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    if (interpolatedTime < 1) {
                        //Updates the button's height
                        lp.height = (int) (startHeight + (goalHeight - startHeight) * interpolatedTime);
                        separator.setAlpha((lp.height - separator.getTop()) / alpha1);
                        list.setAlpha((lp.height - list.getTop()) / alpha2);
                        list.setScaleX(list.getAlpha());
                        list.setScaleY(list.getAlpha());
                        layout.requestLayout();
                        return;
                    }
                    //Animation finish
                    if (expanded) {
                        separator.setVisibility(View.GONE);
                        list.setVisibility(View.GONE);
                    }
                    lp.height = lp.MATCH_PARENT;
                    lp.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.relativeLayout);
                    //A custom method that basically requests layout for whole activity
                    instance.get().Invalidate();
                    expanded = !expanded;
                    this.cancel();
                }
            };
            animation.setInterpolator(new DecelerateInterpolator());
            animation.setDuration(400);
            layout.startAnimation(animation);
        }
    });
    float alpha = expanded ? 1 : 0;
    separator.setAlpha(alpha);
    list.setAlpha(alpha);
    //Kicks off the onLayoutChange method above
    if (!expanded) {
        separator.setVisibility(View.VISIBLE);
        list.setVisibility(View.VISIBLE);
    }
    else
        layout.requestLayout();

}
//动画完成时更新的按钮的当前状态
布尔扩展=假;
@凌驾
公共void onClick(最终视图v){
//获取对视图的引用
最终RelativeLayout布局=(RelativeLayout)按钮。getParent();
最终视图分隔符=布局。findViewById(R.id.separator),列表=
布局。findViewById(R.id.notes\U列表);
最终按钮=(按钮)v;
最终RelativeLayout内容=(RelativeLayout)layout.findViewById(R.id.RelativeLayout);
最终RelativeLayout.LayoutParams lpl=(RelativeLayout.LayoutParams)列表。getLayoutParams(),
lpsw=(RelativeLayout.LayoutParams)layout.findViewById(R.id.event_开关).getLayoutParams(),
lp=(RelativeLayout.LayoutParams)按钮。getLayoutParams();
//已完成获取视图的引用
final int startHeight=lp.height=button.getHeight();
//防止按钮在调用requestLayout时自动调整大小以适应其父级
lp.拆卸工具(相对位置与底部对齐);
layout.addOnLayoutChangeListener(新视图.OnLayoutChangeListener(){
@凌驾
public void onLayoutChange(视图视图、int i、int i1、int i2、int i3、int i4、int i5、int i6、int i7){
layout.removeOnLayoutChangeListener(此);
最终int目标高度=GetExpectedHeight(扩展);
动画=新动画(){
float alpha1=(扩展?startHeight:goalHeight)-分隔符.getTop(),
alpha2=(扩展?startHeight:goalHeight)-list.getTop();
@凌驾
受保护的无效应用转换(浮点插值时间,转换t){
如果(插值时间<1){
//更新按钮的高度
lp.height=(int)(起始高度+(球门高度-起始高度)*插值时间);
separator.setAlpha((lp.height-separator.getTop())/alpha1);
setAlpha((lp.height-list.getTop())/alpha2);
list.setScaleX(list.getAlpha());
list.setScaleY(list.getAlpha());
layout.requestLayout();
返回;
}
//动画结束
如果(扩展){
separator.setVisibility(View.GONE);
list.setVisibility(View.GONE);
}
lp.height=lp.MATCH\u父项;
lp.addRule(RelativeLayout.ALIGN_-BOTTOM,R.id.RelativeLayout);
//基本上要求整个活动布局的自定义方法
instance.get().Invalidate();
扩展=!扩展;
这个。取消();
}
};
setInterpolator(新减速器Interpolator());
动画。设置持续时间(400);
布局。开始动画(动画);
}
});
浮动α=扩展?1:0;
separator.setAlpha(alpha);
列表.setAlpha(alpha);
//启动上面的onLayoutChange方法
如果(!展开){
separator.setVisibility(View.VISIBLE);
list.setVisibility(View.VISIBLE);
}
其他的
layout.requestLayout();
}
然而,在安卓7.0牛轧糖(API 24)上,伴随着涟漪效应,在按钮上覆盖一个矩形,该矩形在动画期间不会更新其高度以匹配按钮的高度。我不知道它在其他Android版本上是什么样子,因为这是我唯一可以测试的两个设备。有没有办法更新涟漪效果的矩形,使其按按钮缩放?如果可能的话,我宁愿保持连锁反应。到目前为止,我已经尝试在动画的每一帧的按钮上调用performClick(),但没有效果。 以下是展开动画期间按钮的屏幕截图:

以及动画的视频:

我认为,如果您添加了代码,可能会有人修复您的问题problem@zombie我以前没有添加代码,因为它非常大,并且有一些检查使得它不整洁,并且与动画没有真正的相关性。但我认为你是对的,所以我清理了它并添加了代码。
//The current state of the button which gets updated on animation finish
boolean expanded = false;
@Override
public void onClick(final View v) {
    //Getting references to views
    final RelativeLayout layout = (RelativeLayout) button.getParent();
    final View separator = layout.findViewById(R.id.separator), list = 
layout.findViewById(R.id.notes_list);
    final Button button = (Button) v;
    final RelativeLayout content = (RelativeLayout) layout.findViewById(R.id.relativeLayout);
    final RelativeLayout.LayoutParams lpl = (RelativeLayout.LayoutParams) list.getLayoutParams(), 
            lpsw = (RelativeLayout.LayoutParams) layout.findViewById(R.id.event_switch).getLayoutParams(),
            lp = (RelativeLayout.LayoutParams) button.getLayoutParams();
    //Finished getting references to views
    final int startHeight = lp.height = button.getHeight();
    //Prevents button from automatically resizing to fit its parent when requestLayout is called
    lp.removeRule(RelativeLayout.ALIGN_BOTTOM);
    layout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
            layout.removeOnLayoutChangeListener(this);
            final int goalHeight = GetExpectedHeight(expanded);
            Animation animation = new Animation() {
                float alpha1 = (expanded ? startHeight : goalHeight) - separator.getTop(),
                alpha2 = (expanded ? startHeight : goalHeight) - list.getTop();
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    if (interpolatedTime < 1) {
                        //Updates the button's height
                        lp.height = (int) (startHeight + (goalHeight - startHeight) * interpolatedTime);
                        separator.setAlpha((lp.height - separator.getTop()) / alpha1);
                        list.setAlpha((lp.height - list.getTop()) / alpha2);
                        list.setScaleX(list.getAlpha());
                        list.setScaleY(list.getAlpha());
                        layout.requestLayout();
                        return;
                    }
                    //Animation finish
                    if (expanded) {
                        separator.setVisibility(View.GONE);
                        list.setVisibility(View.GONE);
                    }
                    lp.height = lp.MATCH_PARENT;
                    lp.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.relativeLayout);
                    //A custom method that basically requests layout for whole activity
                    instance.get().Invalidate();
                    expanded = !expanded;
                    this.cancel();
                }
            };
            animation.setInterpolator(new DecelerateInterpolator());
            animation.setDuration(400);
            layout.startAnimation(animation);
        }
    });
    float alpha = expanded ? 1 : 0;
    separator.setAlpha(alpha);
    list.setAlpha(alpha);
    //Kicks off the onLayoutChange method above
    if (!expanded) {
        separator.setVisibility(View.VISIBLE);
        list.setVisibility(View.VISIBLE);
    }
    else
        layout.requestLayout();

}