2014-12-02 10 views
22

Najnowsza aplikacja na Facebooku na Androida ma bardzo ładne pływające okno komentarza. Tam użytkownik może odrzucić okno przesuwając w górę lub w dół, co czyni go naprawdę łatwym w użyciu.Android Aktywność ruchoma z odrzuceniem na przesunięcie

Chcę zaimplementować podobne zachowanie w mojej aplikacji, ale nie wiem, jak to zrobić. Każdy pomysł lub wskazówka, jak to zrobić, będzie naprawdę doceniony.

Zrzuty ekranu z aplikacji Facebook
(przepraszam, aplikacja Facebook skąd wziąłem zrzuty ekranu jest po japońsku) Swipe up Swipe down

+0

Zaktualizowałem swoją odpowiedź kilkoma zrzutami ekranu;) –

Odpowiedz

26

napisać trochę kodu, które odpowiadają tej zamknięcia/zmiany rozmiaru zachowanie, I don nie wiem, czy to jest droga, ale mój kod jest oparty na klasie aktywności. Pierwszą rzeczą, którą robię, jest utworzenie działania i nadanie mu motywu, aby uzyskać aktywność z przezroczystym tłem.

W moim manifest.xml:

<activity 
    android:name=".PopupActivity" 
    android:label="@string/title_activity_popup" 
    <!-- Use Translucent theme to get transparent activity background 
    and NoTitleBar to avoid super old style title bar ;) --> 
    android:theme="@android:style/Theme.Translucent.NoTitleBar"> 
</activity> 

Potem stworzyć prosty plik układu zawierającego TextView (odpowiadający Facebooku tchatting części) i widok (odpowiadający Facebook "Napisz swój msg" /” Zakładka wysłać buźkę”)

mój układ/activity_popup.xml:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/base_popup_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:padding="8dp" 
    android:background="@android:color/darker_gray" 
    android:layout_marginBottom="124dp"> 

    <TextView 
     android:text="@string/hello_world" 
     android:layout_width="match_parent" 
     android:layout_height="200dp" 
     android:background="@android:color/black"/> 

    <View 
     android:layout_width="match_parent" 
     android:layout_height="80dp" 
     android:layout_alignParentBottom="true" 
     android:background="@android:color/holo_blue_dark"/> 

</RelativeLayout> 

Wreszcie obsługuję zdarzenia dotykowego i przenoszenia w mojej klasie PopupActivity, używam funkcji onTouchListener, która zapewnia wywołanie zwrotne w metodzie onTouch.

PopupActivity

public class PopupActivity 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); 
     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; 
    } 
} 

Istnieją dwa małe metody zwane gdy użytkownik ma zwój wystarczy zamknąć okienko (tj animować i aktywność wykończenie):

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

Z całym tym kodzie powinny być jest w stanie uruchomić PopupActivity, która globalnie pasuje do wyskakujących okien na Facebooku. To tylko projekt klasy i dużo pracy do zrobienia pozostaje: dodaj animacje, prace nad parametrami zamknięcia i tak dalej ...

ekranu:

Screenshot of PopupActivity as written above

+0

Dzięki za szczegółową odpowiedź! –

+2

Dobra odpowiedź, ale nie działa, jeśli widok ma właściwość przewijania – Shah

+0

To nie działa dla mnie. –

Powiązane problemy