Arrange two views programmatically in the corner

So this seems like a very simple question, but I can't figure out how to get the correct location after scaling the view.

I am trying to line up an image in the lower right corner of another imageView. This code works fine if I don't change firstImageView

.

secondImageView.setX(firstImageView.getRight());
secondImageView.setY(firstImageView.getBottom());

      

But after I applied translation or scaling in firstImageView, the above code doesn't seem to work correctly (not corners aligned). I am assuming that scaling does not affect the actual size of the view, although it is clearly resized. So how would I go about setting the secondImageView to the bottom right of the firstImageView even after being scaled, rotated and / or translated?

EDIT: two views in angular code

firstImageView.setOnTouchListener(new View.OnTouchListener() {

            float startX, startY;
            float translationX, translationY;
            float startMoveX, startMoveY;



            public boolean onTouch(View v, MotionEvent e) {

                if (e.getAction() == MotionEvent.ACTION_DOWN) {
                    secondImageView.setX(imageView.getRight());
                    secondImageView.setY(imageView.getBottom());
                    secondImageView.setVisibility(View.VISIBLE);

                    startX = e.getRawX();
                    startY = e.getRawY();

                    startMoveX = firstImageView.getX();
                    startMoveY = firstImageView.getY();




                } else if (e.getAction() == MotionEvent.ACTION_MOVE) {

                    translationX = e.getRawX() - startX + startMoveX;
                    translationY = e.getRawY() - startY + startMoveY;
                    firstImageView.setTranslationX(translationX);
                    firstImageView.setTranslationY(translationY);


                    secondImageView.setTranslationX(firstImageView.getX()+firstImageView.getMeasuredWidth());
                    secondImageView.setTranslationY(firstImageView.getY()+firstImageView.getMeasuredHeight());

                } else if (e.getAction() == MotionEvent.ACTION_UP) {

                }
                return true;
            }
        });
    }

      

scaling code:

secondImageView.setScaleX(2);
secondImageView.setScaleY(2);

      

0


source to share


2 answers


You are correct in your assumption. Translation does not affect presentation boundaries . However, if you are calculating the position offset (delta) of the second view from the first at the beginning of the gesture, you can translate both views at the same time. Here's a working sample you can use.

activity_test.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">

  <ImageView
    android:id="@+id/photo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="false"
    android:layout_marginTop="0dp"
    android:src="@drawable/photo"/>

  <ImageView
    android:id="@+id/photo_two"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignRight="@+id/photo"
    android:layout_alignBottom="@+id/photo"
    android:src="@drawable/ic_launcher"/>

</RelativeLayout>

      

TestActivity.java

public class TestActivity extends Activity {

  private static String TAG = "TestActivity";
  private ImageView mPhoto;
  private ImageView mPhotoTwo;
  private float mStartX;
  private float mStartY;
  private float mDeltaX;
  private float mDeltaY;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
    Log.d(TAG, "onCreate");

    mPhoto = (ImageView)findViewById(R.id.photo);
    mPhotoTwo = (ImageView)findViewById(R.id.photo_two);

    mPhoto.setOnTouchListener(new View.OnTouchListener(){
      @Override
      public boolean onTouch(View view, MotionEvent e) {
        boolean result = false;
        int action = e.getAction();

        if(action == MotionEvent.ACTION_DOWN){

          mStartX = e.getX();
          mStartY = e.getY();
          mDeltaX = mPhoto.getWidth() - mPhotoTwo.getWidth();
          mDeltaY = mPhoto.getHeight() - mPhotoTwo.getHeight();
          result = true;

        }else if(action == MotionEvent.ACTION_MOVE){

          float x = e.getX();
          float y = e.getY();
          float deltaX = x - mStartX;
          float deltaY = y - mStartY;

          float viewX = view.getX();
          float viewY = view.getY();
          float valueX = deltaX + viewX;
          float valueY = deltaY + viewY;

          mPhoto.setX(valueX);
          mPhoto.setY(valueY);

          float valueTwoX = valueX + mDeltaX;
          float valueTwoY = valueY + mDeltaY;

          mPhotoTwo.setX(valueTwoX);
          mPhotoTwo.setY(valueTwoY);

          result = true;
        }

        return result;

      }
    });
  }
}

      

UPDATE



As requested I am changing the code to remove all layout_align properties from the layout files. All positioning (including the initial rendering of the view) will be done programmatically.

activity_test.xml

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

  <ImageView
    android:id="@+id/photo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/photo"/>

  <ImageView
    android:id="@+id/photo_two"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_launcher"/>

</RelativeLayout>

      

TestActivity.java

public class TestActivity extends Activity {

  private static String TAG = "TestActivity";
  private RelativeLayout mRelativeLayout;
  private ImageView mPhoto;
  private ImageView mPhotoTwo;
  private float mStartX;
  private float mStartY;
  private float mDeltaX;
  private float mDeltaY;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
    Log.d(TAG, "onCreate");

    mRelativeLayout = (RelativeLayout)findViewById(R.id.relativelayout);
    mPhoto = (ImageView)findViewById(R.id.photo);
    mPhotoTwo = (ImageView)findViewById(R.id.photo_two);

    ViewTreeObserver observer = mRelativeLayout.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
      @Override
      public void onGlobalLayout() {
        float viewX = mPhoto.getX();
        float viewY = mPhoto.getY();

        mDeltaX = mPhoto.getWidth() - mPhotoTwo.getWidth();
        mDeltaY = mPhoto.getHeight() - mPhotoTwo.getHeight();

        float valueTwoX = viewX + mDeltaX;
        float valueTwoY = viewY + mDeltaY;

        mPhotoTwo.setX(valueTwoX);
        mPhotoTwo.setY(valueTwoY);
      }
    });


    mPhoto.setOnTouchListener(new View.OnTouchListener(){
      @Override
      public boolean onTouch(View view, MotionEvent e) {
        boolean result = false;
        int action = e.getAction();

        if(action == MotionEvent.ACTION_DOWN){

          mStartX = e.getX();
          mStartY = e.getY();
          result = true;

        }else if(action == MotionEvent.ACTION_MOVE){

          float x = e.getX();
          float y = e.getY();
          float deltaX = x - mStartX;
          float deltaY = y - mStartY;

          float viewX = view.getX();
          float viewY = view.getY();
          float valueX = deltaX + viewX;
          float valueY = deltaY + viewY;

          mPhoto.setX(valueX);
          mPhoto.setY(valueY);

          float valueTwoX = valueX + mDeltaX;
          float valueTwoY = valueY + mDeltaY;

          mPhotoTwo.setX(valueTwoX);
          mPhotoTwo.setY(valueTwoY);

          result = true;
        }

        return result;

      }
    });
  }
}

      

0


source


The original layout was drawn using the first image scale. After the zoom changes, you need to redraw the layout to make the changes you made.

when firing rescale requestLayout () or invalidate ()

findViewById(android.R.id.content).invalidate();

      



If the view's bounds may need to be changed during event processing, the view will call requestLayout ().

Likewise, if the appearance of the view can be changed during the event processing, the view will call invalidate ().

If either requestLayout () or invalidate () were called, the framework will take care of measuring, laying out and drawing the tree as needed.

0


source







All Articles