View Pager with previous and next item smaller in size with infinite scroll
Solution 1
UPDATE - if you want to make current page zoom use below PageTransformer
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
public class JavaActivity extends AppCompatActivity {
ViewPager2 myViewPager2;
MyAdapter MyAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);
myViewPager2 = findViewById(R.id.viewpager);
MyAdapter = new MyAdapter(this);
myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
myViewPager2.setAdapter(MyAdapter);
myViewPager2.setOffscreenPageLimit(3);
float pageMargin = getResources().getDimensionPixelOffset(R.dimen.pageMargin);
float pageOffset = getResources().getDimensionPixelOffset(R.dimen.offset);
myViewPager2.setPageTransformer((page, position) -> {
float myOffset = position * -(2 * pageOffset + pageMargin);
if (position < -1) {
page.setTranslationX(-myOffset);
} else if (position <= 1) {
float scaleFactor = Math.max(0.7f, 1 - Math.abs(position - 0.14285715f));
page.setTranslationX(myOffset);
page.setScaleY(scaleFactor);
page.setAlpha(scaleFactor);
} else {
page.setAlpha(0);
page.setTranslationX(myOffset);
}
});
}
}
OUTPUT
NOTE: you can download complete code from my GitHub repositories
Try this way
JavaActivity
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.viewpager2.widget.ViewPager2;
public class JavaActivity extends AppCompatActivity {
ViewPager2 myViewPager2;
MyAdapter MyAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);
myViewPager2 = findViewById(R.id.viewpager);
MyAdapter = new MyAdapter(this);
myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
myViewPager2.setAdapter(MyAdapter);
myViewPager2.setOffscreenPageLimit(3);
float pageMargin= getResources().getDimensionPixelOffset(R.dimen.pageMargin);
float pageOffset = getResources().getDimensionPixelOffset(R.dimen.offset);
myViewPager2.setPageTransformer(new ViewPager2.PageTransformer() {
@Override
public void transformPage(@NonNull View page, float position) {
float myOffset = position * -(2 * pageOffset + pageMargin);
if (myViewPager2.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
if (ViewCompat.getLayoutDirection(myViewPager2) == ViewCompat.LAYOUT_DIRECTION_RTL) {
page.setTranslationX(-myOffset);
} else {
page.setTranslationX(myOffset);
}
} else {
page.setTranslationY(myOffset);
}
}
});
}
}
activity_java layout file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context=".JavaActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:clipToPadding="false"
android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
>
MyAdapter
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
public MyAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.tvName.setText(String.format("Row number%d", position));
if (position % 2 ==0){
holder.imgBanner.setBackgroundColor(Color.RED);
}else {
holder.imgBanner.setBackgroundColor(Color.GREEN);
}
}
@Override
public int getItemCount() {
return 15;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
ImageView imgBanner;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tvName);
imgBanner = itemView.findViewById(R.id.imgBanner);
}
}
}
row_item layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_marginLeft="@dimen/pageMarginAndOffset"
android:layout_marginRight="@dimen/pageMarginAndOffset"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imgBanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:contentDescription="@string/app_name"/>
<TextView
android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:layout_centerInParent="true"
android:textColor="@android:color/white"
android:textSize="20sp"
android:textStyle="bold"
tools:text="Hello"/>
</RelativeLayout>
OUTPUT
Solution 2
Using ViewPager2 (that has RecyclerView in it).
vp2 is instance of ViewPager2
This worked for me:
RecyclerView rv = (RecyclerView) vp2.getChildAt(0);
rv.setPadding(80, 0, 80, 0);
rv.setClipToPadding(false);
I used FragmentStateAdapter for it and overriding getItemId()
and containsItem()
for add/remove fragments.
result is here:
![mdDroid](https://i.stack.imgur.com/xb5s0.jpg?s=256&g=1)
mdDroid
I am Software Developer interested in JAVA and Android ; Wish to be expert in Android Apps.Currently working as Sr. Software Engineer (Android) Enthusiastic about Java Programming, and Android ,Love to explore IT ,Keen learner, Self-motivated ,Innovative, Enjoys R&D. Aim: To take up challenges in Software Development and create value & recognition on work place by producing the best result for the organization through synchronize, hard work & determination. Specialties: Android (Native App with ADT), JAVA J2EE Spring , Web technology (HTML, CSS, JSP),MySQL, Sqlite ,Oracle
Updated on June 21, 2022Comments
-
mdDroid about 2 years
Want to create the view pager same as following UI, applied custom transformer but not working.
ViewPager.java
public class MyViewPager extends ViewPager implements ViewPager.PageTransformer { public static final String TAG = "MyViewPager"; private float MAX_SCALE = 0.0f; private int mPageMargin; private boolean animationEnabled=true; private boolean fadeEnabled=false; private float fadeFactor=0.5f; public MyViewPager(Context context) { this(context, null); } public MyViewPager(Context context, AttributeSet attrs) { super(context, attrs); // clipping should be off on the pager for its children so that they can scale out of bounds. setClipChildren(false); setClipToPadding(false); // to avoid fade effect at the end of the page setOverScrollMode(2); setPageTransformer(false, this); setOffscreenPageLimit(3); mPageMargin = dp2px(context.getResources(), 50); setPadding(mPageMargin, mPageMargin, mPageMargin, mPageMargin); } public int dp2px(Resources resource, int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resource.getDisplayMetrics()); } public void setAnimationEnabled(boolean enable) { this.animationEnabled = enable; } public void setFadeEnabled(boolean fadeEnabled) { this.fadeEnabled = fadeEnabled; } public void setFadeFactor(float fadeFactor) { this.fadeFactor = fadeFactor; } @Override public void setPageMargin(int marginPixels) { mPageMargin = marginPixels; // setPadding(mPageMargin, mPageMargin, mPageMargin, mPageMargin); } @Override public void transformPage(View page, float position) { if (mPageMargin <= 0|| !animationEnabled) return; page.setPadding(mPageMargin / 3, mPageMargin / 3, mPageMargin / 3, mPageMargin / 3); if (MAX_SCALE == 0.0f && position > 0.0f && position < 1.0f) { MAX_SCALE = position; } position = position - MAX_SCALE; float absolutePosition = Math.abs(position); if (position <= -1.0f || position >= 1.0f) { if(fadeEnabled) page.setAlpha(fadeFactor); // Page is not visible -- stop any running animations } else if (position == 0.0f) { // Page is selected -- reset any views if necessary page.setScaleX((1 + MAX_SCALE)); page.setScaleY((1 + MAX_SCALE)); page.setAlpha(1); } else { page.setScaleX(1 + MAX_SCALE * (1 - absolutePosition)); page.setScaleY(1 + MAX_SCALE * (1 - absolutePosition)); if(fadeEnabled) page.setAlpha( Math.max(fadeFactor, 1 - absolutePosition)); } } }
-
Albert Vila Calvo almost 5 yearsThanks for this! I've been trying to implement the carousel with
ViewPager2
for a few hours with no success. -
Albert Vila Calvo almost 5 yearsI don't think that you need to set
clipToPadding="false"
on theViewPager
because it doesn't have any padding. Also, I don't think that you needclipChildren="false"
either since you are not scaling any item more than 100% (ie. you're not drawing outside of theViewPager
). On your GitHub code nothing changes if I remove them. I'd suggest to remove this attributes if they are useless. -
AskNilesh almost 5 years@AlbertVilaCalvo okay i will remove that
-
Albert Vila Calvo almost 5 yearsAnother thing: you are setting
offscreenPageLimit
to 3. This means that there are 3 items retained on each side (total 6), even though you are only showing 1 extra item at each side. Unless you have the need to do so, you can lower this number to 2 or even 1 (everything keeps working fine). -
Danilo Lemes over 4 yearsThis code is related to ViewPager, OP is using ViewPager2
-
Shubham AgaRwal almost 3 yearssomehow this is leaving empty blank space after some scrolling