以编程方式在角落排列两个视图

时间:2014-04-18 18:03:01

标签: java android android-widget android-imageview android-view

所以这似乎是一个非常简单的问题,但我无法弄清楚如何在缩放视图后获得正确的位置。

我试图将imageView排成另一个imageView的右下角。如果我不修改firstImageView,此代码可以正常工作。

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

但是在我将翻译或缩放应用到firstImageView之后,上面的代码似乎无法正常工作(不会在角落排列)。我猜测缩放不会影响视图的实际大小,即使它已经明确调整大小。那么,即使在修改了缩放,旋转和/或平移之后,如何将secondImageView设置到firstImageView的右下角呢?

编辑:角落代码中的两个视图

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

扩展代码:

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

2 个答案:

答案 0 :(得分:0)

最初使用第一个图像比例绘制布局。稍后进行比例更改时,您需要重新绘制布局以实现所做的更改。

关于规模变化运行      requestLayout()或invalidate()

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

如果在处理事件的过程中,可能需要更改视图的边界,视图将调用requestLayout()。

同样,如果在处理事件的过程中可能需要更改视图的外观,视图将调用invalidate()。

如果调用了requestLayout()或invalidate(),框架将负责适当地测量,布局和绘制树。

答案 1 :(得分:0)

你的假设是正确的。 翻译不会影响视图的范围。但是,如果您在手势开始时计算第二个视图的位置偏移(delta),则可以一次平移两个视图。这是您可以使用的工作示例

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;

      }
    });
  }
}

更新

根据请求我修改代码以从布局文件中删除所有layout_align属性。所有定位(包括视图的初始渲染)都将以编程方式完成。

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;

      }
    });
  }
}