I am having a strange problem. I scale an image and, while scaling works correctly, the image always gets clipped. I tried different scale types - things changed but I never could make it work.
Just to be clear, here's what I need to solve:
1. I have a HorizontalScrollView
around the ImageView
and a ScrollView
around the HorizontalView
.
2. I scroll around (using scrollTo
of both scroll views) and, upon a certain event, zoom in.
3. What I'd like to happen is for the ImageView
to scale around my current scroll position.
Here's the layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:overScrollMode="never">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:overScrollMode="never">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:scaleType="fitCenter" />
</HorizontalScrollView>
</ScrollView>
</FrameLayout>
And here's the scaling code (originalWidth
/originalHeight
are calculated at scale of 1
; targetView
points to the ImageView
):
public synchronized void changeScale(float newScaleFactor) {
this.scaleFactor = Math.max(min_zoom, Math.min(newScaleFactor, max_zoom));
if (targetView != null && originalWidth > 0) {
int newWidth = (int)(originalWidth * scaleFactor);
int newHeight = (int)(originalHeight * scaleFactor);
onScaleChanged(targetView, scaleFactor, newWidth, newHeight);
}
}
public void onScaleChanged(View targetView, float scaleFactor, int newWidth, int newHeight) {
ViewGroup.LayoutParams layoutParams = targetView.getLayoutParams();
layoutParams.width = newWidth;
layoutParams.height = newHeight;
// This is needed to increase the pane size (rather than zoom within the initial layout)
targetView.setLayoutParams(layoutParams);
// Tell the system to recalculate the layout
targetView.requestLayout();
// This is needed to specify the center of scaling
HorizontalScrollView horizontalScrollView = (HorizontalScrollView)targetView.getParent();
ScrollView vertScrollView = (ScrollView)horizontalScrollView.getParent();
// ~~~ the pivot points are probably wrong
targetView.setPivotX(horizontalScrollView.getScrollX() * scaleFactor);
targetView.setPivotY(vertScrollView.getScrollY() * scaleFactor);
// This is needed for actual zooming
targetView.setScaleX(scaleFactor);
targetView.setScaleY(scaleFactor);
};
public void zoomIn(float scaleDelta) {
changeScale(scaleFactor + scaleDelta);
}
public void zoomOut(float scaleDelta) {
changeScale(scaleFactor - scaleDelta);
}
Question 1: How do I prevent clipping? I can't find the right combination of scaleType
and layout resizing.
Question 2: When I use setScaleX
/setScaleY
, should my pivot be calculated after applying the new scale factor or does the renderer take care of that automatically?
After updating the scale you need to invalidate(), and requestLayout() the views.
targetView.invalidate();
targetView.requestLayout();
I usually calculate the scale differently for images. You could try to scale the image view using the MATRIX scale type. You will need to know the size of your bound DPI.
// Get the scaled DPI
int boundBoxInDp = getResources().getDisplayMetrics().densityDpi * scaleFactor
// Determine how much to scale: the dimension requiring less scaling is
// closer to its side. This way the image always stays inside your
// bound AND either x/y axis touches the bound but neither will go over.
float xScale = ((float) boundBoxInDp) / newWidth;
float yScale = ((float) boundBoxInDp) / newHeight;
float scale = (xScale <= yScale) ? xScale : yScale;
// scale using our calculated scale
targetView.setScaleX(scale);
targetView.setScaleY(scale);
As to your second question about the Pivot. That will probably need to be set to the center of the visible scroll area. The the scrollable area should be increased when you change the image size since you are using FIT_CENTER
;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With