BannerViewPager.java 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  1. package com.zhpan.bannerview;
  2. import android.content.Context;
  3. import android.os.Build;
  4. import android.os.Handler;
  5. import androidx.annotation.ColorInt;
  6. import androidx.annotation.Nullable;
  7. import androidx.lifecycle.Lifecycle;
  8. import androidx.lifecycle.LifecycleObserver;
  9. import androidx.lifecycle.LifecycleRegistry;
  10. import androidx.lifecycle.OnLifecycleEvent;
  11. import androidx.recyclerview.widget.RecyclerView;
  12. import androidx.viewpager2.widget.CompositePageTransformer;
  13. import androidx.viewpager2.widget.MarginPageTransformer;
  14. import androidx.viewpager2.widget.ViewPager2;
  15. import android.util.AttributeSet;
  16. import android.view.MotionEvent;
  17. import android.view.View;
  18. import android.view.ViewGroup;
  19. import android.widget.RelativeLayout;
  20. import com.zhpan.bannerview.annotation.AIndicatorGravity;
  21. import com.zhpan.bannerview.annotation.APageStyle;
  22. import com.zhpan.bannerview.annotation.Visibility;
  23. import com.zhpan.bannerview.constants.PageStyle;
  24. import com.zhpan.bannerview.manager.BannerManager;
  25. import com.zhpan.bannerview.manager.BannerOptions;
  26. import com.zhpan.bannerview.provider.ScrollDurationManger;
  27. import com.zhpan.bannerview.transform.OverlapPageTransformer;
  28. import com.zhpan.bannerview.transform.ScaleInTransformer;
  29. import com.zhpan.bannerview.utils.BannerUtils;
  30. import com.zhpan.bannerview.provider.ViewStyleSetter;
  31. import com.zhpan.indicator.IndicatorView;
  32. import com.zhpan.indicator.annotation.AIndicatorSlideMode;
  33. import com.zhpan.indicator.annotation.AIndicatorStyle;
  34. import com.zhpan.indicator.base.IIndicator;
  35. import java.util.ArrayList;
  36. import java.util.List;
  37. import static com.zhpan.bannerview.BaseBannerAdapter.MAX_VALUE;
  38. import static com.zhpan.bannerview.constants.IndicatorGravity.CENTER;
  39. import static com.zhpan.bannerview.constants.IndicatorGravity.END;
  40. import static com.zhpan.bannerview.constants.IndicatorGravity.START;
  41. import static com.zhpan.bannerview.manager.BannerOptions.DEFAULT_REVEAL_WIDTH;
  42. import static com.zhpan.bannerview.transform.ScaleInTransformer.DEFAULT_MIN_SCALE;
  43. /**
  44. * Created by zhpan on 2017/3/28.
  45. */
  46. public class BannerViewPager<T, VH extends BaseViewHolder<T>> extends RelativeLayout implements LifecycleObserver {
  47. private int currentPosition;
  48. private boolean isCustomIndicator;
  49. private boolean isLooping;
  50. private OnPageClickListener mOnPageClickListener;
  51. private IIndicator mIndicatorView;
  52. private RelativeLayout mIndicatorLayout;
  53. private ViewPager2 mViewPager;
  54. private BannerManager mBannerManager;
  55. private Handler mHandler = new Handler();
  56. private BaseBannerAdapter<T, VH> mBannerPagerAdapter;
  57. private ViewPager2.OnPageChangeCallback onPageChangeCallback;
  58. private Runnable mRunnable = new Runnable() {
  59. @Override
  60. public void run() {
  61. handlePosition();
  62. }
  63. };
  64. private int startX, startY;
  65. private CompositePageTransformer mCompositePageTransformer;
  66. private MarginPageTransformer mMarginPageTransformer;
  67. private ViewPager2.PageTransformer mDefaultPageTransformer;
  68. private ViewPager2.OnPageChangeCallback mOnPageChangeCallback = new ViewPager2.OnPageChangeCallback() {
  69. @Override
  70. public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
  71. super.onPageScrolled(position, positionOffset, positionOffsetPixels);
  72. int listSize = mBannerPagerAdapter.getListSize();
  73. int realPosition = BannerUtils.getRealPosition(isCanLoop(), position, listSize);
  74. if (listSize > 0) {
  75. if (onPageChangeCallback != null) {
  76. onPageChangeCallback.onPageScrolled(realPosition, positionOffset, positionOffsetPixels);
  77. }
  78. if (mIndicatorView != null) {
  79. mIndicatorView.onPageScrolled(realPosition, positionOffset, positionOffsetPixels);
  80. }
  81. }
  82. }
  83. @Override
  84. public void onPageSelected(int position) {
  85. super.onPageSelected(position);
  86. int size = mBannerPagerAdapter.getListSize();
  87. currentPosition = BannerUtils.getRealPosition(isCanLoop(), position, size);
  88. if (size > 0 && isCanLoop() && position == 0 || position == MAX_VALUE - 1) {
  89. resetCurrentItem(currentPosition);
  90. }
  91. if (onPageChangeCallback != null) {
  92. onPageChangeCallback.onPageSelected(currentPosition);
  93. }
  94. if (mIndicatorView != null) {
  95. mIndicatorView.onPageSelected(currentPosition);
  96. }
  97. }
  98. @Override
  99. public void onPageScrollStateChanged(int state) {
  100. super.onPageScrollStateChanged(state);
  101. if (mIndicatorView != null) {
  102. mIndicatorView.onPageScrollStateChanged(state);
  103. }
  104. if (onPageChangeCallback != null) {
  105. onPageChangeCallback.onPageScrollStateChanged(state);
  106. }
  107. }
  108. };
  109. public BannerViewPager(Context context) {
  110. this(context, null);
  111. }
  112. public BannerViewPager(Context context, AttributeSet attrs) {
  113. this(context, attrs, 0);
  114. }
  115. public BannerViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
  116. super(context, attrs, defStyleAttr);
  117. init(context, attrs);
  118. }
  119. private void init(Context context, AttributeSet attrs) {
  120. mCompositePageTransformer = new CompositePageTransformer();
  121. mBannerManager = new BannerManager();
  122. mBannerManager.initAttrs(context, attrs);
  123. initView();
  124. }
  125. private void initView() {
  126. inflate(getContext(), R.layout.bvp_layout, this);
  127. mViewPager = findViewById(R.id.vp_main);
  128. mIndicatorLayout = findViewById(R.id.bvp_layout_indicator);
  129. mViewPager.setPageTransformer(mCompositePageTransformer);
  130. }
  131. @Override
  132. protected void onDetachedFromWindow() {
  133. // stopLoop();
  134. super.onDetachedFromWindow();
  135. }
  136. @Override
  137. protected void onAttachedToWindow() {
  138. super.onAttachedToWindow();
  139. // startLoop();
  140. }
  141. @Override
  142. public boolean dispatchTouchEvent(MotionEvent ev) {
  143. switch (ev.getAction()) {
  144. case MotionEvent.ACTION_DOWN:
  145. isLooping = true;
  146. stopLoop();
  147. break;
  148. case MotionEvent.ACTION_UP:
  149. case MotionEvent.ACTION_CANCEL:
  150. case MotionEvent.ACTION_OUTSIDE:
  151. isLooping = false;
  152. startLoop();
  153. break;
  154. default:
  155. break;
  156. }
  157. return super.dispatchTouchEvent(ev);
  158. }
  159. @Override
  160. public boolean onInterceptTouchEvent(MotionEvent ev) {
  161. boolean canIntercept = mViewPager.isUserInputEnabled() || mBannerPagerAdapter != null && mBannerPagerAdapter.getData().size() <= 1;
  162. if (!canIntercept) {
  163. return super.onInterceptTouchEvent(ev);
  164. }
  165. switch (ev.getAction()) {
  166. case MotionEvent.ACTION_DOWN:
  167. startX = (int) ev.getX();
  168. startY = (int) ev.getY();
  169. break;
  170. case MotionEvent.ACTION_MOVE:
  171. int endX = (int) ev.getX();
  172. int endY = (int) ev.getY();
  173. int disX = Math.abs(endX - startX);
  174. int disY = Math.abs(endY - startY);
  175. int orientation = mBannerManager.getBannerOptions().getOrientation();
  176. if (orientation == ViewPager2.ORIENTATION_VERTICAL) {
  177. onVerticalActionMove(endY, disX, disY);
  178. } else if (orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
  179. onHorizontalActionMove(endX, disX, disY);
  180. }
  181. break;
  182. case MotionEvent.ACTION_UP:
  183. case MotionEvent.ACTION_CANCEL:
  184. getParent().requestDisallowInterceptTouchEvent(false);
  185. break;
  186. case MotionEvent.ACTION_OUTSIDE:
  187. default:
  188. break;
  189. }
  190. return super.onInterceptTouchEvent(ev);
  191. }
  192. private void onVerticalActionMove(int endY, int disX, int disY) {
  193. if (disY > disX) {
  194. if (!isCanLoop()) {
  195. if (currentPosition == 0 && endY - startY > 0) {
  196. getParent().requestDisallowInterceptTouchEvent(false);
  197. } else if (currentPosition == getData().size() - 1 && endY - startY < 0) {
  198. getParent().requestDisallowInterceptTouchEvent(false);
  199. } else {
  200. getParent().requestDisallowInterceptTouchEvent(true);
  201. }
  202. } else {
  203. getParent().requestDisallowInterceptTouchEvent(true);
  204. }
  205. } else if (disX > disY) {
  206. getParent().requestDisallowInterceptTouchEvent(false);
  207. }
  208. }
  209. private void onHorizontalActionMove(int endX, int disX, int disY) {
  210. if (disX > disY) {
  211. if (!isCanLoop()) {
  212. if (currentPosition == 0 && endX - startX > 0) {
  213. getParent().requestDisallowInterceptTouchEvent(false);
  214. } else if (currentPosition == getData().size() - 1 && endX - startX < 0) {
  215. getParent().requestDisallowInterceptTouchEvent(false);
  216. } else {
  217. getParent().requestDisallowInterceptTouchEvent(true);
  218. }
  219. } else {
  220. getParent().requestDisallowInterceptTouchEvent(true);
  221. }
  222. } else if (disY > disX) {
  223. getParent().requestDisallowInterceptTouchEvent(false);
  224. }
  225. }
  226. private void handlePosition() {
  227. if (mBannerPagerAdapter.getListSize() > 1 && isAutoPlay()) {
  228. mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
  229. mHandler.postDelayed(mRunnable, getInterval());
  230. }
  231. }
  232. private void initBannerData() {
  233. List<T> list = mBannerPagerAdapter.getData();
  234. if (list != null) {
  235. setIndicatorValues(list);
  236. setupViewPager(list);
  237. initRoundCorner();
  238. }
  239. }
  240. private void setIndicatorValues(List<T> list) {
  241. mIndicatorLayout.setVisibility(mBannerManager.getBannerOptions().getIndicatorVisibility());
  242. BannerOptions bannerOptions = mBannerManager.getBannerOptions();
  243. bannerOptions.resetIndicatorOptions();
  244. if (isCustomIndicator && null != mIndicatorView) {
  245. initIndicator(mIndicatorView);
  246. } else {
  247. initIndicator(new IndicatorView(getContext()));
  248. }
  249. mIndicatorView.setIndicatorOptions(bannerOptions.getIndicatorOptions());
  250. bannerOptions.getIndicatorOptions().setPageSize(list.size());
  251. mIndicatorView.notifyDataChanged();
  252. }
  253. private void initIndicator(IIndicator indicatorView) {
  254. mIndicatorView = indicatorView;
  255. if (((View) mIndicatorView).getParent() == null) {
  256. mIndicatorLayout.removeAllViews();
  257. mIndicatorLayout.addView((View) mIndicatorView);
  258. initIndicatorViewMargin();
  259. initIndicatorGravity();
  260. }
  261. }
  262. private void initIndicatorGravity() {
  263. RelativeLayout.LayoutParams layoutParams =
  264. (RelativeLayout.LayoutParams) ((View) mIndicatorView).getLayoutParams();
  265. switch (mBannerManager.getBannerOptions().getIndicatorGravity()) {
  266. case CENTER:
  267. layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
  268. break;
  269. case START:
  270. layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
  271. break;
  272. case END:
  273. layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
  274. break;
  275. default:
  276. break;
  277. }
  278. }
  279. private void initIndicatorViewMargin() {
  280. ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) ((View) mIndicatorView).getLayoutParams();
  281. BannerOptions.IndicatorMargin indicatorMargin = mBannerManager.getBannerOptions().getIndicatorMargin();
  282. if (indicatorMargin == null) {
  283. int dp10 = BannerUtils.dp2px(10);
  284. layoutParams.setMargins(dp10, dp10, dp10, dp10);
  285. } else {
  286. layoutParams.setMargins(indicatorMargin.getLeft(), indicatorMargin.getTop(),
  287. indicatorMargin.getRight(), indicatorMargin.getBottom());
  288. }
  289. }
  290. private void initRoundCorner() {
  291. int roundCorner = mBannerManager.getBannerOptions().getRoundRectRadius();
  292. if (roundCorner > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  293. ViewStyleSetter viewStyleSetter = new ViewStyleSetter(this);
  294. viewStyleSetter.setRoundRect(roundCorner);
  295. }
  296. }
  297. private void setupViewPager(List<T> list) {
  298. if (mBannerPagerAdapter == null) {
  299. throw new NullPointerException("You must set adapter for BannerViewPager");
  300. }
  301. BannerOptions bannerOptions = mBannerManager.getBannerOptions();
  302. if (bannerOptions.getScrollDuration() != 0) {
  303. ScrollDurationManger.reflectLayoutManager(mViewPager, bannerOptions.getScrollDuration());
  304. }
  305. if (bannerOptions.getRightRevealWidth() != DEFAULT_REVEAL_WIDTH || bannerOptions.getLeftRevealWidth() != DEFAULT_REVEAL_WIDTH) {
  306. RecyclerView recyclerView = (RecyclerView) mViewPager.getChildAt(0);
  307. int orientation = bannerOptions.getOrientation();
  308. int padding2 = bannerOptions.getPageMargin() + bannerOptions.getRightRevealWidth();
  309. int padding1 = bannerOptions.getPageMargin() + bannerOptions.getLeftRevealWidth();
  310. if (orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
  311. recyclerView.setPadding(padding1, 0, padding2, 0);
  312. } else if (orientation == ViewPager2.ORIENTATION_VERTICAL) {
  313. recyclerView.setPadding(0, padding1, 0, padding2);
  314. }
  315. recyclerView.setClipToPadding(false);
  316. }
  317. currentPosition = 0;
  318. mBannerPagerAdapter.setCanLoop(isCanLoop());
  319. mBannerPagerAdapter.setPageClickListener(mOnPageClickListener);
  320. mViewPager.setAdapter(mBannerPagerAdapter);
  321. if (list.size() > 1 && isCanLoop()) {
  322. mViewPager.setCurrentItem(MAX_VALUE / 2 - ((MAX_VALUE / 2) % list.size()) + 1, false);
  323. }
  324. mViewPager.unregisterOnPageChangeCallback(mOnPageChangeCallback);
  325. mViewPager.registerOnPageChangeCallback(mOnPageChangeCallback);
  326. mViewPager.setOrientation(bannerOptions.getOrientation());
  327. mViewPager.setOffscreenPageLimit(bannerOptions.getOffScreenPageLimit());
  328. initPageStyle();
  329. startLoop();
  330. }
  331. private void initPageStyle() {
  332. switch (mBannerManager.getBannerOptions().getPageStyle()) {
  333. case PageStyle.MULTI_PAGE_OVERLAP:
  334. setMultiPageStyle(true, mBannerManager.getBannerOptions().getPageScale());
  335. break;
  336. case PageStyle.MULTI_PAGE_SCALE:
  337. setMultiPageStyle(false, mBannerManager.getBannerOptions().getPageScale());
  338. break;
  339. default:
  340. break;
  341. }
  342. }
  343. private void setMultiPageStyle(boolean overlap, float scale) {
  344. if (mDefaultPageTransformer != null) {
  345. mCompositePageTransformer.removeTransformer(mDefaultPageTransformer);
  346. }
  347. if (overlap && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  348. mDefaultPageTransformer = new OverlapPageTransformer(mBannerManager.getBannerOptions().getOrientation(), scale, 0f, 1, 0);
  349. } else {
  350. mDefaultPageTransformer = new ScaleInTransformer(scale);
  351. }
  352. addPageTransformer(mDefaultPageTransformer);
  353. }
  354. private void resetCurrentItem(int item) {
  355. if (isCanLoop() && mBannerPagerAdapter.getListSize() > 1) {
  356. mViewPager.setCurrentItem(MAX_VALUE / 2 - ((MAX_VALUE / 2) % mBannerPagerAdapter.getListSize()) + 1 + item, false);
  357. } else {
  358. mViewPager.setCurrentItem(item, false);
  359. }
  360. }
  361. private int getInterval() {
  362. return mBannerManager.getBannerOptions().getInterval();
  363. }
  364. private boolean isAutoPlay() {
  365. return mBannerManager.getBannerOptions().isAutoPlay();
  366. }
  367. private boolean isCanLoop() {
  368. return mBannerManager.getBannerOptions().isCanLoop();
  369. }
  370. /**
  371. * @return BannerViewPager data set
  372. */
  373. public List<T> getData() {
  374. return mBannerPagerAdapter.getData();
  375. }
  376. /**
  377. * Start loop
  378. */
  379. public void startLoop() {
  380. if (!isLooping && isAutoPlay() && mBannerPagerAdapter != null &&
  381. mBannerPagerAdapter.getListSize() > 1) {
  382. mHandler.postDelayed(mRunnable, getInterval());
  383. isLooping = true;
  384. }
  385. }
  386. /**
  387. * stoop loop
  388. */
  389. public void stopLoop() {
  390. if (isLooping) {
  391. mHandler.removeCallbacks(mRunnable);
  392. isLooping = false;
  393. }
  394. }
  395. public BannerViewPager<T, VH> setAdapter(BaseBannerAdapter<T, VH> adapter) {
  396. this.mBannerPagerAdapter = adapter;
  397. return this;
  398. }
  399. public BaseBannerAdapter<T, VH> getAdapter() {
  400. return mBannerPagerAdapter;
  401. }
  402. /**
  403. * Set round rectangle effect for BannerViewPager.
  404. * <p>
  405. * Require SDK_INT>=LOLLIPOP(API 21)
  406. *
  407. * @param radius round radius
  408. */
  409. public BannerViewPager<T, VH> setRoundCorner(int radius) {
  410. mBannerManager.getBannerOptions().setRoundRectRadius(radius);
  411. return this;
  412. }
  413. /**
  414. * Set round rectangle effect for BannerViewPager.
  415. * <p>
  416. * Require SDK_INT>=LOLLIPOP(API 21)
  417. *
  418. * @param radius round radius
  419. */
  420. public BannerViewPager<T, VH> setRoundRect(int radius) {
  421. setRoundCorner(radius);
  422. return this;
  423. }
  424. /**
  425. * Enable/disable auto play
  426. *
  427. * @param autoPlay is enable auto play
  428. */
  429. public BannerViewPager<T, VH> setAutoPlay(boolean autoPlay) {
  430. mBannerManager.getBannerOptions().setAutoPlay(autoPlay);
  431. if (isAutoPlay()) {
  432. mBannerManager.getBannerOptions().setCanLoop(true);
  433. }
  434. return this;
  435. }
  436. /**
  437. * Enable/disable loop
  438. *
  439. * @param canLoop is can loop
  440. */
  441. public BannerViewPager<T, VH> setCanLoop(boolean canLoop) {
  442. mBannerManager.getBannerOptions().setCanLoop(canLoop);
  443. if (!canLoop) {
  444. mBannerManager.getBannerOptions().setAutoPlay(false);
  445. }
  446. return this;
  447. }
  448. /**
  449. * Set loop interval
  450. *
  451. * @param interval loop interval,unit is millisecond.
  452. */
  453. public BannerViewPager<T, VH> setInterval(int interval) {
  454. mBannerManager.getBannerOptions().setInterval(interval);
  455. return this;
  456. }
  457. /**
  458. * @param transformer PageTransformer that will modify each page's animation properties
  459. */
  460. public BannerViewPager<T, VH> setPageTransformer(@Nullable ViewPager2.PageTransformer transformer) {
  461. if (transformer != null) {
  462. mViewPager.setPageTransformer(transformer);
  463. }
  464. return this;
  465. }
  466. /**
  467. * @param transformer PageTransformer that will modify each page's animation properties
  468. */
  469. public BannerViewPager<T, VH> addPageTransformer(@Nullable ViewPager2.PageTransformer transformer) {
  470. if (transformer != null) {
  471. mCompositePageTransformer.addTransformer(transformer);
  472. }
  473. return this;
  474. }
  475. public void removeTransformer(@Nullable ViewPager2.PageTransformer transformer) {
  476. if (transformer != null) {
  477. mCompositePageTransformer.removeTransformer(transformer);
  478. }
  479. }
  480. public void removeDefaultPageTransformer() {
  481. if (mDefaultPageTransformer != null) {
  482. mCompositePageTransformer.removeTransformer(mDefaultPageTransformer);
  483. }
  484. }
  485. public void removeMarginPageTransformer() {
  486. if (mMarginPageTransformer != null) {
  487. mCompositePageTransformer.removeTransformer(mMarginPageTransformer);
  488. }
  489. }
  490. /**
  491. * set page margin
  492. *
  493. * @param pageMargin page margin
  494. */
  495. public BannerViewPager<T, VH> setPageMargin(int pageMargin) {
  496. mBannerManager.getBannerOptions().setPageMargin(pageMargin);
  497. if (mMarginPageTransformer != null) {
  498. mCompositePageTransformer.removeTransformer(mMarginPageTransformer);
  499. }
  500. mMarginPageTransformer = new MarginPageTransformer(pageMargin);
  501. mCompositePageTransformer.addTransformer(mMarginPageTransformer);
  502. return this;
  503. }
  504. /**
  505. * set item click listener
  506. *
  507. * @param onPageClickListener item click listener
  508. */
  509. public BannerViewPager<T, VH> setOnPageClickListener(OnPageClickListener onPageClickListener) {
  510. this.mOnPageClickListener = onPageClickListener;
  511. return this;
  512. }
  513. /**
  514. * Set page scroll duration
  515. *
  516. * @param scrollDuration page scroll duration
  517. */
  518. public BannerViewPager<T, VH> setScrollDuration(int scrollDuration) {
  519. mBannerManager.getBannerOptions().setScrollDuration(scrollDuration);
  520. return this;
  521. }
  522. /**
  523. * set indicator color
  524. *
  525. * @param checkedColor checked color of indicator
  526. * @param normalColor unchecked color of indicator
  527. */
  528. public BannerViewPager<T, VH> setIndicatorSliderColor(@ColorInt int normalColor,
  529. @ColorInt int checkedColor) {
  530. mBannerManager.getBannerOptions().setIndicatorSliderColor(normalColor, checkedColor);
  531. return this;
  532. }
  533. /**
  534. * set indicator circle radius
  535. * <p>
  536. * if the indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#DASH}
  537. * or {@link com.zhpan.indicator.enums.IndicatorStyle#ROUND_RECT}
  538. * the indicator dash width=2*radius
  539. *
  540. * @param radius 指示器圆点半径
  541. */
  542. public BannerViewPager<T, VH> setIndicatorSliderRadius(int radius) {
  543. setIndicatorSliderRadius(radius, radius);
  544. return this;
  545. }
  546. /**
  547. * set indicator circle radius
  548. *
  549. * @param normalRadius unchecked circle radius
  550. * @param checkedRadius checked circle radius
  551. */
  552. public BannerViewPager<T, VH> setIndicatorSliderRadius(int normalRadius, int checkedRadius) {
  553. mBannerManager.getBannerOptions().setIndicatorSliderWidth(normalRadius * 2, checkedRadius * 2);
  554. return this;
  555. }
  556. public BannerViewPager<T, VH> setIndicatorSliderWidth(int indicatorWidth) {
  557. setIndicatorSliderWidth(indicatorWidth, indicatorWidth);
  558. return this;
  559. }
  560. /**
  561. * Set indicator dash width,if indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#CIRCLE},
  562. * the indicator circle radius is indicatorWidth/2.
  563. *
  564. * @param normalWidth if the indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#DASH} the params means unchecked dash width
  565. * if the indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#ROUND_RECT} means unchecked round rectangle width
  566. * if the indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#CIRCLE } means unchecked circle diameter
  567. * @param checkWidth if the indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#DASH} the params means checked dash width
  568. * if the indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#ROUND_RECT} the params means checked round rectangle width
  569. * if the indicator style is {@link com.zhpan.indicator.enums.IndicatorStyle#CIRCLE } means checked circle diameter
  570. */
  571. public BannerViewPager<T, VH> setIndicatorSliderWidth(int normalWidth, int checkWidth) {
  572. mBannerManager.getBannerOptions().setIndicatorSliderWidth(normalWidth, checkWidth);
  573. return this;
  574. }
  575. public BannerViewPager<T, VH> setIndicatorHeight(int indicatorHeight) {
  576. mBannerManager.getBannerOptions().setIndicatorHeight(indicatorHeight);
  577. return this;
  578. }
  579. /**
  580. * Set Indicator gap of dash/circle
  581. *
  582. * @param indicatorGap indicator gap
  583. */
  584. public BannerViewPager<T, VH> setIndicatorSliderGap(int indicatorGap) {
  585. mBannerManager.getBannerOptions().setIndicatorGap(indicatorGap);
  586. return this;
  587. }
  588. /**
  589. * Set the visibility state of indicator view.
  590. *
  591. * @param visibility One of {@link View#VISIBLE}, {@link View#INVISIBLE}, or {@link View#GONE}.
  592. */
  593. public BannerViewPager<T, VH> setIndicatorVisibility(@Visibility int visibility) {
  594. mBannerManager.getBannerOptions().setIndicatorVisibility(visibility);
  595. return this;
  596. }
  597. /**
  598. * set indicator gravity in BannerViewPager
  599. *
  600. * @param gravity indicator gravity
  601. * {@link com.zhpan.bannerview.constants.IndicatorGravity#CENTER}
  602. * {@link com.zhpan.bannerview.constants.IndicatorGravity#START}
  603. * {@link com.zhpan.bannerview.constants.IndicatorGravity#END}
  604. */
  605. public BannerViewPager<T, VH> setIndicatorGravity(@AIndicatorGravity int gravity) {
  606. mBannerManager.getBannerOptions().setIndicatorGravity(gravity);
  607. return this;
  608. }
  609. /**
  610. * Set Indicator slide mode,default value is {@link com.zhpan.indicator.enums.IndicatorSlideMode#NORMAL}
  611. *
  612. * @param slideMode Indicator slide mode
  613. * @see com.zhpan.indicator.enums.IndicatorSlideMode#NORMAL
  614. * @see com.zhpan.indicator.enums.IndicatorSlideMode#SMOOTH
  615. */
  616. public BannerViewPager<T, VH> setIndicatorSlideMode(@AIndicatorSlideMode int slideMode) {
  617. mBannerManager.getBannerOptions().setIndicatorSlideMode(slideMode);
  618. return this;
  619. }
  620. /**
  621. * Set custom indicator.
  622. * the custom indicator view must extends BaseIndicator or implements IIndicator
  623. *
  624. * @param customIndicator custom indicator view
  625. */
  626. public BannerViewPager<T, VH> setIndicatorView(IIndicator customIndicator) {
  627. if (customIndicator instanceof View) {
  628. isCustomIndicator = true;
  629. mIndicatorView = customIndicator;
  630. }
  631. return this;
  632. }
  633. /**
  634. * Set indicator style
  635. *
  636. * @param indicatorStyle indicator style
  637. * @see com.zhpan.indicator.enums.IndicatorStyle#CIRCLE
  638. * @see com.zhpan.indicator.enums.IndicatorStyle#DASH
  639. * @see com.zhpan.indicator.enums.IndicatorStyle#ROUND_RECT
  640. */
  641. public BannerViewPager<T, VH> setIndicatorStyle(@AIndicatorStyle int indicatorStyle) {
  642. mBannerManager.getBannerOptions().setIndicatorStyle(indicatorStyle);
  643. return this;
  644. }
  645. /**
  646. * Create BannerViewPager with data.
  647. * If data has fetched when create BannerViewPager,you can call this method.
  648. */
  649. public void create(List<T> data) {
  650. if (mBannerPagerAdapter == null) {
  651. throw new NullPointerException("You must set adapter for BannerViewPager");
  652. }
  653. mBannerPagerAdapter.setData(data);
  654. initBannerData();
  655. }
  656. /**
  657. * Create BannerViewPager with no data
  658. * If there is no data while you create BannerViewPager(for example,The data is from remote server),you can call this method.
  659. * Then,while you fetch data successfully,just need call {@link #refreshData(List)} method to refresh.
  660. */
  661. public void create() {
  662. create(new ArrayList<T>());
  663. }
  664. /**
  665. * Sets the orientation of the ViewPager2.
  666. *
  667. * @param orientation {@link androidx.viewpager2.widget.ViewPager2#ORIENTATION_HORIZONTAL} or
  668. * {@link androidx.viewpager2.widget.ViewPager2#ORIENTATION_VERTICAL}
  669. */
  670. public BannerViewPager<T, VH> setOrientation(@ViewPager2.Orientation int orientation) {
  671. mBannerManager.getBannerOptions().setOrientation(orientation);
  672. return this;
  673. }
  674. /**
  675. * Refresh data.
  676. * Confirm the {@link #create()} or {@link #create(List)} method has been called,
  677. * else the data won't be shown.
  678. */
  679. public void refreshData(List<T> list) {
  680. if (list != null && mBannerPagerAdapter != null) {
  681. stopLoop();
  682. mBannerPagerAdapter.setData(list);
  683. mBannerPagerAdapter.notifyDataSetChanged();
  684. resetCurrentItem(getCurrentItem());
  685. setIndicatorValues(list);
  686. mBannerManager.getBannerOptions().getIndicatorOptions()
  687. .setCurrentPosition(BannerUtils.getRealPosition(isCanLoop(),
  688. mViewPager.getCurrentItem(), list.size()));
  689. mIndicatorView.notifyDataChanged();
  690. startLoop();
  691. }
  692. }
  693. /**
  694. * @return the currently selected page position.
  695. */
  696. public int getCurrentItem() {
  697. return currentPosition;
  698. }
  699. /**
  700. * Set the currently selected page. If the ViewPager has already been through its first
  701. * layout with its current adapter there will be a smooth animated transition between
  702. * the current item and the specified item.
  703. *
  704. * @param item Item index to select
  705. */
  706. public void setCurrentItem(int item) {
  707. if (isCanLoop() && mBannerPagerAdapter.getListSize() > 1) {
  708. int currentItem = mViewPager.getCurrentItem();
  709. int pageSize = mBannerPagerAdapter.getListSize();
  710. int realPosition = BannerUtils.getRealPosition(isCanLoop(), currentItem, mBannerPagerAdapter.getListSize());
  711. if (currentItem != item) {
  712. if (item == 0 && realPosition == pageSize - 1) {
  713. mViewPager.setCurrentItem(currentItem + 1);
  714. } else if (realPosition == 0 && item == pageSize - 1) {
  715. mViewPager.setCurrentItem(currentItem - 1);
  716. } else {
  717. mViewPager.setCurrentItem(currentItem + (item - realPosition));
  718. }
  719. mViewPager.setCurrentItem(currentItem + (item - realPosition));
  720. }
  721. } else {
  722. mViewPager.setCurrentItem(item);
  723. }
  724. }
  725. /**
  726. * Set the currently selected page.
  727. *
  728. * @param item Item index to select
  729. * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
  730. */
  731. public void setCurrentItem(int item, boolean smoothScroll) {
  732. if (isCanLoop() && mBannerPagerAdapter.getListSize() > 1) {
  733. int pageSize = mBannerPagerAdapter.getListSize();
  734. int currentItem = mViewPager.getCurrentItem();
  735. int realPosition = BannerUtils.getRealPosition(isCanLoop(), currentItem, pageSize);
  736. if (currentItem != item) {
  737. if (item == 0 && realPosition == pageSize - 1) {
  738. mViewPager.setCurrentItem(currentItem + 1, smoothScroll);
  739. } else if (realPosition == 0 && item == pageSize - 1) {
  740. mViewPager.setCurrentItem(currentItem - 1, smoothScroll);
  741. } else {
  742. mViewPager.setCurrentItem(currentItem + (item - realPosition), smoothScroll);
  743. }
  744. }
  745. } else {
  746. mViewPager.setCurrentItem(item, smoothScroll);
  747. }
  748. }
  749. /**
  750. * Set Page Style for Banner
  751. * {@link PageStyle#NORMAL}
  752. * {@link PageStyle#MULTI_PAGE}
  753. *
  754. * @return BannerViewPager
  755. */
  756. public BannerViewPager<T, VH> setPageStyle(@APageStyle int pageStyle) {
  757. return setPageStyle(pageStyle, DEFAULT_MIN_SCALE);
  758. }
  759. public BannerViewPager<T, VH> setPageStyle(@APageStyle int pageStyle, float pageScale) {
  760. mBannerManager.getBannerOptions().setPageStyle(pageStyle);
  761. mBannerManager.getBannerOptions().setPageScale(pageScale);
  762. return this;
  763. }
  764. /**
  765. * @param revealWidth 一屏多页模式下两边页面显露出来的宽度
  766. */
  767. public BannerViewPager<T, VH> setRevealWidth(int revealWidth) {
  768. setRevealWidth(revealWidth, revealWidth);
  769. return this;
  770. }
  771. /**
  772. * @param leftRevealWidth left page item reveal width
  773. * @param rightRevealWidth right page item reveal width
  774. */
  775. public BannerViewPager<T, VH> setRevealWidth(int leftRevealWidth, int rightRevealWidth) {
  776. mBannerManager.getBannerOptions().setRightRevealWidth(rightRevealWidth);
  777. mBannerManager.getBannerOptions().setLeftRevealWidth(leftRevealWidth);
  778. return this;
  779. }
  780. /**
  781. * Suggest to use default offScreenPageLimit.
  782. */
  783. public BannerViewPager<T, VH> setOffScreenPageLimit(int offScreenPageLimit) {
  784. mBannerManager.getBannerOptions().setOffScreenPageLimit(offScreenPageLimit);
  785. return this;
  786. }
  787. public BannerViewPager<T, VH> setIndicatorMargin(int left, int top, int right, int bottom) {
  788. mBannerManager.getBannerOptions().setIndicatorMargin(left, top, right, bottom);
  789. return this;
  790. }
  791. /**
  792. * Enable or disable user initiated scrolling
  793. */
  794. public BannerViewPager<T, VH> setUserInputEnabled(boolean userInputEnabled) {
  795. mBannerManager.getBannerOptions().setUserInputEnabled(userInputEnabled);
  796. mViewPager.setUserInputEnabled(userInputEnabled);
  797. return this;
  798. }
  799. public interface OnPageClickListener {
  800. void onPageClick(int position);
  801. }
  802. public BannerViewPager<T, VH> registerOnPageChangeCallback(ViewPager2.OnPageChangeCallback onPageChangeCallback) {
  803. this.onPageChangeCallback = onPageChangeCallback;
  804. return this;
  805. }
  806. /**
  807. * @param showIndicator is show indicator
  808. * @deprecated Use {@link #setIndicatorVisibility(int)} instead.
  809. */
  810. @Deprecated
  811. public BannerViewPager<T, VH> showIndicator(boolean showIndicator) {
  812. mIndicatorLayout.setVisibility(showIndicator ? VISIBLE : GONE);
  813. return this;
  814. }
  815. /**
  816. * @deprecated user {@link #setUserInputEnabled(boolean)} instead.
  817. */
  818. @Deprecated
  819. public BannerViewPager<T, VH> disableTouchScroll(boolean disableTouchScroll) {
  820. mBannerManager.getBannerOptions().setUserInputEnabled(!disableTouchScroll);
  821. return this;
  822. }
  823. public BannerViewPager<T, VH> setLifecycleRegistry(Lifecycle lifecycleRegistry) {
  824. lifecycleRegistry.addObserver(this);
  825. return this;
  826. }
  827. @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
  828. public void onPause() {
  829. stopLoop();
  830. }
  831. @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
  832. public void onResume() {
  833. startLoop();
  834. }
  835. }