【问题标题】:Translate animation is behind other layout翻译动画落后于其他布局
【发布时间】:2014-03-18 08:51:11
【问题描述】:

我的屏幕上有四种线性布局。

第一个布局包含一个文本视图。

我正在尝试使用翻译动画将我的 textView 移动到右侧的第四个布局。

但是当我这样做时,文本视图会移动到另一个布局后面,如果我将布局从右侧的第四个布局移动到左侧的第一个布局,那就没问题了。

我的 xml 我已经放在了所有布局中

android:clipChildren="false"

image

你能帮帮我吗?

谢谢

【问题讨论】:

  • 您是否尝试过在布局上调用 BringToFront?
  • 是的,但这不起作用
  • 检查我的答案,它有效并经过测试

标签: android layout


【解决方案1】:

使用 setZAdjustment 将您的视图放在其他视图的前面。

http://developer.android.com/reference/android/view/animation/Animation.html#setZAdjustment%28int%29

【讨论】:

  • 您确定您使用的是ZORDER_NORMALZORDER_TOPZORDER_BOTTOM 之一吗?
【解决方案2】:

奇巧之前:

yourLayout.bringToFront();
((View)yourLayout.getParent()).requestLayout();
((View)yourLayout.getParent()).invalidate();

奇巧:

yourLayout.bringToFront();

【讨论】:

  • 如果我这样做动画不会开始到好的坐标
  • 能否请您详细说明一下“从良好的协调开始”
【解决方案3】:

Android 线性布局构造从第一个元素开始。所以任何首先定义的元素都会被创建然后休息,所以无论你做什么,你都无法通过线性布局来实现。尝试相对布局

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <LinearLayout
            android:id="@+id/testAnimTranslate"
            android:layout_width="wrap_content"
            android:layout_height="80dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:gravity="center_vertical"
            android:orientation="horizontal" >

            <LinearLayout
                android:layout_width="30dp"
                android:layout_height="70dp"
                android:background="#0000dd"
                android:orientation="vertical" />

            <LinearLayout
                android:layout_width="30dp"
                android:layout_height="70dp"
                android:layout_alignParentBottom="true"
                android:background="#0dd0dd"
                android:orientation="vertical" />

            <LinearLayout
                android:layout_width="30dp"
                android:layout_height="70dp"
                android:layout_alignParentBottom="true"
                android:background="#ddd0dd"
                android:orientation="vertical" />

            <LinearLayout
                android:layout_width="30dp"
                android:layout_height="70dp"
                android:layout_alignParentBottom="true"
                android:background="#44d0dd"
                android:orientation="vertical" />
     </LinearLayout>

        <TextView
            android:id="@+id/textAnimate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@id/testAnimTranslate"
            android:layout_alignTop="@id/testAnimTranslate"
            android:layout_toLeftOf="@id/testAnimTranslate"
            android:gravity="center"
            android:background="#00000000"
            android:text="qweqwew" />

</RelativeLayout>

在动画文件夹中或以编程方式定义您的翻译动画。确保添加

    LinearInterpolator
    setFillAfter to true

并启动动画

【讨论】:

    【解决方案4】:

    我认为你在代码中创建了视图,所以你应该添加 setClipChildren(false) 在你的构造函数中。

    【讨论】:

      【解决方案5】:

      docs

      ZORDER_TOP:请求在动画持续时间内将动画内容强制置于所有其他内容之上。

      请检查setFillAfter(true) 是否与此用法不匹配。 有帮助吗?

      【讨论】:

        【解决方案6】:

        您尝试做的主要问题是您想在其父级之外绘制一个视图。它落后于其他 LinearLayout,因为它们是在 View 的 LinearLayout 父级之后绘制的。就算被提上日程,似乎也只和单亲内的孩子有关?

        如果您查看 Fragment 动画的工作原理,您需要重新创建 Fragment 以将一个帧从一个帧转换为另一个帧。您还需要两个单独的动画。

        BlackBeard 的解决方案将起作用,因为它使 TextView 成为最外层父级的子级并最后声明它。这意味着 TextView 是在其他所有内容之后绘制的,因此将被绘制在其他所有内容之上。

        这并没有实现我认为您正在尝试做的事情。如果您希望 TextView 在动画之后属于其目标 LinearLayout,您需要重新创建 TextView 并将其添加到层次结构中正确位置的 LinearLayout。您还需要第二个动画来将新的 TextView 移动到它的位置。

        如果处理得当,动画应该可以完美地相互叠加,如果在 LinearLayout 中,一个或另一个动画视图将在其他所有内容之上传递。

        activity_main.xml

        <LinearLayout
            android:id="@+id/frame"
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipChildren="false"
            android:orientation="horizontal"
            tools:context=".MainActivity">
        
            <LinearLayout
                android:id="@+id/layout1"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFAABBCC"
                android:orientation="vertical">
        
                <TextView
                    android:id="@+id/textView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="24sp"
                    android:text="I'm some text"/>
        
            </LinearLayout>
        
            <LinearLayout
                android:id="@+id/layout2"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFBBCCAA"
                android:orientation="vertical">
        
            </LinearLayout>
        
            <LinearLayout
                android:id="@+id/layout3"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFCCAABB"
                android:orientation="vertical">
        
            </LinearLayout>
        
            <LinearLayout
                android:id="@+id/layout4"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFBBAACC"
                android:orientation="vertical">
        
            </LinearLayout>
        
        </LinearLayout>
        

        MainActivity.java

        private LinearLayout mLayout1;
        private LinearLayout mLayout2;
        private LinearLayout mLayout3;
        private LinearLayout mLayout4;
        private TextView mTextView;
        private View.OnTouchListener mOnTouchListener;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        
            mLayout1 = (LinearLayout) findViewById(R.id.layout1);
            mLayout2 = (LinearLayout) findViewById(R.id.layout2);
            mLayout3 = (LinearLayout) findViewById(R.id.layout3);
            mLayout4 = (LinearLayout) findViewById(R.id.layout4);
            mTextView = (TextView) findViewById(R.id.textView);
            mOnTouchListener = new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // simple trigger to start the animation.
                    startAnimation();
                    mTextView.setOnTouchListener(null);
                    return true;
                }
            };
            mTextView.setOnTouchListener(mOnTouchListener);
        }
        
        private void startAnimation() {
        
            final LinearLayout origin = (LinearLayout) mTextView.getParent();
            LinearLayout destination = null;
            // I'm not sure what kind of behaviour you want. This just randomises the destination.
            do {
                switch (new Random().nextInt(4)) {
                    case 0:
                        destination = mLayout1;
                        break;
                    case 1:
                        destination = mLayout2;
                        break;
                    case 2:
                        destination = mLayout3;
                        break;
                    case 3:
                        destination = mLayout4;
                        break;
                    default:
                }
                // if destination == origin or is null, try again.
            } while (destination == origin || destination == null);
        
            // Create another TextView and initialise it to match mTextView
            final TextView textViewNew = new TextView(this);
            textViewNew.setText(mTextView.getText());
            textViewNew.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextView.getTextSize());
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            textViewNew.setLayoutParams(params);
            textViewNew.setOnTouchListener(mOnTouchListener);
        
            // Add the new TextView to the destination LinearLayout
            destination.addView(textViewNew);
        
            // Create animations based on origin and destination LinearLayouts
            ObjectAnimator outAnimator = getOutAnimator(origin, destination);
            // The in animator also requires a reference to the new TextView
            ObjectAnimator inAnimator = getInAnimator(textViewNew, origin, destination);
            // All animators must be created before any are started because they are calculated
            // using values that are modified by the animation itself.
            outAnimator.start();
            inAnimator.start();
            // Add a listener to update mTextView reference to the new TextView when complete.
            inAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
        
                }
        
                @Override
                public void onAnimationEnd(Animator animation) {
        
                    origin.removeView(mTextView);
                    mTextView = textViewNew;
                }
        
                @Override
                public void onAnimationCancel(Animator animation) {
                }
        
                @Override
                public void onAnimationRepeat(Animator animation) {
                }
            });
        }
        
        /**
         * This method creates an ObjectAnimator to move the existing TextView out of its parent
         * towards its destination
         */
        private ObjectAnimator getOutAnimator(View origin, View destination) {
        
            // Calculate the difference between x of destination and of origin
            float layoutDifferenceX = destination.getX() - origin.getX();
            // initialX is simply mTextView.getX()
            // the distance moved == layoutDifferenceX
            float finalX = mTextView.getX() + layoutDifferenceX;
        
            ObjectAnimator animator = ObjectAnimator.ofFloat(mTextView, "x",
                    mTextView.getX(), finalX);
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.setDuration(500);
        
            return animator;
        }
        
        /**
         * This method creates an ObjectAnimator to move the new TextView from the initial position
         * of mTextView, relative to the new TextView's parent, to its destination.
         */
        private ObjectAnimator getInAnimator(View newView, View origin, View destination) {
        
            // Calculate the difference between x of destination and of origin
            float layoutDifferenceX = destination.getX() - origin.getX();
            // initialX relative to destination
            float initialX = mTextView.getX() - layoutDifferenceX;
        
            // finalX relative to destination == initialX relative to origin
            float finalX = mTextView.getX();
        
            ObjectAnimator animator = ObjectAnimator.ofFloat(newView, "x",
                    initialX, finalX);
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.setDuration(500);
        
            return animator;
        }
        
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
        
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
        
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
        
            return super.onOptionsItemSelected(item);
        }
        

        编辑:您还可以在 xml 中声明 TextView 并对其进行膨胀以摆脱所有初始化它的代码。

        【讨论】:

          猜你喜欢
          • 2016-07-15
          • 1970-01-01
          • 2015-08-01
          • 2016-08-09
          • 2013-06-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-24
          相关资源
          最近更新 更多