Android Modern Image Slider using ViewPager 2 and KenBurnsView | Android Studio

In this tutorial, we will make a modern image slider using ViewPager2 in which we will implement a ken burns view to animate the image. Here we will use static data for the slider but you can use data from API as well.

The question is what is Ken Burns View effect? Let’s see what is Ken Burns effect

Ken Burns View

Android library that provides an extension to ImageView that creates an immersive experience by animating it’s drawable using the Ken Burns Effect.

KenBurnsView provides the following advantages:

Now let’s create a modern Image Slider using Viewpager

Gradle Integration

dependencies {
implementation 'com.google.android.material:material:1.3.0'
//Ppicasso- for image loading
implementation 'com.squareup.picasso:picasso:2.71828'
//Ken Burns view - for ken burns effect
implementation 'com.flaviofaria:kenburnsview:1.0.7'
//viewpager 2
implementation "androidx.viewpager2:viewpager2:1.0.0"
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}

Design the main view

now in the main XML file create your design and add the view pager.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:background="@color/white"
tools:context=".ModernImageSlider.ModernImageSliderActivity">
<androidx.cardview.widget.CardView
android:layout_width="40dp"
android:layout_height="40dp"
android:id="@+id/cardProfilePic"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="20dp"
app:cardElevation="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/app_name"
android:src="@drawable/profile_pic"
android:scaleType="fitXY"/>
</androidx.cardview.widget.CardView> <TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textHello"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:text="@string/hello_android"
android:textColor="#212121"
android:textSize="17sp"
android:fontFamily="@font/product_sans_bold"
app:layout_constraintBottom_toBottomOf="@id/cardProfilePic"
app:layout_constraintEnd_toStartOf="@id/cardProfilePic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/cardProfilePic"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textWhereAreWe"
android:text="@string/seven_wonders"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
android:textColor="#212121"
android:textSize="35sp"
android:fontFamily="@font/antonio_bold"
android:includeFontPadding="false"
app:layout_constraintTop_toBottomOf="@id/cardProfilePic"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textGoing"
android:text="@string/of_the_world"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textColor="#757575"
android:textSize="30sp"
android:includeFontPadding="false"
android:fontFamily="@font/antonio_bold"
app:layout_constraintTop_toBottomOf="@id/textWhereAreWe"/>
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/locationViewPager"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:paddingStart="40dp"
android:paddingEnd="40dp"
app:layout_constraintBottom_toTopOf="@id/bottomText"
app:layout_constraintTop_toBottomOf="@id/textGoing"/>
<TextView
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="@+id/bottomText"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:gravity="center"
android:text="@string/do_you_find_it_helpful"
android:fontFamily="@font/product_sans_bold"
android:textColor="#212121"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Design Viewpager item

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp"
app:cardCornerRadius="12dp"
app:cardElevation="5dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.flaviofaria.kenburnsview.KenBurnsView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/kbvLocation"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:background="@drawable/background_star_rating"
android:gravity="center_vertical"
android:paddingStart="8dp"
android:paddingTop="2dp"
android:paddingEnd="8dp"
android:paddingBottom="2dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="16dp"
android:layout_height="16sp"
android:contentDescription="@string/app_name"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:src="@drawable/ic_baseline_star_24"
app:tint="#FFFFFF" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textStartRating"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:textColor="#FFFFFF"
android:textSize="15sp"/>
</LinearLayout> <View
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#D6000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="@id/textTitle"/>
<ImageView
android:layout_width="18sp"
android:layout_height="18sp"
android:id="@+id/imageLocation"
android:layout_marginStart="20dp"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_baseline_location_on_24"
app:tint="#FFFFFF"
app:layout_constraintBottom_toBottomOf="@id/textLocation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/textLocation"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textLocation"
android:layout_marginStart="2dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="8dp"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:fontFamily="@font/antonio_bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageLocation"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textTitle"
android:layout_marginStart="20dp"
android:layout_marginBottom="2dp"
android:layout_marginEnd="20dp"
android:paddingTop="4dp"
android:textColor="#FFFFFF"
android:textSize="19sp"
android:fontFamily="@font/antonio_bold"
app:layout_constraintBottom_toTopOf="@id/imageLocation"/>
</androidx.constraintlayout.widget.ConstraintLayout></androidx.cardview.widget.CardView>

you can change it according to your needs.

Create a model class

now create a model class for the items data we’re going to set in the adapter class. For that create a new java file in your package.

package com.codewithgolap.androidtutorial.ModernImageSlider;public class TravelLocation {    public String title, location, imageUrl;
public Float startRating;
}

Create an adapter

Now create an adapter class for your item layout that we need to inflate.

package com.codewithgolap.androidtutorial.ModernImageSlider;import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.codewithgolap.androidtutorial.R;
import com.flaviofaria.kenburnsview.KenBurnsView;
import com.squareup.picasso.Picasso;
import java.util.List;public class TravelLocationAdapter extends RecyclerView.Adapter<TravelLocationAdapter.TravelLocationViewHolder>{ private List<TravelLocation> travelLocations; public TravelLocationAdapter(List<TravelLocation> travelLocations) {
this.travelLocations = travelLocations;
}
@NonNull
@Override
public TravelLocationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new TravelLocationViewHolder(
LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_container_location,
parent, false
)
);
}
@Override
public void onBindViewHolder(@NonNull TravelLocationViewHolder holder, int position) {
holder.setLocationData(travelLocations.get(position));
}
@Override
public int getItemCount() {
return travelLocations.size();
}
static class TravelLocationViewHolder extends RecyclerView.ViewHolder { private KenBurnsView kbvLocation;
private TextView textTitle, textLocation, textStartRating;
TravelLocationViewHolder(@NonNull View itemView) {
super(itemView);
kbvLocation = itemView.findViewById(R.id.kbvLocation);
textTitle = itemView.findViewById(R.id.textTitle);
textStartRating = itemView.findViewById(R.id.textStartRating);
textLocation = itemView.findViewById(R.id.textLocation);
}
void setLocationData(TravelLocation travelLocation){
Picasso.get().load(travelLocation.imageUrl).into(kbvLocation);
textTitle.setText(travelLocation.title);
textLocation.setText(travelLocation.location);
textStartRating.setText(String.valueOf(travelLocation.startRating));
}
}
}

Add functionality

now in the main java file, add your view pager and create a list of the model class to add the static data. Here we use static data.

package com.codewithgolap.androidtutorial.ModernImageSlider;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.CompositePageTransformer;
import androidx.viewpager2.widget.MarginPageTransformer;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import android.view.View;
import com.codewithgolap.androidtutorial.R;import java.util.ArrayList;
import java.util.List;
public class ModernImageSliderActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_modern_image_slider);
ViewPager2 locationViewPager = findViewById(R.id.locationViewPager); List<TravelLocation> travelLocations = new ArrayList<>(); TravelLocation travelLocationET = new TravelLocation();
travelLocationET.imageUrl = "https://images.unsplash.com/photo-1500297726361-1715d90aec00?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1047&q=80";
travelLocationET.title = "China";
travelLocationET.location = "Grate Wall of China";
travelLocationET.startRating = 4.8f;
travelLocations.add(travelLocationET);
TravelLocation travelLocationMV = new TravelLocation();
travelLocationMV.imageUrl = "https://images.unsplash.com/photo-1567930009485-07d60c813306?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80";
travelLocationMV.title = "Mexico";
travelLocationMV.location = "Chichén Itzá";
travelLocationMV.startRating = 4.5f;
travelLocations.add(travelLocationMV);
TravelLocation travelLocationTM = new TravelLocation();
travelLocationTM.imageUrl = "https://images.unsplash.com/photo-1589825274556-94746a018766?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80";
travelLocationTM.title = "Jordan";
travelLocationTM.location = "Petra";
travelLocationTM.startRating = 4.7f;
travelLocations.add(travelLocationTM);
TravelLocation travelLocationF = new TravelLocation();
travelLocationF.imageUrl = "https://images.unsplash.com/photo-1456244440184-1d494704a505?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80";
travelLocationF.title = "Peru";
travelLocationF.location = "Machu Picchu";
travelLocationF.startRating = 4.6f;
travelLocations.add(travelLocationF);
TravelLocation travelLocationFi = new TravelLocation();
travelLocationFi.imageUrl = "https://images.unsplash.com/photo-1595688878177-b72dfeeed683?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1151&q=80";
travelLocationFi.title = "Brazil";
travelLocationFi.location = "Christ the Redeemer";
travelLocationFi.startRating = 4.6f;
travelLocations.add(travelLocationFi);
TravelLocation travelLocationS = new TravelLocation();
travelLocationS.imageUrl = "https://images.unsplash.com/photo-1482401204742-eb3c31c24722?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1112&q=80";
travelLocationS.title = "Italy";
travelLocationS.location = "Colosseum";
travelLocationS.startRating = 4.7f;
travelLocations.add(travelLocationS);
TravelLocation travelLocationSe = new TravelLocation();
travelLocationSe.imageUrl = "https://images.unsplash.com/photo-1524492412937-b28074a5d7da?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1051&q=80";
travelLocationSe.title = "India";
travelLocationSe.location = "Taj Mahal";
travelLocationSe.startRating = 4.8f;
travelLocations.add(travelLocationSe);
locationViewPager.setAdapter(new TravelLocationAdapter(travelLocations)); locationViewPager.setClipToPadding(false);
locationViewPager.setClipChildren(false);
locationViewPager.setOffscreenPageLimit(3);
locationViewPager.getChildAt(0).setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
CompositePageTransformer compositePageTransformer = new CompositePageTransformer();
compositePageTransformer.addTransformer(new MarginPageTransformer(40));
compositePageTransformer.addTransformer(new ViewPager2.PageTransformer() {
@Override
public void transformPage(@NonNull View page, float position) {
float r = 1 - Math.abs(position);
page.setScaleY(0.90f + r * 0.04f);
}
});
locationViewPager.setPageTransformer(compositePageTransformer);
}
}

Output

Follow me on IG at @androidapps.development.blogs

Hi everyone, myself Golap an Android app developer with UI/UX designer.