【问题标题】:Android - Updating View's Height on translationY() AnimationAndroid - 在 translationY() 动画上更新视图的高度
【发布时间】:2015-08-20 00:59:57
【问题描述】:

我有一个布局,想要在点击按钮后展开,如下图:

问题是我需要使用动画,所以我决定使用View.animate.translationY()。这是我的代码:

private void showBottomThreeLines(boolean show){
    if(show)
        mShiftContainer.animate().translationY(0);
    else
        mShiftContainer.animate().translationY(-(mFifthLineContainer.getHeight() * 3));
}

但是,这是我测试后得到的:

当前高度仍与之前的高度相同!视图的高度使用MATCH_PARENT。我什至尝试将其更改为1000dp,但它仍然具有相同的高度。如何在translationY() 动画期间更新视图的高度?

【问题讨论】:

  • translate 没有设置高度..它将视图移动到 x,y ... scale 为您完成工作...使用 mShiftContainer.animate().scaleY(-(mFifthLineContainer. getHeight() * 3)).setDuration(2000);
  • 是的,它没有。这就是为什么我认为我需要别的东西......我尝试了mShiftContainer.animate().scaleY(-(mFifthLineContainer.getHeight() * 3)).setDuration(2000);,但布局上升,它使我的屏幕变成空白。我认为scaleY() 的参数是错误的。
  • 尝试不同的属性...例如 mShiftContainer.animate().scaleYBy() 或 mShiftContainer.animate().y()
  • 我不认为scaleY() 是一个好的解决方案,因为它会放大我的字体大小、填充、边距等。它只会破坏我的布局。我也试过y(),但它只会更新我的 Y 位置而不增加它的高度。

标签: android android-layout android-animation


【解决方案1】:

经过一番研究,我发现在翻译后定义视图高度根本不会增加它的高度整个视图的高度总和似乎不能超过其父布局的高度。这意味着,如果您将父布局的高度设置为 MATCH_PARENT 并且您的屏幕尺寸为 960 dp,那么即使您定义了它的高度,您的子视图的最大高度也将是 960 dp,例如android:layout_height="1200dp".

因此,我决定动态调整父布局的高度,并将页脚布局的高度设为MATCH_PARENT。默认情况下,我的父布局的高度是MATCH_PARENT,但我在onCreateView() 上调用以下方法:

private void adjustParentHeight(){
    WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics metrics = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(metrics);
    ViewGroup.LayoutParams params = mView.getLayoutParams();
    mFifthLineContainer.measure(0, 0);
    params.height = metrics.heightPixels + (mFifthLineContainer.getMeasuredHeight() * 3);
    mView.setLayoutParams(params);
}

这将使我的页脚布局脱离屏幕。然后我尝试使用View.animate().translationY(),但随后我遇到了另一个问题! Android 动画中存在一个错误在您调用时会导致闪烁 View.setY() on onAnimationEnd()。似乎原因是onAnimationEnd() 在动画真正结束之前被调用。以下是我用来解决此问题的参考资料:

Android Animation Flicker

Android Flicker when using Animation and onAnimationEnd Listener

因此,我改变了我的showBottomThreeLines() 方法:

private void showBottomThreeLines(boolean show){
    if(show){
        TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, -(mFifthLineContainer.getHeight() * 3), 0);
        translateAnimation.setDuration(300);
        translateAnimation.setFillAfter(true);
        translateAnimation.setFillEnabled(true);
        translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                mShiftContainer.setY(mShiftContainer.getY() + mFifthLineContainer.getHeight() * 3);
            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        mShiftContainer.startAnimation(translateAnimation);
    } else{
        TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, mFifthLineContainer.getHeight() * 3, 0);
        translateAnimation.setDuration(300);
        translateAnimation.setFillAfter(true);
        translateAnimation.setFillEnabled(true);
        translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                mShiftContainer.setY(mFifthLineContainer.getY());
            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        mShiftContainer.startAnimation(translateAnimation);
    }
}

【讨论】:

    【解决方案2】:

    使用这个:

    private ActionMode mActionMode;
    
    ...
    
    
    private void expandView(View summary, int height, final boolean isSearch) {
            if (isSearch) summary.setVisibility(View.VISIBLE);
    
            final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.EXACTLY);
            summary.measure(widthSpec, height);
    
            Animator animator = slideAnimator(summary.getHeight(), height, summary);
            animator.start();
        }
    
        private void collapseView(final View summary, int height, final boolean isSearch) {
            int finalHeight = summary.getHeight();
    
            ValueAnimator mAnimator = slideAnimator(finalHeight, height, summary);
            final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.EXACTLY);
            summary.measure(widthSpec, height);
    
            Animator animator = slideAnimator(summary.getHeight(), height, summary);
            animator.start();
            mAnimator.start();
        }
    
        /**
         * Slide animation
         *
         * @param start   start animation from position
         * @param end     end animation to position
         * @param summary view to animate
         * @return valueAnimator
         */
        private ValueAnimator slideAnimator(int start, int end, final View summary) {
    
            ValueAnimator animator = ValueAnimator.ofInt(start, end);
    
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    //Update Height
                    int value = (Integer) valueAnimator.getAnimatedValue();
    
                    ViewGroup.LayoutParams layoutParams = summary.getLayoutParams();
                    layoutParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, value, getResources().getDisplayMetrics());//value;
                    summary.setLayoutParams(layoutParams);
                }
            });
            return animator;
        }
    
        private ActionMode.Callback mActionModeCallBack = new ActionMode.Callback() {
            //Contextual action menu. Shows different options in action bar when a list item is long clicked!
            @Override
            public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                // Inflate a menu resource providing context menu items
                MenuInflater inflater = actionMode.getMenuInflater();
                inflater.inflate(R.menu.contextual_menu_options, menu);
                return true;
            }
    
            @Override
            public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
                return false;
            }
    
            @Override
            public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
                mActionMode.finish();
                return true;
            }
    
            @Override
            public void onDestroyActionMode(ActionMode actionMode) {
                mActionMode = null;
            }
        };
    

    希望对您有所帮助!

    【讨论】:

    • 感谢您的回答!我已经尝试了您的代码,但仍然没有运气。高度发生了变化,但布局 Y 位置没有。您的代码中是否有任何部分需要修改才能实现我的目标?
    • @Harry 你能发布你的xml文件吗
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 2011-04-05
    • 2015-12-26
    • 2016-08-25
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多