ObjectAnimator,更改“ScaleX”或“Left”,但文本未保持正确居中

时间:2016-03-11 09:24:35

标签: android objectanimator

当用户点击按钮时,我需要为三个元素设置动画以显示其他信息。我有一个标签(TextView tvAvailableToPair)从按钮(Button bSearchForDevices)下面滑出 - 两者都以fill_parent的宽度开始 - 同时它同时向上滑动。我有完美的变化,但它没有动画:我通过SetLayoutParams实现了这一点:

bSearchForDevices.setText(R.string.bSearchForDevicesDiscoveryStartedText);
FrameLayout.LayoutParams lp_bSFD = 
        (FrameLayout.LayoutParams) bSearchForDevices.getLayoutParams();
int mWidthOfBSearchForDevices = lp_bSFD.width = 
        (int) Math.round(fMeasureScreenWidth * 0.4);
int mLeftMarginOfBSearchForDevices = lp_bSFD.leftMargin = 
        Math.round(fMeasureScreenWidth - (fHorizontalMargin + lp_bSFD.width));
bSearchForDevices.setLayoutParams(lp_bSFD);

lp_bSFD = (FrameLayout.LayoutParams) tvAvailableToPair.getLayoutParams();
lp_bSFD.width = mLeftMarginOfBSearchForDevices;
lp_bSFD.leftMargin = 0;
tvAvailableToPair.setLayoutParams(lp_bSFD);
ViewGroup.LayoutParams lp = llAvailableToPair.getLayoutParams();
lp.height = Math.round(getResources().getDimensionPixelSize(
        R.dimen.llAvailableToPair_height_expanded) * MainActivity.displayMetrics.density);

我了解到FrameLayout允许您将元素放在不同的Z轴值上(在另一个元素的顶部或下面;覆盖或被另一个元素覆盖)。这是我活动的xml:

<RelativeLayout
    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"
    tools:context=".MainActivity"
    android:id="@+id/rlDeviceListLayout"
    android:background="@android:color/holo_blue_dark"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:fitsSystemWindows="true"
    android:animateLayoutChanges="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" >

    <android.support.design.widget.AppBarLayout
        android:id="@+id/ablToolbarLayout"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_alignParentTop="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            app:popupTheme="@style/AppTheme.PopupOverlay" />
    </android.support.design.widget.AppBarLayout>

    <LinearLayout>
        <!-- Existing devices for user to select -->
    </LinearLayout>

    <!-- This is what needs to be animated up once user presses the button -->
    <LinearLayout
        android:id="@+id/llAvailableToPairLayout"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="@dimen/llAvailableToPair_height_collapsed"
        android:layout_alignParentBottom="true"
        android:paddingTop="4dp">

        <!-- This Layout is used to stack the button over the textview -->
        <FrameLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:layout_marginBottom="4dp">

            <!-- We'll change the width of this programmatically so that it appears to 
                elegantly slide to the left -->
            <TextView
                android:id="@+id/tvAvailableToPair"
                android:text="@string/tvAvailableToPair"
                android:layout_width="fill_parent"
                android:layout_height="@dimen/bSearchForDevices_height"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:inputType="none"
                android:gravity="center"
                android:foregroundGravity="left"
                android:textSize="16sp"
                android:textColor="#ffffff" />

            <!-- We'll change the text, width and left of this so that it reveals the 
                textview under it. It needs to appear as if it were elegantly squeezed 
                toward the right -->
            <Button
                android:id="@+id/bSearchForDevices"
                android:text="@string/bSearchForDevicesPreliminaryText"
                android:layout_width="fill_parent"
                android:layout_height="@dimen/bSearchForDevices_height"
                android:layout_marginLeft="@dimen/activity_horizontal_margin"
                android:layout_marginRight="@dimen/activity_horizontal_margin"
                android:foregroundGravity="right"
                android:visibility="visible"
                android:theme="@style/Base.ThemeOverlay.AppCompat.Dark"
                android:gravity="center" />
        </FrameLayout>

        <ListView
            android:id="@+id/lvAvailableToPair"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:visibility="visible" />
    </LinearLayout>
</RelativeLayout>

我正在改变的最后三个要素。使用SetLayoutParams保持文本居中(并且我缩短了按钮上的文本以允许更小的屏幕和标签 - 我需要在更改后对其进行动画处理,可能使用TextSwitcher Animate Text Using TextSwitcher In Android)。继续将这些更改变为动画,我不得不使用不同的方法:

bSearchForDevices.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            FrameLayout.LayoutParams lpTVATP = (FrameLayout.LayoutParams) tvAvailableToPair.getLayoutParams();
            Paint paint = new Paint();
            AnimatorSet RevealAvailableDevices = new AnimatorSet();
            float fMeasuretvAvailableToPairTextWidth = paint.measureText(tvAvailableToPair.getText().toString());       // Function returns dp, not pixels
            float fMeasurebSearchForDevicesTextWidth = paint.measureText(bSearchForDevices.getText().toString());
            float fMeasureScreenWidth = MainActivity.displayMetrics.widthPixels;    // + 0.5f;         // Extra 0.5 to simplify/speed up rounding w/o a lot of excess code (LoungeKatt, via https://stackoverflow.com/questions/1016896/get-screen-dimensions-in-pixels) and used on Google's Android docs for just this purpose @ https://developer.android.com/guide/practices/screens_support.html#dips-pels
            float fHorizontalMargin;
            // If the screen is cramped, we'll shorten the margins:
            if (fMeasuretvAvailableToPairTextWidth > (fMeasureScreenWidth * 0.5)) {
                fHorizontalMargin = (getResources().getDimension(R.dimen.activity_horizontal_margin_compressed) / MainActivity.displayMetrics.density);
            } else {
                fHorizontalMargin = (getResources().getDimension(R.dimen.activity_horizontal_margin) / MainActivity.displayMetrics.density);
            }

            /* This works PERFECTLY, but isn't animated:
            bSearchForDevices.setText(R.string.bSearchForDevicesDiscoveryStartedText);
            FrameLayout.LayoutParams lp_bSFD = (FrameLayout.LayoutParams) bSearchForDevices.getLayoutParams();
            int mWidthOfBSearchForDevices = lp_bSFD.width = (int) Math.round(fMeasureScreenWidth * 0.4);
            int mLeftMarginOfBSearchForDevices = lp_bSFD.leftMargin = Math.round(fMeasureScreenWidth - (fHorizontalMargin + lp_bSFD.width));
            bSearchForDevices.setLayoutParams(lp_bSFD);

            lp_bSFD = (FrameLayout.LayoutParams) tvAvailableToPair.getLayoutParams();
            lp_bSFD.width = mLeftMarginOfBSearchForDevices;
            lp_bSFD.leftMargin = 0;
            tvAvailableToPair.setLayoutParams(lp_bSFD);
            ViewGroup.LayoutParams lp = llAvailableToPair.getLayoutParams();
            lp.height = Math.round(getResources().getDimensionPixelSize(R.dimen.llAvailableToPair_height_expanded) * MainActivity.displayMetrics.density);
            */
            float fWidthOfbSearchForDevices = (float) ((fMeasureScreenWidth * 0.4));
            float fWidthOftvATP = (fMeasureScreenWidth - ((fWidthOfbSearchForDevices * 1) + (fHorizontalMargin * 2)));
            float fXOfbSearchForDevices = (fMeasureScreenWidth - (fWidthOfbSearchForDevices + (1 * fHorizontalMargin)));
            Log.d(TAG, "...\nfMeasureScreenWidth = " + fMeasureScreenWidth + "\nfWidthOfbSearchForDevices = " + fWidthOfbSearchForDevices + "\nfHorizontalMargin = " + fHorizontalMargin +
                    "\nbSearchForDevices.getX() = " + bSearchForDevices.getX() + "\n  (fXOfbSearchForDevices) X is going to be " + fXOfbSearchForDevices);

            ObjectAnimator aniButtonMove = ObjectAnimator.ofInt(bSearchForDevices, "Left", (int) fXOfbSearchForDevices);
            bSearchForDevices.setPivotX(fXOfbSearchForDevices + (fWidthOfbSearchForDevices / 2));   // No effect: To be in the center of where the button will end up at.
            ObjectAnimator aniTextViewResize = ObjectAnimator.ofInt(tvAvailableToPair, "Right", (int) fXOfbSearchForDevices);
            Log.d(TAG, "tvAvailableToPair's width = " + tvAvailableToPair.getWidth() + "     tvAvailableToPair is supposed to be " + fWidthOftvATP + "\nWidth of bSearchForDevices = " + bSearchForDevices.getWidth());
            RevealAvailableDevices.play(aniTextViewResize).with(aniButtonMove);
            RevealAvailableDevices.start();

这会生成一个正确移动textview和按钮边界的动画,但不会将文本居中到这些元素的新边界(边缘/左右坐标):我的按钮现在显示很多前导空在它之前的空间显示S,E和“搜索设备”的A的一半;换句话说,它被剪裁了。我需要它保持居中(就像使用SetLayoutParams时一样)。这同样适用于textview:“可用设备”的最后5个字母被剪掉。

有没有更好的方法来创建这个有三个元素改变形状的动画(最好也可以更改按钮的文字)?我已经尝试过ScaleX,但我无法正确同步,因为它在中心枢转而不向右侧滑动,也不会在缩小时滑动textview ...也许是ScaleX但是将枢轴更改为左边缘..或者也许是PropertyValuesHolder?

2016/3/15更新: 这就是我所拥有的:https://www.dropbox.com/s/n14hed6xcknfh9b/SS_20160315_135938.mp4?dl=0

我需要它看起来像post animation

0 个答案:

没有答案