简体   繁体   English

当imageview的宽度使用dp单位时,Android属性动画不起作用

[英]Android property animations does not work when imageview's width uses dp units

I am creating a game, where there will be a lot of clickable ImageView(s), and one unclickable imageView, when the clickable ImageView is clicked, it should swap its position with the unclickable ImageView (in this example, its called imageView2). 我正在创建一个游戏,其中将有很多可点击的ImageView和一个不可点击的ImageView,当单击可点击的ImageView时,它应该与不可点击的ImageView交换其位置(在本示例中为它的imageView2)。

Everything works fine when I am using px unit for my imageView(s). 当我将px单位用于imageView时,一切正常。 However, as you know using px units will resulted in different display on different devices. 但是,您知道使用px单位会导致在不同设备上显示不同。 However, the property animations does not work when I use dp units. 但是,当我使用dp单位时,属性动画不起作用。 How do I get it working with dp units ?? 如何在dp单元上使用它?

MainActivity.java MainActivity.java

public class MainActivity extends Activity implements View.OnClickListener {

    ImageView imageView1, imageView2;
    float x, x_9, y, y_9;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView1 = (ImageView) findViewById(R.id.imageView1);
        imageView2 = (ImageView) findViewById(R.id.imageView2);

        imageView1.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {

        // Get x position of clicked imageView
        x = v.getX();
        // Get x position of imageView2
        x_9 = imageView2.getX();

        // Get y position of clicked imageView
        y = v.getY();
        // Get y position of imageView2
        y_9 = imageView2.getY();


        // Check if imageViews are align with each other either horizontally or vertically
        if((x == x_9 && y + 100 == y_9) || (x == x_9 && y - 100 == y_9) || (x + 100 == x_9 && y == y_9) || (x - 100 == x_9 && y == y_9)) {

            // If they are aligned, swap their position with property animation

            PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("translationX", x_9);
            PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("translationY", y_9);

            PropertyValuesHolder pvhX9 = PropertyValuesHolder.ofFloat("translationX", x);
            PropertyValuesHolder pvhY9 = PropertyValuesHolder.ofFloat("translationY", y);

            ObjectAnimator blockAnim = ObjectAnimator.ofPropertyValuesHolder(v, pvhX, pvhY);
            blockAnim.setDuration(500);
            blockAnim.setRepeatCount(0);
            blockAnim.start();

            ObjectAnimator blockAnim2 = ObjectAnimator.ofPropertyValuesHolder(imageView2, pvhX9, pvhY9);
            blockAnim2.setDuration(500);
            blockAnim2.setRepeatCount(0);
            blockAnim2.start();
        }
    }
}

activity_main.xml activity_main.xml

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/relative"
        android:background="@color/grey"
        android:layout_width="400dp"
        android:layout_height="400dp"
        >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/smiley1"/>

        <ImageView
            android:id="@+id/imageView2"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/smiley2"
            android:translationX="100dp"/>

    </RelativeLayout>

</RelativeLayout>

How do I work around this problem ? 如何解决此问题? All suggestions are greatly welcomed. 所有建议都将受到欢迎。 Thank you. 谢谢。

As suggested by Nikola Milutinovic, I added GlobalLayoutListener like below 正如Nikola Milutinovic所建议的那样,我如下添加了GlobalLayoutListener

        this.findViewById(R.id.relative).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                x = v.getX();
                x_9 = imageView2.getX();

                y = v.getY();
                y_9 = imageView2.getY();
            }
        });

I think the way to do it is to change your hard coded referece to the width and height by the actual value contained by the imageViews. 我认为这样做的方法是通过imageViews包含的实际值将您的硬编码裁判更改为宽度和高度。 In your if condition change 100 to getHeight() or getWidth(); 在您的if条件中,将100更改为getHeight()或getWidth();。

int height = imageView1.getHeight();
int width = imageView1.getWidth();

if((x == x_9 && y + height == y_9) || (x == x_9 && y - height == y_9) ||
    (x + width == x_9 && y == y_9) || (x - width == x_9 && y == y_9)){

}

This way you do not have a reference to px. 这样,您就没有对px的引用。 The "100" value that your were using meant 100px. 您使用的“ 100”值表示100px。 The real width or height for an hdpi device would of been something like 1.5*100 = 150px. hdpi设备的实际宽度或高度大约为1.5 * 100 = 150px。 By using getWidth() and getHeight(), you are using the actual value of px in your screen. 通过使用getWidth()和getHeight(),可以在屏幕上使用px的实际值。 I hope it is clear. 我希望这很清楚。 You will need to modify your if condition for more than 2 imageViews, but the principle is the same. 您将需要为两个以上的imageView修改if条件,但是原理是相同的。

Finally it is better to use AnimatorSet if you want your animations to be synchronized. 最后,如果要同步动画,最好使用AnimatorSet。

ArrayList <Animator> animations = new ArrayList<Animator>();
animations.add(ObjectAnimator.ofPropertyValuesHolder(v, pvhX, pvhY));
animations.add(ObjectAnimator.ofPropertyValuesHolder(imageView2, pvhX9, pvhY9));

AnimatorSet animatoreSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.setRepeatCount(0);
animatorSet.playTogether(animations);
animatorSet.start();

By doing this if you need to add listeners you just add them once. 如果您需要添加侦听器,则只需添加一次即可。

See documentation for these two methods below and find which one suits you the most. 请参阅下面有关这两种方法的文档,并找到最适合您的一种。 container would be your root layout (this RelativeLayout at the top or this with id relative ) container将是您的根布局(此RelativeLayout位于顶部或ID为relative

    container.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

        }
    });

    container.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
        @Override
        public void onDraw() {

        }
    });

Here is the example of my implementation of this listener. 这是我实现此侦听器的示例。 I do all sorts of stuff inside. 我在里面做各种各样的事情。 Please take a look. 请看一下。

public class CustomOnGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {

private Context context;
private View fragment;
private float x1;
private float y1;
private float x2;
private float y2;

public CustomOnGlobalLayoutListener(Context context, View view,  float x1, float y1, float x2, float y2) {
    this.context = context;
    this.fragment = view;
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
}

@Override
public void onGlobalLayout() {
    fragment.setX(x1);
    fragment.setY(y1);
    removeOnGlobalLayoutListener();
    FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fragment.getLayoutParams();
    fragment.setLayoutParams(layoutParams);
    fragment.setPivotX(0);
    fragment.setPivotY(0);
    fragment.setScaleX((x2 - x1) / fragment.getMeasuredWidth());
    fragment.setScaleY((y2 - y1) / fragment.getMeasuredHeight());
    fragment.setAlpha(0f);
    PropertyValuesHolder pA = PropertyValuesHolder.ofFloat(View.ALPHA, 1f);
    PropertyValuesHolder pX = PropertyValuesHolder.ofFloat(View.X, 0f);
    PropertyValuesHolder pY = PropertyValuesHolder.ofFloat(View.Y, 0f);
    PropertyValuesHolder pSx = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
    PropertyValuesHolder pSy = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
    final ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(fragment, pA, pX, pY, pSx, pSy);

    animator1.setInterpolator(new AccelerateDecelerateInterpolator());
    animator1.setDuration(200);
    animator1.start();

}

private void removeOnGlobalLayoutListener() {
    if (Build.VERSION.SDK_INT < 16) {
        //noinspection deprecation
        fragment.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    } else {
        fragment.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
}

} }

DO NOT FORGET TO REMOVE GLOBAL LAYOUT LISTENER; 不要忘了删除全球布局设计师;

If you have any problem implementing this, write and we will think something out :) 如果您在执行此操作时遇到任何问题,请写信,我们会考虑的:)

You can also check my github repo where I am actually using this to achieve opening fragment with viewpager from point of touch. 您还可以检查我的github存储库,实际上我是在哪里使用它来实现从viewpointr到viewpager的打开片段的。

https://github.com/mrnmilutinovic/HumanityTestProject https://github.com/mrnmilutinovic/HumanityTestProject

Check ImagePagerFragment class to see it's usage. 检查ImagePagerFragment类以查看其用法。 This code is compilable, so you can also run and see that it works. 该代码是可编译的,因此您也可以运行并查看它是否有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 onDraw在ImageView Android上不起作用 - onDraw does not work on ImageView Android Android单击使用动画的ImageView时动态重置ImageView位置 - Android Reset ImageView Location dynamically When Clicking on ImageView that uses Animation canvas.drawCircle`的半径是dp单位吗? - Is `canvas.drawCircle` metho's radius in dp units? 有没有办法获得 MP Android BarChart 的 px/dp 的条宽? - Is there a way I can get the Bar Width in px/dp's of an MP Android BarChart? android:scaleType =“ center”不能满足我的要求:dp vs px如何工作? - android:scaleType=“center” doesn't do what I think it should: how does dp vs px work? 当Android中imageview具有width和height值时,如何将textview和imageview合并为图像复合? - How to combine textview and imageview into image compound when imageview has width and height values in android? 以dp为单位将“drawables”绘制到画布上 - Drawing “drawables” to a canvas in dp units “ android:padding = -5dp”是什么意思? - what does “android:padding=-5dp” mean? Android:以英寸为单位设置视图宽度(在英寸和dp之间转换) - Android: Setting width of View in inches (converting between inches and dp) Android:防止在 ImageView 上没有图像时转到下一个活动 - Android: Prevent go to next activity when there's no image at ImageView
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM