Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to implement both swipe and click over a Relative Layout in android?

enter image description here
I am creating a Relative Layout and want to add click as well as swipe(touch and move pointer over the layout to move it in real time) and detect left and right swipe. I have tried the following code so far.

public bool OnTouch(View v, MotionEvent e)
    {
        if (gestureDetector.OnTouchEvent(e))
        {
            //This is a Click
            return true;
        }
        else
        {
            int initialTouchX = 0, initialTouchY = 0;
            int newx = 0;
            var x = v.Left;
            switch (e.Action)
            {

                case MotionEventActions.Down:
                    {
                        _viewX = e.GetX();
                        _viewY = e.GetY();
                        initialTouchX = (int)e.RawX;
                        initialTouchY = (int)e.RawY;
                        break;
                    }

                case MotionEventActions.Move:
                    {

                        var left = (int)(e.RawX - _viewX);
                        newx = left;
                        var right = (int)(left + v.Width);

                        var top = (int)(e.RawY - _viewY);
                        var bottom = (int)(top + v.Height);

                        v.Layout(left, top, right, bottom);

                        break;
                    }
                case MotionEventActions.Up:
                    {
                        int lastX = (int)e.GetX();
                        int lastY = (int)e.GetY();
                       if ((x - newx) > 40)
                        {
                          //Detect Right Swipe

                        }
                        else if ((newx - x > 40))
                        {
            //Detect Left Swipe
                        }
                        else
                        {
                            //Skip others
                        }
        break;
                    }

            }
        }
        return true;
    }

My code for gestureDetector.OnTouchEvent(e)

gestureDetector = new GestureDetector(this, new SingleTapUp());

class SingleTapUp : Android.Views.GestureDetector.SimpleOnGestureListener 
    {

        public override bool OnSingleTapUp(MotionEvent e) {
           // Toast.MakeText(this,, ToastLength.Long).Show();
            return true;
        }

    }

My code is working fine on some devices as well as emulator. But not working sometimes and onclick the layout moves automatically(The layout out centers itself at touch pointer). I think something is wrong and causing the issue. You can suggest me the best/standard way to do it. Any help will be greatly appreciated.

like image 552
soumya sambit Kunda Avatar asked Oct 19 '22 00:10

soumya sambit Kunda


1 Answers

Im implementing swype in this way:

public class MainActivity : Activity, GestureDetector.IOnGestureListener
{
private GestureDetector _gestureDetector;

public bool OnDown(MotionEvent e)
    {
        return false;
    }
    public bool OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
        bool result = false;
        int SWIPE_THRESHOLD = 80;
        int SWIPE_VELOCITY_THRESHOLD = 80;
        try
        {
            float diffY = e2.GetY() - e1.GetY();
            float diffX = e2.GetX() - e1.GetX();
            if (Math.Abs(diffX) > Math.Abs(diffY))
            {
                if (Math.Abs(diffX) > SWIPE_THRESHOLD && Math.Abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
                {
                    if (diffX > 0)
                    {
                        //code for swipe right here

                    }
                    else
                    {
                        //code for swipe Left here

                    }
                }
            }
        }
        catch (Exception exception)
        {
            //exception.printStackTrace();
        }
        return result;
    }
    public void OnLongPress(MotionEvent e) {}
    public bool OnScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
        return false;
    }
    public void OnShowPress(MotionEvent e) {}
    public bool OnSingleTapUp(MotionEvent e)
    {
        return false;
    }
public override bool OnTouchEvent(MotionEvent e)
    {
        _gestureDetector.OnTouchEvent(e);
        return false;
    }

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        SetContentView (Resource.Layout.Main);
        _gestureDetector = new GestureDetector(this);

    }
}

For ViewPager you can overlap Pages with something like this PageTransformation:

using System;

using Android.Views;
using Android.Support.V4.View;

namespace SomeName
{
public class SinkAndSlideTransformer : Java.Lang.Object, ViewPager.IPageTransformer
{
public void TransformPage(View view, float position)
{
if (position < -1 || position > 1) 
{
view.Alpha = 0; // The view is offscreen.
} 
else
{
view.Alpha = 1;

if (position < 0) 
{
// 'Sink' the view if it's to the left.
// Scale the view.
view.ScaleX = 1 - Math.Abs (position);
view.ScaleY = 1 - Math.Abs (position);

// Set the translationX to keep the view in the middle.
view.TranslationX = view.Width * Math.Abs (position);
} 
}
}
}
}

Which will give this effect:
enter image description here

With this Adapter:

using System;
using System.Collections.Generic;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Support.V4.View;

using Square.Picasso;

namespace StaffPro
{
public class SlideshowPagerAdapter : PagerAdapter
{
    List<Uri> _items = new List<Uri>();
    private readonly Activity _context;

    public SlideshowPagerAdapter (Activity context, List<Uri> items) : base()
    {
        _items = items;
        _context = context;
    }
    public override int Count 
    {
        get { return _items.Count; }
    }
    public override bool IsViewFromObject(View view, Java.Lang.Object _object) 
    {
        return view == ((RelativeLayout) _object);
    }
    public override Java.Lang.Object InstantiateItem(ViewGroup container, int position)
    {
        var view = LayoutInflater.From (container.Context).Inflate (Resource.Layout.SlideshowViewPager, container, false);
        ImageView imageView = view.FindViewById<ImageView> (Resource.Id.slideshowImageView);
        Picasso.With(_context).Load(_items [position].ToString()).Into(imageView);
        container.AddView(view);

        return view;
    }
    public override void DestroyItem(ViewGroup container, int position, Java.Lang.Object _object)
    {
        container.RemoveView((View)_object);
    }
}
}

And to call the viewpages and the adapter with something like this:

var viewPagerAdapter = new SlideshowPagerAdapter(Activity, some_Uri_images);
        slideshowViewPager.Adapter = viewPagerAdapter;
        slideshowViewPager.SetPageTransformer (true, new SinkAndSlideTransformer ());

More Transformations you can find here.

Also keep in mind that the ViewPager has a method called setPageMargin(). This method can receive a negative value which will make the fragments/views to overlap each other.
You can also use view.Rotation inside your Transformation code to implement the photo randomly dropped and overlapped effect you want.
If you need to retain many images loaded and displayed check also ViewPager.OffscreenPageLimit it will override the default cache limit of storing pages for the next and previous item, be careful about high memory usage however.

like image 131
CDrosos Avatar answered Oct 21 '22 17:10

CDrosos