How to enable CardView in ViewPager

jason picture jason · Apr 29, 2015 · Viewed 10.3k times · Source

I have tried using CardView in ViewPager and everytime I swipe left/right on CardView it goes to the next screen. I want the card to delete itself then. Currently as a standalone both are working fine but when I combine then only viewpager is working and not cardswipe dismiss.

I tried to disable ViewPager with the code below but this code also disables CardView swipe gestures. How can I make only CardView to have gesture and when you swipe in between 2 cards then its should have ViewPager as its not connected to card element.

Or disable ViewPager completely and use it as buttons and enable swipe on CardView. I really appreciate any help. Thanks in Advance.

FYI: I have tried android_horizontal_listview in ViewPager and that works fine and exactly like this.

For ViewPager:

mPager.setOnTouchListener(new OnTouchListener()
{           
    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        return true;
    }
});

For CardView:

SwipeableRecyclerViewTouchListener swipeTouchListener =

new SwipeableRecyclerViewTouchListener(mRecyclerView,
    new SwipeableRecyclerViewTouchListener.SwipeListener() {
        @Override
        public boolean canSwipe(int position) {
            return true;
        }

        @Override
        public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
            for (int position : reverseSortedPositions) {
                mItems.remove(position);
                mAdapter.notifyItemRemoved(position);
            }
            mAdapter.notifyDataSetChanged();
        }

        @Override
        public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
            for (int position : reverseSortedPositions) {
                mItems.remove(position);
                mAdapter.notifyItemRemoved(position);
            }
            mAdapter.notifyDataSetChanged();
        }
    });

mRecyclerView.addOnItemTouchListener(swipeTouchListener);

Mainactivity.java

public class MainActivity extends Activity implements ActionBar.TabListener {


    ViewPager vp;
    View viewpager_layout_1;
    View viewpager_layout_2;
    View viewpager_layout_3;
    ActionBar.Tab tab_1;
    ActionBar.Tab tab_2;
    ActionBar.Tab tab_3;
    ActionBar bar;
    /////
    String jsonstring1;
    CardViewAdapter spinnerArray;
    ImageLoader imageLoader = ImageLoader.getInstance();//
    DisplayImageOptions options;
    ArrayList<HashMap<String, String>> array_list1;
    RecyclerView recyclerView;
    RelativeLayout re1;
    private Context mContext;

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

        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);
        mContext = this;


        viewpager_layout_1 = new View(mContext);
        viewpager_layout_1 = getLayoutInflater().inflate(R.layout.sample1, null);


        viewpager_layout_3 = new View(mContext);
        viewpager_layout_3 = getLayoutInflater().inflate(R.layout.sample2, null);


        viewpager_layout_2 = new View(mContext);
        viewpager_layout_2 = getLayoutInflater().inflate(R.layout.sample3, null);


        vp = (ViewPager) findViewById(R.id.vp);
        bar = getActionBar();


        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        bar.setDisplayShowTitleEnabled(false);
        bar.setDisplayShowHomeEnabled(false);

        Vector<View> pages = new Vector<View>();

        pages.add(viewpager_layout_1);
        pages.add(viewpager_layout_3);
        pages.add(viewpager_layout_2);

        CustomPagerAdapter adapter = new CustomPagerAdapter(mContext, pages);
        vp.setAdapter(adapter);

        vp.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {

                bar.setSelectedNavigationItem(position);
            }
        });

        tab_1 = bar.newTab();
        tab_1.setCustomView(R.layout.tab_layout_1);
        tab_1.setTabListener(this);
        bar.addTab(tab_1);


        tab_2 = bar.newTab();
        tab_2.setCustomView(R.layout.tab_layout_2);
        tab_2.setTabListener(this);
        bar.addTab(tab_2);


        tab_3 = bar.newTab();
        tab_3.setCustomView(R.layout.tab_layout_3);
        tab_3.setTabListener(this);
        bar.addTab(tab_3);


        ////


        imageLoader.init(ImageLoaderConfiguration.createDefault(MainActivity.this));


        jsonstring1 = "[{\"category\":\"1\",\"no\":\"1\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/c/c3/Jordan_by_Lipofsky_16577.jpg\"},{\"category\":\"2\",\"no\":\"2\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Basketball_World_Cup_2014.jpg/800px-Basketball_World_Cup_2014.jpg\"},{\"category\":\"3\",\"no\":\"3\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/4/4e/Basketball_Goal.jpg\"},{\"category\":\"4\",\"no\":\"4\",\"image\":\"http://upload.wikimedia.org/wikipedia/commons/1/10/Basketball_through_hoop.jpg\"}]";

        //////////

        array_list1 = new ArrayList<HashMap<String, String>>();
        JSONArray arr = null;
        try {
            arr = new JSONArray(jsonstring1);
            for (int i = 0; i < arr.length(); i++) {
                JSONObject e1 = arr.getJSONObject(i);
                String category = e1.getString("category").trim();
                String no = e1.getString("no").trim();
                String image = e1.getString("image").trim();

                HashMap<String, String> map = new HashMap<String, String>();
                map.put("category", category);
                map.put("no", no);
                map.put("image", image);
                // adding HashList to ArrayList
                array_list1.add(map);
            }


        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        OnItemTouchListener itemTouchListener = new OnItemTouchListener() {
            @Override
            public void onCardViewTap(View view, int position) {
                Toast.makeText(MainActivity.this, "Tapped " + array_list1.get(position), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onButton1Click(View view, int position) {
                Toast.makeText(MainActivity.this, "Clicked Button1 in " + array_list1.get(position), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onButton2Click(View view, int position) {
                Toast.makeText(MainActivity.this, "Clicked Button2 in " + array_list1.get(position), Toast.LENGTH_SHORT).show();
            }
        };

        spinnerArray = new CardViewAdapter(itemTouchListener, MainActivity.this, array_list1);
        recyclerView = (RecyclerView) viewpager_layout_3.findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        SlideInBottomAnimationAdapter alphaAdapter = new SlideInBottomAnimationAdapter(spinnerArray);
        ScaleInAnimationAdapter alphaAdapter2 = new ScaleInAnimationAdapter(alphaAdapter);
        final AlphaInAnimationAdapter alphaAdapter3 = new AlphaInAnimationAdapter(alphaAdapter2);
        alphaAdapter3.setDuration(500);
        alphaAdapter3.setFirstOnly(true);
        recyclerView.setAdapter(alphaAdapter3);


        final SwipeableRecyclerViewTouchListener swipeTouchListener =
                new SwipeableRecyclerViewTouchListener(recyclerView,
                        new SwipeableRecyclerViewTouchListener.SwipeListener() {
                            @Override
                            public boolean canSwipe(int position) {
                                return true;
                            }


                            @Override
                            public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
                                for (int position : reverseSortedPositions) {
//                                    mItems.remove(position);
                                    Toast.makeText(MainActivity.this, array_list1.get(position) + " swiped left", Toast.LENGTH_SHORT).show();
                                    array_list1.remove(position);
                                    alphaAdapter3.notifyItemRemoved(position);
                                }
                                alphaAdapter3.notifyDataSetChanged();
                            }

                            @Override
                            public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
                                for (int position : reverseSortedPositions) {
//
                                    Toast.makeText(MainActivity.this, array_list1.get(position) + " swiped right", Toast.LENGTH_SHORT).show();
                                    array_list1.remove(position);
                                    alphaAdapter3.notifyItemRemoved(position);
                                }
                                alphaAdapter3.notifyDataSetChanged();
                            }
                        });

        recyclerView.addOnItemTouchListener(swipeTouchListener);


    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
        //  Toast.makeText(getBaseContext(), tab.toString(), 5).show();
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        //      Toast.makeText(getBaseContext(), tab.toString(), 5).show();
        vp.setCurrentItem(tab.getPosition());
        if (tab.getPosition() == 2) {


            tab_2.setCustomView(null);
            tab_2.setCustomView(R.layout.tab_layout_2);

            tab_1.setCustomView(null);
            tab_1.setCustomView(R.layout.tab_layout_1);


            tab_3.setCustomView(null);
            tab_3.setCustomView(R.layout.tab_layout_33);


        } else if (tab.getPosition() == 1) {


            tab_2.setCustomView(null);
            tab_2.setCustomView(R.layout.tab_layout_22);

            tab_1.setCustomView(null);
            tab_1.setCustomView(R.layout.tab_layout_1);


            tab_3.setCustomView(null);
            tab_3.setCustomView(R.layout.tab_layout_3);


        } else if (tab.getPosition() == 0) {

            tab_1.setCustomView(null);
            tab_1.setCustomView(R.layout.tab_layout_11);


            if (tab_2 != null) {

                tab_2.setCustomView(null);
                tab_2.setCustomView(R.layout.tab_layout_2);
            }


            if (tab_3 != null) {

                tab_3.setCustomView(null);
                tab_3.setCustomView(R.layout.tab_layout_3);
            }


        }
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
        //  Toast.makeText(getBaseContext(), tab.toString(), 5).show();

    }


    public interface OnItemTouchListener {

        // this will disallow the touch request for parent scroll on touch of child view


        /**
         * Callback invoked when the user Taps one of the RecyclerView items
         *
         * @param view     the CardView touched
         * @param position the index of the item touched in the RecyclerView
         */
        public void onCardViewTap(View view, int position);

        /**
         * Callback invoked when the Button1 of an item is touched
         *
         * @param view     the Button touched
         * @param position the index of the item touched in the RecyclerView
         */
        public void onButton1Click(View view, int position);

        /**
         * Callback invoked when the Button2 of an item is touched
         *
         * @param view     the Button touched
         * @param position the index of the item touched in the RecyclerView
         */
        public void onButton2Click(View view, int position);
    }

    public class CustomPagerAdapter extends PagerAdapter {

        private final Context mContext;
        private final Vector<View> pages;

        public CustomPagerAdapter(Context context, Vector<View> pages) {
            this.mContext = context;
            this.pages = pages;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {

            View page = pages.get(position);
            container.addView(page);


            return page;
        }

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

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view.equals(object);
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }


    }

    public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.ViewHolder> {
        ArrayList<HashMap<String, String>> d;
        Activity a;
        private List<String> cards;
        private OnItemTouchListener onItemTouchListener2;


        public CardViewAdapter(OnItemTouchListener onItemTouchListener, Activity a, ArrayList<HashMap<String, String>> d) {
            //  this.cards = cards;
            this.onItemTouchListener2 = onItemTouchListener;
            this.a = a;
            this.d = d;
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view_layout, viewGroup, false);
            return new ViewHolder(v);
        }

        @Override
        public void onBindViewHolder(ViewHolder viewHolder, int i) {
            //  viewHolder.title.setText(cards.get(i));

            HashMap<String, String> item = d.get(i);
            viewHolder.title.setText(item.get("category"));
            imageLoader.displayImage(item.get("image"), viewHolder.im2);

        }

        @Override
        public int getItemCount() {
            //   return d == null ? 0 : d.size();
            return (null != d ? d.size() : 0);
            // return d.size();
        }

        public class ViewHolder extends RecyclerView.ViewHolder {

            MotionEvent motionEvent;
            private int mSlop;
            private int mMinFlingVelocity;
            private int mMaxFlingVelocity;
            private long mAnimationTime;
            // Fixed properties
            //   private RecyclerView mRecyclerView;
            private SwipeableRecyclerViewTouchListener.SwipeListener mSwipeListener;

            // Transient properties
            private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
            private int mDismissAnimationRefCount = 0;
            private float mAlpha;
            private float mDownX;
            private float mDownY;
            private boolean mSwiping;
            private int mSwipingSlop;
            private VelocityTracker mVelocityTracker;
            private int mDownPosition;
            private int mAnimatingPosition = ListView.INVALID_POSITION;
            private View mDownView;
            private boolean mPaused;
            private float mFinalDelta;
            ///
            private TextView title;
            private Button button1;
            private Button button2;
            private ImageView im2;

            public ViewHolder(View itemView) {
                super(itemView);
                title = (TextView) itemView.findViewById(R.id.card_view_title);

                im2 = (ImageView) itemView.findViewById(R.id.imageView);

            }
        }
    }


}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/relativelayout_1">


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:id="@+id/linearlayout_1"
        android:orientation="vertical">

        <android.support.v4.view.ViewPager
            android:id="@+id/vp"
            android:layout_width="match_parent"
            android:layout_height="0dp"

            android:layout_weight="1"
            />


    </LinearLayout>


</RelativeLayout>

sample2.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/re1"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical">

</android.support.v7.widget.RecyclerView>

</RelativeLayout>

Answer

Cindy picture Cindy · May 15, 2017

To solve this issue I used an ItemTouchHelper provided by Android to easily swipe to delete an item from a RecyclerView.

Please see implementation below:

MainActivity:

Here I have the implementation of the ViewPager and it's child Fragments.

package za.co.gadgetgirl.testcardpager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);
    }

    private void setupViewPager(ViewPager viewPager) {
        Adapter adapter = new Adapter(getSupportFragmentManager());

        Frag1 frag1 = new Frag1();
        Frag2 frag2 = new Frag2();
        Frag3 frag3 = new Frag3();

        adapter.addFragment(frag1, "frag1");
        adapter.addFragment(frag2, "frag2");
        adapter.addFragment(frag3, "frag3");
        viewPager.setAdapter(adapter);
    }

    static class Adapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragments = new ArrayList<>();
        private final List<String> mFragmentTitles = new ArrayList<>();

        public Adapter(FragmentManager fm) {
            super(fm);
        }

        public void addFragment(Fragment fragment, String title) {
            mFragments.add(fragment);
            mFragmentTitles.add(title);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }

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

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitles.get(position);
        }
    }
}

Frag1:

On this Fragment I have a RecyclerView that has an ItemTouchHelper attached. The ItemTouchHelper listens for the onSwiped(...) method that is defined in the SimpleCallback interface and I just remove the swiped item in this method.

package za.co.gadgetgirl.testcardpager;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Frag1 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.frag1, container, false);

        final RecyclerView rv = (RecyclerView) v.findViewById(R.id.rv);
        final LinearLayoutManager llm = new LinearLayoutManager(getActivity());
        rv.setLayoutManager(llm);

        final RVAdapter rvAdapter = new RVAdapter(Person.initializeData());
        rv.setAdapter(rvAdapter);

        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                rvAdapter.removeItem(viewHolder.getAdapterPosition());
            }
        });

        itemTouchHelper.attachToRecyclerView(rv);

        return v;
    }

}

RVAdapter:

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {


    //...implementation...

    public void removeItem(int position) {
        persons.remove(position);
        notifyItemRemoved(position);
    }
}

To use the ItemTouchHelper, you will need the appcompat-v7:22.2.0 dependency and above defined in your app gradle file.