0

How it looks

I want to check intersection between ImageView to ImageView2 as LinearLayout slides towards ImageView2. I used Rect but it is not working, ImageView2 Just passed throught it without getting intersect. Please help me!!

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >


<ImageView
    android:id="@+id/tile"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:src="@drawable/tile" />

   <LinearLayout
    android:id="@+id/l1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="100" >

    <ImageView
        android:id="@+id/b1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="50"
        android:background="#000"
        android:src="@drawable/b" />

    <ImageView
        android:id="@+id/b2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="70dp"
        android:layout_weight="50"
        android:background="#000"
        android:src="@drawable/b" />
</LinearLayout>

@SuppressLint("NewApi") 
public class MainActivity extends Activity {
    Rect tileRect = new Rect();
    Rect b1Rect = new Rect();
    Rect b2Rect = new Rect();
    ImageView tile,b1,b2;
    RelativeLayout layout;
    LinearLayout l1;

    final Handler h = new Handler();
    Boolean tileRight=false;



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


        init();
         move();

    }


    private void init() {
        // TODO Auto-generated method stub




        b1 = (ImageView)findViewById(R.id.b1);
        b2 = (ImageView)findViewById(R.id.b2);
        tile = (ImageView)findViewById(R.id.tile);
        layout = (RelativeLayout)findViewById(R.id.layout);
        l1 = (LinearLayout)findViewById(R.id.l1);
         tile.setX(320);
        tile.setY(800);


        l1.setVisibility(View.VISIBLE);

    }


    public void move()
    {
        final int delay = 45;
        h.postDelayed(new Runnable()
        {

            @Override
            public void run() {
                // TODO Auto-generated method stub

                layout.setOnTouchListener(new View.OnTouchListener() {

                    @Override
                    public boolean onTouch(View arg0, MotionEvent event) {
                        // TODO Auto-generated method stub

                        if(event.getAction() == MotionEvent.ACTION_UP)
                        {

                            if(tileRight==true)
                                tileRight=false;
                            else
                                tileRight=true;

                        return true;
                        }

                        return false;
                    }
                });


            if(tileRight==true)
            {
              if(tile.getX()>600f)
              {
                  tile.setX(tile.getX()); 
              }

              else{
                tile.setX(tile.getX()+speedTile);

                    }
            }
            else{
                 if(tile.getX()<40f)
                  {
                      tile.setX(tile.getX()); 
                  }
                 else{
                tile.setX(tile.getX()-speedTile);

                 }

            }

            tile.getHitRect(tileRect);
            b1.getHitRect(b1Rect);
            b2.getHitRect(b2Rect);

            if(Rect.intersects(tileRect, b1Rect) || Rect.intersects(tileRect, b2Rect))
            {
                gameOver();

            }



            l1.setY(l1.getY()+10f);


            h.postDelayed(this, delay);
            }



        },delay);


    }
    private void gameOver() {

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}
Ash
  • 473
  • 2
  • 10

2 Answers2

0

Android's View has getLocationOnScreen() method that shows absolute position of your view. https://developer.android.com/reference/android/view/View.html#getLocationOnScreen(int[])

anhtuannd
  • 918
  • 9
  • 16
0

The issue occurs because view.getHitRect() is used before the layouts are inflated.

Any of the view's position or measurement APIs like getWidth(), getTop(), getRight() etc. will return 0 (getHitRect() initializes the Rect with (0,0,0,0)) in onCreate() or onResume() before the views are inflated.

In your case, it appears that the Handler's delay period executes the intersection logic earlier than view inflation.

You could post from the view and the run() method will execute after the view inflates and then obtain the view's measurement parameters or a Rect .

Here is an example:

public class MyTestActivity extends AppCompatActivity{

    int mNumberOfViewsInitialized = 0;

    ImageView mImageViewRight, mImageViewLeft;

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

        mImageViewLeft = (ImageView) findViewById(R.id.image_view_left);
        mImageViewRight = (ImageView) findViewById(R.id.image_view_right);

        // calling method here will log that the views do not intersect
        // which happens because they haven't been inflated yet.
        // doViewsOverlap();


        mImageViewLeft.post(new Runnable(){

            @Override
            public void run() {
                mNumberOfViewsInitialized++;
                intersectionLogic();
            }
        });

        mImageViewRight.post(new Runnable(){

            @Override
            public void run() {
                mNumberOfViewsInitialized++;
                intersectionLogic();
            }
        });
    }

    private void intersectionLogic(){
        /* the constant could be something else, depending 
         on the number of views you'd like to test intersection for*/
        if(mNumberOfViewsInitialized == 2){
            doViewsOverlap(mImageViewLeft,mImageViewRight);
        }
    }

   private void doViewsOverlap(final View firstView, final View secondView){

        Rect leftRect = new Rect();
        firstView.getHitRect(leftRect);

        Rect rightRect = new Rect();
        secondView.getHitRect(rightRect);

        if(Rect.intersects(leftRect,rightRect) || Rect.intersects(rightRect,leftRect))
            Log.v("intersects","views intersect");
        else
            Log.v("intersects","views do not intersect");
    }
}

I used a layout which does not animate / move the images, but the same issue should occur when the images are moved as well

<ImageView
    android:id="@+id/image_view_left"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:layout_alignParentLeft="true"
    android:background="@android:color/holo_blue_dark"
    android:src = "@mipmap/ic_launcher"/>

<ImageView
    android:id="@+id/image_view_right"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:layout_alignParentRight="true"
    android:background="@android:color/holo_green_dark"
    android:gravity="end"
    android:src="@mipmap/ic_launcher"/>

Images contained in a RelativeLayout.

Here is a screenshot of the UI:

enter image description here

This problem is related to this: If I call getMeasuredWidth() or getWidth() for layout in onResume they return 0

Hope this helps.

Community
  • 1
  • 1
user1841702
  • 2,683
  • 6
  • 35
  • 53