所以这似乎是一个非常简单的问题,但我不知道如何在缩放视图后获得正确的位置。
我正在尝试将一个imageView排列到另一个imageView的右下角。如果我不修改firstImageView
,这个代码就可以正常工作。
secondImageView.setX(firstImageView.getRight());
secondImageView.setY(firstImageView.getBottom());
但是,在我对第一个ImageView应用翻译或缩放后,上面的代码似乎无法正常工作(在角落处没有对齐)。我猜缩放不会影响视图的实际大小,即使它已经明显调整了大小。那么,即使在修改了缩放、旋转和/或平移之后,我该如何将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);
您的假设是正确的翻译不会影响视图的边界。但是,如果在手势开始时计算第二个视图相对于第一个视图的位置偏移(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>
测试活动.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>
测试活动.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;
}
});
}
}
最初使用第一个图像比例绘制布局。稍后进行比例更改时,需要重新绘制布局以实现所做的更改。
按比例变化运行requestLayout()或invalidate()
findViewById(android.R.id.content).invalidate();
如果在处理事件的过程中,视图的边界可能需要更改,则视图将调用requestLayout()。
类似地,如果在处理事件的过程中可能需要更改视图的外观,则视图将调用invalidate()。
如果调用了requestLayout()或invalidate(),框架将负责测量、布局和绘制树。