
Schnodahipfe
Ich habe eine Aktivität mit a RelativeLayout
und eine Privatklasse drin, die das erweitert SimpleOnScaleGestureListener
. Im onScale
Methode des Zuhörers Ich möchte das gesamte Layout (alles, was der Benutzer sieht) vergrößern/verkleinern, indem der Benutzer seine Finger spreizt/kneift.
Ich möchte, dass die Änderungen am Layout NICHT dauerhaft sind, dh wenn die Spread/Pinch-Geste vorbei ist, möchte ich, dass das Layout wieder auf den ursprünglichen Zustand zurückkehrt (jedes Zurücksetzen könnte in der onScaleEnd
Methode der SimpleOnScaleGestureListener
zum Beispiel).
Ich habe versucht, es per Anruf umzusetzen setScaleX
und setScaleY
auf der RelativeLayout
und auch durch die Verwendung von a ScaleAnimation
. Beides führte nicht zu einem reibungslosen Zoomen (oder irgendetwas, das überhaupt als Zoomen bezeichnet werden könnte). Ist es überhaupt möglich, ein/aus zu zoomen? RelativeLayout
?
Die einzige Idee, die mir noch bleibt, wäre, einen Screenshot aus dem Cache zu lesen und ihn als ImageView
auf das gesamte Layout und das Vergrößern/Verkleinern dieses Bildes über setImageMatrix
. Ich habe aber keine Ahnung, wie ich das umsetzen soll.
Viele Layouts enthalten auch einen Container für ein Fragment, das zu dem Zeitpunkt, an dem das Zoomen möglich sein soll, leer ist. Im onScaleEnd
Geste, das Fragment wird in seinen Container gelegt (bereits implementiert und funktioniert gut). Hier ist mein Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_pinch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff" >
<!-- Layout containing the thumbnail ImageViews -->
<LinearLayout
android:id="@+id/thumbnail_group_pui"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tn_c1"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tn_c2"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tn_c3"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tn_c4"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tn_c5"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tn_c6"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tn_c7"/>
</LinearLayout>
<!-- Layout containing the dashed boxes -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="152dp"
android:layout_centerVertical="true"
android:orientation="horizontal" >
<ImageView
android:layout_width="177dp"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="@drawable/dashed_box"/>
<ImageView
android:layout_width="177dp"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="@drawable/dashed_box"/>
<ImageView
android:layout_width="177dp"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="@drawable/dashed_box"/>
<ImageView
android:layout_width="177dp"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="@drawable/dashed_box"/>
<ImageView
android:layout_width="177dp"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="@drawable/dashed_box"/>
<ImageView
android:layout_width="177dp"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="@drawable/dashed_box"/>
<ImageView
android:layout_width="177dp"
android:layout_height="match_parent"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="@drawable/dashed_box"/>
</LinearLayout>
<!-- Container for the fragments -->
<FrameLayout
android:id="@+id/fragment_container_pui"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
BEARBEITEN
Ich habe diese beiden verwandten Themen gefunden:
Erweitern von RelativeLayout und Überschreiben von dispatchDraw(), um eine zoombare ViewGroup zu erstellen
Inhalt in einem RelativeLayout vergrößern
Die Umsetzung habe ich aber nicht hinbekommen. Welche anderen Methoden muss ich in die erweiterte Klasse aufnehmen, um das Layout tatsächlich zu skalieren oder zurückzusetzen?

Schnodahipfe
Also habe ich eine Unterklasse von erstellt RelativeLayout
wie in den oben genannten Themen beschrieben. Es sieht aus wie das:
public class ZoomableRelativeLayout extends RelativeLayout {
float mScaleFactor = 1;
float mPivotX;
float mPivotY;
public ZoomableRelativeLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public ZoomableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ZoomableRelativeLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScaleFactor, mScaleFactor, mPivotX, mPivotY);
super.dispatchDraw(canvas);
canvas.restore();
}
public void scale(float scaleFactor, float pivotX, float pivotY) {
mScaleFactor = scaleFactor;
mPivotX = pivotX;
mPivotY = pivotY;
this.invalidate();
}
public void restore() {
mScaleFactor = 1;
this.invalidate();
}
}
Meine Umsetzung der SimpleOnScaleGestureListener
sieht aus wie das:
private class OnPinchListener extends SimpleOnScaleGestureListener {
float startingSpan;
float endSpan;
float startFocusX;
float startFocusY;
public boolean onScaleBegin(ScaleGestureDetector detector) {
startingSpan = detector.getCurrentSpan();
startFocusX = detector.getFocusX();
startFocusY = detector.getFocusY();
return true;
}
public boolean onScale(ScaleGestureDetector detector) {
mZoomableRelativeLayout.scale(detector.getCurrentSpan()/startingSpan, startFocusX, startFocusY);
return true;
}
public void onScaleEnd(ScaleGestureDetector detector) {
mZoomableRelativeLayout.restore();
}
}
Hoffe das hilft!
Aktualisieren:
Sie können sich integrieren OnPinchListener
für dein ZoomableRelativelayout
durch die Nutzung ScaleGestureDetector
:
ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(this, new OnPinchListener());
Und Sie müssen den Touch-Listener des zoombaren Layouts mit dem Touch-Listener von ScaleGestureDetector binden:
mZoomableLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
scaleGestureDetector.onTouchEvent(event);
return true;
}
});

Ashish Kumar Pal
Erstellen Sie eine Klasse namens Zoomlayout, die jedes Layout erweitert, das Sie zoomen möchten, in meinem Fall ist es Relative Layout.
public class ZoomLayout extends RelativeLayout 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 = 4.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;
public ZoomLayout(Context context) {
super(context);
init(context);
}
public ZoomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ZoomLayout(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:
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();
}
return true;
}
});
}
// 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);
}
}
Danach fügen Sie ZoomLayout in XML hinzu, das nur ein untergeordnetes Element hat. Zum Beispiel
<?xml version="1.0" encoding="utf-8"?>
<com.focusmedica.digitalatlas.headandneck.ZoomLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/zoomLayout"
android:background="#000000"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:paddingTop="5dp"
android:textColor="#ffffff"
android:text="Heading"
android:gravity="center"
android:textAlignment="textStart"
android:paddingLeft="5dp"
android:textSize="20sp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tvSubtitle2"
android:layout_toLeftOf="@+id/ivOn"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ImageView
android:id="@+id/ivOff"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/off_txt"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<ImageView
android:id="@+id/ivOn"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/on_txt"
android:layout_alignParentTop="true"
android:layout_alignLeft="@+id/pinOn"
android:layout_alignStart="@+id/pinOn" />
<ImageView
android:id="@+id/pinOff"
android:visibility="invisible"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/pin_off"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<ImageView
android:id="@+id/pinOn"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/pin_on"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/ivOff"
android:layout_toStartOf="@+id/ivOff" />
<RelativeLayout
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true">
<ImageView
android:src="@drawable/wait"
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/fullIVideo"/>
<ImageView
android:src="@drawable/wait"
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/colorCode"/>
<ImageView
android:src="@drawable/wait"
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/labelText"/>
<ImageView
android:src="@drawable/download"
android:layout_marginTop="91dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/label_play"
android:layout_alignTop="@+id/fullIVideo"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
<LinearLayout
android:orientation="vertical"
android:id="@+id/custom_toast_layout"
android:layout_width="300dp"
android:layout_above="@+id/up"
android:background="@drawable/rectangle_frame"
android:paddingLeft="10dp"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:paddingRight="10dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_height="wrap_content">
<TextView
android:textSize="15sp"
android:textColor="#ffffff"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text"
android:id="@+id/tvLabel" />
<TextView
android:textColor="#ffffff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="New Text"
android:layout_gravity="center"
android:id="@+id/tvLabelDescription" />
</LinearLayout>
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/up"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:id="@+id/up" />
</RelativeLayout>
</com.focusmedica.digitalatlas.headandneck.ZoomLayout>
Erstellen Sie nun in MainActivity ein Objekt von ZoomLayout und definieren Sie id.Like
ZoomLayout zoomlayout= findViewbyId(R.id.zoomLayout);
zoomlayout.setOnTouchListener(FullScreenVideoActivity.this);
public boolean onTouch(View v, MotionEvent event) {
linear.init(FullScreenVideoActivity.this);
return false;
}
Ich glaube, ich habe es geschafft, Schnodahipfes Antwort ein wenig zu verbessern. Ich habe der ZoomableRelativeLayout-Klasse zwei Methoden hinzugefügt.
public void relativeScale(float scaleFactor, float pivotX, float pivotY)
{
mScaleFactor *= scaleFactor;
if(scaleFactor >= 1)
{
mPivotX = mPivotX + (pivotX - mPivotX) * (1 - 1 / scaleFactor);
mPivotY = mPivotY + (pivotY - mPivotY) * (1 - 1 / scaleFactor);
}
else
{
pivotX = getWidth()/2;
pivotY = getHeight()/2;
mPivotX = mPivotX + (pivotX - mPivotX) * (1 - scaleFactor);
mPivotY = mPivotY + (pivotY - mPivotY) * (1 - scaleFactor);
}
this.invalidate();
}
public void release()
{
if(mScaleFactor < MIN_SCALE)
{
final float startScaleFactor = mScaleFactor;
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
scale(startScaleFactor + (MIN_SCALE - startScaleFactor)*interpolatedTime,mPivotX,mPivotY);
}
};
a.setDuration(300);
startAnimation(a);
}
else if(mScaleFactor > MAX_SCALE)
{
final float startScaleFactor = mScaleFactor;
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
scale(startScaleFactor + (MAX_SCALE - startScaleFactor)*interpolatedTime,mPivotX,mPivotY);
}
};
a.setDuration(300);
startAnimation(a);
}
}
und schrieb die Klasse OnPinchListener so um
private class OnPinchListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
{
float currentSpan;
float startFocusX;
float startFocusY;
public boolean onScaleBegin(ScaleGestureDetector detector)
{
currentSpan = detector.getCurrentSpan();
startFocusX = detector.getFocusX();
startFocusY = detector.getFocusY();
return true;
}
public boolean onScale(ScaleGestureDetector detector)
{
ZoomableRelativeLayout zoomableRelativeLayout= (ZoomableRelativeLayout) ImageFullScreenActivity.this.findViewById(R.id.imageWrapper);
zoomableRelativeLayout.relativeScale(detector.getCurrentSpan() / currentSpan, startFocusX, startFocusY);
currentSpan = detector.getCurrentSpan();
return true;
}
public void onScaleEnd(ScaleGestureDetector detector)
{
ZoomableRelativeLayout zoomableRelativeLayout= (ZoomableRelativeLayout) ImageFullScreenActivity.this.findViewById(R.id.imageWrapper);
zoomableRelativeLayout.release();
}
}
Die ursprüngliche Antwort würde die Skala jedes Mal zurücksetzen, wenn das Berührungsereignis endete, aber so können Sie mehrmals hinein- und herauszoomen.

Brian begann
für Fragmente müssen Sie nur getActivity() anstelle von Activity Name übergeben
final ZoomLayout zoomlayout = (ZoomLayout) findViewById(R.id.zoomLayout);
zoomlayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
zoomlayout.init(getActivity());
return false;
}
});
.
7850600cookie-checkAndroid – Vergrößern/Verkleinern von RelativeLayout mit Spreizen/Kneifenyes
um ein Layout zu zoomen, wie verwenden wir
ZoomableRelativeLayout
? Muss ich meine Ansicht als Parameter an den Konstruktor übergeben?– Mushahid
10. August 15 um 08:12 Uhr