我需要缩放整个布局包含Image,TextViews等。我发现缩放功能仅适用于Imageview。
答案 0 :(得分:1)
默认情况下,布局没有缩放功能。 我资助了这个,https://code.google.com/archive/p/android-zoom-view/downloads
在这个答案中,用户解释了如何使用它。 https://stackoverflow.com/a/15850113/6093353
希望这能帮到你!
答案 1 :(得分:1)
创建一个名为Layout
的自定义ZoomeLinearLayout
类。
<强> ZoomLinearLayout.java 强>
public class ZoomLinearLayout extends LinearLayout implements ScaleGestureDetector.OnScaleGestureListener {
private enum Mode {
NONE,
DRAG,
ZOOM
}
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 4.0f;
private Mode mode = Mode.NONE;
private float scale = 1.0f;
private float lastScaleFactor = 0f;
private float startX = 0f;
private float startY = 0f;
private float dx = 0f;
private float dy = 0f;
private float prevDx = 0f;
private float prevDy = 0f;
public ZoomLinearLayout(Context context) {
super(context);
init(context);
}
public ZoomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ZoomLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (scale > MIN_ZOOM) {
mode = Mode.DRAG;
startX = motionEvent.getX() - prevDx;
startY = motionEvent.getY() - prevDy;
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == Mode.DRAG) {
dx = motionEvent.getX() - startX;
dy = motionEvent.getY() - startY;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = Mode.ZOOM;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = Mode.DRAG;
break;
case MotionEvent.ACTION_UP:
mode = Mode.NONE;
prevDx = dx;
prevDy = dy;
break;
}
scaleDetector.onTouchEvent(motionEvent);
if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
dx = Math.min(Math.max(dx, -maxDx), maxDx);
dy = Math.min(Math.max(dy, -maxDy), maxDy);
applyScaleAndTranslation();
}
return true;
}
});
}
@Override
public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
return true;
}
@Override
public boolean onScale(ScaleGestureDetector scaleDetector) {
float scaleFactor = scaleDetector.getScaleFactor();
if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
scale *= scaleFactor;
scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
lastScaleFactor = scaleFactor;
} else {
lastScaleFactor = 0;
}
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector scaleDetector) {
}
private void applyScaleAndTranslation() {
child().setScaleX(scale);
child().setScaleY(scale);
child().setTranslationX(dx);
child().setTranslationY(dy);
}
private View child() {
return getChildAt(0);
}
}
然后在Layout
文件中,使用LinearLayout
包裹您想要缩放的ZoomLinearLayout
。 请注意,ZoomLinearLayout
只有一个直接子女。
<com.asif.test.ZoomLinearLayout
android:layout_width="match_parent"
android:id="@+id/zoom_linear_layout"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
</com.asif.test.ZoomLinearLayout>
现在在Activity
中,创建ZoomLinearLayout
对象并为其设置onTouch()
事件。
final ZoomLinearLayout zoomLinearLayout = (ZoomLinearLayout) findViewById(R.id.zoom_linear_layout);
zoomLinearLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
zoomLinearLayout.init(MainActivity.this);
return false;
}
});
答案 2 :(得分:1)
创建一个名为ZoomLayout的自定义布局类。在这个布局中,我使用了Framelayout,你可以扩展所有智能布局。
ZoomLayout.java
public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {
private enum Mode {
NONE,
DRAG,
ZOOM
}
private static final String TAG = "ZoomLayout";
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 16.0f;
private Mode mode = Mode.NONE;
private float scale = 1.0f;
private float lastScaleFactor = 0f;
// Where the finger first touches the screen
private float startX = 0f;
private float startY = 0f;
// How much to translate the canvas
private float dx = 0f;
private float dy = 0f;
private float prevDx = 0f;
private float prevDy = 0f;
ZoomViewListener listener;
public ZoomLayout(Context context) {
super(context);
init(context);
setListner(getListener());
}
public ZoomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
setListner(getListener());
}
public ZoomLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
setListner(getListener());
}
private void init(Context context) {
final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
/*float eventX = motionEvent.getX();
float eventY = motionEvent.getY();
float[] eventXY = new float[]{eventX, eventY};
// float [] src = {motionEvent.getX(),motionEvent.getY()}; // float [] dst = new float [2];
Matrix invertMatrix = new Matrix();
((ImageView) getChildAt(1)).getImageMatrix().invert(invertMatrix);
invertMatrix.mapPoints(eventXY);
//invertMatrix.mapPoints(src,dst);
int x = Integer.valueOf((int) eventXY[0]);
int y = Integer.valueOf((int) eventXY[1]);
Log.e("image x", "===img ki x==" + x);
Log.e("image y", "===img ki y==" + y);
Drawable imgDrawable = ((ImageView) getChildAt(1)).getDrawable();
Bitmap bitmap = ((BitmapDrawable) imgDrawable).getBitmap();
// int color_value= getHitboxColour(x,y,(ImageView) getChildAt(0));
//限制位图中的x,y范围
if (x < 0) {
x = 0;
} else if (x > bitmap.getWidth() - 1) {
x = bitmap.getWidth() - 1;
}
if (y < 0) {
y = 0;
} else if (y > bitmap.getHeight() - 1) {
y = bitmap.getHeight() - 1;
}
//Log.e("touched color: ", "" + "#" + Integer.toHexString(color_value));
int touchedRGB = bitmap.getPixel(x, y);
int redValue = Color.red(touchedRGB);
int blueValue = Color.blue(touchedRGB);
int greenValue = Color.green(touchedRGB);
Log.e("touched color: ", "" + "#" + Integer.toHexString(touchedRGB));
listener.onPlaceChosen(touchedRGB);*/
Log.i(TAG, "DOWN");
if (scale > MIN_ZOOM) {
mode = Mode.DRAG;
startX = motionEvent.getX() - prevDx;
startY = motionEvent.getY() - prevDy;
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == Mode.DRAG) {
dx = motionEvent.getX() - startX;
dy = motionEvent.getY() - startY;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = Mode.ZOOM;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = Mode.DRAG;
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "UP");
mode = Mode.NONE;
prevDx = dx;
prevDy = dy;
break;
}
scaleDetector.onTouchEvent(motionEvent);
/* if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
dx = Math.min(Math.max(dx, -maxDx), maxDx);
dy = Math.min(Math.max(dy, -maxDy), maxDy);
Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx
+ ", max " + maxDx);
applyScaleAndTranslation();
}*/
if (( scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
dx = Math.min(Math.max(dx, -maxDx), maxDx);
dy = Math.min(Math.max(dy, -maxDy), maxDy);
// Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx);
// applyScaleAndTranslation();
child().setScaleX(scale);
child().setScaleY(scale);
float maxDx1 = (child2().getWidth() - (child2().getWidth() / scale)) / 2 * scale;
float maxDy1 = (child2().getHeight() - (child2().getHeight() / scale)) / 2 * scale;
dx = Math.min(Math.max(dx, -maxDx1), maxDx1);
dy = Math.min(Math.max(dy, -maxDy1), maxDy1);
// Log.i(TAG, "Width: " + child2().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx1);
// applyScaleAndTranslation();
child2().setScaleX(scale);
child2().setScaleY(scale);
}
if(mode == Mode.DRAG ){
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
dx = Math.min(Math.max(dx, -maxDx), maxDx);
dy = Math.min(Math.max(dy, -maxDy), maxDy);
// Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx);
child().setTranslationX(dx);
child().setTranslationY(dy);
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx1 = (child2().getWidth() - (child2().getWidth() / scale)) / 2 * scale;
float maxDy1 = (child2().getHeight() - (child2().getHeight() / scale)) / 2 * scale;
dx = Math.min(Math.max(dx, -maxDx1), maxDx1);
dy = Math.min(Math.max(dy, -maxDy1), maxDy1);
// Log.i(TAG, "Width: " + child2().getWidth() + ", scale " + scale + ", dx " + dx + ", max " + maxDx);
child2().setTranslationX(dx);
child2().setTranslationY(dy);
}
return true;
}
});
}
public int getHitboxColour(int x, int y,ImageView iv) {
// ImageView iv = (ImageView) findViewById(R.id.img_hitbox);
Bitmap bmpHotspots;
int pixel;
//通过定位屏幕元素(如活动标题栏)来修复任何偏移。
//当我测试Bill Lahti的代码时,这部分导致了我的问题。
int[] location = new int[2];
iv.getLocationOnScreen(location);
x -= location[0];
y -= location[1];
//防止崩溃,返回背景噪音
if ((x < 0) || (y < 0)) {
return Color.WHITE;
}
//将缩放后的位图绘制到内存中
iv.setDrawingCacheEnabled(true);
bmpHotspots = Bitmap.createBitmap(iv.getDrawingCache());
iv.setDrawingCacheEnabled(false);
pixel = bmpHotspots.getPixel(x, y);
bmpHotspots.recycle();
return pixel;
}
// ScaleGestureDetector
@Override
public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
Log.i(TAG, "onScaleBegin");
return true;
}
@Override
public boolean onScale(ScaleGestureDetector scaleDetector) {
float scaleFactor = scaleDetector.getScaleFactor();
Log.i(TAG, "onScale" + scaleFactor);
if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
scale *= scaleFactor;
scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
lastScaleFactor = scaleFactor;
} else {
lastScaleFactor = 0;
}
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector scaleDetector) {
Log.i(TAG, "onScaleEnd");
}
private void applyScaleAndTranslation() {
child().setScaleX(scale);
child().setScaleY(scale);
child().setTranslationX(dx);
child().setTranslationY(dy);
}
private View child() {
return getChildAt(0);
}
private View child2() {
return getChildAt(1);
}
public interface ZoomViewListener {
void onZoomStarted(float zoom, float zoomx, float zoomy);
void onZooming(float zoom, float zoomx, float zoomy);
void onZoomEnded(float zoom, float zoomx, float zoomy);
void onPlaceChosen(int color);
}
public ZoomViewListener getListener() {
return listener;
}
public void setListner(final ZoomViewListener listener) {
this.listener = listener;
}}
答案 3 :(得分:0)
Xml其中布局
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:layout_centerHorizontal="true"
android:id="@+id/llzoom"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/text"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="20dp"
android:text="School"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textColor="@android:color/black"
android:textStyle="bold" />
</LinearLayout>
导入强>
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
用于缩小动画
findViewById(R.id.llzoom).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Animation zoomout = AnimationUtils.loadAnimation(SelectBuyerActivity.this, R.anim.zoomout);
findViewById(R.id.llzoom).startAnimation(zoomout);
}
});
res / anim文件夹中的动画
<强> zoomout.xml 强>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/bounce_interpolator"
android:fromXScale="0.5"
android:toXScale="1"
android:fromYScale="0.5"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="500"
android:fillAfter="true">
</scale>
您还使用了更多动画,例如向下
<强> slide_down.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="0%p"
android:interpolator="@android:anim/accelerate_interpolator"
android:toYDelta="100%p" />
</set>
<强> slide_up.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="100%p"
android:toYDelta="0" />
</set>