7

Ich habe derzeit Ansichten in einem ViewPager horizontal ausgerichtet und können mit einem PagerAdapter durch sie durchlaufen. Zur Ausführung der Aktion, die ich beim Wischen ausführen möchte, muss ich jetzt zweimal auf die Seite "Ansicht" tippen. Ich könnte Code schreiben, aber es ist etwas schwierig, die notwendigen Teile zu extrahieren ...Implementieren Sie die Funktion wie iOS App schließen vertikalen Swipe-to-Dismiss mit ViewPager

Was ich möchte, ist die Fähigkeit, vertikal auf diese Ansichten zu wischen, sie vertikal mit Swipe und Fade-Out zu übersetzen, und führen Sie dann ein Aktion, wenn sie eine bestimmte Entfernung von der Kante des Geräts erreichen.

Um eine Vorstellung davon zu bekommen, was ich denke, können Sie in der Galerie-App ein geöffnetes Foto kneifen, um es zu verkleinern und eine horizontale Filmstreifenansicht zu öffnen. Von dort können Sie auf einem Foto/Video nach oben oder unten wischen, um es zu löschen. Für diejenigen, die nicht die gleiche Galerie-App haben, ist es genau wie das Schließen von Anwendungen auf iOS.

Ich habe versucht, den Quellcode für die Galerie App zu scannen, aber kein Glück, die richtige Aktivität zu finden.

Antwort

3

landete ich diese immer arbeiten mehr oder weniger durch das Klonen gut geschrieben Android-SwipeToDismiss Bibliothek und nur den ListView-Code mit einem ViewPager ersetzen.

Das fertige Produkt sah so aus.

end result

+0

Können Sie Ihren Code posten, den Sie für Viewpager implementiert haben? –

+0

Wie ich in der Frage gesagt habe, ist es schwierig, ein minimales Codebeispiel zu extrahieren. Es gibt 5 Klassen und 2 Schnittstellen, die beteiligt sind. Ich habe den Link zur Bibliothek zur Verfügung gestellt und das ListView-Beispiel geändert, um einen ViewPager zu verwenden ist einfach (meiner Meinung nach) –

+0

Also meinst du, ich muss nur ListView durch ViewPager ersetzen und es wird funktionieren? –

4
view.setOnTouchListener(new View.OnTouchListener(){ 
    public boolean onTouch(View v, MotionEvent motion) { 
     float y = motion.getY(); 
     /* NOTE: the following line might need to be in runOnUiThread() */ 
     view.animate().alpha(1-Math.abs(y-height/2)/(height/2)).setDuration(50).start(); 
     return true; //false if you want to pass this event on to other listeners 
    } 
}); 

Die Erklärung für 1-Math.abs(y-height/2)/(height/2) ist, dass ich alpha will 1 sein, wenn ich in der Mitte bin und alpha 0 sein, wenn es an der Ober- oder Unterseite ist. Sie müssen selbst bestimmen, wie Sie den Wert height erhalten, oder ob Sie eine andere Methode zur Berechnung von Alpha verwenden möchten. Wenn Sie anstelle der Position relativ zur Ansicht die Berührungsposition relativ zum Bildschirm erhalten möchten, verwenden Sie .

Zusätzlich kann es sinnvoll sein, für Sie zu sehen, dass wissen, ob die Motion eine Presse ist, ziehen, oder ein Ereignis freigeben, verwenden motion.getAction() == mit MotionEvent.ACTION_UP, MotionEvent.ACTION_MOVE und MotionEvent.ACTION_DOWN sind.

+0

Und wenn ich eine Positionsänderung in alpha wollen eher als ein durational ändern? Ich möchte, dass die Ansicht entweder in Bezug auf ihre ursprüngliche Position oder die Kante, zu der sie hinübergeschwungen wird, verblasst. –

+0

Aktualisierter Code, der dies widerspiegelt. Benutzt keine Gesten mehr. – geokavel

+0

Okay, wie wäre es dann, die View im ViewPager zu übersetzen, während sie verblasst? Es sieht so aus, als ob dieser Code nur die Ansicht basierend auf der Berührungsposition verblasst. –

1

den Code unten überprüfen, dies hilfreich sein für Sie:

public class MainActivity extends Activity implements View.OnTouchListener{ 

    private RelativeLayout baseLayout; 

    private int previousFingerPosition = 0; 
    private int baseLayoutPosition = 0; 
    private int defaultViewHeight; 

    private boolean isClosing = false; 
    private boolean isScrollingUp = false; 
    private boolean isScrollingDown = false; 

    @Override 
    protected void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_popup); 
     baseLayout = (RelativeLayout) findViewById(R.id.base_popup_layout);//this is the main layout 
     baseLayout.setOnTouchListener(this); 
    } 


    public boolean onTouch(View view, MotionEvent event) { 

     // Get finger position on screen 
     final int Y = (int) event.getRawY(); 

     // Switch on motion event type 
     switch (event.getAction() & MotionEvent.ACTION_MASK) { 

      case MotionEvent.ACTION_DOWN: 
       // save default base layout height 
       defaultViewHeight = baseLayout.getHeight(); 

       // Init finger and view position 
       previousFingerPosition = Y; 
       baseLayoutPosition = (int) baseLayout.getY(); 
       break; 

      case MotionEvent.ACTION_UP: 
       // If user was doing a scroll up 
       if(isScrollingUp){ 
        // Reset baselayout position 
        baseLayout.setY(0); 
        // We are not in scrolling up mode anymore 
        isScrollingUp = false; 
       } 

       // If user was doing a scroll down 
       if(isScrollingDown){ 
        // Reset baselayout position 
        baseLayout.setY(0); 
        // Reset base layout size 
        baseLayout.getLayoutParams().height = defaultViewHeight; 
        baseLayout.requestLayout(); 
        // We are not in scrolling down mode anymore 
        isScrollingDown = false; 
       } 
       break; 
      case MotionEvent.ACTION_MOVE: 
       if(!isClosing){ 
        int currentYPosition = (int) baseLayout.getY(); 

        // If we scroll up 
        if(previousFingerPosition >Y){ 
         // First time android rise an event for "up" move 
         if(!isScrollingUp){ 
          isScrollingUp = true; 
         } 

        // Has user scroll down before -> view is smaller than it's default size -> resize it instead of change it position 
        if(baseLayout.getHeight()<defaultViewHeight){ 
         baseLayout.getLayoutParams().height = baseLayout.getHeight() - (Y - previousFingerPosition); 
         baseLayout.requestLayout(); 
        } 
        else { 
         // Has user scroll enough to "auto close" popup ? 
         if ((baseLayoutPosition - currentYPosition) > defaultViewHeight/4) { 
          closeUpAndDismissDialog(currentYPosition); 
          return true; 
         } 

         // 
        } 
        baseLayout.setY(baseLayout.getY() + (Y - previousFingerPosition)); 

       } 
       // If we scroll down 
       else{ 

        // First time android rise an event for "down" move 
        if(!isScrollingDown){ 
         isScrollingDown = true; 
        } 

        // Has user scroll enough to "auto close" popup ? 
        if (Math.abs(baseLayoutPosition - currentYPosition) > defaultViewHeight/2) 
        { 
         closeDownAndDismissDialog(currentYPosition); 
         return true; 
        } 

        // Change base layout size and position (must change position because view anchor is top left corner) 
        baseLayout.setY(baseLayout.getY() + (Y - previousFingerPosition)); 
        baseLayout.getLayoutParams().height = baseLayout.getHeight() - (Y - previousFingerPosition); 
        baseLayout.requestLayout(); 
       } 

       // Update position 
       previousFingerPosition = Y; 
      } 
      break; 
     } 
     return true; 
    } 
} 

Für Animation unten Methoden verwenden:

public void closeUpAndDismissDialog(int currentPosition){ 
    isClosing = true; 
    ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(baseLayout, "y", currentPosition, -baseLayout.getHeight()); 
    positionAnimator.setDuration(300); 
    positionAnimator.addListener(new Animator.AnimatorListener() 
    { 
     . . . 
     @Override 
     public void onAnimationEnd(Animator animator) 
     { 
      finish(); 
     } 
     . . . 
    }); 
    positionAnimator.start(); 
} 

public void closeDownAndDismissDialog(int currentPosition){ 
    isClosing = true; 
    Display display = getWindowManager().getDefaultDisplay(); 
    Point size = new Point(); 
    display.getSize(size); 
    int screenHeight = size.y; 
    ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(baseLayout, "y", currentPosition, screenHeight+baseLayout.getHeight()); 
    positionAnimator.setDuration(300); 
    positionAnimator.addListener(new Animator.AnimatorListener() 
    { 
     . . . 
     @Override 
     public void onAnimationEnd(Animator animator) 
     { 
      finish(); 
     } 
     . . . 
    }); 
    positionAnimator.start(); 
} 
+0

Ich vermute, das BaseLayout kann ViewPager anstelle von LinearLayout sein? Ist es auch wichtig, ob mein ViewPager, mit dem ich das versuche, in einem Fragment enthalten ist? –

+0

baseLayout ist die Stammelternansicht in Ihrem XML-Layout –

+0

Ich möchte nicht, dass die gesamte Aktivität verschoben wird, sondern nur die einzelne Ansicht, die derzeit vom ViewPager angezeigt wird. –

Verwandte Themen