我实现了一个ImageView扩展视图,通过手势监听器进行缩放和平移。它工作得很好,但我的问题是我需要在这个视图周围有一个白色边框。
我尝试添加填充并将位图背景设置为白色,但它没有正常工作:视图右侧和顶部有白色边框但是朝向它们缩放。
将视图放置到布局中可以正常工作(我尝试过),但这样会使其布局代码变得复杂。
我试图在图像后面绘制矩形,但它没有正常工作。事实上,我试过的方式根本没有用。
所以我想知道有没有办法拥有(绘制或填充)视图周围的白色边框,可以缩放和平移。
我认为这个问题在onMeasure中存在,但我真的不知道从哪里开始。
我的视图被放置在布局中,覆盖了onMeasure(顺便说一下如何使它更好?它现在很难看:():
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int myWidth = MeasureSpec.getSize(widthMeasureSpec);
int myHeight = MeasureSpec.getSize(heightMeasureSpec);
float leftHeight = myHeight * 12f / 15f;
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child != null) {
switch (child.getId()) {
case R.id.llButtons:
child.measure(MeasureSpec.makeMeasureSpec(myWidth - 20,
MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec((int) (myHeight / 15f), MeasureSpec.AT_MOST)
);
break;
case R.id.hsvFilters:
child.measure(myWidth, MeasureSpec.makeMeasureSpec((int) (myHeight * 2f /
15f),
MeasureSpec.AT_MOST
));
break;
case R.id.flFrame:
child.measure(myWidth - 20,
(int) leftHeight);
break;
}
}
}
}
布局:
<com.project.android.views.FluidContainer 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:id="@+id/fdAdjustImage"
android:orientation="vertical"
tools:context="com.project.android.dialogs.AdjustImageFragment">
<LinearLayout
android:weightSum="100"
android:id="@+id/llButtons"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="wrap_content">
<com.inkly.android.views.ButtonFont
android:id="@+id/bChangePhoto"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="15dp"
android:textSize="19sp"
android:layout_weight="45"
android:text="@string/change_photo"
android:background="@drawable/btn_blue"
style="@style/RegularButton"/>
<View
android:layout_weight="10"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
<com.inkly.android.views.ButtonFont
android:id="@+id/bDone"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:gravity="center"
android:textSize="19sp"
android:layout_weight="45"
android:text="@string/done"
android:background="@drawable/btn_green"
style="@style/RegularButton"/>
</LinearLayout>
<com.inkly.android.views.FluidCard
android:background="#fff"
android:layout_gravity="center"
android:padding="10dp"
android:id="@+id/flFrame"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ProgressBar
android:id="@+id/progress"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateOnly="true"
android:layout_gravity="center"
style="@android:style/Widget.Holo.Light.ProgressBar.Large"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:scrollbars="none"
android:id="@+id/hsvFilters"
android:background="#fff"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:orientation="horizontal"
android:id="@+id/llFilters"
android:layout_height="wrap_content"/>
</HorizontalScrollView>
和我的观点:
缩放:
public FluidCard(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setScaleType(ScaleType.MATRIX);
mScaleDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
float mFocusX;
float mFocusY;
float mScaleMoveX = 0;
float mScaleMoveY = 0;
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mFocusX = detector.getFocusX();
mFocusY = detector.getFocusY();
mScaleMoveX = mFocusX * (1f - mScaleFactor);
mScaleMoveY = mFocusY * (1f - mScaleFactor);
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float newScaleFactor = mScaleFactor * detector.getScaleFactor();
if (newScaleFactor < mScaleFactor) {
newScaleFactor *= 0.94f;
}
newScaleFactor = Math.max(1f, Math.min(newScaleFactor, 10.0f));
boolean isDecrease = newScaleFactor < mScaleFactor;
mScaleFactor = newScaleFactor;
float newScaleMoveX = mFocusX * (1f - mScaleFactor);
float newScaleMoveY = mFocusY * (1f - mScaleFactor);
if (newScaleMoveX != mScaleMoveX || newScaleMoveY != mScaleMoveY) {
float dx = newScaleMoveX - mScaleMoveX;
float dy = newScaleMoveY - mScaleMoveY;
if (isDecrease) {
float minOffsX = getMeasuredWidth() - 10 - mScaledWidth * mScaleFactor;
if (mMoveX + dx < minOffsX) {
mMoveX = minOffsX;
} else {
if (mMoveX + dx <= 0) {
mMoveX += dx;
} else {
mMoveX = 0;
}
}
float minOffsY = getMeasuredHeight() - 10 - mScaledHeight * mScaleFactor;
if (mMoveY + dy < minOffsY) {
mMoveY = minOffsY;
} else {
if (mMoveY + dy <= 0) {
mMoveY += dx;
} else {
mMoveY = 0;
}
}
} else {
mMoveX += dx;
mMoveY += dy;
}
mScaleMoveX = newScaleMoveX;
mScaleMoveY = newScaleMoveY;
mForceInvalidate = true;
}
return true;
}
});
mMoveDetector = new MoveGestureDetector(context, new MoveGestureDetector.SimpleOnMoveGestureListener() {
@Override
public boolean onMoveBegin(MoveGestureDetector detector) {
return true;
}
@Override
public boolean onMove(MoveGestureDetector detector) {
PointF focusDelta = detector.getFocusDelta();
float newX = mMoveX + focusDelta.x;
if (newX <= 0 && newX + mScaledWidth * mScaleFactor >= getMeasuredWidth() - 10) {
mMoveX = newX;
mForceInvalidate = true;
}
float newY = mMoveY + focusDelta.y;
if (newY <= 0 && newY + mScaledHeight * mScaleFactor >= getMeasuredHeight() - 10) {
mMoveY = newY;
mForceInvalidate = true;
}
return true;
}
});
mPaint.setFilterBitmap(false);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
rectPaint.setColor(Color.WHITE);
mBackground = new Rect();
}
onMeasure:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (w == 0 && h == 0) {
int oldWidth = MeasureSpec.getSize(widthMeasureSpec);
int oldHeight = MeasureSpec.getSize(heightMeasureSpec);
double width, height;
if (mAspectRatio > 1f) {
height = oldHeight;
width = Math.ceil(oldHeight / mAspectRatio);
} else {
width = oldWidth;
height = Math.ceil(oldWidth * mAspectRatio);
}
if (height > oldHeight || width > oldWidth) {
float k = 1.1f;
while (height > oldHeight || width > oldWidth) {
height /= k;
width /= k;
k += 0.01f;
}
}
w = (int) Math.ceil(width);
h = (int) Math.ceil(height);
}
if (getDrawable() != null) {
setupMatrix(w, h);
}
setMeasuredDimension(w, h);
}
onTouch:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mEditEnabled) {
mScaleDetector.onTouchEvent(event);
boolean isScaling = mScaleDetector.isInProgress();
if (!isScaling) mMoveDetector.onTouchEvent(event);
if (mForceInvalidate) {
mForceInvalidate = false;
mMatrix.reset();
mMatrix.setScale(mScale, mScale);
if (mScaleFactor > 1) {
mMatrix.postScale(mScaleFactor, mScaleFactor);
}
mMatrix.postTranslate(mMoveX, mMoveY);
invalidate();
}
return true;
}
return super.onTouchEvent(event);
}
拉伸:
@Override
public void draw(Canvas canvas) {
int sc = canvas.saveLayer(10, 10, getWidth() - 10, getHeight() - 10, null,
Canvas.CLIP_TO_LAYER_SAVE_FLAG);// | Canvas.FULL_COLOR_LAYER_SAVE_FLAG ?
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.setMatrix(mMatrix);
super.draw(canvas);
canvas.restore();
canvas.restoreToCount(sc);
}
UPD:
android:cropToPadding="true"
没有按照我需要的方式工作,虽然结果图片现在变小了(但这并不好)。