8

I currently have Views lined up horizontally in a ViewPager and can cycle through them with a PagerAdapter. Currently, to perform the action that I would like to do on swipe, I have to do a double-tap on the View's page. I could post code, but it's somewhat difficult to extract the necessary pieces...

What I would like is the ability to swipe vertically on these views, have them translate vertically with swipe and fade-out, and then perform an action when they reach a certain distance away from the edge of the device.

To get an idea of what I am thinking, in the Gallery app you can pinch an opened photo to zoom-out and open a horizontal filmstrip view. From there you can swipe up (or down) on a photo/video to delete it. For those who do not have the same Gallery app, it's exactly like closing applications on iOS.

I've tried scanning though the source code for the Gallery app, but no luck finding the correct Activity.

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245

3 Answers3

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

The explanation for using 1-Math.abs(y-height/2)/(height/2) is that I want alpha to be 1 when I am in the center, and alpha to be 0 when it is at the top or bottom. You have to determine yourself how you obtain the height value, or if you want to use a different method to calculate alpha. If you want to get the touch position relative to the screen instead of the position relative to the view, use getRawY().

Additionally, it may be useful for you to know that to see if the MotionEvent is a press, drag, or release event, use motion.getAction() == with MotionEvent.ACTION_UP, MotionEvent.ACTION_MOVE, and MotionEvent.ACTION_DOWN, respectively.

geokavel
  • 619
  • 4
  • 12
  • And if I want a positional change in alpha rather than a durational change? I would like the view to fade with respect to either its original position or the edge it is being swiped towards. – OneCricketeer Oct 16 '15 at 14:47
  • Updated code to reflect this. No longer uses gestures. – geokavel Oct 16 '15 at 18:17
  • Okay, then how about translating the View in the ViewPager while it fades? It looks like this code just fades the view based on the touch position. – OneCricketeer Oct 16 '15 at 19:16
  • I haven't done what you're doing specifically before, but maybe something like this will work `view.setY(y)`. Maybe that only works with certain layouts though. – geokavel Oct 16 '15 at 19:31
4

I ended up getting this working more-or-less by cloning the well-written Android-SwipeToDismiss library and just replacing the ListView code with a ViewPager.

The finished product looked like this.

end result

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • Can you post your code which you have implemented for viewpager? – Krishna Meena Apr 23 '16 at 12:22
  • As I stated in the question, it's difficult to extract a minimal code sample. There are 5 classes and 2 interfaces that are involved. I've provided the link to the library and modifying the ListView example to use a ViewPager is straightforward (in my opinion) – OneCricketeer Apr 23 '16 at 16:11
  • So you mean I just have to replace ListView with ViewPager and it will work? – Krishna Meena Apr 24 '16 at 19:42
  • More or less, yes. There are several sections that need changed to use a vertical swipe instead of a horizontal swipe. And I used a ViewPager within a Fragment, which displayed Fragment pages, so that's where the complexity started – OneCricketeer Apr 24 '16 at 19:46
  • 1
    @KrishnaMeena have you got success in this ? – DjHacktorReborn Oct 07 '16 at 07:33
1

Check the below code, this may helpful to you:

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

For animation use the below methods:

   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();
}
bhavesh N
  • 787
  • 3
  • 9
  • 27