15

W mojej aplikacji na Androida potrzebuję utworzyć działania z możliwością powiększania. Znalazłem użyteczny kod do powiększania układu liniowego here. Ale w mojej aplikacji kilka czynności zaczyna się od scrollview i ten kod nie rozpoznaje scrollview. Jak zrobić powiększenie z szczyptą dla przewijalnej aktywności? To jeden z moich układów.Jak zrobić powiększany przewijany widok?

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/scrollViewZoom" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:layout_centerHorizontal="true" 
android:layout_centerVertical="true" > 

<LinearLayout 
    android:id="@+id/wd_content" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_marginTop="10dp" 
    android:orientation="vertical" > 

    <!-- Start Circle --> 

    <TableRow 
     android:id="@+id/row_circl1" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_gravity="center" 
     android:layout_marginTop="30dp" 
     android:background="@color/purple_color" > 

     <RelativeLayout 
      android:id="@+id/circle_layout1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:background="@color/white_color" > 

      <ImageView 
       android:id="@+id/img_engin_circle1" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_centerHorizontal="true" 
       android:background="@drawable/circle_engin_bg" 
       android:contentDescription="TODO" /> 
     </RelativeLayout> 

     <RelativeLayout 
      android:id="@+id/circle_layout2" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:background="@color/white_color" > 

      <ImageView 
       android:id="@+id/img_engin_circle2" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_centerHorizontal="true" 
       android:background="@drawable/circle_engin_bg" 
       android:contentDescription="TODO" /> 
     </RelativeLayout> 
    </TableRow> 

    <TableRow 
     android:id="@+id/row_name_circle" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_gravity="center" 
     android:layout_marginTop="30dp" > 

     <RelativeLayout 
      android:id="@+id/circle_name_layout1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginTop="-15dp" 
      android:background="@color/white_color" > 

      <ImageView 
       android:id="@+id/img_name_circle1" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_centerHorizontal="true" 
       android:background="@drawable/circle_gauge_name" 
       android:contentDescription="TODO" /> 
     </RelativeLayout> 

     <RelativeLayout 
      android:id="@+id/circle_name_layout2" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginTop="-15dp" 
      android:background="@color/white_color" > 

      <ImageView 
       android:id="@+id/img_name_circle2" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_centerHorizontal="true" 
       android:background="@drawable/circle_gauge_name" 
       android:contentDescription="TODO" /> 
     </RelativeLayout> 
    </TableRow> 

    <!-- End Circle --> 

</LinearLayout> 

</ScrollView> 

Każdy pomysł może mi pomóc. Dzięki.

+0

Proszę sprawdzić ten link: [umożliwiającą-zoom-on-przewijania-view] [1] powodzenia. [1]: http://stackoverflow.com/questions/18572014/enabling-zoom-on-scroll-view –

+0

Dzięki za odpowiedzi @ Adir.el ale znalazłem inne rozwiązanie. – IndieBoy

Odpowiedz

22

Ok. Po zaoraniu sieci, w końcu znalazłem odpowiedź. Znalazłem onTouchEvent() dla scrollview nie działa, więc muszę użyć dispatchTouchEvent() zamiast onTouchEvent(). Na górze możesz zobaczyć mój kod xml (w moim pytaniu) a oto mój kod aktywności oczywiście z komentarzami.

// step 1: add some instance 
private float mScale = 1f; 
private ScaleGestureDetector mScaleDetector; 
GestureDetector gestureDetector; 

//step 2: create instance from GestureDetector(this step sholude be place into onCreate()) 
gestureDetector = new GestureDetector(this, new GestureListener()); 

// animation for scalling 
mScaleDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener() 
    {         
     @Override 
     public boolean onScale(ScaleGestureDetector detector) 
     { 
      float scale = 1 - detector.getScaleFactor(); 

      float prevScale = mScale; 
      mScale += scale; 

      if (mScale < 0.1f) // Minimum scale condition: 
       mScale = 0.1f; 

      if (mScale > 10f) // Maximum scale condition: 
       mScale = 10f; 
      ScaleAnimation scaleAnimation = new ScaleAnimation(1f/prevScale, 1f/mScale, 1f/prevScale, 1f/mScale, detector.getFocusX(), detector.getFocusY()); 
      scaleAnimation.setDuration(0); 
      scaleAnimation.setFillAfter(true); 
      ScrollView layout =(ScrollView) findViewById(R.id.scrollViewZoom); 
      layout.startAnimation(scaleAnimation); 
      return true; 
     } 
    }); 


// step 3: override dispatchTouchEvent() 
@Override 
public boolean dispatchTouchEvent(MotionEvent event) { 
    super.dispatchTouchEvent(event); 
    mScaleDetector.onTouchEvent(event); 
    gestureDetector.onTouchEvent(event); 
    return gestureDetector.onTouchEvent(event); 
} 

//step 4: add private class GestureListener 

private class GestureListener extends GestureDetector.SimpleOnGestureListener { 
    @Override 
    public boolean onDown(MotionEvent e) { 
     return true; 
    } 
    // event when double tap occurs 
    @Override 
    public boolean onDoubleTap(MotionEvent e) { 
     // double tap fired. 
     return true; 
    } 
} 

Wielkie dzięki.

+5

Kolejne życie zapisane! Kolejne piwo gwarantowane tutaj w Brazi! –

+2

Wyświetla tylko przybliżenie zbliżenia, nie przewijając po zaimplementowaniu. –

+0

Czy możesz wyjaśnić, gdzie muszę go użyć? Tworzę niestandardową klasę rozszerzającą Scrollview i umieszczam powyższy kod w tej klasie. ale to daje wyjątek init –

1

Dzięki za rozwiązanie, I wdrożone to nieco inaczej, ponieważ mój Scrollview jest wewnątrz fragmentu, a nie działania, aby przekazać całą logikę do widoku Polecam dodać dispatchTouchEvent w tym samym widoku niestandardowego przewijania:

package com.your.package; 

import android.content.Context; 
import android.util.AttributeSet; 
import android.view.GestureDetector; 
import android.view.MotionEvent; 
import android.view.ScaleGestureDetector; 
import android.view.animation.ScaleAnimation; 
import android.widget.ScrollView; 

import com.your.package.R; 

public class CustomZoomScrollView extends ScrollView { 


    // step 1: add some instance 
    private float mScale = 1f; 
    private ScaleGestureDetector mScaleDetector; 
    GestureDetector gestureDetector; 


    public CustomZoomScrollView(Context context) { 
     super(context); 
    } 

    public CustomZoomScrollView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     //step 2: create instance from GestureDetector(this step should be place into onCreate()) 
     gestureDetector = new GestureDetector(getContext(), new GestureListener()); 

     mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener() 
     { 
      @Override 
      public boolean onScale(ScaleGestureDetector detector) 
      { 
       float scale = 1 - detector.getScaleFactor(); 

       float prevScale = mScale; 
       mScale += scale; 

       if (mScale < 0.1f) // Minimum scale condition: 
        mScale = 0.1f; 

       if (mScale > 10f) // Maximum scale condition: 
        mScale = 10f; 
       ScaleAnimation scaleAnimation = new ScaleAnimation(1f/prevScale, 1f/mScale, 1f/prevScale, 1f/mScale, detector.getFocusX(), detector.getFocusY()); 
       scaleAnimation.setDuration(0); 
       scaleAnimation.setFillAfter(true); 
       getRootView().findViewById(R.id.svSeats).startAnimation(scaleAnimation); 
       return true; 
      } 
     }); 
    } 

    // step 3: override dispatchTouchEvent() 
    @Override 
    public boolean dispatchTouchEvent(MotionEvent event) { 
     super.dispatchTouchEvent(event); 
     mScaleDetector.onTouchEvent(event); 
     gestureDetector.onTouchEvent(event); 
     return gestureDetector.onTouchEvent(event); 
    } 

//step 4: add private class GestureListener 

    private class GestureListener extends GestureDetector.SimpleOnGestureListener { 
     @Override 
     public boolean onDown(MotionEvent e) { 
      return true; 
     } 
     // event when double tap occurs 
     @Override 
     public boolean onDoubleTap(MotionEvent e) { 
      // double tap fired. 
      return true; 
     } 
    } 
}