پیاده سازی ViewPager با قابلیت Auto Scroll در اندروید


پیاده سازی ViewPager با قابلیت Auto Scroll

در مقاله های پیشین به پیاده سازی ViewPager پرداخته ایم. در این مقاله به پیاده سازی ViewPager با قابلیت auto scroll پرداخته ایم. در این قسمت از آموزش های صفر و صد مثل همیشه پروژه را قدم به قدم پیاده می سازیم. برنامه نمونه ای که در این مقاله می سازیم شامل ViewPager، TabLayout و FragmentStatePagerAdapter می باشد.

نتیجه نهایی پیاده سازی ViewPager با auto scroll به صورت زیر می باشد.

مراحل پیاده سازی Auto Scroll ViewPager

  • ایجاد پروژه و import کتابخانه های لازم
  • ساخت component اختصاصی (AutoScrollViewPager)
  • آماده سازی layout مربوطه
  • نوشتن کلاس FragmentPagerAdapter
  • ساخت آداپتر برای آیتم های فرگمنت
  • طراحی layout مربوط به slider
  • ملحق نمودن این layout به فرگمنت
  • ساخت ViewModel برای ارتباط با ViewPager
  • آپدیت کلاس MainActivity
  • ساخت نمونه ای ازFragmentPagerAdapter
  • ست نمودن آداپتر برای ViewPager
  • تنظیم ViewPager روی TabLayout برای indicator پروژه

قدم اول : ایجاد پروژه و import کتابخانه های لازم

پس از ایجاد پروژه کتابخانه های لازم را در build.gradle که androidx و material io می باشند، اضافه می نماییم :

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'com.google.android.material:material:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

قدم دوم : ساخت component اختصاصی (AutoScrollViewPager)

زیر کلاسی از ViewPager با نام AutoScrollViewPager می سازیم. در این کلاس قطعه کد زیر را وارد می کنیم:

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
public class AutoScrollViewPager extends ViewPager {
  public static final int DEFAULT_INTERVAL = 1500;
  public static final int LEFT = 0;
  public static final int RIGHT = 1;
  private static final String TAG = "AutoScrollViewPager";
  public static final int SLIDE_BORDER_MODE_NONE = 0;
  public static final int SLIDE_BORDER_MODE_CYCLE = 1;
  public static final int SLIDE_BORDER_MODE_TO_PARENT = 2;
  private long interval = DEFAULT_INTERVAL;
  private int direction = RIGHT;
  private boolean isCycle = true;
  private boolean stopScrollWhenTouch = true;
  private int slideBorderMode = SLIDE_BORDER_MODE_NONE;
  private boolean isBorderAnimation = true;
  private double autoScrollFactor = 1.0;
  private double swipeScrollFactor = 1.0;
  private Handler handler;
  @Nullable
  private DurationScroller scroller;
  public static final int SCROLL_WHAT = 0;
  public AutoScrollViewPager(Context paramContext) {
    super(paramContext);
    init();
  }
  public AutoScrollViewPager(Context paramContext, AttributeSet paramAttributeSet) {
    super(paramContext, paramAttributeSet);
    init();
  }
  private void init() {
    handler = new MyHandler(this);
    setViewPagerScroller();
  }
  /**
   * start auto scroll, first scroll delay time is {@link #getInterval()}.
   */
  public void startAutoScroll() {
    if (scroller != null) {
      sendScrollMessage(
          (long) (interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
    }
  }
  /**
   * start auto scroll.
   *
   * @param delayTimeInMills first scroll delay time.
   */
  public void startAutoScroll(int delayTimeInMills) {
    sendScrollMessage(delayTimeInMills);
  }
  /**
   * stop auto scroll.
   */
  public void stopAutoScroll() {
    handler.removeMessages(SCROLL_WHAT);
  }
  /**
   * set the factor by which the duration of sliding animation will change while swiping.
   */
  public void setSwipeScrollDurationFactor(double scrollFactor) {
    swipeScrollFactor = scrollFactor;
  }
  /**
   * set the factor by which the duration of sliding animation will change while auto scrolling.
   */
  public void setAutoScrollDurationFactor(double scrollFactor) {
    autoScrollFactor = scrollFactor;
  }
  private void sendScrollMessage(long delayTimeInMills) {
    /** remove messages before, keeps one message is running at most **/
    handler.removeMessages(SCROLL_WHAT);
    handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
  }
  /**
   * set ViewPager scroller to change animation duration when sliding.
   */
  private void setViewPagerScroller() {
    try {
      Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
      scrollerField.setAccessible(true);
      Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
      interpolatorField.setAccessible(true);
      scroller =
          new DurationScroller(getContext(), (Interpolator) interpolatorField.get(null));
      scrollerField.set(this, scroller);
    } catch (IllegalAccessException e) {
      Log.e(TAG, "setViewPagerScroller: ",e );
    //  Timber.e(e);
    } catch (NoSuchFieldException e) {
      Log.e(TAG, "setViewPagerScroller: ",e );
     // Timber.e(e);
    }
  }
  /**
   * scroll only once.
   */
  public void scrollOnce() {
    PagerAdapter adapter = getAdapter();
    int currentItem = getCurrentItem();
    int totalCount = adapter != null ? adapter.getCount() : -100;
    if (adapter == null || totalCount <= 1) {
      return;
    }
    int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
    if (nextItem < 0) {
      if (isCycle) {
        setCurrentItem(totalCount - 1, isBorderAnimation);
      }
    } else if (nextItem == totalCount) {
      if (isCycle) {
        setCurrentItem(0, isBorderAnimation);
      }
    } else {
      setCurrentItem(nextItem, true);
    }
  }
  private static class MyHandler extends Handler {
    private final WeakReference<AutoScrollViewPager> autoScrollViewPager;
    public MyHandler(AutoScrollViewPager autoScrollViewPager) {
      this.autoScrollViewPager = new WeakReference<AutoScrollViewPager>(autoScrollViewPager);
    }
    @Override
    public void handleMessage(Message msg) {
      super.handleMessage(msg);
      if (msg.what == SCROLL_WHAT) {
        AutoScrollViewPager pager = this.autoScrollViewPager.get();
        if (pager != null && pager.scroller != null) {
          pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
          pager.scrollOnce();
          pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
          pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
        }
      }
    }
  }
  /**
   * get auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}.
   *
   * @return the interval.
   */
  public long getInterval() {
    return interval;
  }
  /**
   * set auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}.
   *
   * @param interval the interval to set.
   */
  public void setInterval(long interval) {
    this.interval = interval;
  }
  /**
   * get auto scroll direction.
   *
   * @return {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
   */
  public int getDirection() {
    return (direction == LEFT) ? LEFT : RIGHT;
  }
  /**
   * set auto scroll direction.
   *
   * @param direction {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
   */
  public void setDirection(int direction) {
    this.direction = direction;
  }
  /**
   * whether automatic cycle when auto scroll reaching the last or first item, default is true.
   *
   * @return the isCycle.
   */
  public boolean isCycleScroll() {
    return isCycle;
  }
  /**
   * set whether automatic cycle when auto scroll reaching the last or first item, default is true.
   *
   * @param isCycle the isCycle to set.
   */
  public void setCycle(boolean isCycle) {
    this.isCycle = isCycle;
  }
  /**
   * whether stop auto scroll when touching, default is true.
   *
   * @return the stopScrollWhenTouch.
   */
  public boolean isStopScrollWhenTouch() {
    return stopScrollWhenTouch;
  }
  /**
   * set whether stop auto scroll when touching, default is true.
   */
  public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
    this.stopScrollWhenTouch = stopScrollWhenTouch;
  }
  /**
   * get how to process when sliding at the last or first item.
   *
   * @return the slideBorderMode {@link #SLIDE_BORDER_MODE_NONE},
   * {@link #SLIDE_BORDER_MODE_TO_PARENT},
   * {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
   */
  public int getSlideBorderMode() {
    return slideBorderMode;
  }
  /**
   * set how to process when sliding at the last or first item.
   *
   * @param slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, {@link #SLIDE_BORDER_MODE_TO_PARENT},
   * {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
   */
  public void setSlideBorderMode(int slideBorderMode) {
    this.slideBorderMode = slideBorderMode;
  }
  /**
   * whether animating when auto scroll at the last or first item, default is true.
   */
  public boolean isBorderAnimationEnabled() {
    return isBorderAnimation;
  }
  /**
   * set whether animating when auto scroll at the last or first item, default is true.
   */
  public void setBorderAnimation(boolean isBorderAnimation) {
    this.isBorderAnimation = isBorderAnimation;
  }
}

برای مدیریت مدت زمان scroll کلاسی می سازیم که از Scroller ارث بری کند.

import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;
public class DurationScroller extends Scroller {
  private double scrollFactor = 1;
  public DurationScroller(Context context) {
    super(context);
  }
  public DurationScroller(Context context, Interpolator interpolator) {
    super(context, interpolator);
  }
  public void setScrollDurationFactor(double scrollFactor) {
    this.scrollFactor = scrollFactor;
  }
  @Override
  public void startScroll(int startX, int startY, int dx, int dy, int duration) {
    super.startScroll(startX, startY, dx, dy, (int)(duration * scrollFactor));
  }
}

حالا این component آماده استفاده است. به این منظور viewpager را با این component به صورت زیر عوض می نماییم.

<android.support.v4.view.ViewPager
      android:id="@+id/view_pager"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      />

جا به جا می شود با :

<com.example.autoscrollviewpager.AutoScrollViewPager
      android:id="@+id/view_pager"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      />

قدم سوم : آماده سازی layout مربوطه

به layout مربوط به MainActivity رفته و component و TabLayout برای indicator را به فایل xml اضافه می نماییم :

<?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="@drawable/background"
    tools:context=".MainActivity"
    >
  <LinearLayout
      android:id="@+id/layoutSignUp"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_margin="@dimen/default_margin"
      android:gravity="center"
      android:orientation="horizontal"
      app:layout_constraintBottom_toBottomOf="parent"
      >
    <TextView
        android:id="@+id/textViewFreeAccount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/free_account"
        android:textColor="@color/colorTextLight"
        android:textSize="@dimen/text_12"
        />
    <TextView
        android:id="@+id/tvBecomeMember"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/default_margin"
        android:layout_marginStart="@dimen/default_margin"
        android:text="@string/become_member_text"
        android:textColor="@color/colorAccent"
        android:textSize="@dimen/text_12"
        android:textStyle="bold"
        />
  </LinearLayout>
  <View
      android:id="@+id/view"
      android:layout_width="match_parent"
      android:layout_height="2dp"
      android:layout_marginBottom="@dimen/default_margin"
      android:background="@drawable/divider_dotted"
      android:layerType="software"
      app:layout_constraintBottom_toTopOf="@id/layoutSignUp"
      />
  <androidx.appcompat.widget.AppCompatTextView
      android:id="@+id/tvTermCondition"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginBottom="@dimen/dp_32"
      android:letterSpacing="0.05"
      android:text="@string/terms_conditions"
      android:textColor="@color/colorWhite"
      android:textSize="@dimen/text_10"
      app:layout_constraintBottom_toTopOf="@+id/view"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      tools:ignore="UnusedAttribute"
      />
  <androidx.appcompat.widget.AppCompatTextView
      android:id="@+id/login_button"
      android:layout_width="wrap_content"
      android:layout_height="@dimen/dp_36"
      android:layout_margin="@dimen/default_margin"
      android:gravity="center"
      android:paddingEnd="@dimen/max_padding"
      android:paddingLeft="@dimen/max_padding"
      android:paddingRight="@dimen/max_padding"
      android:paddingStart="@dimen/max_padding"
      android:text="@string/on_boarding_login_button_text"
      app:layout_constraintBottom_toTopOf="@+id/tvTermCondition"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      style="@style/app_buttons_style"
      />
  <TextView
      android:id="@+id/textView5"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginBottom="@dimen/default_margin"
      android:text="@string/above_login_button_text"
      android:textColor="@color/colorWhite"
      android:textSize="@dimen/text_12"
      app:layout_constraintBottom_toTopOf="@+id/login_button"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      />
  <com.google.android.material.tabs.TabLayout
      android:id="@+id/tabs"
      android:layout_width="match_parent"
      android:layout_height="@dimen/activity_vertical_margin"
      android:layout_marginBottom="@dimen/activity_vertical_margin"
      app:layout_constraintBottom_toTopOf="@+id/textView5"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@id/view_pager"
      app:tabBackground="@drawable/viewpager_tab_selector"
      app:tabGravity="center"
      app:tabIndicatorHeight="0dp"
      />
  <com.example.autoscrollviewpager.AutoScrollViewPager
      android:id="@+id/view_pager"
      android:layout_width="match_parent"
      android:layout_height="0dp"
      app:layout_constraintBottom_toTopOf="@+id/tabs"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      />
</androidx.constraintlayout.widget.ConstraintLayout>

فایل resource با نام viewpager_tab_selector را به شکل زیر می سازیم :

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/viewpager_selected_dot"
      android:state_selected="true"/>
  <item android:drawable="@drawable/viewpager_un_selected_dot"/>
</selector>

هم چنین فایل resource برای مورد انتخابی از indicator نقطه ای با نام  viewpager_selected_dot را به شکل زیر می سازیم:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <shape
        android:innerRadius="0dp"
        android:shape="ring"
        android:thickness="5dp"
        android:useLevel="false">
      <solid android:color="@color/colorAccent"/>
    </shape>
  </item>
</layer-list>

به همین ترتیب برای گزینه ای که در indicator انتخاب نشده فایل resource زیر را پیاده می سازیم :

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <shape
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:innerRadius="0dp"
        android:shape="ring"
        android:thickness="5dp"
        android:useLevel="false">
      <solid android:color="@android:color/transparent"
          />
      <stroke
          android:color="#e0e0e0"
          android:width="1dp"/>
    </shape>
  </item>
</layer-list>

قدم چهارم : نوشتن کلاس FragmentPagerAdapter

زیر کلاسی از FragmentPagerAdapter را با قطعه کد زیر می نویسیم:

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
public class AutoScrollPagerAdapter extends FragmentPagerAdapter {
  public AutoScrollPagerAdapter(FragmentManager fm) {
    super(fm);
  }
  @Override
  public Fragment getItem(int position) {
    // Return a SlideFragment (defined as a static inner class below).
    return SlideFragment.newInstance(position + 1);
  }
  @Override
  public int getCount() {
    // Show 3 total pages.
    return 3;
  }
}

قدم پنجم : ساخت فرگمنت با نام SlideFragment

view مربوط به این فرگمنت چنین layout ی دارد :

<?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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.SlideFragment"
    >
  <TextView
      android:id="@+id/section_label"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginEnd="8dp"
      android:layout_marginLeft="8dp"
      android:layout_marginRight="8dp"
      android:layout_marginStart="8dp"
      android:layout_marginTop="32dp"
      android:gravity="center"
      android:text="Code"
      android:textAllCaps="true"
      android:textColor="@color/colorWhite"
      android:textSize="22sp"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/imageView"
      tools:layout_constraintLeft_creator="1"
      tools:layout_constraintTop_creator="1"
      />
  <ImageView
      android:id="@+id/imageView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginBottom="8dp"
      android:layout_marginEnd="8dp"
      android:layout_marginLeft="8dp"
      android:layout_marginRight="8dp"
      android:layout_marginStart="8dp"
      android:layout_marginTop="8dp"
      android:src="@drawable/code_icon"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      />
</androidx.constraintlayout.widget.ConstraintLayout>

 

و کلاس جاوایی این فرگمنت نیز به شکل زیر می باشد :

import android.os.Bundle;
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.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.example.autoscrollviewpager.R;
public class SlideFragment extends Fragment {
  private static final String ARG_SECTION_NUMBER = "section_number";
  @StringRes
  private static final int[] PAGE_TITLES =
      new int[] { R.string.page_text_1, R.string.page_text_2, R.string.page_text_3 };
  @StringRes
  private static final int[] PAGE_IMAGE =
      new int[] {
          R.drawable.code_icon, R.drawable.eat_icon, R.drawable.sleep_icon
      };
  private SliderViewModel sliderViewModel;
  public static SlideFragment newInstance(int index) {
    SlideFragment fragment = new SlideFragment();
    Bundle bundle = new Bundle();
    bundle.putInt(ARG_SECTION_NUMBER, index);
    fragment.setArguments(bundle);
    return fragment;
  }
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sliderViewModel = ViewModelProviders.of(this).get(SliderViewModel.class);
    int index = 1;
    if (getArguments() != null) {
      index = getArguments().getInt(ARG_SECTION_NUMBER);
    }
    sliderViewModel.setIndex(index);
  }
  @Override
  public View onCreateView(
      @NonNull LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_main, container, false);
    final TextView textView = root.findViewById(R.id.section_label);
    final ImageView imageView = root.findViewById(R.id.imageView);
    sliderViewModel.getText().observe(this, new Observer<Integer>() {
      @Override public void onChanged(Integer index) {
        textView.setText(PAGE_TITLES[index]);
        imageView.setImageResource(PAGE_IMAGE[index]);
      }
    });
    return root;
  }
}

گوگل برای ارتباط میان فرگمنت ها استفاده از ViewModel را توصیه می نماید. در این کلاس ViewModel به کمک MutableLiveData این ارتباط را میسر می سازیم.

import androidx.arch.core.util.Function;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;
import androidx.lifecycle.ViewModel;
public class SliderViewModel extends ViewModel {
  private MutableLiveData<Integer> mIndex = new MutableLiveData<>();
  private LiveData<Integer> mPagerIndex =
      Transformations.map(mIndex, new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer input) {
          return input - 1;
        }
      });
  public void setIndex(int index) {
    mIndex.setValue(index);
  }
  public LiveData<Integer> getText() {
    return mPagerIndex;
  }
}

قدم نهایی : تکمیل نمودن کلاس MainActivity

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.example.autoscrollviewpager.ui.main.AutoScrollPagerAdapter;
import com.google.android.material.tabs.TabLayout;
public class MainActivity extends AppCompatActivity {
  private static final int AUTO_SCROLL_THRESHOLD_IN_MILLI = 1000;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    AutoScrollPagerAdapter autoScrollPagerAdapter =
        new AutoScrollPagerAdapter(getSupportFragmentManager());
    AutoScrollViewPager viewPager = findViewById(R.id.view_pager);
    viewPager.setAdapter(autoScrollPagerAdapter);
    TabLayout tabs = findViewById(R.id.tabs);
    tabs.setupWithViewPager(viewPager);
    // start auto scroll
    viewPager.startAutoScroll();
    // set auto scroll time in mili
    viewPager.setInterval(AUTO_SCROLL_THRESHOLD_IN_MILLI);
    // enable recycling using true
    viewPager.setCycle(true);
  }
}

پیاده سازی ViewPager با قابلیت auto scroll | پیاده سازی ViewPager به صورت قدم به قدم

به این پست امتیاز دهید

روی ستاره های کلیک کنید و امتیاز بدید

میانگین امتیاز 3 / 5. تعداد: 2

از امتیاز شما متشکریم

2 دیدگاه در نوشته: “پیاده سازی ViewPager با قابلیت Auto Scroll در اندروید

  1. محمد گفت:

    سلام تمام این کد هارو خودتون نوشتید؟؟؟
    چند ساله برنامه نویسی اندروید رو شروع کردید؟؟؟

    1. نسیم نژند گفت:

      سلام
      تقریبا بله، ولی خب سرچ هم کردم بابت قسمت هایی که به مشکل خوردم
      برنامه نویسی رو با سی شروع کردم و الان نه ماهی میشه اندروید کار میکنم.

      ممنون از توجه شما

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

Enter Captcha Here : *

Reload Image