当imageview的宽度使用dp单位

时间:2015-09-18 14:19:50

标签: java android animation android-animation

我正在创建一个游戏,其中会有大量可点击的ImageView和一个无法点击的imageView,当点击可点击的ImageView时,它应该将其位置与不可点击的ImageView交换(在此示例中,它被调用imageView2)。

当我使用px单元作为我的imageView(s)时,一切正常。但是,如您所知,使用px单元会导致不同设备上的显示不同。但是,当我使用dp单位时,属性动画不起作用。我如何使用dp单位?

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中

<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>

如何解决此问题?所有建议都受到欢迎。谢谢。

根据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();
            }
        });

2 个答案:

答案 0 :(得分:2)

我认为这样做的方法是通过imageViews包含的实际值将硬编码引用更改为宽度和高度。在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)){

}

这样你就没有对px的引用。您使用的“100”值意味着100px。 hdpi设备的实际宽度或高度可能是1.5 * 100 = 150px。通过使用getWidth()和getHeight(),您将在屏幕中使用px的实际值。我希望很清楚。您将需要修改超过2个imageView的if条件,但原理是相同的。

如果你想让动画同步,最好使用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();

如果您需要添加侦听器,请执行此操作,只需添加一次。

答案 1 :(得分:0)

请参阅下面这两种方法的文档,找出最适合您的方法。 container将是您的根布局(此顶部的RelativeLayout或ID为relative的<)

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

        }
    });

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

        }
    });

以下是我实现此侦听器的示例。 我在里面做各种各样的事情。请看一下。

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);
    }
}

}

不要忘记删除全球布局的聆听者;

如果您在实现此问题时遇到任何问题,请写下来,我们会考虑一些问题:)

您还可以查看我的github repo,我实际上在这里使用它来从触摸点实现viewpager的打开片段。

https://github.com/mrnmilutinovic/HumanityTestProject

检查ImagePagerFragment课程以查看其使用情况。 此代码是可编译的,因此您也可以运行并查看它是否有效。