android-layout animate - Android:zoom in / out RelativeLayout con spread / pizzico




everything example (5)

Ho un'attività con un RelativeLayout e una classe privata al suo interno, che estende SimpleOnScaleGestureListener . Nel metodo onScale del listener, vorrei ingrandire / ridurre l'intero layout (tutto quello che l'utente vede) con l'utente che sparge / pizzica le dita.

Mi piacerebbe che le modifiche al layout NON fossero permanenti, cioè quando il gesto spread / pizzico è finito mi piacerebbe che il layout tornasse a quello che era al primo posto (qualsiasi ripristino potrebbe essere fatto nel metodo onScaleEnd di il SimpleOnScaleGestureListener per esempio).

Ho provato a implementarlo chiamando setScaleX e setScaleY su RelativeLayout e anche usando ScaleAnimation . Nessuno dei due ha provocato uno zoom fluido (o qualsiasi cosa che potrebbe essere definita come zooming). È anche possibile ingrandire / ridurre un RelativeLayout ?

L'unica idea che ho lasciato sarebbe quella di leggere uno screenshot dalla cache e metterlo come una ImageView sopra l'intero layout e lo zoom in / out di questa immagine tramite setImageMatrix . Non ho idea, tuttavia, su come implementarlo.

Il layout di maggio contiene anche un contenitore per un frammento, che è vuoto al momento in cui lo zoom dovrebbe essere possibile. Nel gesto onScaleEnd , il frammento viene inserito nel suo contenitore (già implementato e funzionante). Ecco il mio 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>

EDIT Ho trovato questi due argomenti correlati:
Estensione di RelativeLayout e sovrascrittura di dispatchDraw () per creare un ViewGroup zoomabile
Zoom del contenuto in un RelativeLayout

Non ho avuto l'implementazione, comunque. Quali altri metodi devo includere nella classe estesa per ridimensionare effettivamente il layout o resettarlo?


Answers

Penso di essere riuscito a migliorare un po 'la risposta di Schnodahipfe. Ho aggiunto due metodi alla classe 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);
    }
}

e riscritto la classe OnPinchListener in questo modo

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 risposta originale reimposta la scala ogni volta che termina l'evento touch, ma in questo modo è possibile eseguire lo zoom avanti e indietro più volte.


Crea una classe chiamata Zoomlayout che estende qualsiasi layout che vuoi ingrandire nel mio caso è Layout 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);
 }

}

Dopo questo aggiungi ZoomLayout in xml che ha un solo figlio. Ad esempio

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

Ora in MainActivity crea l'oggetto di ZoomLayout e definisci 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;
 }

Lo farò funzionare. Se questo codice funzionerà, per favore fallo come accettato.


Così ho creato una sottoclasse di RelativeLayout come descritto negli argomenti sopra menzionati. Sembra questo:

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

}

La mia implementazione di SimpleOnScaleGestureListener il SimpleOnScaleGestureListener aspetto:

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

Spero che questo ti aiuti!

Aggiornare:

Puoi integrare OnPinchListener per ZoomableRelativelayout usando ScaleGestureDetector :

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

E tu sei tenuto a legare l'ascoltatore tattile del layout Zoomable con l'ascoltatore touch di ScaleGestureDetector:

mZoomableLayout.setOnTouchListener(new OnTouchListener() {

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

per i frammenti è sufficiente passare getActivity () anziché Nome attività

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

Android SDK rev. 17 supporta l'accelerazione di macchine virtuali utilizzando le tecnologie di virtualizzazione AMD e Intel.

Questa funzione può migliorare molto le prestazioni dell'emulatore!

Vedere la sezione seguente nella documentazione dell'emulatore Android per ulteriori dettagli: Configurazione dell'accelerazione della macchina virtuale

Non dimenticare di installare il driver appropriato per il tuo sistema operativo:

Dopo aver installato i driver e scaricato un'immagine di sistema X86 per Android (come descritto nella documentazione) dovresti essere in grado di creare un nuovo AVD usando l'immagine x86:

Per esempio:

  • Target: Intel Atom x86 System Image - Livello API 10
  • CPU / ABI: Intel Atom (x86)




android android-layout android-animation