GithubHelp home page GithubHelp logo

diolor / swipecards Goto Github PK

View Code? Open in Web Editor NEW
2.3K 87.0 586.0 18.93 MB

A Tinder-like Android library to create the swipe cards effect. You can swipe left or right to like or dislike the content.

License: Apache License 2.0

Java 100.00%

swipecards's Introduction

Swipecards

Travis master: Build Status

A Tinder-like cards effect as of August 2014. You can swipe left or right to like or dislike the content. The library creates a similar effect to Tinder's swipable cards with Fling animation.

It handles greatly asynchronous loading of adapter's data and uses the same layout parameters as FrameLayout (you may use android:layout_gravity in your layout xml file).


Installation

Maven Central

Go ahead find the latest version on Gradle please cowboy! Be sure to add the @aar suffix.

dependencies {
    compile 'com.lorentzos.swipecards:library:X.X.X@aar'
}

Example

The example is quite straightforward and documented in comments. You may find it under the relevant directory.

//implement the onFlingListener
public class MyActivity extends Activity {
    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        //add the view via xml or programmatically
        SwipeFlingAdapterView flingContainer = (SwipeFlingAdapterView) findViewById(R.id.frame);

        al = new ArrayList<String>();
        al.add("php");
        al.add("c");
        al.add("python");
        al.add("java");

        //choose your favorite adapter
        arrayAdapter = new ArrayAdapter<String>(this, R.layout.item, R.id.helloText, al );
        
        //set the listener and the adapter
        flingContainer.setAdapter(arrayAdapter);
        flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {
            @Override
            public void removeFirstObjectInAdapter() {
                // this is the simplest way to delete an object from the Adapter (/AdapterView)
                Log.d("LIST", "removed object!");
                al.remove(0);
                arrayAdapter.notifyDataSetChanged();
            }

            @Override
            public void onLeftCardExit(Object dataObject) {
                //Do something on the left!
                //You also have access to the original object.
                //If you want to use it just cast it (String) dataObject
                Toast.makeText(MyActivity.this, "Left!", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onRightCardExit(Object dataObject) {
                Toast.makeText(MyActivity.this, "Right!", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAdapterAboutToEmpty(int itemsInAdapter) {
                // Ask for more data here
                al.add("XML ".concat(String.valueOf(i)));
                arrayAdapter.notifyDataSetChanged();
                Log.d("LIST", "notified");
                i++;
            }
        });
        
        // Optionally add an OnItemClickListener
        flingContainer.setOnItemClickListener(new SwipeFlingAdapterView.OnItemClickListener() {
            @Override
            public void onItemClicked(int itemPosition, Object dataObject) {
                makeToast(MyActivity.this, "Clicked!");
            }
        });
    }
}

You can alternatively use a helpful method which sets in one line both the listeners and the adapter.

    // where "this" stands for the Context
    flingContainer.init(this, arrayAdapter);

Adding buttons is easy. Get the top card listener and trigger manually the right or left animation. On the end of the animation the above listeners (e.g. removeFirstObjectInAdapter) will be triggered depending on the direction.

    /**
     * Trigger the right event manually.
     */
    flingContainer.getTopCardListener().selectRight();

Tip: If you start a new Activity in the onItemClicked you will probably want to avoid double activity instances. If so these solutions might work for you: 1, 2 and I personally prefer 3

Configuration

You can optionally specify some attrs for the animation and the stack. The easiest way is in xml:

<com.lorentzos.flingswipe.SwipeFlingAdapterView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:rotation_degrees="16"
    app:max_visible="4"
    app:min_adapter_stack="6" />

Or use styles:

<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="SwipeFlingStyle">@style/SwipeFling</item>
</style>
  • rotation_degrees: the degrees of the card rotation offset
  • max_visible: the max visible cards at the time
  • min_adapter_stack: the min number of objects left. Initiates onAdapterAboutToEmpty() method.

License

   Copyright 2014 Dionysis Lorentzos

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

Android Arsenal

swipecards's People

Contributors

diolor avatar dwang999 avatar mg6maciej avatar qichuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swipecards's Issues

Feature request: Swipe direction

Firstly., i think this is an absolutely great library!

I was wondering if it is possible to make the swipe direction more generic. Right now, its only left and right, but what if it provided up and down or maybe all 4, splitting the screen into 4 quadrants.

onLeftCardExit
onRightCardExit
onUpCardExit
onDownCardExit

If we need to make it even more flexible, we could register the exit listener between angles. Like 0-180 would be right. or 45-135 could be right in the quadrant system, etc etc.

Event when new card at top

The listener should also listen to when a new card is on top so you can for example start loading a video or someting!

Using this trough fragment.

Hi there, Is it possible to use this through fragment? I'id know how to. :D

Im sorry about this. Im just a bit retarded and if you declare the library on the layout and recover it on the rootView, this works perfectly. Ty mate, this really will improve my app.

Throw card on clicking button

how to throw the card left or right on clicking a button. (Eg. Similar to tinder application where we have two buttons)

Incorrect Draw

Hi, Diolor,

 First, thanks for your project. I find one problem, but I can't find the solution, could you give some help. The problem is as shown in follow image.

device-2015-01-14-165937

ScrollView onScrollListener triggers the card underneath

I use a ScrollView in my layout and when scrolling I'm opening a mapview but it happens on the card behind the visible one.

I will upload code tomorrow if it's required to explain what is wrong.

Edit: There is no need for code. Basically it's using the front card but its calling onScroll from the back one.

A Bug In Example

Hello:
The author has done a great job.
There is a bug in the example, In MyActivity, line 85, the override function onScroll(). If a person swipes a view out by action_up and quickly touch on that view before it escape. Then it will incur the onScroll() function, but flingContainer.getSelectedView() returns null which will lead to a NullPointerException. Add a judgement will fix this bug. Please forgive my poor English.

Image on card underneath is not displayed when card above is partially swiped.

Hi Diolor, first of, awesome library.

I am using this library with images and some text. The issue is when a card is partially swiped, the image in the card underneath is not drawn. The image gets drawn only after the card above is fully swiped. This is not the case for the text underneath, the text is shown when the card is partially swiped. I want this behavior to apply for the image also.

I'm trying to achieve something where you can sneak peek fully what's below the card.

Please let me know if there's a solution to this.

Cheers

Issue when using ViewStub in card

Hi all,

I have a complicated View to be shown when user click on the card, thus I use the ViewStub layout as recommended by Google, and invoke ViewStub.inflate() on the touch event (via OnItemClickListener).

However the inflated view is never displayed (the height and width are both 0).

The xml layout file for the card item is shown below.

<FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentTop="true"
            android:layout_marginBottom="40dp">

            <ViewStub
                android:id="@+id/stub_photo_grid"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

            <ImageView
                android:id="@+id/img_profile"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:visibility="visible" />
        </FrameLayout>

I have tried other AdatperView such as ListView and RecyclerView, the inflated view is correctly shown, therefore I think this could be a issue with swipecards library.

Any comments or suggestions are appricated!

Card's exit position

The exit position of the card needs a simple fix. I will fix this during the next few days, time permitted.

Changing the minSDK to 9

I was wondering if it would be possible to change the min SDK to 9.
I'm making an app which needs to work with lower SDK phone whereas the library requires minSDK 14.
Thankyou.

Adapter does not visible

Hi, I try to implement your gradle libs to me project, but i have a little issue, SwipeFlingAdapterView does not visible in me view. I created custom BaseAdapter and set up it

swipeFlingAdapterView.setAdapter(adapter);

but nothing to show in layout except button

Showing as stack of cards

Hello,

How am I supposed to show the cards a stack of cards one after the another. Any suggestions?

Removes two cards on double click and swipe.

I have just tried out the library and it looks really cool. However, there is something that I don't like and would like to fix it. I followed the example from https://github.com/Diolor/Swipecards/blob/master/example/src/main/java/com/lorentzos/swipecards/MyActivity.java

When I double click on a card and swipe (even sometimes one click and swipe), I get a null pointer exception in the onScroll method. Tried removing it and now when I do a double click and swipe, two cards disappear at once. The error I got was:

12-17 20:55:20.702    2283-2283/com.testproject  E/InputEventReceiver﹕ Exception dispatching input event.
12-17 20:55:20.702    2283-2283/com.testproject  E/MessageQueue-JNI﹕ Exception in MessageQueue callback: handleReceiveCallback
12-17 20:55:20.702    2283-2283/com.testproject  E/MessageQueue-JNI﹕ java.lang.NullPointerException

And when I tried just to print what was happening. I got:

12-17 21:00:15.218    2370-2370/com.testproject D/LIST﹕ Scroll: 0.27310812
12-17 21:00:15.234    2370-2370/com.testproject D/LIST﹕ Scroll: 0.5979347
12-17 21:00:15.250    2370-2370/com.testproject D/LIST﹕ Scroll: 1.0
12-17 21:00:15.266    2370-2370/com.testproject D/LIST﹕ Scroll: 1.0
12-17 21:00:15.266    2370-2370/com.testproject D/LIST﹕ removed object!
12-17 21:00:15.266    2370-2370/com.testproject D/LIST﹕ Right!
12-17 21:00:15.266    2370-2370/com.testproject D/LIST﹕ Scroll: 1.0
12-17 21:00:15.386    2370-2370/com.testproject D/LIST﹕ removed object!
12-17 21:00:15.386    2370-2370/com.testproject D/LIST﹕ Right!

It seems like a really simple bug, but it is annoying and I would like some help on how I can fix it. Looks like the removeFirstObjectInAdapter function get called twice. A really simple fix would be to change it to something like:

            public void removeFirstObjectInAdapter() {
                // this is the simplest way to delete an object from the Adapter (/AdapterView)
                long time = System.currentTimeMillis();
                if (time - last_delete > 200) {
                    Log.d("LIST", "removed object!");
                    al.remove(0);
                    last_delete = time;
                }
                arrayAdapter.notifyDataSetChanged();
            }

However, it doesn't look very reliable. Please help me fix this?

AlertDialog invalidates FlingListener

Showing a AlertDialog and after dismissing it, the SwipeFlingAdapterView has no listener.

Even in OnDismissListener this does not help:

fling.init( activity, adapter );
fling.setFlingListener( activity );

If I leave the activity and come back it works so it seems it has nothing to do with the activity. If the listener has stopped working and I go into another activity and back it still does not work.

Edit:
onScroll is not being called after dismissing the dialog.

Top card doesn't change on NotifyDataSetChanges

I am using an arraylist in my adapter as the data source for the cards. On a button toggle, I have to change the cards displayed. Hence I call the clear() function of my array and then do an addAll() with the required data. Followed by a call to the adapters notifyDataSetChanged()

The data does change but the first card is the same as what i saw before the button toggle. on swiping away this card I see that the next card is the second card of my second list(and same for the 3rd,4th etc hence I conclude the data has changed). But why didn't the first card refresh to show the new list?

Complex card views result in skipped frames

Animation stutters and logcat also reports skipped frames when using complexer card views.

I/Choreographer﹕ Skipped 50 frames! The application may be doing too much work on its main thread.

Any idea how to fix this? Txn! Great library BTW!

Dynamically Changing Swipecard Height Width during runtime

Hi,
I want to have a square imageview in my swipecard. I am fetching screen dimensions during runtime and want to change the swipecard dimension accordingly.
I tried to input a LayoutParams in the imageview in getView() but it doesn't seem to work.

Any way I can make it work?

onAdapterAboutToEmpty is called at the wrong time

In the SwipeFlingAdapterView there is a line:

if(adapterCount < MAX_VISIBLE) mFlingListener.onAdapterAboutToEmpty(adapterCount);

Instead it should be if(adapterCount <= MIN_ADAPTER_STACK) mFlingListener.onAdapterAboutToEmpty(adapterCount);.

Also as a side note, it would be really useful to merge pull request #18. Thanks.

Why my first card's position is a little bit lower than those behind?

When I open my demo, the first card is always lower than others.
And then I swipe away the first card, the rest of them is in the correct position.

In the method named makeAndAddView, the childTop value is diffent than those behind.
Is it the ActionBar play a part of this?
qq 20150311162714

how to create stack.

I want to create a stack of 3 cards to be shown at once i.e little layer of below card to be shown.
So user get to know that there is more cards below.

Your library do have methods of class SwipeFlingAdapterView but these doesn't work or this indicate something different that I am not able to understand.

  1. setMinStackInAdapter(3);
  2. setMaxVisible(3);

Please help if there is any method regarding this.

Thanks in Advance.

Redraw

Hi.

I've tried using this with a custom BaseAdapter and custom views. The views have an ImageView in them, and I am using AsyncTask to populate them with downloaded images. As soon as I load an image into the ImageView, all the views are inflated again, and it's an infinite loop.
As soon as I take out the image loading, everything works ok.

I've attached the sources below,

Main layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black">

    <com.lorentzos.flingswipe.SwipeFlingAdapterView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/adapterView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:rotation_degrees="16"
        app:max_visible="10"
        app:min_adapter_stack="4" />

</LinearLayout>

Main activity:

public class TestActivity extends Activity {

    public final static String TAG = "TEST_ACTIVITY";

    private TestAdapter testAdapter;
    private SwipeFlingAdapterView adapterView;

    private ArrayList<String> itemsList;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        Log.i(TAG, "onCreate");

        itemsList = new ArrayList<String>();
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");
        itemsList.add("http://logo.png");

        adapterView = (SwipeFlingAdapterView) findViewById(R.id.adapterView);

        testAdapter = new TestAdapter(TestActivity.this, itemsList);
        adapterView.setAdapter(testAdapter);
        adapterView.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {

            @Override
            public void removeFirstObjectInAdapter() {
                // this is the simplest way to delete an object from the Adapter (/AdapterView)
                Log.d("LIST", "removed object!");
                //al.remove(0);
                itemsList.remove(0);
                testAdapter.notifyDataSetChanged();
            }

            @Override
            public void onLeftCardExit(Object dataObject) {
                //Do something on the left!
                //You also have access to the original object.
                //If you want to use it just cast it (String) dataObject

                Toast.makeText(TestActivity.this, "Left", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onRightCardExit(Object dataObject) {

                Toast.makeText(TestActivity.this, "Right", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAdapterAboutToEmpty(int itemsInAdapter) {
                // Ask for more data here
                Log.d(TAG, "loading more items");
                //al.add("XML ".concat(String.valueOf(i)));
                testAdapter.notifyDataSetChanged();
                Log.d("LIST", "notified");
                //i++;
            }
        });
    }
}

Custom view for the adapter:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="10dp"
        android:paddingBottom="60dp"
        android:paddingLeft="5dp"
        android:paddingRight="5dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="5dp"
            android:orientation="vertical">

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="200dp">

                <ImageView
                    android:id="@+id/testView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scaleType="center" />

            </FrameLayout>

        </LinearLayout>

    </FrameLayout>

</RelativeLayout>

The adapter:

public class TestAdapter extends BaseAdapter {

    public final static String TAG = "TEST_ADAPTER";

    private Context context;
    private ArrayList<String> items;
    protected ViewHolder holder;

    public TestAdapter (Context context, ArrayList<String> items) {

        this.context = context;
        this.items = items;
    }

    /**
     *  add one item to list
     */
    public void add(String item) {
        this.items.add(item);
    }

    /**
     *  add one item to list
     */
    public void add(int position, String item) {
        this.items.add(position, item);
    }

    /**
     *  remove one item from list
     */
    public void remove(String item) {
        this.items.remove(item);
    }

    public void clear() {
        this.items.clear();
    }

    @Override
    public int getCount() {
        return this.items.size();
    }

    @Override
    public String getItem(int position) {
        return this.items.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @SuppressWarnings("deprecation")
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        final String item = getItem(position);

        Log.d(TAG, "item: " + item + ", position: " + position);

        View view = convertView;

        if (view == null) {

            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            view = inflater.inflate(R.layout.test_view, parent, false);

            holder = new ViewHolder();

            holder.testView = (ImageView) view.findViewById(R.id.testView);

            view.setTag(holder);

        } else {
            holder = (ViewHolder) view.getTag();
        }

        // load the image
        if (item != null && !item.equals("")) {
            new LoadImage(holder).execute(item);
        }

        return view;
    }

    public class ViewHolder {
        ImageView testView;
    }

    private class LoadImage extends AsyncTask<String, Void, Bitmap> {

        private ViewHolder holder;

        public LoadImage(ViewHolder holder) {
            this.holder = holder;
        }

        @Override
        protected Bitmap doInBackground(String... params) {

            Bitmap bmp = null;
            try {
                URL urlValue = new URL(params[0]);
                bmp = BitmapFactory.decodeStream(urlValue.openConnection().getInputStream());
                if (bmp != null) {
                    return bmp;
                }
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap bmp) {

            if (bmp != null) {
                holder.testView.setImageBitmap(bmp);
            }
        }
    }

}

Sorry for the long text, it's as detailed as possible :)

Any suggestions?

IllegalArgumentException

Sometime app throws IllegalArgumentException

java.lang.IllegalArgumentException: pointerIndex out of range
    at android.view.MotionEvent.nativeGetAxisValue(Native Method)
    at android.view.MotionEvent.getX(MotionEvent.java:1983)
    at com.lorentzos.flingswipe.FlingCardListener.onTouch(FlingCardListener.java:78)
    at android.view.View.dispatchTouchEvent(View.java:8382)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2424)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2158)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2314)
    at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1692)
    at android.app.Activity.dispatchTouchEvent(Activity.java:2739)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2275)
    at android.view.View.dispatchPointerEvent(View.java:8578)
    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4021)
    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3887)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5701)
    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5675)
    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5646)
    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5791)
    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
    at android.os.MessageQueue.nativePollOnce(Native Method)
    at android.os.MessageQueue.next(MessageQueue.java:143)
    at android.os.Looper.loop(Looper.java:122)
    at android.app.ActivityThread.main(ActivityThread.java:5221)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

More user guides

Hi all, not so much a bug but as a new developer I find it hard to extend this much beyond the example. It would be great to see some example code/a bit more explanation on perhaps how images could be added and what not.

I am going to try and work through it and create some sort of sample project, but I am not sure I'll be able to. Any help with this I believe would be appreciated by the wider android community.

edit: These are the main questions I had whilst trying to get the example working. I will work on it over the weekend and see if I can answer any myself but if anyone can provide answers I'd appreciate it. Perhaps then we could then put them into a guide for future reference.

Could you have different item.xml per card? How would this be achieved? (I have a feeling this would be done with array adapter, but I am not familiar with them and am not sure how to do it).

(Linked to above) Could each card contain a different layout? what layout is suitable to put onto a card? how would you achieve this?

Could you have a stack of google now style cards (perhaps https://github.com/afollestad/Cards-UI)?

I think if someone can help me answer the first question, I can answer the ones that follow.

-Matt

SwipeFlingAdapterView not swipable anymore after 1 card swipped

Hi guys,

First, thank you for the library, it's the best one I've come across searching for a Tinder-like swipe card effect, and I have to say I'm impressed by the good work here :)

I'm setting up my own SwipeFlingAdapterView with a custom ArrayAdapter of my own, nothing special.

But the problem I have is that the SwipeFlingAdapterView stop being interactive after I successfuly swipe one card.

After I swipped the first card, I can see the 2nd card underneath, but it's like an image, it's frozen, the 2nd card won't move.

The only way I can get my SwipeFlingAdapterView to become interactive again is to go somewhere else in my app (different fragment) and come back in order for the 2nd card to be interactive as expected.

I tried several workarounds, here is my latest (unsuccessful) attempt of modifying removeFirstObjectAdapter :

        public void removeFirstObjectInAdapter() {
            if (swipeAdapter.getItem(0) != null){
                nManager.getProfilePool().remove(0);
            }
            synchronized (swipeAdapter){
                swipeAdapter.notifyAll();
                swipeFlingAdapterView.setAdapter(swipeFlingAdapterView.getAdapter());
            }
        }

Any idea ? :)
Thanks for your help :)

PS : I don't know if it's related to #39 or not but right after initialization of my SwipeFlingAdapterView, I sometime see the library spamming the adapter with "getView" method call.

AntiAliasing when Moving the Card?

hey,man
I'm using this awsome library these days.And I find that at the MotionEvent.Action_Move event,when the frame's rotation is large,the frame has antialiasing.Because of this,the card looks not so beautiful.
I know this is not a bug.Maybe it's a enhance?
image

Change visibility of a LinearLayout in the top card view

Hi,

I try to change a linearlayout visibility contained in the top selected view of my SwipeFlingAdapterView by clicking a button also contained in the the top selected view.

So there in my onClick method :

         vh.mOtherShowTimesLayout.setVisibility(View.GONE);

        vh.mTimeRemaining.setText("" + ApplicationUtils.getTimeString(bst.mTimeRemaining));
        vh.mMovieTitle.setText(mResult.mMovies.get(bst.mMovieId).title);
        vh.mTheaterName.setText(mResult.mTheaters.get(bst.mTheaterId).mName);

        vh.showOtherShowTimesButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Log.d("Clicked : ", "" + ((ViewHolder)mFeedContainer.getSelectedView().getTag()).mMovieTitle.getText());
                if ( mFeedContainer.getSelectedView().findViewById(R.id.movieShowTimesLayout).getVisibility() == View.GONE) {
                    mFeedContainer.getSelectedView().findViewById(R.id.movieShowTimesLayout).setVisibility(View.VISIBLE);
                } else {
                    mFeedContainer.getSelectedView().findViewById(R.id.movieShowTimesLayout).setVisibility(View.GONE);
                }
                Log.d("Visibility", "" +  mFeedContainer.getSelectedView().findViewById(R.id.movieShowTimesLayout).getVisibility());
                mFeedContainer.invalidate();
            }
        });

I try to do a notifyDatasetChanged of my adapter, but the first item is removed when the adapter is set :

public void removeFirstObjectInAdapter() {
    // this is the simplest way to delete an object from the Adapter (/AdapterView)
    mNextMovies.remove(0);
    mFeedAdapter.notifyDataSetChanged();
}

Card drawn incorrectly when starting to move it

Hey Dionysis,
I've have just tried to use your lib and encountered an issue, which is best explained with a screenshot: screenshot_2014-10-21-16-23-06

After the image is loaded with Picasso it looks correct:
screenshot_2014-10-21-16-23-26

Only when I start moving it around, it looks like on the first screenshot or goes totally blank.

Have you ever encountered this issue? I made a simple test and just returned #ff0000 colored View from Adapter.getView and it's the same. This happens on Nexus 5. On Genymotion the issue does not appear, but there is another glitch.

Swiping in ViewPager

I tried including this view within a ViewPager, but the swiping mechanism is buggy. It'll only swipe right if the page is the first in the PagerAdapter and left if the page is the last in the PagerAdapter. Is there any workaround for this, or are you planning on implementing this feature anytime in the near future?

Card not exiting on Android version 4.1.2

Hello,

First of all thanks for developing such a great library. Unfortunately I am having some problems on Android version 4.1.2. When I swipe a card, the card is not exiting. It is moving through half of the screen, but it is hanging such a way that the card is displayed as rotated. It does not change until I touch the card again and try to put it out of the screen with more than one swipe gestures.

Do you have any idea about this issue?

Regards.

glEndTilingQCOM: 0x502

Hello:

When I drag view, there is keeping printing following error: com.lorentzos.swipecards.example E/﹕ glEndTilingQCOM: 0x502. Is there anything wrong?

Conflict with Picasso

It looks like there is a conflict with Picasso:
If you initiate Picasso in the getView method of the adapter it requests the container (FlingSwipeAdapterView) continuously.

This will sap down the performance but the user probably will not notice it.

Will investigate more.

How to add a onClickListener?

Hi @Diolor

Thanks for this wonderful library. Awesome!

In my application I can swipe left, and right and I would like to add a listener to click in the card and call some action.

Is this possible?

ArrayAdapter<Pair<String, String>> instead of ArrayAdapter<String>

Sorry, this isn't a bug but more like a feature implementation question.
I'm not very experimented in android dev: I managed to pass the Pair value, but it shows me that:
untitled
how/where can I override this behavior in order to access the child value instead ?
Id like to keep an array or object instead of simple string so I can gather informations on Swiped values

Cards not displaying properly

I tried creating a dummy example with 6 cards which only contain text. This is what they look like:
screen shot 2014-11-12 at 8 56 56 pm

xml:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyApp">

    <com.lorentzos.flingswipe.SwipeFlingAdapterView
        android:id="@+id/explore_cards"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#eee9e2"
        />

</RelativeLayout>

build.grade:

compile 'com.android.support:support-v4:18.0.+'
compile 'com.android.support:appcompat-v7:18.0.+'
compile 'com.lorentzos.swipecards:library:1.0.7@aar'

relevant pieces of java:

SwipeFlingAdapterView swipeView = (SwipeFlingAdapterView) v.findViewById(R.id.explore_cards);
tempArray = new ArrayList<String>();
tempArray.add("hi");
tempArray.add("hey");
tempArray.add("yo");
tempArray.add("blah");
tempArray.add("hin");
tempArray.add("heeeee");
swipeView.setAdapter(arrayAdapter);
swipeView.setFlingListener(this);

...........

@Override
public void removeFirstObjectInAdapter() {
    Log.i(LOG_TAG, "REMOVE FIRST");
    tempArray.remove(0);
    arrayAdapter.notifyDataSetChanged();;
}

@Override
public void onLeftCardExit(Object o) {
    Log.i(LOG_TAG, "EXIT LEFT");
}

@Override
public void onRightCardExit(Object o) {
    Log.i(LOG_TAG, "EXIT RIGHT");
}

@Override
public void onAdapterAboutToEmpty(int i) {
    Log.i(LOG_TAG, "ABOUT TO EMPTY");
}

I suppose it's also worth mentioning that this is all placed inside a (support) Fragment. I also get a message in my XML file stating 'Failed to find style 'SwipeFlingStyle' in current theme'

Any help would be appreciated, thanks a bunch!

onItemClick not firing

I'm currently testing the library before integrating it in a project I'm working on. I've came across a problem - onItemClickListener doesn't seem to fire when items are clicked. I've checked the sources and couldn't spot the problem. Below is (part of) my code

    searchWidget = (SwipeFlingAdapterView) v.findViewById(R.id.search_widget);
    searchWidget.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick (AdapterView<?> parent, View view, int position,
                long id) {
            Log.t("clicked " + position);
        }
    });

    searchWidget.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {
        @Override
        public void removeFirstObjectInAdapter () {
            results.remove(0);
            adapter.notifyDataSetChanged();
        }

        @Override
        public void onLeftCardExit (Object o) {
          //Unrelated code
        }

        @Override
        public void onRightCardExit (Object o) {
                            //Unrelated code
    }


        @Override
        public void onAdapterAboutToEmpty (int i) {
          //Unrelated code
        }

        @Override
        public void onScroll (float v) {
        }
    });

    searchWidget.setAdapter(adapter);
    searchWidget.setEmptyView(v.findViewById(android.R.id.empty));

The item's XML: (GitHub seems to cut some of it, anyway just so you know the root is a relative layout)

<ImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/quick_view_picture"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:src="@drawable/default_car"
    android:scaleType="centerCrop"
    android:layout_above="@+id/quick_view_title"/>


<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:text="@string/price"
    android:singleLine="true"
    android:id="@+id/quick_view_price"
    android:background="#4c4e53"
    android:textColor="@android:color/white"
    fontPath="@string/font_light"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:layout_marginBottom="30dp"
    android:paddingBottom="8dp"
    android:paddingTop="8dp"
    android:layout_alignBottom="@+id/quick_view_picture"
    android:layout_alignLeft="@+id/quick_view_picture"
    android:layout_alignStart="@+id/quick_view_picture"/>


<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:layout_centerHorizontal="true"
    android:id="@+id/quick_view_info_wrapper"
    android:orientation="horizontal"
    android:layout_alignParentBottom="true"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawablePadding="2dp"
        android:layout_marginTop="1dp"
        android:gravity="center"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textSize="18sp"
        android:textColor="#808080"
        fontPath="@string/font_light"
        android:id="@+id/quick_view_location"
        android:layout_marginRight="10dp"
        android:layout_marginEnd="10dp"
        android:drawableLeft="@drawable/ic_location_med"
        android:drawableStart="@drawable/ic_location_med"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dp"
        android:layout_marginLeft="10dp"
        android:gravity="center"
        android:layout_marginStart="10dp"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textSize="18sp"
        android:drawablePadding="4dp"
        android:textColor="#808080"
        android:id="@+id/quick_view_likes"
        fontPath="@string/font_light"
        android:drawableLeft="@drawable/ic_like_med"
        android:drawableStart="@drawable/ic_like_med"
        />

</LinearLayout>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:layout_marginTop="16dp"
    fontPath="@string/font_light"
    android:textSize="23sp"
    android:layout_above="@+id/quick_view_info_wrapper"
    android:id="@+id/quick_view_title"
    android:layout_centerHorizontal="true"/>


<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceSmall"
    android:layout_marginRight="10dp"
    android:layout_marginTop="10dp"
    android:layout_marginEnd="10dp"
    android:gravity="center"
    android:id="@+id/quick_view_pic_count"
    android:layout_alignParentTop="true"
    android:textColor="@android:color/white"
    android:drawableLeft="@drawable/ic_camera_med"
    android:drawableStart="@drawable/ic_camera_med"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"/>

Any hints?

Customizable Layouts

At the moment you can only give one layout and a block of text to the library.
It'd be good to have at least two of them - one background image (drawable) and the text.
Or just get any more open API to let us customize it ourself, like just giving a handler that also customizes the design.

Spammy Errors

About every second i actively use the Library in the App, i get about 1-5 error messages with the following pattern:

01-30 00:26:03.126 3211-3211/name.of.my.app E/ClipboardServiceEx﹕ clipEx is android.sec.clipboard.ClipboardExManager@1874208
01-30 00:26:03.126 3211-3211/name.of.my.app E/ClipboardServiceEx﹕ clipEx has text data : false

I use Android 5.0 on Samsung S5. As i use the dependencie i can't fix it myself.

How to set the FrameLayout height used in the item.xml by getView function ?

I have used custom Adapter and item.xml contains Imageview along with TextView. I want to change the height and width of the FrameLayout and of the contained ImageView dynamically.
I have written below code, but no cards visible when I run this piece of code. Library is awesome, I don't want to change the library, So please help me.

   public View getView(final int position, View convertView, ViewGroup parent) {
       View view = inflater.inflate(R.layout.item, parent, false);
        final Holder holder = new Holder();
        holder.ivPhoto = (ImageView) view.findViewById(R.id.ivImage);
        holder.ivInfo = (TextView) view.findViewById(R.id.ivInfo);        
        holder.frame_layout = (FrameLayout) view.findViewById(R.id.frame_layout);        

        holder.frame_layout.setLayoutParams(new FrameLayout.LayoutParams(width/2, height/2));        
        return view;
   }

private class Holder {
    private ImageView ivPhoto;
    private TextView ivInfo;        
    private FrameLayout frame_layout;        
}

I am getting height "height and width" as follows:

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;

If I am doing something wrong please correct me.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.