Swipe card view Android with Example[Updated]

In this tutorial, we will develop views and architecture to simulate the Swipe card view in android.  using PlaceHolderView.

Step 1:

Set up the project in the android studio.

In app’s build.gradle add the dependencies like RetrofitRecyclerview, glide etc.

dependencies {
    compile 'com.mindorks:placeholderview:0.7.2'
    implementation 'com.android.support:recyclerview-v7:27.0.2'
    implementation 'com.android.support:cardview-v7:27.0.2'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'com.github.bumptech.glide:glide:4.6.1'
}

Add Internet permission in the app’s AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>

Related Post: Android Loading Circle Animation

Related Post: Create Reusable Alert Dialog in Android

Related Post: Glide Android – Image loading framework for Android with Example [updated]


Step 2

setup the layouts.

  1. Add PlaceHolderView into your main activity layout.
    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout 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"
        android:padding="20dp"
        android:background="#717171"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/button_selected"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="16dp"
            android:padding="10dp"
            android:text="selected"
            android:background="#7bc741"
            android:textColor="@android:color/white"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/button_rejected"
            app:layout_constraintTop_toBottomOf="@+id/swipePlaceHolder"/>
    
        <Button
            android:id="@+id/button_rejected"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:layout_marginTop="8dp"
            android:layout_marginStart="16dp"
            android:text="Rejected"
            android:background="#ff5252"
            android:textColor="@android:color/white"
            app:layout_constraintEnd_toStartOf="@+id/button_selected"
            app:layout_constraintHorizontal_chainStyle="spread"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/swipePlaceHolder"/>
    
        <com.mindorks.placeholderview.SwipePlaceHolderView
            android:id="@+id/swipePlaceHolder"
            android:layout_width="300dp"
            android:layout_height="300dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
        </com.mindorks.placeholderview.SwipePlaceHolderView>
    </android.support.constraint.ConstraintLayout>
  2. Add layout for the Swipecard view.
    swipecardview_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="300dp"
            android:layout_height="300dp"
          android:background="@drawable/ic_launcher_background"
          android:scaleType="centerCrop"/>
    
        <TextView
            android:id="@+id/textview_name"
            android:layout_width="300dp"
            android:layout_height="40dp"
            android:layout_gravity="bottom"
          android:background="#b1b0b0"
          android:gravity="center"
          android:textColor="@android:color/white"
            android:text="Hello World" />
    </FrameLayout>
  3. Add a separate view for swipe in view and swipe out views.
    swipe_in_layout will appear when you start swipe in.
    swipe_in_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@android:color/holo_green_dark"
            android:textStyle="bold"
            android:textSize="25sp"
            android:text="Selected"/>
    
    </LinearLayout>

    swipe_out_layout will appear when you start swipe out.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:textColor="@android:color/holo_red_dark"
            android:textStyle="bold"
            android:textSize="25sp"
            android:text="Rejected"/>
    
    </LinearLayout>

Step 3:

Setup an HTTP client for Android. In this tutorial, I am using Retrofit. Please check my detailed post about Retrofit.

  1. setup Retrofit instance.
    ApiClient.java

    public class ApiClient {
    
      private static String BASE_URL="http://www.mocky.io/v2/";
    
      private static Retrofit retrofit;
    
      public static Retrofit getInstance(){
        if(retrofit == null){
          retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
              .addConverterFactory(GsonConverterFactory.create())
              .build();
        }
        return retrofit;
      }
    }
  2. creating an API interface.
    ApiInterface.java

    public interface ApiInterface {
    
      @GET("5a8fefef3000004f00248c70")
      Call<List<Movie>> getAllMovies();
    }
  3.  movie model.
    Movie.java

    public class Movie {
    
        @SerializedName("name")
        private String name;
        @SerializedName("desc")
        private String desc;
    
        public String getImageUrl() {
            return imageUrl;
        }
    
        public void setImageUrl(String imageUrl) {
            this.imageUrl = imageUrl;
        }
    
        @SerializedName("imageUrl")
        private String imageUrl;
    
        public Movie(String name, String desc, String image) {
            this.name = name;
            this.desc = desc;
            this.imageUrl = image;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    
        @Override
        public String toString() {
            return "Movie{" +
                    "name='" + name + '\'' +
                    ", desc='" + desc + '\'' +
                    ", image=" + imageUrl +
                    '}';
        }
    }
  4. JSON Response for the API I am using http://www.mocky.io/v2/5a8fefef3000004f00248c70.
    [
    {
    name: "Johnny Depp",
    desc: "Pirates of the Caribbean",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1_UY317_CR4,0,214,317_AL_.jpg"
    },
    {
    name: "Arnold Schwarzenegger",
    desc: "The Terminator",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1._SY209_CR13,0,140,209_.jpg"
    },
    {
    name: "Johnny Depp",
    desc: "Pirates of the Caribbean",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1_UY317_CR4,0,214,317_AL_.jpg"
    },
    {
    name: "Arnold Schwarzenegger",
    desc: "The Terminator",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1._SY209_CR13,0,140,209_.jpg"
    },
    {
    name: "Johnny Depp",
    desc: "Pirates of the Caribbean",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1_UY317_CR4,0,214,317_AL_.jpg"
    },
    {
    name: "Arnold Schwarzenegger",
    desc: "The Terminator",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1._SY209_CR13,0,140,209_.jpg"
    },
    {
    name: "Johnny Depp",
    desc: "Pirates of the Caribbean",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1_UY317_CR4,0,214,317_AL_.jpg"
    },
    {
    name: "Arnold Schwarzenegger",
    desc: "The Terminator",
    imageUrl: "http://ia.media-imdb.com/images/M/[email protected]@._V1._SY209_CR13,0,140,209_.jpg"
    }
    ]

Step 4

setup the swipe card view.

  1. initialize and setup placeholder view in your MainActivity.java. Also, Add swipe in layout and swipe out layouts.

    private SwipePlaceHolderView swipePlaceHolderView;
    
    swipePlaceHolderView = findViewById(R.id.swipePlaceHolder);
    
    swipePlaceHolderView.getBuilder().setDisplayViewCount(3)
                    .setSwipeDecor(new SwipeDecor().setPaddingTop(20)
                    .setRelativeScale(0.01f).setSwipeInMsgLayoutId(R.layout.swipe_in_layout)
                    .setSwipeOutMsgLayoutId(R.layout.swipe_out_layout));
  2. Once initialize the SwipePlaceHolderView, then load the data from the API and create swipecard view. That swipecard view needs to be added in SwipePlaceHolderView.
    private void loadData() {
    
            ApiInterface apiInterface = ApiClient.getInstance().create(ApiInterface.class);
            apiInterface.getAllMovies().enqueue(new Callback<List<Movie>>() {
                @Override
                public void onResponse(Call<List<Movie>> call, Response<List<Movie>> response) {
                    movieList = response.body();
                    for (Movie movie : movieList){
                        swipePlaceHolderView.addView(new SwipeCardView(context,swipePlaceHolderView,movie));
                    }
                }
    
                @Override
                public void onFailure(Call<List<Movie>> call, Throwable t) {
                  Log.d("Movielist",t.getMessage());
                }
            });
        }
  3. SwipeCardView.java
    @Layout(R.layout.swiprcardview_layout)
    public class SwipeCardView {
    
        private SwipeCardCallback swipecardCallback;
        public static String TAG ="SwipeCardView";
    
        @View(R.id.imageView)
        private ImageView imageView;
        @View(R.id.textview_name)
        private TextView textViewName;
        private Movie mMovie;
        private Context mContext;
        private SwipePlaceHolderView mSwipePlaceHolderView;
        public SwipeCardView(Context context, SwipePlaceHolderView swipePlaceHolderView, Movie movie) {
            this.mContext = context;
            this.swipecardCallback = (SwipeCardCallback) context;
            this.mSwipePlaceHolderView = swipePlaceHolderView;
            this.mMovie = movie;
        }
    
        @Resolve
        private void onResolve(){
            Glide.with(mContext).load(mMovie.getImageUrl()).apply(RequestOptions.centerCropTransform()).into(imageView);
            textViewName.setText(mMovie.getName());
        }
    
        @SwipeIn
        private void onSwipeIn(){
            swipecardCallback.onSwipeIn();
        }
    
        @SwipeOut
        private void onSwipeOut(){
           swipecardCallback.onSwipeOut();
        }
    
    }

    Here,

    1. @layout –  Used to bind the layout with this class.
    2. @View –  Bind the views in a layout we want to refer to.
    3. @Resolve – Annotation bind a method to be executed when the view is ready to be used. Any operation we want to perform on view references should be written in a method and annotated with this.
    4. @SwipeOut – Calls the annotated method when the card has been rejected.
    5. @SwipeIn – Calls the annotated method when the card has been accepted.
  1.  The callback of the swipe event to MainActivity.
    public interface SwipeCardCallback {
        void onSwipeIn();
        void onSwipeOut();
    }
  2. Implement the callback in your MainActivity,
    public class MainActivity extends AppCompatActivity implements SwipeCardSwipeCallback{
    
    @Override
        public void onSwipeIn() {
            selected = selected + 1;
            buttonSelected.setText("Selected ("+selected+")");
        }
    
        @Override
        public void onSwipeOut() {
            rejected = rejected + 1;
            buttonRejected.setText("Rejected ("+rejected+")");
        }
    }
SwipecardviewAndroid

SwipecardviewAndroid

2 thoughts on - Swipe card view Android with Example[Updated]

  • Hi,
    I followed this tutorial quite exactly in my own app and for some reason, I keep running into this error:
    Attempt to invoke virtual method ‘boolean android.widget.TextView.isEnabled()’ on a null object reference

    meaning that the TextView within the activity is not being accessed. I double checked the id’s and everything can’t seem to find the problem.

    • Hi. Please download the example I have attached and compare with your program. Else please share more error details

Leave a Reply

Your email address will not be published. Required fields are marked *