android?viewpager實(shí)現(xiàn)輪播效果
本文是基于ViewPager實(shí)現(xiàn)的無限自動輪播banner,供大家參考,具體內(nèi)容如下
分為四步去實(shí)現(xiàn):
第一步是有限手動輪播;
第二步是無限輪播;
第三步是自動輪播;
第四步是指示器適配
第一步:有限手動輪播實(shí)現(xiàn)
布局:
<androidx.viewpager.widget.ViewPager ? ? android:id="@+id/banner" ? ? android:layout_width="match_parent" ? ? android:layout_height="wrap_content" ? ? android:layout_marginStart="12dp" ? ? android:layout_marginEnd="12dp" />
adapter實(shí)現(xiàn):
public class BannerAdapter extends PagerAdapter { ? ?? ? ? private List<String> bannerList; ? ? ? public BannerAdapter(List<String> bannerList) { ? ? ? ? this.bannerList = bannerList; ? ? } ? ? ? @Override ? ? public int getCount() { ? ? ? ? return bannerList.size(); ? ? } ? ? ? @Override ? ? public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { ? ? ? ? return view == object; ? ? } ? ? ? @NonNull ? ? @Override ? ? public Object instantiateItem(@NonNull ViewGroup container, int position) { ? ? ? ? ImageView bannerImageView = new ImageView(container.getContext()); ? ? ? ? ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); ? ? ? ? bannerImageView.setLayoutParams(lp); ? ? ? ? bannerImageView.setScaleType(ImageView.ScaleType.FIT_XY); ? ? ? ? Glide.with(container.getContext()).load(bannerList.get(position)).into(bannerImageView); ? ? ? ? ? container.addView(bannerImageView); ? ? ? ? return bannerImageView; ? ? } ? ? ? @Override ? ? public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { ? ? ? ? container.removeView((View) object); ? ? } }
Activity中:
// scrollview中viewpager一定要設(shè)置高度,此處根據(jù)圖片的寬高比來設(shè)定高度 ? int bannerWidth = (Utils.getScreenWidth(getContext()) - Utils.dip2pixel(getContext(), 24)); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) bannerView.getLayoutParams(); lp.width = LinearLayout.LayoutParams.MATCH_PARENT; lp.height = (int) (bannerWidth * 90f / 345); bannerView.setLayoutParams(lp); ? bannerView.setAdapter(new BannerAdapter(getUrlList()));
注意:ScrollView包裹ViewPager時(shí),ViewPager的高度一定要有確定值,否則內(nèi)容無法加載出來,可以在xml中指定,也可以代碼設(shè)定,但一定要有確定值。
第二步:無限輪播
無限輪播只需要在有限輪播的基礎(chǔ)上,做以下兩個(gè)改動點(diǎn),修改getCount返回值且在加載數(shù)據(jù)時(shí)獲取正確的數(shù)據(jù)源即可
public class BannerAdapter extends PagerAdapter { ? ? ? private List<String> bannerList; ? ? ? public BannerAdapter(List<String> bannerList) { ? ? ? ? this.bannerList = bannerList; ? ? } ? ? ? @Override ? ? public int getCount() { // ? ? ? ?return bannerList.size(); ?// before ? ? ? ? return Integer.MAX_VALUE; ? // now ? ? } ? ? ? @Override ? ? public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { ? ? ? ? return view == object; ? ? } ? ? ? @NonNull ? ? @Override ? ? public Object instantiateItem(@NonNull ViewGroup container, int position) { ? ? ? ? ImageView bannerImageView = new ImageView(container.getContext()); ? ? ? ? int realPosition = position % bannerList.size(); // 獲取要加載數(shù)據(jù)的真實(shí)位置 ? ? ? ? ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); ? ? ? ? bannerImageView.setLayoutParams(lp); ? ? ? ? bannerImageView.setScaleType(ImageView.ScaleType.FIT_XY); // ? ? ? ?Glide.with(container.getContext()).load(bannerList.get(position)).into(bannerImageView); // before ? ? ? ? Glide.with(container.getContext()).load(bannerList.get(realPosition)).into(bannerImageView); // now ? ? ? ? ? container.addView(bannerImageView); ? ? ? ? return bannerImageView; ? ? } ? ? ? @Override ? ? public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { ? ? ? ? container.removeView((View) object); ? ? } }
修改完發(fā)現(xiàn)banner只能向右無限輪播,第一次左滑滑不動,這個(gè)時(shí)候我們強(qiáng)制設(shè)置viewpager位置在中間就可以解決這個(gè)問題了
bannerView.setAdapter(new BannerAdapter(getUrlList())); bannerView.setCurrentItem(getUrlList().size() * 5);
第三步:自動輪播
handler每隔輪播間隔發(fā)送消息,設(shè)置viewpager為下一個(gè)位置
private Runnable bannerRunnable = new Runnable() { ? ? ? ? @Override ? ? ? ? public void run() { ? ? ? ? ? ? bannerView.setCurrentItem(bannerView.getCurrentItem() + 1); ? ? ? ? ? ? mHandler.postDelayed(bannerRunnable, 3000); ? ? ? ? } ? ? }; ? bannerView.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { ? ? ? ? ? ? ? } ? ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onPageSelected(int position) { ? ? ? ? ? ? ? ? // 手滑動到某一位置,重新開始計(jì)時(shí) ? ? ? ? ? ? ? ? start(); ? ? ? ? ? ? } ? ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onPageScrollStateChanged(int state) { ? ? ? ? ? ? ? } ? ? ? ? }); ? private void start() { ? ? ? ? mHandler.removeCallbacksAndMessages(null); ? ? ? ? mHandler.postDelayed(bannerRunnable, 3000); ? ? }
第四步:添加指示器
指示器樣式及表現(xiàn)可以自己去根據(jù)需求實(shí)現(xiàn),以相對簡單和常見的小圓圈指示器為例,添加和banner數(shù)量相同的小圓圈,小圓圈設(shè)置selector,在選中時(shí)為黑色選中樣式,在非選中時(shí)為灰色默認(rèn)樣式,根據(jù)當(dāng)前選中的banner的實(shí)際position,設(shè)置指示器的selected屬性,從而展示不同的樣式
private void initIndicator() { ? ? ? ? for (int i = 0; i < getUrlList().size(); i++) { ? ? ? ? ? ? View view = new View(getActivity()); ? ? ? ? ? ? LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(Utils.dip2pixel(getActivity(), 6), Utils.dip2pixel(getActivity(), 6)); ? ? ? ? ? ? lp.rightMargin = Utils.dip2pixel(getActivity(), 8); ? ? ? ? ? ? view.setLayoutParams(lp); ? ? ? ? ? ? view.setBackgroundResource(R.drawable.selector_indicator_view); ? ? ? ? ? ? view.setSelected(i == 0); ? ? ? ? ? ? llIndicatorView.addView(view); ? ? ? ? } ? ? } ? ? private void initBannerView() { ? ? ? ? bannerView.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { ? ? ? ? ? ? ? } ? ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onPageSelected(int position) { ? ? ? ? ? ? ? ? // 手滑動到某一位置,重新開始計(jì)時(shí) ? ? ? ? ? ? ? ? realPosition = 0; ? ? ? ? ? ? ? ? realPosition = position % getUrlList().size(); ? ? ? ? ? ? ? ? // 根據(jù)當(dāng)前滑動到的banner設(shè)置指示器的狀態(tài) ? ? ? ? ? ? ? ? for (int i = 0; i < llIndicatorView.getChildCount(); i++) { ? ? ? ? ? ? ? ? ? ? llIndicatorView.getChildAt(i).setSelected(i == realPosition); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? start(); ? ? ? ? ? ? } ? ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onPageScrollStateChanged(int state) { ? ? ? ? ? ? ? } ? ? ? ? }); ? ? }
附:Utils文件
public class Utils { ? ? public static void setFullScreen(Activity activity) { ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ? ? ? ? ? ? ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); ? ? ? ? ? ? decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); ? ? ? ? ? ? activity.getWindow().setStatusBarColor(Color.TRANSPARENT); ? ? ? ? } ? ? } ? ? ? public static int dip2pixel(Context context, float n) { ? ? ? ? int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, n, context.getResources().getDisplayMetrics()); ? ? ? ? return value; ? ? } ? ? ? /** ? ? ?* 獲取屏幕寬度 ? ? ?* @param context ? ? ?* @return 屏幕寬度 ? ? ?*/ ? ? public static int getScreenWidth(Context context) { ? ? ? ? WindowManager wm = (WindowManager) context ? ? ? ? ? ? ? ? .getSystemService(Context.WINDOW_SERVICE); ? ? ? ? DisplayMetrics outMetrics = new DisplayMetrics(); ? ? ? ? wm.getDefaultDisplay().getMetrics(outMetrics); ? ? ? ? return outMetrics.widthPixels; ? ? } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)自動變換大小的ViewPager
- Android使用ViewPager實(shí)現(xiàn)翻頁效果
- Android自定義View實(shí)現(xiàn)遙控器按鈕
- Android單選多選按鈕的使用方法
- Android實(shí)現(xiàn)單選按鈕
- Android 中使用RadioGroup和Fragment實(shí)現(xiàn)底部導(dǎo)航欄的功能
- Android基礎(chǔ)控件RadioGroup使用方法詳解
- Android RadioGroup多行顯示效果 解決單選問題
- Kotlin RadioGroup與ViewPager實(shí)現(xiàn)底層分頁按鈕方法
相關(guān)文章
uniapp打包Android的apk(原生APP-云打包)及發(fā)布測試全過程
uni-app本地打包apk需要提前做非常多的準(zhǔn)備工作,而且可能會勸退一些開發(fā)者,下面這篇文章主要給大家介紹了關(guān)于uniapp打包Android的apk(原生APP-云打包)及發(fā)布測試的相關(guān)資料,需要的朋友可以參考下2023-02-02Android刮刮樂效果-proterDuffXfermode的示例代碼
這篇文章主要介紹了Android刮刮樂效果-proterDuffXfermode,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12Flutter實(shí)現(xiàn)自定義篩選框的示例代碼
本文主要介紹了Flutter實(shí)現(xiàn)自定義篩選框的示例代碼,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07Android Studio 3.0中mipmap-anydpi-v26是什么東東
在Android Studio 3.0中一旦我們創(chuàng)建了一個(gè)項(xiàng)目,一個(gè)名為mipmap-anydpi-v26自動創(chuàng)建的文件夾在res文件夾下。它究竟能干什么?為什么我們需要這個(gè)?我們在開發(fā)時(shí)該如何利用它,下面通過本文給大家介紹下2017-12-12Flutter實(shí)現(xiàn)網(wǎng)絡(luò)請求的方法示例
這篇文章主要介紹了Flutter實(shí)現(xiàn)網(wǎng)絡(luò)請求的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03