1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Android 輪播圖從 0 到 1

        共 3725字,需瀏覽 8分鐘

         ·

        2022-02-28 18:11

        47138cea3e504f33ee8a9072796ac1cd.webp

        從 0 到 1

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

        345eb6fa2edba2173de0940d4f1cabb5.webp

        漏洞百出

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

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

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

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

        經過排查,找到了原因,因為 Viewpager add Fragment 我全部放在一個類,因此:

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

        這里 static 壞事了,之前一個 banner 沒有暴露出來。

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

        4、banner 沒有寫點擊回調。

        再次封裝

        綜合以上問題,我進行了優(yōu)化,繼承 LinearLayout,當一個控件來引用,省去不必要的麻煩,底部 point 的位置可以設置:

        pointLayout.setGravity(bannerPointGravity);

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

        /**
        ?*?Created?by?WuXiaolong?on?2017/8/24.
        ?*?個人博客: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>
        使用說明

        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"?/>

        調用:

        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?設置方法完畢時最后調用?start?方法
        ????????bannerView.start(bannerList);
        ????}

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

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

        現(xiàn)有輪子

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

        92ec6d177a59df56ed588c399a10002b.webpe9557a257ad2df0f04e0d3eac8fdc7da.webp92ec6d177a59df56ed588c399a10002b.webp9406639d4ca258133fa4dd75be62b928.webp

        還內置了多種 PageTransformer 效果

        e8f93be17e8d1ca19bdf68f7e2011070.webp

        如何下載源碼?在公眾號 「Android 指南」 后臺回復 banner 獲取源碼。

        瀏覽 60
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            91人妻人人澡人人精品 | 午夜成人视频网站 | 噜啪啪 | 黑人日比 | 性videosgratis喷水 | 日韩一二 | 国产玖玖精品视频 | 亚洲九一| 国产91 对白在线播放 | 东北少妇高潮抽搐 |