添加一个视图到ConstraintLayout,并使用与另一个子视图相似的约束。

8
我有一个使用constraint layout(alpha9)的布局,其中的视图分散在整个布局中。我需要复制其中一个特定的ImageView,像这样添加更多相似的ImageViews。布局如下: Basic layout 主要目的是在按钮按下时播放5个“coin”ImageViews的动画。我需要生成的ImageViews带有与下面按钮后面的ImageView完全相同的属性(具有相同的约束)。 The imageView behind the button 我尝试做的是以下内容:
private ImageView generateCoin() {
    ImageView coin = new ImageView(this);
    constraintLayout.addView(coin,-1,originCoinImage.getLayoutParams());//originCoinImage is the imageView behind the button
    coin.setImageResource(R.drawable.ic_coin);
    coin.setScaleType(ImageView.ScaleType.FIT_XY);
    coin.setVisibility(View.VISIBLE);
    return coin;
}

而且它失败了。 编辑:它没有显示我想要的,有时在屏幕左上角会显示一个硬币,有时什么也不显示,但无论如何,硬币数量都会增加(这意味着动画正在尝试实际操作,然后调用onAnimationFinished方法)。
我使用EasyAndroidAnimations库进行动画处理。
代码如下:
MainActivity.java
@OnClick(R.id.addCoin)
public void addCoin() {
//        for (int x = 0 ; x < 5 ; x++){
    final View newCoin = generateCoin();

    sendCoin(newCoin, 300, new AnimationListener() {
        @Override
        public void onAnimationEnd(com.easyandroidanimations.library.Animation animation) {
            incrementCoins();
            constraintLayout.removeView(newCoin);
            shakeCoin(targetCoinImage, 200, null);
        }
    });
//        }
}

private void incrementCoins() {
    coins++;
    coinNumber.setText(String.valueOf(coins));
}

private void sendCoin(View coinView, long duration, AnimationListener listener) {
    new TransferAnimation(coinView)
            .setDestinationView(targetCoinImage)
            .setDuration(duration)
            .setInterpolator(new AccelerateDecelerateInterpolator())
            .setListener(listener)
            .animate();
}

private void shakeCoin(View coinView, long duration, AnimationListener listener) {
    new ShakeAnimation(coinView)
            .setDuration(duration)
            .setShakeDistance(6f)
            .setNumOfShakes(5)
            .setListener(listener)
            .animate();
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="seaskyways.canvasanddrawtest.MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="Coins : "
        android:textSize="30sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/coinNumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="16dp"
        android:layout_marginStart="8dp"
        android:text="0"
        android:textColor="@color/colorPrimary"
        android:textSize="50sp"
        android:textStyle="normal|bold"
        app:layout_constraintBottom_toBottomOf="@+id/textView"
        app:layout_constraintLeft_toRightOf="@+id/textView"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/textView" />

    <ImageView
        android:id="@+id/coinOrigin"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:scaleType="fitXY"
        app:layout_constraintBottom_toBottomOf="@+id/addCoin"
        app:layout_constraintLeft_toLeftOf="@+id/addCoin"
        app:layout_constraintTop_toTopOf="@+id/addCoin"
        app:srcCompat="@drawable/ic_coin"
        app:layout_constraintRight_toRightOf="@+id/addCoin" />

    <ImageView
        android:id="@+id/coinTarget"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:scaleType="fitXY"
        app:layout_constraintBottom_toBottomOf="@+id/coinNumber"
        app:layout_constraintLeft_toRightOf="@+id/coinNumber"
        app:layout_constraintTop_toTopOf="@+id/coinNumber"
        app:srcCompat="@drawable/ic_coin" />

    <Button
        android:id="@+id/addCoin"
        android:layout_width="0dp"
        android:layout_height="75dp"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginStart="16dp"
        android:text="Button"
        android:textAlignment="center"
        android:textSize="36sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>

当您按下按钮时,您会得到什么输出? - O_o
如果我理解正确的话,您想让硬币从底部按钮移动到顶部硬币,并在动画完成时,硬币数量增加一个。所以您想将它们增加五个,这意味着5个硬币应该从底部到顶部进行动画。我说得对吗? - mihanovak1024
正是我想要的,但如果只有一枚硬币,那么一百万也不会有所区别。 @mihanovak1024 - Seaskyways
那么动画只需要向上垂直移动吗?还是需要有更多的运动方式?您想到了什么样的动画?一般的TranslateAnimation是否足够? - mihanovak1024
@mihanovak1024 这不是关于动画,而是关于程序化地正确放置 ImageView。 - Seaskyways
@Seaskyways,我建议您将ImageView定位到动画结束时所需的位置,并将其可见性设置为gone或invisible,然后将其从屏幕底部动画到实际视图位置,在动画开始时将其可见性设置为visible。 - mihanovak1024
1个回答

24

ConstraintLayout.LayoutParams 会缓存它的参数,并与您使用它的小部件相关联,因此您不能简单地将一个小部件的 layoutParams 传递给另一个小部件。

相反,您需要为新对象生成新的layoutParams,并复制相应的字段。

例如,如果您有这样一个代码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    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:id="@+id/content_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginStart="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="16dp" />

</android.support.constraint.ConstraintLayout>

那么你可以这样做:

ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.content_main);
ConstraintLayout.LayoutParams params = 
                (ConstraintLayout.LayoutParams) button.getLayoutParams();

Button anotherButton = new Button(this);

ConstraintLayout.LayoutParams newParams = new ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.WRAP_CONTENT,
                ConstraintLayout.LayoutParams.WRAP_CONTENT);

newParams.leftToLeft = params.leftToLeft;
newParams.topToTop = params.topToTop;
newParams.leftMargin = params.leftMargin;
newParams.topMargin = params.topMargin;

layout.addView(anotherButton, -1, newParams);

这将使第二个按钮正好放置在与XML中定义的按钮相同的位置。


你好,Nicolas Roard, 如果我的UI比较复杂,例如按钮是动态的,并且有许多布局参数和约束条件,我想在同一位置添加一个新的按钮,应该怎么做?谢谢。 - Changwei
无论如何,谢谢。 我通过以下方式实现:val screenshotViewLayoutParams = ConstraintLayout.LayoutParams(cl.width, cl.height) screenshotView.layoutParams = screenshotViewLayoutParams cs.connect(screenshotView.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, cl.x.toInt()) cs.connect(screenshotView.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, cl.y.toInt()) - Changwei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接