examples example changes card animations animate android android-layout android-animation

example - button animation android



Android-acercar/alejar RelativeLayout con spread/pinch (4)

Así que creé una subclase de RelativeLayout como se describe en los temas mencionados anteriormente. Se parece a esto:

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(); } }

Mi implementación de SimpleOnScaleGestureListener ve así:

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(); } }

¡Espero que esto ayude!

Actualizar:

Puede integrar OnPinchListener para su ZoomableRelativelayout usando ScaleGestureDetector :

ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(this, new OnPinchListener());

Y se le solicita que vincule touch listener of Zoomable layout con el detector táctil de ScaleGestureDetector:

mZoomableLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub scaleGestureDetector.onTouchEvent(event); return true; } });

Tengo una actividad con RelativeLayout y una clase privada, que amplía SimpleOnScaleGestureListener . En el método onScale del oyente me gustaría acercar / alejar todo el diseño (todo lo que el usuario ve) con el usuario extendiendo / pellizcando sus dedos.

Me gustaría que los cambios en el diseño NO sean permanentes, es decir, cuando el gesto de propagación / pellizco termine, me gustaría que el diseño vuelva a ser lo que estaba en primer lugar (cualquier reinicio podría hacerse en el método onScaleEnd de SimpleOnScaleGestureListener por ejemplo).

Intenté implementarlo llamando a setScaleX y setScaleY en RelativeLayout y también usando ScaleAnimation . Ninguno de los dos dio como resultado un zoom suave (ni nada que se pudiera llamar zoom). ¿Es posible incluso acercar / alejar un RelativeLayout ?

La única idea que me queda sería leer una captura de pantalla del caché y ponerlo como un ImageView en la parte superior de todo el diseño y el acercamiento / setImageMatrix de esta imagen a través de setImageMatrix . Sin embargo, no tengo idea de cómo implementar esto.

El diseño de mayo también contiene un contenedor para un fragmento, que está vacío en el momento en que se supone que el zoom es posible. En el gesto onScaleEnd , el fragmento se coloca en su contenedor (ya implementado y funcionando bien). Aquí está mi diseño:

<?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>

EDITAR Encontré estos dos temas relacionados:
Extendiendo RelativeLayout, y reemplazando dispatchDraw () para crear un ViewGroup con zoom
Zoom de contenido en un Relative Layout

No recibí la implementación, sin embargo. ¿Qué otros métodos debo incluir en la clase extendida para realmente escalar el diseño o restablecerlo?


Crea una clase llamada Zoomlayout que amplía cualquier diseño que quieras ampliar en mi caso es Diseño relativo.

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); } }

Después de esto, agregue ZoomLayout en xml que tenga solo un elemento secundario. Por ejemplo

<?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>

Ahora en MainActivity crea el objeto de ZoomLayout y define id.Like

ZoomLayout zoomlayout=(ZoomLayout)findviewbyid(R.id.zoomLayout); zoomlayout.setOnTouchListener(FullScreenVideoActivity.this); public boolean onTouch(View v, MotionEvent event) { linear.init(FullScreenVideoActivity.this); return false; }

Supongo que funcionará. Si este código funciona, por favor haga que sea aceptado.


Creo que logré mejorar la respuesta de Schnodahipfe un poco. Agregué dos métodos a la clase ZoomableRelativeLayout.

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); } }

y reescribí la clase OnPinchListener como esta

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(); } }

La respuesta original restablecería la escala cada vez que finalizara el evento táctil, pero así se puede acercar y alejar varias veces.


para fragmentos solo necesita pasar getActivity () en lugar de Activity Name

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; } });