<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android 輪播圖從 0 到 1

          共 3725字,需瀏覽 8分鐘

           ·

          2022-02-28 18:11

          47138cea3e504f33ee8a9072796ac1cd.webp

          從 0 到 1

          輪播圖是 Android 常用功能之一,效果大概是這樣的:

          345eb6fa2edba2173de0940d4f1cabb5.webp

          漏洞百出

          之前我封裝寫了一個(gè),基本達(dá)到了要求,是繼承了 Fragment(當(dāng)時(shí)腦袋肯定銹掉了),里面 Viewpager add Fragment,這次項(xiàng)目多處有輪播圖,發(fā)現(xiàn)之前封裝的不夠用,簡(jiǎn)直漏洞百出:

          1、比如底部 point 的位置,之前固定在中間,現(xiàn)在可能要放在右下角,point 最好也能動(dòng)態(tài)改圖片;

          2、現(xiàn)在項(xiàng)目跟微信一樣,底部 tab 切換,中間是 Fragment 替換,發(fā)現(xiàn)輪播圖有問(wèn)題,F(xiàn)ragment A 循環(huán)的 point 的 positoin 居然影響到了 Fragment B,照理,這是兩個(gè) BannerFragment,不會(huì)影響的啊,報(bào)以下錯(cuò)誤:

          java.lang.IllegalStateException:?The?application's?PagerAdapter?changed?the?adapter's?contents?without?calling?PagerAdapter#notifyDataSetChanged!

          經(jīng)過(guò)排查,找到了原因,因?yàn)?Viewpager add Fragment 我全部放在一個(gè)類,因此:

          public?static?List?bannerList?=?new?ArrayList<>();

          這里 static 壞事了,之前一個(gè) banner 沒(méi)有暴露出來(lái)。

          3、繼承了 Fragment,引用比較麻煩,F(xiàn)ragment 有兩者引用方法,xml 和代碼,兩者方式 addData 卻報(bào)錯(cuò);

          4、banner 沒(méi)有寫點(diǎn)擊回調(diào)。

          再次封裝

          綜合以上問(wèn)題,我進(jìn)行了優(yōu)化,繼承 LinearLayout,當(dāng)一個(gè)控件來(lái)引用,省去不必要的麻煩,底部 point 的位置可以設(shè)置:

          pointLayout.setGravity(bannerPointGravity);

          另外自定義了屬性,動(dòng)態(tài)設(shè)置 point 大小和圖片,輪播圖循環(huán)時(shí)間,也能代碼設(shè)置,完整代碼示例:

          /**
          ?*?Created?by?WuXiaolong?on?2017/8/24.
          ?*?個(gè)人博客:http://wuxiaolong.me
          ?*/


          public?class?BannerLayout?extends?LinearLayout?{

          ????private?ViewPager?viewPager;
          ????private?LinearLayout?pointLayout;
          ????private?ScheduledExecutorService?scheduler;
          ????private?int?mPosition?=?0;
          ????private?int?mBannerCount?=?1;
          ????private?Context?context;
          ????private?Activity?activity;
          ????private?int?bannerPointSize;
          ????private?int?bannerPointGravity;
          ????private?int?bannerPointDrawableSelected,?bannerPointDrawableUnselected;
          ????private?int?bannerDelaySecond;

          ????public?BannerLayout(Context?context)?{
          ????????this(context,?null);

          ????}

          ????public?BannerLayout(Context?context,?@Nullable?AttributeSet?attrs)?{
          ????????this(context,?attrs,?0);
          ????}

          ????public?BannerLayout(Context?context,?@Nullable?AttributeSet?attrs,?int?defStyleAttr)?{
          ????????super(context,?attrs,?defStyleAttr);
          ????????initView(context,?attrs);
          ????}


          ????private?void?initView(Context?context,?AttributeSet?attrs)?{
          ????????this.context?=?context;
          ????????activity?=?(Activity)?context;
          ????????TypedArray?typedArray?=?context.obtainStyledAttributes(attrs,?R.styleable.BannerLayout);
          ????????bannerPointSize?=?typedArray.getDimensionPixelSize(R.styleable.BannerLayout_bannerPointSize,?10);
          ????????bannerPointGravity?=?typedArray.getInt(R.styleable.BannerLayout_bannerPointGravity,?Gravity.CENTER);
          ????????bannerDelaySecond?=?typedArray.getInt(R.styleable.BannerLayout_bannerDelaySecond,?5);
          ????????bannerPointDrawableSelected?=?typedArray.getResourceId(R.styleable.BannerLayout_bannerPointDrawableSelected,?R.mipmap.point01);
          ????????bannerPointDrawableUnselected?=?typedArray.getResourceId(R.styleable.BannerLayout_bannerPointDrawableUnselected,?R.mipmap.point02);
          ????????typedArray.recycle();
          ????????View?view?=?View.inflate(context,?R.layout.banner_view_pager,?null);
          ????????addView(view);
          ????????viewPager?=?(ViewPager)?view.findViewById(R.id.viewPager);
          ????????pointLayout?=?(LinearLayout)?view.findViewById(R.id.pointLayout);
          ????????pointLayout.setGravity(bannerPointGravity);
          ????????viewPager.addOnPageChangeListener(new?ViewPager.OnPageChangeListener()?{
          ????????????@Override
          ????????????public?void?onPageScrolled(int?position,?float?positionOffset,?int?positionOffsetPixels)?{
          ????????????}

          ????????????@Override
          ????????????public?void?onPageSelected(int?position)?{
          ????????????????addPointLayout(position);
          ????????????}

          ????????????@Override
          ????????????public?void?onPageScrollStateChanged(int?state)?{
          ????????????}
          ????????});
          ????}

          ????public?void?start(List?bannerList)?{
          ????????bannerShutdown();
          ????????mBannerCount?=?bannerList.size();
          ????????BannerPagerAdapter?bannerPagerAdapter?=?new?BannerPagerAdapter(context,?bannerList);
          ????????viewPager.setAdapter(bannerPagerAdapter);

          ????????addPointLayout(0);
          ????????startScheduler();
          ????}

          ????private?void?addPointLayout(int?position)?{

          ????????pointLayout.removeAllViews();
          ????????for?(int?i?=?0;?i?????????????ImageView?imageView?=?new?ImageView(context);
          ????????????LinearLayout.LayoutParams?layoutParams?=?new?LinearLayout.LayoutParams(bannerPointSize,?bannerPointSize);
          ????????????layoutParams.setMargins(10,?0,?0,?0);
          ????????????imageView.setLayoutParams(layoutParams);

          ????????????if?(position?==?i)?{
          ????????????????imageView.setImageResource(bannerPointDrawableSelected);
          ????????????}?else?{
          ????????????????imageView.setImageResource(bannerPointDrawableUnselected);
          ????????????}
          ????????????pointLayout.addView(imageView);
          ????????}

          ????}


          ????private?void?startScheduler()?{
          ????????scheduler?=?Executors.newSingleThreadScheduledExecutor();
          ????????scheduler.scheduleAtFixedRate(new?Runnable()?{

          ????????????@Override
          ????????????public?void?run()?{
          ????????????????mPosition?=?viewPager.getCurrentItem();
          ????????????????if?(mPosition?1)?{
          ????????????????????mPosition++;
          ????????????????}?else?{
          ????????????????????mPosition?=?0;
          ????????????????}

          ????????????????activity.runOnUiThread(new?Runnable()?{
          ????????????????????@Override
          ????????????????????public?void?run()?{
          ????????????????????????viewPager.setCurrentItem(mPosition);
          ????????????????????}
          ????????????????});
          ????????????}
          ????????},?1,?bannerDelaySecond,?TimeUnit.SECONDS);
          ????}

          ????public?void?bannerShutdown()?{
          ????????if?(scheduler?!=?null)
          ????????????scheduler.shutdown();
          ????}

          ????private?class?BannerPagerAdapter?extends?PagerAdapter?{
          ????????private?List?bannerList?=?new?ArrayList<>();
          ????????private?Context?context;

          ????????BannerPagerAdapter(Context?context,?List?bannerList)?{
          ????????????this.context?=?context;
          ????????????this.bannerList.clear();
          ????????????this.bannerList.addAll(bannerList);
          ????????}

          ????????@Override
          ????????public?int?getCount()?{
          ????????????return?bannerList.size();
          ????????}

          ????????@Override
          ????????public?boolean?isViewFromObject(View?view,?Object?object)?{
          ????????????return?view?==?object;
          ????????}

          ????????@Override
          ????????public?Object?instantiateItem(ViewGroup?container,?final?int?position)?{
          ????????????ImageView?imageView?=?new?ImageView(context);
          ????????????imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
          ????????????Object?object?=?bannerList.get(position);
          ????????????//這里我封裝了?Glide?4.0?的工具類,用于顯示圖片
          ????????????ImageLoaderUtil.load(context,?object,?imageView);
          ????????????container.addView(imageView);

          ????????????return?imageView;
          ????????}

          ????????@Override
          ????????public?void?destroyItem(ViewGroup?container,?int?position,?Object?object)?{
          ????????????container.removeView((View)?object);
          ????????}
          ????}

          ????public?int?dp2px(float?var0)?{
          ????????float?var1?=?context.getResources().getDisplayMetrics().density;
          ????????return?(int)?(var0?*?var1?+?0.5F);
          ????}

          ????public?void?setBannerPointSize(int?bannerPointSize)?{
          ????????this.bannerPointSize?=?dp2px(bannerPointSize);
          ????}

          ????public?void?setBannerPointGravity(int?bannerPointGravity)?{
          ????????this.bannerPointGravity?=?bannerPointGravity;
          ????????pointLayout.setGravity(bannerPointGravity);
          ????}

          ????public?void?setBannerPointDrawableSelected(int?bannerPointDrawableSelected)?{
          ????????this.bannerPointDrawableSelected?=?bannerPointDrawableSelected;
          ????}

          ????public?void?setBannerPointDrawableUnselected(int?bannerPointDrawableUnselected)?{
          ????????this.bannerPointDrawableUnselected?=?bannerPointDrawableUnselected;
          ????}

          ????public?void?setBannerDelaySecond(int?bannerDelaySecond)?{
          ????????this.bannerDelaySecond?=?bannerDelaySecond;
          ????}

          }

          其中自定義屬性的 attrs.xml:


          <resources>

          ????<declare-styleable?name="BannerLayout">
          ????????
          ????????<attr?name="bannerPointSize"?format="dimension"?/>
          ????????
          ????????<attr?name="bannerPointGravity"?format="enum">
          ????????????<enum?name="left"?value="3"?/>
          ????????????<enum?name="center"?value="17"?/>
          ????????????<enum?name="right"?value="5"?/>
          ????????attr>
          ????????
          ????????<attr?name="bannerPointDrawableSelected"?format="reference"?/>
          ????????
          ????????<attr?name="bannerPointDrawableUnselected"?format="reference"?/>
          ????????
          ????????<attr?name="bannerDelaySecond"?format="integer"?/>
          ????declare-styleable>
          resources>
          使用說(shuō)明

          xml

          <com.wuxiaolong.bannersample.BannerLayout
          ????android:id="@+id/bannerView"
          ????android:layout_width="match_parent"
          ????android:layout_height="198dp"
          ????app:bannerDelaySecond="3"
          ????app:bannerPointDrawableSelected="@drawable/gray_radius"
          ????app:bannerPointDrawableUnselected="@drawable/white_radius"
          ????app:bannerPointGravity="right"
          ????app:bannerPointSize="10dp"?/>

          調(diào)用:

          public?class?MainActivity?extends?AppCompatActivity?{
          ????private?BannerLayout?bannerView;

          ????@Override
          ????protected?void?onCreate(Bundle?savedInstanceState)?{
          ????????super.onCreate(savedInstanceState);
          ????????setContentView(R.layout.activity_main);
          ????????bannerView?=?(BannerLayout)?findViewById(R.id.bannerView);
          ????????List?bannerList?=?new?ArrayList<>();
          ????????bannerList.add(R.mipmap.horizontal_default);
          ????????bannerList.add("http://pic1.win4000.com/wallpaper/5/598161750eddb.jpg");
          ????????bannerList.add("http://pic1.win4000.com/wallpaper/4/597efb5b6aae8.jpg");
          ????????bannerView.setBannerPointSize(10);
          ????????bannerView.setBannerPointGravity(Gravity.CENTER);
          ????????bannerView.setBannerPointDrawableSelected(R.drawable.gray_radius);
          ????????bannerView.setBannerPointDrawableUnselected(R.mipmap.point01);
          ????????bannerView.setBannerDelaySecond(5);
          ????????//banner?設(shè)置方法完畢時(shí)最后調(diào)用?start?方法
          ????????bannerView.start(bannerList);
          ????}

          ????@Override
          ????protected?void?onStop()?{
          ????????super.onStop();
          ????????bannerView.bannerShutdown();
          ????}
          }

          如果以上還滿足不了你的需求,可以使用 GitHub 上的輪子。

          現(xiàn)有輪子

          這個(gè)庫(kù)使用了 ViewPager2 為基礎(chǔ)控件,支持了 androidx 兼容包,方便了 UI、Indicator 自定義,支持畫廊效果、魅族效果,兼容了水平和垂直輪播,也可以實(shí)現(xiàn)類似淘寶頭條的效果,依賴包目前只需要導(dǎo)入了 ViewPager2。

          92ec6d177a59df56ed588c399a10002b.webpe9557a257ad2df0f04e0d3eac8fdc7da.webp92ec6d177a59df56ed588c399a10002b.webp9406639d4ca258133fa4dd75be62b928.webp

          還內(nèi)置了多種 PageTransformer 效果

          e8f93be17e8d1ca19bdf68f7e2011070.webp

          如何下載源碼?在公眾號(hào) 「Android 指南」 后臺(tái)回復(fù) banner 獲取源碼。

          瀏覽 60
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    国产在线综合网站 | 操小逼逼的操小逼逼 | 国产三级精品视频 | 大香蕉伊人在线网站 | 国产网站91 |